tsparser 0.0.0

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