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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c9b570a983382340953fd68ee0408552ce60d193
|
4
|
+
data.tar.gz: 896fe7d5dd3b272b41e5096ab88908af81912380
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4b9e3fe054142de666f05e80aa732830afd43ecddc07eef9d1644c6d20ac8022458450a4e0910c339dec095fab2d915fdb5b85d1579dbbac0102bcff3d6e6aa5
|
7
|
+
data.tar.gz: 884e82aa43d908815c4d8ef1ec7590d128f50c4ef9a9bce3592318acf76db286a103782dd4d8068fa118de890c03d5d16b28de70abae93ee580171b3b4d275e7
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 rokugatsu
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,441 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module TSparser
|
3
|
+
module AribStringDecoder
|
4
|
+
ESC = 0x1B
|
5
|
+
|
6
|
+
def decode(binary)
|
7
|
+
decoder = self.class.new_decoder
|
8
|
+
return decoder.decode(binary).to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included(klass)
|
12
|
+
klass.extend ClassExtension
|
13
|
+
end
|
14
|
+
|
15
|
+
# --------------------------------------------------
|
16
|
+
# Module for class extension when AribStringDecoder is included.
|
17
|
+
# --------------------------------------------------
|
18
|
+
module ClassExtension
|
19
|
+
def new_decoder
|
20
|
+
args = [@code_caller, @code_operator, @code_set_map, @code_proc_map, @code_length_map,
|
21
|
+
@group_map, @region_map, @control_code_map]
|
22
|
+
return AribStringDecoder::Decoder.new(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def def_default_group_map(&block)
|
26
|
+
@group_map = block.call
|
27
|
+
end
|
28
|
+
|
29
|
+
def def_default_region_map(&block)
|
30
|
+
@region_map = block.call
|
31
|
+
end
|
32
|
+
|
33
|
+
def def_control_code(control_code_name, &block)
|
34
|
+
@control_code_map ||= Hash.new
|
35
|
+
@control_code_map[control_code_name] = AribStringDecoder::Definition::ControlCode.new
|
36
|
+
@control_code_map[control_code_name].instance_eval(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def def_code_call(&block)
|
40
|
+
@code_caller = AribStringDecoder::Definition::CodeCaller.new
|
41
|
+
@code_caller.instance_eval(&block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def def_code_operation(&block)
|
45
|
+
@code_operator = AribStringDecoder::Definition::CodeOperator.new
|
46
|
+
@code_operator.instance_eval(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def def_code_set(set_name, &block)
|
50
|
+
@code_set_map ||= Hash.new
|
51
|
+
@code_set_map[set_name] = AribStringDecoder::Definition::CodeSet.new
|
52
|
+
@code_set_map[set_name].instance_eval(&block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def def_code(code_length, *code_names, &block)
|
56
|
+
@code_proc_map ||= Hash.new
|
57
|
+
@code_length_map ||= Hash.new
|
58
|
+
code_names.each do |code_name|
|
59
|
+
@code_proc_map[code_name] = block
|
60
|
+
@code_length_map[code_name] = code_length
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def def_mapping(map_name, &block)
|
65
|
+
AribStringDecoder.const_set(map_name, block.call)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# --------------------------------------------------
|
70
|
+
# Classes to retain definition of code.
|
71
|
+
# These class's instance is used to define setting in AribString.
|
72
|
+
# --------------------------------------------------
|
73
|
+
module Definition
|
74
|
+
class ControlCode
|
75
|
+
def initialize
|
76
|
+
@map = Hash.new
|
77
|
+
end
|
78
|
+
|
79
|
+
def set(name, code_num, operation_name, *args)
|
80
|
+
@map[code_num] = [operation_name, args]
|
81
|
+
end
|
82
|
+
|
83
|
+
def match?(byte)
|
84
|
+
return !!@map[byte.to_i(0)]
|
85
|
+
end
|
86
|
+
|
87
|
+
def get(byte)
|
88
|
+
return @map[byte.to_i(0)]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class CodeCaller
|
93
|
+
def initialize
|
94
|
+
@map_whole = Hash.new
|
95
|
+
@map_part = Hash.new{0}
|
96
|
+
end
|
97
|
+
|
98
|
+
def set(name, seq, group, target_region, call_type)
|
99
|
+
seq = seq.map{|int| Binary.from_int(int)}
|
100
|
+
@map_whole[seq] = [group, target_region, call_type]
|
101
|
+
seq.length.times do |i|
|
102
|
+
@map_part[seq[0..i]] += 1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def candidates(seq)
|
107
|
+
return @map_part[seq]
|
108
|
+
end
|
109
|
+
|
110
|
+
def pull(seq)
|
111
|
+
unless res = @map_whole[seq]
|
112
|
+
raise "No call match with #{seq}."
|
113
|
+
end
|
114
|
+
return res
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class CodeOperator
|
119
|
+
def initialize
|
120
|
+
@map = Hash.new
|
121
|
+
@map_part = Hash.new{0}
|
122
|
+
end
|
123
|
+
|
124
|
+
def set(seq, set_name, group_name)
|
125
|
+
seq = seq[0..(seq.length-2)].map{|int| Binary.from_int(int)}
|
126
|
+
@map[seq] = [set_name, group_name]
|
127
|
+
seq.length.times do |i|
|
128
|
+
@map_part[seq[0..i]] += 1
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def candidates(seq, set_map)
|
133
|
+
res = @map_part[seq]
|
134
|
+
set_name, group_name = @map[seq[0..(seq.length-2)]]
|
135
|
+
if set_name && set_map[set_name] && set_map[set_name].find_final_code(seq[-1])
|
136
|
+
res += 1
|
137
|
+
end
|
138
|
+
return res
|
139
|
+
end
|
140
|
+
|
141
|
+
def pull(seq, set_map)
|
142
|
+
set_name, group_name = @map[seq[0..(seq.length-2)]]
|
143
|
+
raise "No operation match with #{seq}." unless set_name
|
144
|
+
raise "Code set \"#{set_name}\" is undefined." unless set_map[set_name]
|
145
|
+
code_name, byte_length = set_map[set_name].find_final_code(seq[-1])
|
146
|
+
raise "Terminal symbol \"#{seq[-1]}\" is not found." unless code_name
|
147
|
+
return [code_name, group_name]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class CodeSet
|
152
|
+
def initialize
|
153
|
+
@final_code_map = Hash.new
|
154
|
+
end
|
155
|
+
|
156
|
+
def set(name, final_code, byte_length)
|
157
|
+
final_code = Binary.from_int(final_code)
|
158
|
+
@final_code_map[final_code] = [name, byte_length]
|
159
|
+
end
|
160
|
+
|
161
|
+
def find_final_code(final_code)
|
162
|
+
return @final_code_map[final_code]
|
163
|
+
end
|
164
|
+
|
165
|
+
def each_code(&block)
|
166
|
+
@final_code_map.each_key(&block)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# --------------------------------------------------
|
172
|
+
# Class which is express decoding process.
|
173
|
+
# Receive all coding definition object when instance is maked.
|
174
|
+
# --------------------------------------------------
|
175
|
+
class Decoder
|
176
|
+
def initialize(caller, operator, set_map, proc_map, length_map, group_map, region_map, control_code_map)
|
177
|
+
@caller = caller
|
178
|
+
@operator = operator
|
179
|
+
@set_map = set_map
|
180
|
+
@proc_map = proc_map
|
181
|
+
@length_map = length_map
|
182
|
+
@decoded = Decoded.new
|
183
|
+
@outputer = CodeOutputer.new(proc_map, @decoded)
|
184
|
+
@control_code_processor = ControlCodeProcessor.new(control_code_map, @decoded)
|
185
|
+
@current_group_map = group_map.dup
|
186
|
+
@current_region_map = region_map.dup
|
187
|
+
@current_single_region_map = Hash.new
|
188
|
+
end
|
189
|
+
|
190
|
+
def decode(binary)
|
191
|
+
begin
|
192
|
+
parse_one(binary) while binary.readable?
|
193
|
+
rescue => error
|
194
|
+
return @decoded if @decoded.to_s rescue nil
|
195
|
+
parse_error(error, binary)
|
196
|
+
end
|
197
|
+
return @decoded
|
198
|
+
end
|
199
|
+
|
200
|
+
def parse_error(error, binary)
|
201
|
+
STDERR.puts "Error occurred on the way to decode following bytes."
|
202
|
+
STDERR.puts " \"#{binary.dump}\""
|
203
|
+
STDERR.puts "Now process pointer is pointing at #{binary.bit_pointer / 8}-th byte."
|
204
|
+
begin
|
205
|
+
STDERR.puts "Trying to print now decoded string..."
|
206
|
+
STDERR.puts "Decoded: \"#{@decoded}\""
|
207
|
+
rescue
|
208
|
+
STDERR.puts "Sorry, failed."
|
209
|
+
end
|
210
|
+
raise error
|
211
|
+
end
|
212
|
+
|
213
|
+
def parse_one(binary)
|
214
|
+
byte = binary.read_byte_as_binary(1)
|
215
|
+
if byte >= 0x21 && byte <= 0x7E
|
216
|
+
output_code(byte, binary, :GL)
|
217
|
+
elsif byte >= 0xA1 && byte <= 0xFE
|
218
|
+
output_code(byte, binary, :GR)
|
219
|
+
elsif @control_code_processor.match?(byte)
|
220
|
+
@control_code_processor.process(byte, binary)
|
221
|
+
else
|
222
|
+
parse_control_code(byte, binary)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def output_code(byte, binary, target)
|
227
|
+
code_name = query_code(target)
|
228
|
+
if @length_map[code_name] == 1
|
229
|
+
byte &= 0x7F if target == :GR
|
230
|
+
@outputer.output(code_name, byte)
|
231
|
+
elsif @length_map[code_name] == 2
|
232
|
+
byte2 = binary.read_byte_as_binary(1)
|
233
|
+
if target == :GR
|
234
|
+
byte &= 0x7F
|
235
|
+
byte2 &= 0x7F
|
236
|
+
end
|
237
|
+
@outputer.output(code_name, byte, byte2)
|
238
|
+
else
|
239
|
+
raise "Unsupported code length #{@length_map[code_name]} (from #{code_name})."
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def parse_control_code(byte, binary)
|
244
|
+
control_code = [byte]
|
245
|
+
loop do
|
246
|
+
caller_candidates = @caller.candidates(control_code)
|
247
|
+
operator_candidates = @operator.candidates(control_code, @set_map)
|
248
|
+
if caller_candidates == 0 && operator_candidates == 0
|
249
|
+
raise "Unacceptable control code (#{control_code})."
|
250
|
+
end
|
251
|
+
if caller_candidates == 1 && operator_candidates == 0
|
252
|
+
set_target(*@caller.pull(control_code))
|
253
|
+
break
|
254
|
+
end
|
255
|
+
if caller_candidates == 0 && operator_candidates == 1
|
256
|
+
set_code_set(*@operator.pull(control_code, @set_map))
|
257
|
+
break
|
258
|
+
end
|
259
|
+
unless binary.readable?
|
260
|
+
raise "Binary is finished before accepting some operation code (now: #{control_code})."
|
261
|
+
end
|
262
|
+
control_code << binary.read_byte_as_binary(1)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def set_target(group_name, target_region, call_type)
|
267
|
+
case call_type
|
268
|
+
when :locking
|
269
|
+
@current_region_map[target_region] = group_name
|
270
|
+
when :single
|
271
|
+
@current_single_region_map[target_region] = group_name
|
272
|
+
else
|
273
|
+
raise "Unsupported call type \"#{call_type}\"."
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def set_code_set(code_name, group_name)
|
278
|
+
@current_group_map[group_name] = code_name
|
279
|
+
end
|
280
|
+
|
281
|
+
def query_code(region)
|
282
|
+
group_name = @current_single_region_map[region] || @current_region_map[region]
|
283
|
+
unless group_name
|
284
|
+
raise "No group is set to region \"#{region}\"."
|
285
|
+
end
|
286
|
+
code_name = @current_group_map[group_name]
|
287
|
+
unless code_name
|
288
|
+
raise "No code is set to group \"#{group_name}\"."
|
289
|
+
end
|
290
|
+
@current_single_region_map = Hash.new
|
291
|
+
return code_name
|
292
|
+
end
|
293
|
+
|
294
|
+
# Inner class to process control code(bytes).
|
295
|
+
class ControlCodeProcessor
|
296
|
+
def initialize(control_code_map, decoded)
|
297
|
+
@control_code_map = control_code_map
|
298
|
+
@decoded = decoded
|
299
|
+
end
|
300
|
+
|
301
|
+
def match?(byte)
|
302
|
+
return @control_code_map[:C0].match?(byte) || @control_code_map[:C1].match?(byte)
|
303
|
+
end
|
304
|
+
|
305
|
+
def get(byte)
|
306
|
+
if @control_code_map[:C0].match?(byte)
|
307
|
+
return @control_code_map[:C0].get(byte)
|
308
|
+
elsif @control_code_map[:C1].match?(byte)
|
309
|
+
return @control_code_map[:C1].get(byte)
|
310
|
+
else
|
311
|
+
raise "Undefined code #{byte}."
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def process(byte, binary)
|
316
|
+
operation_name, args = get(byte)
|
317
|
+
@binary = binary
|
318
|
+
send(operation_name, *args)
|
319
|
+
@binary = nil
|
320
|
+
end
|
321
|
+
|
322
|
+
def putstr(str)
|
323
|
+
@decoded.push_str(str)
|
324
|
+
end
|
325
|
+
|
326
|
+
def read_one
|
327
|
+
raise "Binary is not found." unless @binary
|
328
|
+
return @binary.read_byte_as_integer(1)
|
329
|
+
end
|
330
|
+
|
331
|
+
def exec(arg_num, proc)
|
332
|
+
args = []
|
333
|
+
arg_num.times{ args << read_one }
|
334
|
+
instance_exec(*args, &proc)
|
335
|
+
end
|
336
|
+
|
337
|
+
def nothing
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
# Inner class to output string code(bytes).
|
342
|
+
class CodeOutputer
|
343
|
+
def initialize(code_proc_map, decoded)
|
344
|
+
@code_proc_map = code_proc_map
|
345
|
+
@decoded = decoded
|
346
|
+
end
|
347
|
+
|
348
|
+
def output(code_name, *args)
|
349
|
+
unless @code_proc_map[code_name]
|
350
|
+
raise "Undefined code \"#{code_name}\" is called."
|
351
|
+
end
|
352
|
+
instance_exec(*args, &@code_proc_map[code_name])
|
353
|
+
end
|
354
|
+
|
355
|
+
def output_ascii_code(byte_integer)
|
356
|
+
@decoded.push_jis_ascii(Binary.from_int(byte_integer))
|
357
|
+
end
|
358
|
+
|
359
|
+
def assign(code_name, *args)
|
360
|
+
output(code_name, *args)
|
361
|
+
end
|
362
|
+
|
363
|
+
def output_str(string)
|
364
|
+
@decoded.push_str(string)
|
365
|
+
end
|
366
|
+
|
367
|
+
def output_jis_ascii(byte)
|
368
|
+
@decoded.push_jis_ascii(byte)
|
369
|
+
end
|
370
|
+
|
371
|
+
def output_jis_hankaku(byte)
|
372
|
+
@decoded.push_jis_hankaku(byte)
|
373
|
+
end
|
374
|
+
|
375
|
+
def output_jis_zenkaku(byte1, byte2)
|
376
|
+
@decoded.push_jis_zenkaku(byte1, byte2)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
# Inner class to retain decoded string.
|
381
|
+
class Decoded
|
382
|
+
CODE_ASCII, CODE_HANKAKU, CODE_ZENKAKU = :ascii, :hankaku, :zenkaku
|
383
|
+
|
384
|
+
def initialize
|
385
|
+
@decoded_utf_8 = "".encode(Encoding::UTF_8)
|
386
|
+
@buffer = Binary.new
|
387
|
+
end
|
388
|
+
|
389
|
+
def push_str(string)
|
390
|
+
convert_buffer
|
391
|
+
@decoded_utf_8 << string
|
392
|
+
end
|
393
|
+
|
394
|
+
def push_jis_ascii(byte)
|
395
|
+
if code_type_change(CODE_ASCII)
|
396
|
+
@buffer << Binary.from_int(ESC, 0x28, 0x42)
|
397
|
+
end
|
398
|
+
@buffer << byte
|
399
|
+
end
|
400
|
+
|
401
|
+
def push_jis_hankaku(byte)
|
402
|
+
if code_type_change(CODE_HANKAKU)
|
403
|
+
@buffer << Binary.from_int(ESC, 0x28, 0x49)
|
404
|
+
end
|
405
|
+
@buffer << byte
|
406
|
+
end
|
407
|
+
|
408
|
+
def push_jis_zenkaku(byte1, byte2)
|
409
|
+
if code_type_change(CODE_ZENKAKU)
|
410
|
+
@buffer << Binary.from_int(ESC, 0x24, 0x42)
|
411
|
+
end
|
412
|
+
@buffer << byte1 << byte2
|
413
|
+
end
|
414
|
+
|
415
|
+
def code_type_change(type)
|
416
|
+
return false if @buffer_current_code_type == type
|
417
|
+
@buffer_current_code_type = type
|
418
|
+
return true
|
419
|
+
end
|
420
|
+
|
421
|
+
def convert_buffer
|
422
|
+
unless @buffer.empty?
|
423
|
+
@decoded_utf_8 << @buffer.encode(Encoding::UTF_8, Encoding::ISO_2022_JP)
|
424
|
+
@buffer.clear
|
425
|
+
@buffer_current_code_type = nil
|
426
|
+
end
|
427
|
+
rescue => error
|
428
|
+
STDERR.puts "Convert error."
|
429
|
+
STDERR.puts "Now buffer(binary): #{@bugger.dump}"
|
430
|
+
STDERR.puts "Now decoded(utf-8): #{decoded_utf_8}"
|
431
|
+
raise error
|
432
|
+
end
|
433
|
+
|
434
|
+
def to_s
|
435
|
+
convert_buffer
|
436
|
+
return @decoded_utf_8
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|