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.
@@ -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,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TSparser
3
+ class AudioComponentDescriptor
4
+ include Parsing
5
+
6
+ def_parsing do
7
+ read :descriptor_tag, Integer, 8
8
+ read :descriptor_length, Integer, 8
9
+ read :rest, Binary, descriptor_length * 8
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TSparser
3
+ class CAContractInformationDescriptor
4
+ include Parsing
5
+
6
+ def_parsing do
7
+ read :descriptor_tag, Integer, 8
8
+ read :descriptor_length, Integer, 8
9
+ read :rest, Binary, descriptor_length * 8
10
+ end
11
+ end
12
+ 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,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TSparser
3
+ class DataContentDescriptor
4
+ include Parsing
5
+
6
+ def_parsing do
7
+ read :descriptor_tag, Integer, 8
8
+ read :descriptor_length, Integer, 8
9
+ read :rest, Binary, descriptor_length * 8
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TSparser
3
+ class DigitalCopyControlDescriptor
4
+ include Parsing
5
+
6
+ def_parsing do
7
+ read :descriptor_tag, Integer, 8
8
+ read :descriptor_length, Integer, 8
9
+ read :rest, Binary, descriptor_length * 8
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TSparser
3
+ class EventGroupDescriptor
4
+ include Parsing
5
+
6
+ def_parsing do
7
+ read :descriptor_tag, Integer, 8
8
+ read :descriptor_length, Integer, 8
9
+ read :rest, Binary, descriptor_length * 8
10
+ end
11
+ end
12
+ 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,13 @@
1
+ # -*- coding: utf-8 -*-
2
+ module TSparser
3
+ class UnknownDescriptor
4
+ include Parsing
5
+
6
+ def_parsing do
7
+ read :descriptor_tag, Integer, 8
8
+ read :descriptor_length, Integer, 8
9
+ read :rest, Binary, descriptor_length * 8
10
+ end
11
+ end
12
+ end
13
+
@@ -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