tsparser 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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