tsparser 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +16 -0
- data/lib/arib_string_decoder.rb +441 -0
- data/lib/binary.rb +202 -0
- data/lib/definition/arib_duration.rb +19 -0
- data/lib/definition/arib_string.rb +327 -0
- data/lib/definition/arib_time.rb +41 -0
- data/lib/definition/descriptor.rb +27 -0
- data/lib/definition/descriptor/audio_component_descriptor.rb +12 -0
- data/lib/definition/descriptor/ca_contract_information_descriptor.rb +12 -0
- data/lib/definition/descriptor/component_descriptor.rb +18 -0
- data/lib/definition/descriptor/content_descriptor.rb +37 -0
- data/lib/definition/descriptor/data_content_descriptor.rb +12 -0
- data/lib/definition/descriptor/digital_copy_control_descriptor.rb +12 -0
- data/lib/definition/descriptor/event_group_descriptor.rb +12 -0
- data/lib/definition/descriptor/extended_event_descriptor.rb +52 -0
- data/lib/definition/descriptor/short_event_descriptor.rb +17 -0
- data/lib/definition/descriptor/unknown_descriptor.rb +13 -0
- data/lib/definition/descriptor_list.rb +17 -0
- data/lib/definition/eit_event.rb +21 -0
- data/lib/definition/event_information_section.rb +53 -0
- data/lib/definition/event_list.rb +17 -0
- data/lib/definition/transport_packet.rb +68 -0
- data/lib/epg.rb +29 -0
- data/lib/parsing.rb +63 -0
- data/lib/psi_section_reader.rb +39 -0
- data/lib/ts.rb +41 -0
- data/lib/tsparser.rb +75 -0
- metadata +72 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class AribTime
|
4
|
+
require 'date'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
def initialize(binary)
|
8
|
+
@mjd = binary.read_byte_as_integer(2)
|
9
|
+
@hour = binary.read_bit_as_integer(4) * 10 + binary.read_bit_as_integer(4)
|
10
|
+
@min = binary.read_bit_as_integer(4) * 10 + binary.read_bit_as_integer(4)
|
11
|
+
@sec = binary.read_bit_as_integer(4) * 10 + binary.read_bit_as_integer(4)
|
12
|
+
end
|
13
|
+
|
14
|
+
def date
|
15
|
+
return @date ||= convert_mjd_to_date(@mjd)
|
16
|
+
end
|
17
|
+
|
18
|
+
# ARIB STD-B10 2, appendix-C
|
19
|
+
def convert_mjd_to_date(mjd)
|
20
|
+
y_ = ((mjd - 15078.2) / 365.25).to_i
|
21
|
+
m_ = ((mjd - 14956.1 - (y_ * 365.25).to_i) / 30.6001).to_i
|
22
|
+
d = mjd - 14956 - (y_ * 365.25).to_i - (m_ * 30.6001).to_i
|
23
|
+
k = (m_ == 14 || m_ == 15) ? 1 : 0
|
24
|
+
y = y_ + k
|
25
|
+
m = m_ - 1 - k * 12
|
26
|
+
return Date.new(1900 + y, m, d)
|
27
|
+
end
|
28
|
+
|
29
|
+
def date_str
|
30
|
+
return sprintf("%02d/%02d/%02d", date.year, date.month, date.day)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
return sprintf("%s %02d:%02d:%02d +0900", date_str, @hour, @min, @sec)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_time
|
38
|
+
return Time.parse(to_s)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class Descriptor
|
4
|
+
|
5
|
+
# ARIB STD-B10 Table5-3
|
6
|
+
DescriptorTable = {
|
7
|
+
0x4D => TSparser::ShortEventDescriptor,
|
8
|
+
0x4E => TSparser::ExtendedEventDescriptor,
|
9
|
+
0x50 => TSparser::ComponentDescriptor,
|
10
|
+
0x54 => TSparser::ContentDescriptor,
|
11
|
+
0xC1 => TSparser::DigitalCopyControlDescriptor,
|
12
|
+
0xC4 => TSparser::AudioComponentDescriptor,
|
13
|
+
0xC7 => TSparser::DataContentDescriptor,
|
14
|
+
0xCB => TSparser::CAContractInformationDescriptor, # Defined in ARIB STD-B25
|
15
|
+
0xD6 => TSparser::EventGroupDescriptor
|
16
|
+
}
|
17
|
+
DescriptorTable.default = TSparser::UnknownDescriptor
|
18
|
+
|
19
|
+
def self.new(binary)
|
20
|
+
now_point = binary.bit_pointer / 8
|
21
|
+
descriptor_tag = binary.b(now_point + 0)
|
22
|
+
descriptor_length = binary.b(now_point + 1)
|
23
|
+
descriptor_whole_binary = binary.read_bit_as_binary(descriptor_length * 8 + 16)
|
24
|
+
return DescriptorTable[descriptor_tag].new(descriptor_whole_binary)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class ComponentDescriptor
|
4
|
+
include Parsing
|
5
|
+
|
6
|
+
def_parsing do
|
7
|
+
read :descriptor_tag, Integer, 8
|
8
|
+
read :descriptor_length, Integer, 8
|
9
|
+
read :reserved_future_use, Binary, 4
|
10
|
+
read :stream_content, Integer, 4
|
11
|
+
read :component_type, Integer, 8
|
12
|
+
read :component_tag, Integer, 8
|
13
|
+
read :iso_639_language_code, String, 24
|
14
|
+
read :text, AribString, descriptor_length * 8 - 48
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class ContentDescriptor
|
4
|
+
include Parsing
|
5
|
+
|
6
|
+
def_parsing do
|
7
|
+
read :descriptor_tag, Integer, 8
|
8
|
+
read :descriptor_length, Integer, 8
|
9
|
+
read :contents, ContentList, descriptor_length * 8
|
10
|
+
end
|
11
|
+
|
12
|
+
class ContentList
|
13
|
+
|
14
|
+
def initialize(binary)
|
15
|
+
@contents = []
|
16
|
+
while binary.readable?
|
17
|
+
@contents << Content.new(binary)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def each(&block)
|
22
|
+
@contents.each(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
class Content
|
26
|
+
include Parsing
|
27
|
+
|
28
|
+
def_parsing do
|
29
|
+
read :content_nibble_level_1, Integer, 4
|
30
|
+
read :content_nibble_level_2, Integer, 4
|
31
|
+
read :user_nibble, Integer, 4
|
32
|
+
read :user_nibble, Integer, 4
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class ExtendedEventDescriptor
|
4
|
+
include Parsing
|
5
|
+
|
6
|
+
def_parsing do
|
7
|
+
read :descriptor_tag, Integer, 8
|
8
|
+
read :descriptor_length, Integer, 8
|
9
|
+
read :descriptor_number, Integer, 4
|
10
|
+
read :last_descriptor_number, Integer, 4
|
11
|
+
read :iso_639_language_code, String, 24
|
12
|
+
read :length_of_items, Integer, 8
|
13
|
+
read :item_map, ItemHash, length_of_items * 8
|
14
|
+
read :text_length, Integer, 8
|
15
|
+
read :text, AribString, text_length * 8
|
16
|
+
end
|
17
|
+
|
18
|
+
class ItemHash
|
19
|
+
def initialize(binary)
|
20
|
+
@item_map = Hash.new
|
21
|
+
while binary.readable?
|
22
|
+
item = Item.new(binary)
|
23
|
+
@item_map[item.item_description.to_utf_8] = item.item.to_utf_8
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](key)
|
28
|
+
return @item_map[key]
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_h
|
32
|
+
return @item_map.dup
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
return @item_map.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
class Item
|
40
|
+
include Parsing
|
41
|
+
|
42
|
+
def_parsing(false) do
|
43
|
+
read :item_description_length, Integer, 8
|
44
|
+
read :item_description, AribString, item_description_length * 8
|
45
|
+
read :item_length, Integer, 8
|
46
|
+
read :item, AribString, item_length * 8
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class ShortEventDescriptor
|
4
|
+
include Parsing
|
5
|
+
|
6
|
+
def_parsing do
|
7
|
+
read :descriptor_tag, Integer, 8
|
8
|
+
read :descriptor_length, Integer, 8
|
9
|
+
read :iso_639_language_code, String, 24
|
10
|
+
read :event_name_length, Integer, 8
|
11
|
+
read :event_name, AribString, event_name_length * 8
|
12
|
+
read :text_length, Integer, 8
|
13
|
+
read :text, AribString, text_length * 8
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class DescriptorList
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(binary)
|
7
|
+
@descriptors = []
|
8
|
+
while binary.readable?
|
9
|
+
@descriptors << Descriptor.new(binary)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@descriptors.each(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class EITEvent
|
4
|
+
include Parsing
|
5
|
+
|
6
|
+
# define data-structure of event_information_section
|
7
|
+
# this is following ARIB-STD-b10v4_9 - 88p
|
8
|
+
def_parsing(false) do
|
9
|
+
read :event_id, Integer, 16
|
10
|
+
read :start_time, AribTime, 40
|
11
|
+
read :duration, AribDuration, 24
|
12
|
+
read :running_status, Integer, 3
|
13
|
+
read :free_ca_mode, Integer, 1
|
14
|
+
read :descriptors_loop_length, Integer, 12
|
15
|
+
read :descriptors, DescriptorList, descriptors_loop_length * 8
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class EventInformationSection
|
4
|
+
include Parsing
|
5
|
+
|
6
|
+
def self.section_length_enough?(section_binary)
|
7
|
+
section_length = (section_binary.b(1, 0..3) << 8) + section_binary.b(2)
|
8
|
+
return section_binary.length >= section_length + 3
|
9
|
+
end
|
10
|
+
|
11
|
+
# define data-structure of event_information_section
|
12
|
+
# this is following ARIB-STD-b10v4_9 - 88p
|
13
|
+
def_parsing do
|
14
|
+
read :table_id, Integer, 8
|
15
|
+
read :section_syntax_indicator, Integer, 1
|
16
|
+
read :reserved_future_use, Integer, 1
|
17
|
+
read :reserved1, Integer, 2
|
18
|
+
read :section_length, Integer, 12
|
19
|
+
read :service_id, Integer, 16
|
20
|
+
read :reserved2, Integer, 2
|
21
|
+
read :version_number, Integer, 5
|
22
|
+
read :current_next_indicator, Integer, 1
|
23
|
+
read :section_number, Integer, 8
|
24
|
+
read :last_section_number, Integer, 8
|
25
|
+
read :transport_stream_id, Integer, 16
|
26
|
+
read :original_network_id, Integer, 16
|
27
|
+
read :segment_last_section_number, Integer, 8
|
28
|
+
read :last_table_id, Integer, 8
|
29
|
+
read :events, EITEventList, section_length * 8 - 88 - 32
|
30
|
+
read :crc_32, Integer, 32
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_epg
|
34
|
+
epg = EPG.new
|
35
|
+
events.each do |event|
|
36
|
+
attr_hash = {
|
37
|
+
:event_id => event.event_id,
|
38
|
+
:start_time => event.start_time.to_s,
|
39
|
+
:duration => event.duration.to_sec
|
40
|
+
}
|
41
|
+
event.descriptors.each do |desc|
|
42
|
+
case desc
|
43
|
+
when ShortEventDescriptor
|
44
|
+
attr_hash[:name] = desc.event_name.to_utf_8
|
45
|
+
attr_hash[:description] = desc.text.to_utf_8
|
46
|
+
end
|
47
|
+
end
|
48
|
+
epg.add(event.event_id, attr_hash) if attr_hash[:name]
|
49
|
+
end
|
50
|
+
return epg
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
class EITEventList
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(binary)
|
7
|
+
@events = []
|
8
|
+
while binary.readable?
|
9
|
+
@events << EITEvent.new(binary)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
@events.each(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
|
4
|
+
# Define data-structure of transport packet.
|
5
|
+
# This is following
|
6
|
+
# iso13818-1, 2.4.3.2, Table2-2 and 2.4.3.5, Table2-6 (adaptation field).
|
7
|
+
class TransportPacket
|
8
|
+
include Parsing
|
9
|
+
|
10
|
+
def_parsing do
|
11
|
+
read :sync_byte, Integer, 8
|
12
|
+
read :transport_error_indicator, Integer, 1
|
13
|
+
read :payload_unit_start_indicator, Integer, 1
|
14
|
+
read :transport_priority, Integer, 1
|
15
|
+
read :pid, Integer, 13
|
16
|
+
read :transport_scrambling_control, Integer, 2
|
17
|
+
read :adaptation_field_control, Integer, 2
|
18
|
+
read :continuity_counter, Integer, 4
|
19
|
+
if adaptation_field_control[1] == 1
|
20
|
+
read :adaptation_field_length, Integer, 8
|
21
|
+
if adaptation_field_length > 0
|
22
|
+
read :adaptation_field, AdaptationField, adaptation_field_length * 8
|
23
|
+
end
|
24
|
+
end
|
25
|
+
if adaptation_field_control[0] == 1
|
26
|
+
read :payload, Binary, rest_all
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Especial parsing of PID for fast calculation.
|
31
|
+
def pid
|
32
|
+
return @pid ||= (@binary.b(1, 0..4) << 8) + @binary.b(2)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Define data-structure of adaptation field in transport packet.
|
37
|
+
# This is following
|
38
|
+
# iso13818-1, 2.4.3.5, Table2-6.
|
39
|
+
class AdaptationField
|
40
|
+
include Parsing
|
41
|
+
|
42
|
+
def_parsing do
|
43
|
+
read :discontinuity_indicator, Integer, 1
|
44
|
+
read :random_acceses_indicator, Integer, 1
|
45
|
+
read :elementary_stream_priority_indicator, Integer, 1
|
46
|
+
read :pcr_flag, Integer, 1
|
47
|
+
read :opcr_flag, Integer, 1
|
48
|
+
read :splicing_point_flag, Integer, 1
|
49
|
+
read :transport_private_data_flag, Integer, 1
|
50
|
+
read :adaptation_field_extension_flag, Integer, 1
|
51
|
+
if pcr_flag == 1
|
52
|
+
|
53
|
+
end
|
54
|
+
if opcr_flag == 1
|
55
|
+
|
56
|
+
end
|
57
|
+
if splicing_point_flag == 1
|
58
|
+
|
59
|
+
end
|
60
|
+
if transport_private_data_flag == 1
|
61
|
+
|
62
|
+
end
|
63
|
+
if adaptation_field_extension_flag == 1
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|