line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Linux::DVB::DVBT::TS ; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Linux::DVB::DVBT::TS - Transport Stream utilities |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Linux::DVB::DVBT::TS ; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my $settings_href = {'debug' => $debug} ; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# get file information |
14
|
|
|
|
|
|
|
my %info = info($filename, $settings_href) ; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# Splitting file... |
17
|
|
|
|
|
|
|
ts_split($filename, $ofilename, \@cuts, $settings_href) ; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Cutting file... |
20
|
|
|
|
|
|
|
ts_cut($filename, $ofilename, \@cuts, $settings_href) ; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# repair a file... |
23
|
|
|
|
|
|
|
my %stats = repair($filename, $ofilename, \&error_display) ; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub error_display |
26
|
|
|
|
|
|
|
{ |
27
|
|
|
|
|
|
|
my ($info_href) = @_ ; |
28
|
|
|
|
|
|
|
print "ERROR: PID $info_href->{'pidinfo'}{'pid'} $info_href->{'error'}{'str'} [$info_href->{'pidinfo'}{'pktnum'}]\n" ; |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# Parse the file, calling subroutines on each frame... |
33
|
|
|
|
|
|
|
parse($filename, { |
34
|
|
|
|
|
|
|
'mpeg2_rgb_callback' = \&colour_callback |
35
|
|
|
|
|
|
|
'user_data' => { |
36
|
|
|
|
|
|
|
'outname' => "$outdir/$base%03d.ppm", |
37
|
|
|
|
|
|
|
}, |
38
|
|
|
|
|
|
|
}) ; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub colour_callback |
41
|
|
|
|
|
|
|
{ |
42
|
|
|
|
|
|
|
my ($tsreader, $info_href, $width, $height, $data, $user_data_href) = @_ ; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
## save image |
45
|
|
|
|
|
|
|
write_ppm($user_data_href->{'outname'}, $info_href->{'framenum'}, |
46
|
|
|
|
|
|
|
$width, $height, |
47
|
|
|
|
|
|
|
$data, |
48
|
|
|
|
|
|
|
) ; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 DESCRIPTION |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Module provides a set of useful transport stream utility routines. As well as an underlying |
56
|
|
|
|
|
|
|
transport stream parsing framework, this module also incorporates MPEG2 video decoding and AAC |
57
|
|
|
|
|
|
|
audio decoding. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 Callbacks |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
The transport stream parsing framework works through the video file, calling user provided |
62
|
|
|
|
|
|
|
callback functions at the appropriate points. If you don't specify any callbacks, then the |
63
|
|
|
|
|
|
|
framework will run through the video file and do nothing! |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Many of the callbacks have the following common arguments passed to them, and are described |
66
|
|
|
|
|
|
|
here rather than in the callback description: |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=over 4 |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=item $tsreader_ref |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
The $tsreader_ref is a pointer to the TS framework parser that is calling the callback. |
73
|
|
|
|
|
|
|
Some other routines accept this value as a parameters (see L). |
74
|
|
|
|
|
|
|
Do not modify this value! |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=item $user_data |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
Optionally, you can pass a reference to your own user data into the settings |
79
|
|
|
|
|
|
|
when calling the framework (see L). This reference is passed back |
80
|
|
|
|
|
|
|
in the $user_data argument |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=back |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
The list of supported callbacks and the arguments they are called with are as follows: |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=head3 PID callback |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
pid_callback($tsreader_ref, $pid, $user_data) |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
The pid of the current stream is passed as an integer in $pid. You must return |
92
|
|
|
|
|
|
|
a TRUE value to tell the framework to continue processing with this pid; otherwise |
93
|
|
|
|
|
|
|
return a FALSE value to indicate that the framework should move on to the next pid. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
You can use this to skip processing any unwanted pids (mainly to speed up operation). |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head3 Error callback |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
error_callback($tsreader_ref, $info_href, $user_data) |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
The information HASH ref contains: |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=over 4 |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
B = HASH ref containing: |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=over 4 |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
B = current pid |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
B = TRUE if error flag is set in this TS packet |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
B = TRUE is this packet is the start of a PES packet |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
B = afc field code |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
B = count of errors (so far) for this pid |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
B = TS packet count (from start of video, starting at 0) |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=back |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
B = HASH ref containing: |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=over 4 |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
B = error code |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
B = error string |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=back |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=back |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Called either when there is an error indication in the transport stream, or for |
136
|
|
|
|
|
|
|
other errors. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head3 TS callback |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
ts_callback($tsreader_ref, $info_href, $packet, $user_data) |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
The information HASH ref contains: |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=over 4 |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
B = (see L) |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=back |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
This is called with the complete transport stream packet. |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head3 Payload callback |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
payload_callback($tsreader_ref, $info_href, $payload, $user_data) |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
The information HASH ref contains: |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=over 4 |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
B = (see L) |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=back |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
This is called with the payload data of the transport stream packet (i.e. with |
166
|
|
|
|
|
|
|
the headers stripped off). |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head3 PES callback |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
pes_callback($tsreader_ref, $info_href, $pes_packet, $user_data) |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
The information HASH ref contains: |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=over 4 |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
B = (see L) |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=back |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=over 4 |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
B = HASH ref containing: |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=over 4 |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
B = number of errors in PES packets |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
B = number of errors in PSI packets |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
B = number of TS packet errors |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
B = String set to: |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=over 4 |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
"PES" for a PES packet |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
"PSI" for an SI packet |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=back |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
B = presentation timestamp as a HASH ref (see below for details) |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
B = display timestamp in same format as B |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
B = first pts in video (in same format as B) |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
B = first dts in video (in same format as B) |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
B = current last pts in video (in same format as B) |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
B = current last dts in video (in same format as B) |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
B = pts relative to start (in same format as B) |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
B = dts relative to start (in same format as B) |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=back |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=back |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
The timestamp format (for pts and dts entries) is a HASH containing: |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=over 4 |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
B = pts integer seconds |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
B = remainder in microseconds |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
B = string of the 33-bit timestamp integer |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=back |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
So the time in seconds and fractional seconds can be displayed using: |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
printf "%d.%06d", $pts->{'secs'}, $pts->{'usecs'} ; |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
(Note: The 33-bit pts value is (roughly) = 'secs'*90000 + 'usecs'*90) |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
Called with the complete PES/PSI packet. |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=head3 PES data callback |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
pes_data_callback($tsreader_ref, $info_href, $pes_data, $user_data) |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
The information HASH ref contains: |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=over 4 |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
B = (see L) |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
B = (see L) |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
=back |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Called with just the PES/PSI data (i.e. with headers removed). |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head3 MPEG2 callback |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
mpeg2_callback($tsreader_ref, $info_href, $width, $height, $image, $user_data) |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
The information HASH ref contains: |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=over 4 |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
B = (see L) |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
B = (see L) |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
B = Frame number (starting at 0) |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
B = TS packet number of the last GOP (see MPEG2 docs for details on a GOP!) |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=back |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
This callback is called with a greyscale image, 1 per video frame. The image data ($image) is |
281
|
|
|
|
|
|
|
$width pixels wides and $height pixels tall, each pixel being a single 8-bit byte value. |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
NOTE: If you use the L with the video pid, you can write the data directly |
284
|
|
|
|
|
|
|
into a file and this data will be the raw MPEG2 video. |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=head3 MPEG2 RGB callback |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
mpeg2_rgb_callback($tsreader_ref, $info_href, $width, $height, $image, $user_data) |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
The information HASH ref is as L |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
This callback is called with a colour image. Here the pixels are represented by 3 consecutive |
294
|
|
|
|
|
|
|
bytes: a byte each for red, green, and blue. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=head3 Audio callback |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
audio_callback($tsreader_ref, $info_href, $audio_data, $user_data) |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
The information HASH ref contains: |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=over 4 |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
B = (see L) |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
B = (see L) |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
B = Number of samples pre second (usually 48000) |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
B = number of audio channels (usually 2) |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
B = Total number of samples in an audio frame (usually 1152) |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
B = the number of audio samples in the data |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
B = Count of audio frames (starting with 0) |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
B = number of samples per frame for a single channel |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=back |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
Called for every audio frame's worth of data. The audio data is stored as 16-bit values, 1 for each channel. |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
NOTE: If you use the L with the audio pid, you can write the data directly |
326
|
|
|
|
|
|
|
into a file and this data will be the raw AAC audio for the video. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=head3 Progress callback |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
progress_callback($tsreader_ref, $state_str, $progress, $total, $user_data) |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
This is a general progress update callback that is called at regular intervals during the parsing of the video |
333
|
|
|
|
|
|
|
file. The $progress and $total values are scaled versions of the current packet count and total number of packets |
334
|
|
|
|
|
|
|
respectively. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
The $state_str string is one of: |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=over 4 |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
"START" = callback will be called once with this string at the start of execution |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
"END" = callback will be called once with this string at the end of execution |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
"RUNNING" = normal execution - framework is parsing the video file |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
"STOPPED" = set if the user has told the framework to abort (see L) |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=back |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=head2 Settings |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
The parsing framework accepts a variety of settings. These are passed as values in a HASH ref. The settings |
353
|
|
|
|
|
|
|
HASH ref consists of: |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
=over 4 |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
B = set this to get debug information (higher setting gives more output) [default=0] |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
B = number of TS packets to process before stopping [default=0 which means the whole file] |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
B = start processing the file this many packets from the origin [default=0] |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
B = used with B. May be 0=FILE START, 1=FILE CENTER, 2=FILE END [default=0] |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
B = set to whatever data you like. This is passed on to all callbacks. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
B = see L |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
B = see L |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
B = see L |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
B = see L |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
B = see L |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
B = see L |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
B = see L |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
B = see L |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
B = see L |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
B = see L |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=back |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
Most of the entries may be omitted, but it is expected that at least one callback function be set. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=head2 Example |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
The following example shows the use of the callback in order to save the AAC audio stream to a file: |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
Linux::DVB::DVBT::TS::parse("file.ts", { |
398
|
|
|
|
|
|
|
# you can put whatever you like in this... |
399
|
|
|
|
|
|
|
'user_data' => { |
400
|
|
|
|
|
|
|
'outname' => "test.aac", |
401
|
|
|
|
|
|
|
}, |
402
|
|
|
|
|
|
|
# the callback routine: |
403
|
|
|
|
|
|
|
'audio_callback' => \&audio_callback, |
404
|
|
|
|
|
|
|
} ; |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub audio_callback |
407
|
|
|
|
|
|
|
{ |
408
|
|
|
|
|
|
|
my ($tsreader_ref, $info_href, $audio_data, $user_data_href) = @_ ; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
open my $fh, ">>$user_data_href->{'outname'}" or die "Unable to write AAC file" ; |
411
|
|
|
|
|
|
|
print $fh $audio_data ; |
412
|
|
|
|
|
|
|
close $fh ; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=cut |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
#============================================================================================ |
422
|
|
|
|
|
|
|
# USES |
423
|
|
|
|
|
|
|
#============================================================================================ |
424
|
3
|
|
|
3
|
|
117915
|
use strict ; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
107
|
|
425
|
3
|
|
|
3
|
|
5565
|
use Env ; |
|
3
|
|
|
|
|
19704
|
|
|
3
|
|
|
|
|
20
|
|
426
|
3
|
|
|
3
|
|
1991
|
use Carp ; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
201
|
|
427
|
3
|
|
|
3
|
|
27
|
use File::Basename ; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
339
|
|
428
|
3
|
|
|
3
|
|
17
|
use File::Path ; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
192
|
|
429
|
|
|
|
|
|
|
|
430
|
3
|
|
|
3
|
|
1420
|
use Data::Dumper ; |
|
3
|
|
|
|
|
13597
|
|
|
3
|
|
|
|
|
4050
|
|
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
#============================================================================================ |
433
|
|
|
|
|
|
|
# EXPORTER |
434
|
|
|
|
|
|
|
#============================================================================================ |
435
|
|
|
|
|
|
|
require Exporter; |
436
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
our @EXPORT = qw/ |
439
|
|
|
|
|
|
|
error_str |
440
|
|
|
|
|
|
|
info |
441
|
|
|
|
|
|
|
parse |
442
|
|
|
|
|
|
|
parse_stop |
443
|
|
|
|
|
|
|
repair |
444
|
|
|
|
|
|
|
ts_cut |
445
|
|
|
|
|
|
|
ts_split |
446
|
|
|
|
|
|
|
/ ; |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
#============================================================================================ |
450
|
|
|
|
|
|
|
# GLOBALS |
451
|
|
|
|
|
|
|
#============================================================================================ |
452
|
|
|
|
|
|
|
our $VERSION = '0.08' ; |
453
|
|
|
|
|
|
|
our $DEBUG = 0 ; |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
#============================================================================================ |
456
|
|
|
|
|
|
|
# XS |
457
|
|
|
|
|
|
|
#============================================================================================ |
458
|
|
|
|
|
|
|
require XSLoader; |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
if (!$ENV{'TS_NO_XS'}) |
461
|
|
|
|
|
|
|
{ |
462
|
|
|
|
|
|
|
XSLoader::load('Linux::DVB::DVBT::TS', $VERSION); |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
else |
465
|
|
|
|
|
|
|
{ |
466
|
|
|
|
|
|
|
print STDERR "WARNING: Running Linux::DVB::DVBT::TS without XS\n" ; |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
#============================================================================================ |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
#============================================================================================ |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=head2 Functions |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=over 4 |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
=cut |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=item B |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
Repair a transport stream file by removing error packets. Returns a hash |
485
|
|
|
|
|
|
|
of repair stats containing a HASH entry per PID. Each entry is of the form: |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=over 4 |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
B => error count for this pid |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
B => HASH where the keys are the error reason string, and the values |
492
|
|
|
|
|
|
|
are the error count for that reason. |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=back |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
If any runtime error occurs (e.g. unable to read file), then an error string is added |
497
|
|
|
|
|
|
|
to the HASH with the field 'error'. |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
$error_display is an optional callback routine (see L) |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
At the moment "repair" is probably an overstatement. What this currently does is just dump |
502
|
|
|
|
|
|
|
any packets that contain any errors (transport stream or PES). All of the players/transcoders |
503
|
|
|
|
|
|
|
I've tried so far seem fine with this approach. It also prevents ffmpeg from grabbing all available |
504
|
|
|
|
|
|
|
memory then crashing! |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=cut |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
sub repair |
510
|
|
|
|
|
|
|
{ |
511
|
0
|
|
|
0
|
1
|
|
my ($src, $dest, $error_display) = @_ ; |
512
|
0
|
|
|
|
|
|
my %stats ; |
513
|
0
|
|
|
|
|
|
my %settings = ( |
514
|
|
|
|
|
|
|
'debug' => $DEBUG, |
515
|
|
|
|
|
|
|
'error_callback' => \&_repair_error_callback, |
516
|
|
|
|
|
|
|
'user_data' => { |
517
|
|
|
|
|
|
|
'error_display' => $error_display, |
518
|
|
|
|
|
|
|
'stats' => \%stats, |
519
|
|
|
|
|
|
|
}, |
520
|
|
|
|
|
|
|
) ; |
521
|
0
|
0
|
|
|
|
|
croak "Unable to read \"$src\"" unless -f $src ; |
522
|
0
|
0
|
|
|
|
|
croak "Zero-length file \"$src\"" unless -s $src ; |
523
|
0
|
0
|
|
|
|
|
croak "Must specify a destination filename" unless $dest ; |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
## Ensure dest dir is present |
526
|
0
|
|
|
|
|
|
my $dir = dirname($dest) ; |
527
|
0
|
0
|
|
|
|
|
if (! -d $dir) |
528
|
|
|
|
|
|
|
{ |
529
|
0
|
0
|
|
|
|
|
mkpath([$dir], 0, 0755) or croak "Unable to create destination directory $dir : $!" ; |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
## repair |
533
|
0
|
|
|
|
|
|
Linux::DVB::DVBT::TS::dvb_ts_repair($src, $dest, \%settings) ; |
534
|
|
|
|
|
|
|
|
535
|
0
|
0
|
|
|
|
|
if (Linux::DVB::DVBT::TS::dvb_ts_error()) |
536
|
|
|
|
|
|
|
{ |
537
|
0
|
|
|
|
|
|
$stats{'error'} = Linux::DVB::DVBT::TS::dvb_ts_error_str() ; |
538
|
0
|
|
|
|
|
|
$stats{'errorcode'} = Linux::DVB::DVBT::TS::dvb_ts_error() ; |
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
|
541
|
0
|
|
|
|
|
|
return %stats ; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=item B |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
Parse a TS file. Uses the settings HASH ref ($settings_href) to configure the callbacks etc. |
549
|
|
|
|
|
|
|
(see L for further details). |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
=cut |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
sub parse |
554
|
|
|
|
|
|
|
{ |
555
|
0
|
|
|
0
|
1
|
|
my ($src, $settings_href) = @_ ; |
556
|
|
|
|
|
|
|
|
557
|
0
|
0
|
|
|
|
|
croak "Unable to read \"$src\"" unless -f $src ; |
558
|
0
|
0
|
|
|
|
|
croak "Zero-length file \"$src\"" unless -s $src ; |
559
|
|
|
|
|
|
|
|
560
|
0
|
|
0
|
|
|
|
$settings_href ||= {} ; |
561
|
0
|
|
|
|
|
|
Linux::DVB::DVBT::TS::dvb_ts_parse($src, $settings_href) ; |
562
|
|
|
|
|
|
|
} |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
=item B |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
Abort the parsing of a TS file now (rather than completing to the end of the file). |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=cut |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
sub parse_stop |
573
|
|
|
|
|
|
|
{ |
574
|
0
|
|
|
0
|
1
|
|
my ($tsreader_ref) = @_ ; |
575
|
|
|
|
|
|
|
|
576
|
0
|
0
|
|
|
|
|
croak "Invalid tsreader reference" unless $tsreader_ref ; |
577
|
0
|
|
|
|
|
|
Linux::DVB::DVBT::TS::dvb_ts_parse_stop($tsreader_ref) ; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=item B |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
Get information about a TS file. Returns a HASH containing information about the transport |
585
|
|
|
|
|
|
|
stream file: |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=over 4 |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
B = total number of TS packets in the file |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
B = first timestamp in file (see L for timestamp format) |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
B = last timestamp in file (see L for timestamp format) |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
B = HASH ref containing video duration information in timestamp format and also: |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=over 4 |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
B = integer hours |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
B = integer minutes |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
B = integer seconds |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=back |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
B = HASH ref containing an entry per pid found in the file. Each pid contains: |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
=over 4 |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
B = (see L) |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
B = (see L) |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=back |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
=back |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
If there is an error of any kind, the returned HASH conatins a single entry: |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
=over 4 |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
B = error string describing the error cause |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
=back |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
=cut |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
sub info |
630
|
|
|
|
|
|
|
{ |
631
|
0
|
|
|
0
|
1
|
|
my ($src, $settings_href) = @_ ; |
632
|
|
|
|
|
|
|
|
633
|
0
|
|
|
|
|
|
my $info_href = {} ; |
634
|
|
|
|
|
|
|
|
635
|
0
|
0
|
|
|
|
|
unless (-f $src) |
636
|
|
|
|
|
|
|
{ |
637
|
0
|
|
|
|
|
|
$info_href->{'error'} = "Unable to read \"$src\"" ; |
638
|
|
|
|
|
|
|
} |
639
|
|
|
|
|
|
|
else |
640
|
|
|
|
|
|
|
{ |
641
|
0
|
|
0
|
|
|
|
$settings_href ||= {} ; |
642
|
0
|
|
|
|
|
|
$info_href = Linux::DVB::DVBT::TS::dvb_ts_info($src, $settings_href) ; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
0
|
|
|
|
|
|
return %$info_href ; |
646
|
|
|
|
|
|
|
} |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
=item B |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
Cut a transport stream file, removing the reqions described in $cuts_aref, saving |
653
|
|
|
|
|
|
|
the results in the new file $dest. |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
The ARRAY ref $cuts_aref consists of an array of HASH refs, each HASH ref defining |
656
|
|
|
|
|
|
|
the start and end of a region to be cut: |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=over 4 |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
B = TS packet number of start of region |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
B = TS packet number of end of region |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
=back |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
(Note that these ar transport stream packet numbers NOT mpeg2 frame counts. You will need |
667
|
|
|
|
|
|
|
to scan the file to produce a lookup table if you want to specify cuts in frames (or video |
668
|
|
|
|
|
|
|
time)). |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
See L for a description of $settings_href. |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
=cut |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
sub ts_cut |
676
|
|
|
|
|
|
|
{ |
677
|
0
|
|
|
0
|
1
|
|
my ($src, $dest, $cuts_aref, $settings_href) = @_ ; |
678
|
|
|
|
|
|
|
|
679
|
0
|
0
|
|
|
|
|
croak "Unable to read \"$src\"" unless -f $src ; |
680
|
0
|
0
|
|
|
|
|
croak "Zero-length file \"$src\"" unless -s $src ; |
681
|
0
|
0
|
|
|
|
|
croak "Must specify a destination filename" unless $dest ; |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
## Ensure dest dir is present |
684
|
0
|
|
|
|
|
|
my $dir = dirname($dest) ; |
685
|
0
|
0
|
|
|
|
|
if (! -d $dir) |
686
|
|
|
|
|
|
|
{ |
687
|
0
|
0
|
|
|
|
|
mkpath([$dir], 0, 0755) or croak "Unable to create destination directory $dir : $!" ; |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
## check cuts |
691
|
0
|
0
|
|
|
|
|
croak "Must specify a cuts list array ref" unless ref($cuts_aref) eq 'ARRAY' ; |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
## run command |
694
|
0
|
|
0
|
|
|
|
$settings_href ||= {} ; |
695
|
0
|
|
|
|
|
|
my $rc = Linux::DVB::DVBT::TS::dvb_ts_cut($src, $dest, $cuts_aref, $settings_href) ; |
696
|
0
|
0
|
|
|
|
|
if ($rc) |
697
|
|
|
|
|
|
|
{ |
698
|
0
|
|
|
|
|
|
croak "Error while running ts_cut() : " . Linux::DVB::DVBT::TS::dvb_ts_error_str() ; |
699
|
|
|
|
|
|
|
} |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
} |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
=item B |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
Split a transport stream file into multiple files, starting a new file at the |
708
|
|
|
|
|
|
|
boundaries described in the ARRAY ref $cuts_aref (see L). |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
In this case, a new file is created at the start of the boundary and at the end of the boundary. |
711
|
|
|
|
|
|
|
This means that the original file is simply the concatenation of all of the individual files. |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
The output files are created using the specified destination name (without any exetension), and appending |
714
|
|
|
|
|
|
|
a 4-digit count: |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
sprintf("%s-%04d.ts", $dest, $filenum) |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
Where $filenum is the file counter (starting at 1). |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
For example, with a cut list of: |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
start=100, end=200 |
723
|
|
|
|
|
|
|
start=500, end=600 |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
and assuming a file of 1000 ts packets, running this function will result in 5 output files (where $dest="file"): |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
file-0001.ts created from packets 0 to 99 |
728
|
|
|
|
|
|
|
file-0002.ts created from packets 100 to 199 |
729
|
|
|
|
|
|
|
file-0003.ts created from packets 200 to 499 |
730
|
|
|
|
|
|
|
file-0004.ts created from packets 500 to 599 |
731
|
|
|
|
|
|
|
file-0005.ts created from packets 600 to 999 |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
See L for a description of $settings_href. |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
=cut |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
sub ts_split |
739
|
|
|
|
|
|
|
{ |
740
|
0
|
|
|
0
|
1
|
|
my ($src, $dest, $cuts_aref, $settings_href) = @_ ; |
741
|
|
|
|
|
|
|
|
742
|
0
|
0
|
|
|
|
|
croak "Unable to read \"$src\"" unless -f $src ; |
743
|
0
|
0
|
|
|
|
|
croak "Zero-length file \"$src\"" unless -s $src ; |
744
|
0
|
0
|
|
|
|
|
croak "Must specify a destination filename" unless $dest ; |
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
## Ensure dest dir is present |
747
|
0
|
|
|
|
|
|
my $dir = dirname($dest) ; |
748
|
0
|
0
|
|
|
|
|
if (! -d $dir) |
749
|
|
|
|
|
|
|
{ |
750
|
0
|
0
|
|
|
|
|
mkpath([$dir], 0, 0755) or croak "Unable to create destination directory $dir : $!" ; |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
## check cuts |
754
|
0
|
0
|
|
|
|
|
croak "Must specify a cuts list array ref" unless ref($cuts_aref) eq 'ARRAY' ; |
755
|
0
|
0
|
|
|
|
|
croak "Must specify a non-empty cuts list array ref" unless @$cuts_aref ; |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
## run command |
758
|
0
|
|
0
|
|
|
|
$settings_href ||= {} ; |
759
|
0
|
|
|
|
|
|
my $rc = Linux::DVB::DVBT::TS::dvb_ts_split($src, $dest, $cuts_aref, $settings_href) ; |
760
|
0
|
0
|
|
|
|
|
if ($rc) |
761
|
|
|
|
|
|
|
{ |
762
|
0
|
|
|
|
|
|
croak "Error while running ts_split() : " . Linux::DVB::DVBT::TS::dvb_ts_error_str() ; |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
} |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
=item B |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
In the event of an error, calling this routine will return the appropriate error |
771
|
|
|
|
|
|
|
string that (hopefully) makes more sense than an error code integer. |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
=cut |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
sub error_str |
776
|
|
|
|
|
|
|
{ |
777
|
0
|
|
|
0
|
1
|
|
return Linux::DVB::DVBT::TS::dvb_ts_error_str() ; |
778
|
|
|
|
|
|
|
} |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
#============================================================================================ |
783
|
|
|
|
|
|
|
# PRIVATE |
784
|
|
|
|
|
|
|
#============================================================================================ |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
#----------------------------------------------------------------------------- |
787
|
|
|
|
|
|
|
sub _repair_error_callback |
788
|
|
|
|
|
|
|
{ |
789
|
0
|
|
|
0
|
|
|
my ($tsreader, $info_href, $user_href) = @_ ; |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
## callback user-provided |
792
|
0
|
|
|
|
|
|
my $error_display = $user_href->{'error_display'} ; |
793
|
0
|
0
|
|
|
|
|
if ($error_display) |
794
|
|
|
|
|
|
|
{ |
795
|
0
|
|
|
|
|
|
&$error_display($info_href) ; |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
## save stats |
799
|
0
|
|
|
|
|
|
my $pid = $info_href->{'pidinfo'}{'pid'} ; |
800
|
0
|
|
|
|
|
|
my ($code, $str) = @{$info_href->{'error'}}{qw/code str/} ; |
|
0
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
|
802
|
0
|
|
|
|
|
|
my $stats_href = $user_href->{'stats'} ; |
803
|
0
|
|
0
|
|
|
|
$stats_href->{$pid} ||= { |
804
|
|
|
|
|
|
|
'errors' => 0, |
805
|
|
|
|
|
|
|
'details' => {}, |
806
|
|
|
|
|
|
|
} ; |
807
|
0
|
|
|
|
|
|
$stats_href->{$pid}{'errors'}++ ; |
808
|
0
|
|
|
|
|
|
$stats_href->{$pid}{'details'}{$str}++ ; |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
# ============================================================================================ |
813
|
|
|
|
|
|
|
# END OF PACKAGE |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
1; |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
__END__ |