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,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.
@@ -0,0 +1,16 @@
1
+ = INSTAL
2
+
3
+ gem install tsparser
4
+
5
+
6
+ = Description
7
+
8
+ MPEG2-TS parser
9
+
10
+
11
+ = Sample Usage
12
+
13
+ require 'tsparser'
14
+
15
+ epg = TSparser.parse_epg('./test.ts')
16
+ p epg
@@ -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