author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /core/multimedia/opieplayer/libmpeg3/mpeg3demux.c | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
Diffstat (limited to 'core/multimedia/opieplayer/libmpeg3/mpeg3demux.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libmpeg3/mpeg3demux.c | 1849 |
1 files changed, 1849 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libmpeg3/mpeg3demux.c b/core/multimedia/opieplayer/libmpeg3/mpeg3demux.c new file mode 100644 index 0000000..cccc820 --- a/dev/null +++ b/core/multimedia/opieplayer/libmpeg3/mpeg3demux.c | |||
@@ -0,0 +1,1849 @@ | |||
1 | #include "libmpeg3.h" | ||
2 | #include "mpeg3io.h" | ||
3 | #include "mpeg3protos.h" | ||
4 | |||
5 | #include <math.h> | ||
6 | #include <stdlib.h> | ||
7 | #include <string.h> | ||
8 | |||
9 | #define ABS(x) ((x) >= 0 ? (x) : -(x)) | ||
10 | |||
11 | /* Don't advance pointer */ | ||
12 | static inline unsigned char mpeg3packet_next_char(mpeg3_demuxer_t *demuxer) | ||
13 | { | ||
14 | return demuxer->raw_data[demuxer->raw_offset]; | ||
15 | } | ||
16 | |||
17 | unsigned char mpeg3packet_read_char(mpeg3_demuxer_t *demuxer) | ||
18 | { | ||
19 | unsigned char result = demuxer->raw_data[demuxer->raw_offset++]; | ||
20 | return result; | ||
21 | } | ||
22 | |||
23 | static inline unsigned int mpeg3packet_read_int16(mpeg3_demuxer_t *demuxer) | ||
24 | { | ||
25 | unsigned int a, b, result; | ||
26 | a = demuxer->raw_data[demuxer->raw_offset++]; | ||
27 | b = demuxer->raw_data[demuxer->raw_offset++]; | ||
28 | result = (a << 8) | b; | ||
29 | |||
30 | return result; | ||
31 | } | ||
32 | |||
33 | static inline unsigned int mpeg3packet_next_int24(mpeg3_demuxer_t *demuxer) | ||
34 | { | ||
35 | unsigned int a, b, c, result; | ||
36 | a = demuxer->raw_data[demuxer->raw_offset]; | ||
37 | b = demuxer->raw_data[demuxer->raw_offset + 1]; | ||
38 | c = demuxer->raw_data[demuxer->raw_offset + 2]; | ||
39 | result = (a << 16) | (b << 8) | c; | ||
40 | |||
41 | return result; | ||
42 | } | ||
43 | |||
44 | static inline unsigned int mpeg3packet_read_int24(mpeg3_demuxer_t *demuxer) | ||
45 | { | ||
46 | unsigned int a, b, c, result; | ||
47 | a = demuxer->raw_data[demuxer->raw_offset++]; | ||
48 | b = demuxer->raw_data[demuxer->raw_offset++]; | ||
49 | c = demuxer->raw_data[demuxer->raw_offset++]; | ||
50 | result = (a << 16) | (b << 8) | c; | ||
51 | |||
52 | return result; | ||
53 | } | ||
54 | |||
55 | static inline unsigned int mpeg3packet_read_int32(mpeg3_demuxer_t *demuxer) | ||
56 | { | ||
57 | unsigned int a, b, c, d, result; | ||
58 | a = demuxer->raw_data[demuxer->raw_offset++]; | ||
59 | b = demuxer->raw_data[demuxer->raw_offset++]; | ||
60 | c = demuxer->raw_data[demuxer->raw_offset++]; | ||
61 | d = demuxer->raw_data[demuxer->raw_offset++]; | ||
62 | result = (a << 24) | (b << 16) | (c << 8) | d; | ||
63 | |||
64 | return result; | ||
65 | } | ||
66 | |||
67 | static inline unsigned int mpeg3packet_skip(mpeg3_demuxer_t *demuxer, long length) | ||
68 | { | ||
69 | demuxer->raw_offset += length; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | int mpeg3_get_adaptation_field(mpeg3_demuxer_t *demuxer) | ||
74 | { | ||
75 | long length; | ||
76 | int pcr_flag; | ||
77 | |||
78 | demuxer->adaptation_fields++; | ||
79 | /* get adaptation field length */ | ||
80 | length = mpeg3packet_read_char(demuxer); | ||
81 | /* get first byte */ | ||
82 | pcr_flag = (mpeg3packet_read_char(demuxer) >> 4) & 1; | ||
83 | |||
84 | if(pcr_flag) | ||
85 | { | ||
86 | unsigned long clk_ref_base = mpeg3packet_read_int32(demuxer); | ||
87 | unsigned int clk_ref_ext = mpeg3packet_read_int16(demuxer); | ||
88 | |||
89 | if (clk_ref_base > 0x7fffffff) | ||
90 | { /* correct for invalid numbers */ | ||
91 | clk_ref_base = 0; /* ie. longer than 32 bits when multiplied by 2 */ | ||
92 | clk_ref_ext = 0; /* multiplied by 2 corresponds to shift left 1 (<<=1) */ | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | clk_ref_base <<= 1; /* Create space for bit */ | ||
97 | clk_ref_base |= (clk_ref_ext >> 15); /* Take bit */ | ||
98 | clk_ref_ext &= 0x01ff; /* Only lower 9 bits */ | ||
99 | } | ||
100 | demuxer->time = clk_ref_base + clk_ref_ext / 300; | ||
101 | if(length) mpeg3packet_skip(demuxer, length - 7); | ||
102 | } | ||
103 | else | ||
104 | mpeg3packet_skip(demuxer, length - 1); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | int mpeg3_get_program_association_table(mpeg3_demuxer_t *demuxer) | ||
110 | { | ||
111 | demuxer->program_association_tables++; | ||
112 | demuxer->table_id = mpeg3packet_read_char(demuxer); | ||
113 | demuxer->section_length = mpeg3packet_read_int16(demuxer) & 0xfff; | ||
114 | demuxer->transport_stream_id = mpeg3packet_read_int16(demuxer); | ||
115 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | int mpeg3packet_get_data_buffer(mpeg3_demuxer_t *demuxer) | ||
120 | { | ||
121 | while(demuxer->raw_offset < demuxer->raw_size && demuxer->data_size < demuxer->data_allocated) | ||
122 | { | ||
123 | demuxer->data_buffer[demuxer->data_size++] = demuxer->raw_data[demuxer->raw_offset++]; | ||
124 | } | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | int mpeg3_get_pes_packet_header(mpeg3_demuxer_t *demuxer, unsigned long *pts, unsigned long *dts) | ||
129 | { | ||
130 | unsigned int pes_header_bytes = 0; | ||
131 | unsigned int pts_dts_flags; | ||
132 | int pes_header_data_length; | ||
133 | |||
134 | /* drop first 8 bits */ | ||
135 | mpeg3packet_read_char(demuxer); | ||
136 | pts_dts_flags = (mpeg3packet_read_char(demuxer) >> 6) & 0x3; | ||
137 | pes_header_data_length = mpeg3packet_read_char(demuxer); | ||
138 | |||
139 | /* Get Presentation Time stamps and Decoding Time Stamps */ | ||
140 | if(pts_dts_flags == 2) | ||
141 | { | ||
142 | *pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ | ||
143 | *pts <<= 15; | ||
144 | *pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
145 | *pts <<= 15; | ||
146 | *pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
147 | pes_header_bytes += 5; | ||
148 | } | ||
149 | else if(pts_dts_flags == 3) | ||
150 | { | ||
151 | *pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ | ||
152 | *pts <<= 15; | ||
153 | *pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
154 | *pts <<= 15; | ||
155 | *pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
156 | *dts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ | ||
157 | *dts <<= 15; | ||
158 | *dts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
159 | *dts <<= 15; | ||
160 | *dts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
161 | pes_header_bytes += 10; | ||
162 | } | ||
163 | /* extract other stuff here! */ | ||
164 | |||
165 | mpeg3packet_skip(demuxer, pes_header_data_length - pes_header_bytes); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int get_unknown_data(mpeg3_demuxer_t *demuxer) | ||
170 | { | ||
171 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | int mpeg3_get_pes_packet_data(mpeg3_demuxer_t *demuxer, unsigned int stream_id) | ||
176 | { | ||
177 | unsigned long pts = 0, dts = 0; | ||
178 | |||
179 | if((stream_id >> 4) == 12 || (stream_id >> 4) == 13) | ||
180 | { | ||
181 | /* Just pick the first available stream if no ID is set */ | ||
182 | if(demuxer->astream == -1) | ||
183 | demuxer->astream = (stream_id & 0x0f); | ||
184 | |||
185 | if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) | ||
186 | { | ||
187 | mpeg3_get_pes_packet_header(demuxer, &pts, &dts); | ||
188 | demuxer->pes_audio_time = pts; | ||
189 | demuxer->audio_pid = demuxer->pid; | ||
190 | return mpeg3packet_get_data_buffer(demuxer); | ||
191 | } | ||
192 | } | ||
193 | else | ||
194 | if((stream_id >> 4)==14) | ||
195 | { | ||
196 | /* Just pick the first available stream if no ID is set */ | ||
197 | if(demuxer->vstream == -1) | ||
198 | demuxer->vstream = (stream_id & 0x0f); | ||
199 | |||
200 | if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) | ||
201 | { | ||
202 | mpeg3_get_pes_packet_header(demuxer, &pts, &dts); | ||
203 | demuxer->pes_video_time = pts; | ||
204 | demuxer->video_pid = demuxer->pid; | ||
205 | return mpeg3packet_get_data_buffer(demuxer); | ||
206 | } | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | return get_unknown_data(demuxer); | ||
211 | } | ||
212 | |||
213 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | int mpeg3_get_pes_packet(mpeg3_demuxer_t *demuxer) | ||
219 | { | ||
220 | unsigned int stream_id; | ||
221 | |||
222 | demuxer->pes_packets++; | ||
223 | stream_id = mpeg3packet_read_char(demuxer); | ||
224 | /* Skip startcode */ | ||
225 | mpeg3packet_read_int24(demuxer); | ||
226 | /* Skip pes packet length */ | ||
227 | mpeg3packet_read_int16(demuxer); | ||
228 | |||
229 | if(stream_id != MPEG3_PRIVATE_STREAM_2 && stream_id != MPEG3_PADDING_STREAM) | ||
230 | { | ||
231 | return mpeg3_get_pes_packet_data(demuxer, stream_id); | ||
232 | } | ||
233 | else | ||
234 | if(stream_id == MPEG3_PRIVATE_STREAM_2) | ||
235 | { | ||
236 | /* Dump private data! */ | ||
237 | fprintf(stderr, "stream_id == MPEG3_PRIVATE_STREAM_2\n"); | ||
238 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
239 | return 0; | ||
240 | } | ||
241 | else | ||
242 | if(stream_id == MPEG3_PADDING_STREAM) | ||
243 | { | ||
244 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
245 | return 0; | ||
246 | } | ||
247 | else | ||
248 | { | ||
249 | fprintf(stderr, "unknown stream_id in pes packet"); | ||
250 | return 1; | ||
251 | } | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | int mpeg3_get_payload(mpeg3_demuxer_t *demuxer) | ||
256 | { | ||
257 | if(demuxer->payload_unit_start_indicator) | ||
258 | { | ||
259 | if(demuxer->pid==0) mpeg3_get_program_association_table(demuxer); | ||
260 | else | ||
261 | if(mpeg3packet_next_int24(demuxer) == MPEG3_PACKET_START_CODE_PREFIX) mpeg3_get_pes_packet(demuxer); | ||
262 | else | ||
263 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
264 | } | ||
265 | else | ||
266 | { | ||
267 | if(demuxer->pid == demuxer->audio_pid && demuxer->do_audio) | ||
268 | { | ||
269 | mpeg3packet_get_data_buffer(demuxer); | ||
270 | } | ||
271 | else | ||
272 | if(demuxer->pid == demuxer->video_pid && demuxer->do_video) | ||
273 | { | ||
274 | mpeg3packet_get_data_buffer(demuxer); | ||
275 | } | ||
276 | else | ||
277 | mpeg3packet_skip(demuxer, demuxer->raw_size - demuxer->raw_offset); | ||
278 | } | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* Read a transport packet */ | ||
283 | int mpeg3_read_transport(mpeg3_demuxer_t *demuxer) | ||
284 | { | ||
285 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
286 | int result = mpeg3io_read_data(demuxer->raw_data, demuxer->packet_size, title->fs); | ||
287 | unsigned int bits; | ||
288 | int table_entry; | ||
289 | |||
290 | demuxer->raw_size = demuxer->packet_size; | ||
291 | demuxer->raw_offset = 0; | ||
292 | if(result) | ||
293 | { | ||
294 | perror("mpeg3_read_transport"); | ||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | /* Sync byte */ | ||
299 | if(mpeg3packet_read_char(demuxer) != MPEG3_SYNC_BYTE) | ||
300 | { | ||
301 | fprintf(stderr, "mpeg3packet_read_char(demuxer) != MPEG3_SYNC_BYTE\n"); | ||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | /* bits = mpeg3packet_read_int24(demuxer) & 0x0000ffff; */ | ||
306 | /* demuxer->transport_error_indicator = bits >> 15; */ | ||
307 | /* demuxer->payload_unit_start_indicator = (bits >> 14) & 1; */ | ||
308 | /* demuxer->pid = bits & 0x00001fff; */ | ||
309 | /* demuxer->transport_scrambling_control = (mpeg3packet_next_char(demuxer) >> 6) & 0x3; */ | ||
310 | /* demuxer->adaptation_field_control = (mpeg3packet_next_char(demuxer) >> 4) & 0x3; */ | ||
311 | /* demuxer->continuity_counter = (mpeg3packet_read_char(demuxer) & 0xf); */ | ||
312 | |||
313 | bits = mpeg3packet_read_int24(demuxer) & 0x00ffffff; | ||
314 | demuxer->transport_error_indicator = (bits >> 23) & 0x1; | ||
315 | demuxer->payload_unit_start_indicator = (bits >> 22) & 0x1; | ||
316 | demuxer->pid = (bits >> 8) & 0x00001fff; | ||
317 | demuxer->transport_scrambling_control = (bits >> 6) & 0x3; | ||
318 | demuxer->adaptation_field_control = (bits >> 4) & 0x3; | ||
319 | demuxer->continuity_counter = bits & 0xf; | ||
320 | |||
321 | if(demuxer->transport_error_indicator) | ||
322 | { | ||
323 | fprintf(stderr, "demuxer->transport_error_indicator\n"); | ||
324 | return 1; | ||
325 | } | ||
326 | |||
327 | if (demuxer->pid == 0x1fff) | ||
328 | { | ||
329 | demuxer->is_padding = 1; /* padding; just go to next */ | ||
330 | return 0; | ||
331 | } | ||
332 | else | ||
333 | { | ||
334 | demuxer->is_padding = 0; | ||
335 | } | ||
336 | |||
337 | /* Get pid */ | ||
338 | for(table_entry = 0, result = 0; table_entry < demuxer->total_pids; table_entry++) | ||
339 | { | ||
340 | if(demuxer->pid == demuxer->pid_table[table_entry]) | ||
341 | { | ||
342 | result = 1; | ||
343 | break; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | /* Not in pid table */ | ||
348 | if(!result) | ||
349 | { | ||
350 | demuxer->pid_table[table_entry] = demuxer->pid; | ||
351 | demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; /* init */ | ||
352 | demuxer->total_pids++; | ||
353 | } | ||
354 | result = 0; | ||
355 | |||
356 | /* Check counters */ | ||
357 | if(demuxer->pid != MPEG3_PROGRAM_ASSOCIATION_TABLE && | ||
358 | demuxer->pid != MPEG3_CONDITIONAL_ACCESS_TABLE && | ||
359 | (demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3)) | ||
360 | { | ||
361 | if(demuxer->continuity_counters[table_entry] != demuxer->continuity_counter) | ||
362 | { | ||
363 | fprintf(stderr, "demuxer->continuity_counters[table_entry] != demuxer->continuity_counter\n"); | ||
364 | /* Reset it */ | ||
365 | demuxer->continuity_counters[table_entry] = demuxer->continuity_counter; | ||
366 | } | ||
367 | if(++(demuxer->continuity_counters[table_entry]) > 15) demuxer->continuity_counters[table_entry] = 0; | ||
368 | } | ||
369 | |||
370 | if(demuxer->adaptation_field_control == 2 || demuxer->adaptation_field_control == 3) | ||
371 | result = mpeg3_get_adaptation_field(demuxer); | ||
372 | |||
373 | if(demuxer->adaptation_field_control == 1 || demuxer->adaptation_field_control == 3) | ||
374 | result = mpeg3_get_payload(demuxer); | ||
375 | |||
376 | return result; | ||
377 | } | ||
378 | |||
379 | int mpeg3_get_system_header(mpeg3_demuxer_t *demuxer) | ||
380 | { | ||
381 | int length = mpeg3packet_read_int16(demuxer); | ||
382 | mpeg3packet_skip(demuxer, length); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | unsigned long mpeg3_get_timestamp(mpeg3_demuxer_t *demuxer) | ||
387 | { | ||
388 | unsigned long timestamp; | ||
389 | /* Only low 4 bits (7==1111) */ | ||
390 | timestamp = (mpeg3packet_read_char(demuxer) >> 1) & 7; | ||
391 | timestamp <<= 15; | ||
392 | timestamp |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
393 | timestamp <<= 15; | ||
394 | timestamp |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
395 | return timestamp; | ||
396 | } | ||
397 | |||
398 | int mpeg3_get_pack_header(mpeg3_demuxer_t *demuxer, unsigned int *header) | ||
399 | { | ||
400 | unsigned long i, j; | ||
401 | unsigned long clock_ref, clock_ref_ext; | ||
402 | |||
403 | /* Get the time code */ | ||
404 | if((mpeg3packet_next_char(demuxer) >> 4) == 2) | ||
405 | { | ||
406 | /* MPEG-1 */ | ||
407 | demuxer->time = (double)mpeg3_get_timestamp(demuxer) / 90000; | ||
408 | /* Skip 3 bytes */ | ||
409 | mpeg3packet_read_int24(demuxer); | ||
410 | } | ||
411 | else | ||
412 | if(mpeg3packet_next_char(demuxer) & 0x40) | ||
413 | { | ||
414 | i = mpeg3packet_read_int32(demuxer); | ||
415 | j = mpeg3packet_read_int16(demuxer); | ||
416 | if(i & 0x40000000 || (i >> 28) == 2) | ||
417 | { | ||
418 | clock_ref = ((i & 0x31000000) << 3); | ||
419 | clock_ref |= ((i & 0x03fff800) << 4); | ||
420 | clock_ref |= ((i & 0x000003ff) << 5); | ||
421 | clock_ref |= ((j & 0xf800) >> 11); | ||
422 | clock_ref_ext = (j >> 1) & 0x1ff; | ||
423 | |||
424 | demuxer->time = (double)(clock_ref + clock_ref_ext / 300) / 90000; | ||
425 | /* Skip 3 bytes */ | ||
426 | mpeg3packet_read_int24(demuxer); | ||
427 | i = mpeg3packet_read_char(demuxer) & 0x7; | ||
428 | |||
429 | /* stuffing */ | ||
430 | mpeg3packet_skip(demuxer, i); | ||
431 | } | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | mpeg3packet_skip(demuxer, 2); | ||
436 | } | ||
437 | |||
438 | *header = mpeg3packet_read_int32(demuxer); | ||
439 | if(*header == MPEG3_SYSTEM_START_CODE) | ||
440 | { | ||
441 | mpeg3_get_system_header(demuxer); | ||
442 | *header = mpeg3packet_read_int32(demuxer); | ||
443 | } | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | /* Program packet reading core */ | ||
448 | int mpeg3_get_ps_pes_packet(mpeg3_demuxer_t *demuxer, unsigned int *header) | ||
449 | { | ||
450 | unsigned long pts = 0, dts = 0; | ||
451 | int stream_id; | ||
452 | int pes_packet_length; | ||
453 | int pes_packet_start; | ||
454 | int i; | ||
455 | mpeg3_t *file = demuxer->file; | ||
456 | |||
457 | stream_id = *header & 0xff; | ||
458 | pes_packet_length = mpeg3packet_read_int16(demuxer); | ||
459 | pes_packet_start = demuxer->raw_offset; | ||
460 | |||
461 | if(stream_id != MPEG3_PRIVATE_STREAM_2 && | ||
462 | stream_id != MPEG3_PADDING_STREAM) | ||
463 | { | ||
464 | if((mpeg3packet_next_char(demuxer) >> 6) == 0x02) | ||
465 | { | ||
466 | /* Get MPEG-2 packet */ | ||
467 | int pes_header_bytes = 0; | ||
468 | int scrambling = (mpeg3packet_read_char(demuxer) >> 4) & 0x3; | ||
469 | int pts_dts_flags = (mpeg3packet_read_char(demuxer) >> 6) & 0x3; | ||
470 | int pes_header_data_length = mpeg3packet_read_char(demuxer); | ||
471 | |||
472 | if(scrambling && (demuxer->do_audio || demuxer->do_video)) | ||
473 | { | ||
474 | /* Decrypt it */ | ||
475 | if(mpeg3_decrypt_packet(demuxer->titles[demuxer->current_title]->fs->css, | ||
476 | demuxer->raw_data)) | ||
477 | { | ||
478 | fprintf(stderr, "mpeg3_get_ps_pes_packet: Decryption not available\n"); | ||
479 | return 1; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | /* Get Presentation and Decoding Time Stamps */ | ||
484 | if(pts_dts_flags == 2) | ||
485 | { | ||
486 | pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ | ||
487 | pts <<= 15; | ||
488 | pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
489 | pts <<= 15; | ||
490 | pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
491 | pes_header_bytes += 5; | ||
492 | } | ||
493 | else | ||
494 | if(pts_dts_flags == 3) | ||
495 | { | ||
496 | pts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ | ||
497 | pts <<= 15; | ||
498 | pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
499 | pts <<= 15; | ||
500 | pts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
501 | dts = (mpeg3packet_read_char(demuxer) >> 1) & 7; /* Only low 4 bits (7==1111) */ | ||
502 | dts <<= 15; | ||
503 | dts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
504 | dts <<= 15; | ||
505 | dts |= (mpeg3packet_read_int16(demuxer) >> 1); | ||
506 | pes_header_bytes += 10; | ||
507 | } | ||
508 | |||
509 | /* Skip unknown */ | ||
510 | mpeg3packet_skip(demuxer, pes_header_data_length - pes_header_bytes); | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | int pts_dts_flags; | ||
515 | /* Get MPEG-1 packet */ | ||
516 | while(mpeg3packet_next_char(demuxer) == 0xff) | ||
517 | { | ||
518 | mpeg3packet_read_char(demuxer); | ||
519 | } | ||
520 | |||
521 | /* Skip STD buffer scale */ | ||
522 | if((mpeg3packet_next_char(demuxer) & 0x40) == 0x40) | ||
523 | { | ||
524 | mpeg3packet_skip(demuxer, 2); | ||
525 | } | ||
526 | |||
527 | /* Decide which timestamps are available */ | ||
528 | pts_dts_flags = mpeg3packet_next_char(demuxer); | ||
529 | |||
530 | if(pts_dts_flags >= 0x30) | ||
531 | { | ||
532 | /* Get the presentation and decoding time stamp */ | ||
533 | pts = mpeg3_get_timestamp(demuxer); | ||
534 | dts = mpeg3_get_timestamp(demuxer); | ||
535 | } | ||
536 | else | ||
537 | if(pts_dts_flags >= 0x20) | ||
538 | { | ||
539 | /* Get just the presentation time stamp */ | ||
540 | pts = mpeg3_get_timestamp(demuxer); | ||
541 | } | ||
542 | else | ||
543 | if(pts_dts_flags == 0x0f) | ||
544 | { | ||
545 | /* End of timestamps */ | ||
546 | mpeg3packet_read_char(demuxer); | ||
547 | } | ||
548 | else | ||
549 | { | ||
550 | return 1; /* Error */ | ||
551 | } | ||
552 | } | ||
553 | |||
554 | /* Now extract the payload. */ | ||
555 | if((stream_id >> 4) == 0xc || (stream_id >> 4) == 0xd) | ||
556 | { | ||
557 | /* Audio data */ | ||
558 | /* Take first stream ID if -1 */ | ||
559 | pes_packet_length -= demuxer->raw_offset - pes_packet_start; | ||
560 | if(!demuxer->do_audio && !demuxer->do_video) | ||
561 | demuxer->astream_table[stream_id & 0x0f] = AUDIO_MPEG; | ||
562 | else | ||
563 | if(demuxer->astream == -1) | ||
564 | demuxer->astream = stream_id & 0x0f; | ||
565 | |||
566 | if((stream_id & 0x0f) == demuxer->astream && demuxer->do_audio) | ||
567 | { | ||
568 | if(pts) demuxer->pes_audio_time = pts; | ||
569 | |||
570 | memcpy(&demuxer->data_buffer[demuxer->data_size], | ||
571 | &demuxer->raw_data[demuxer->raw_offset], | ||
572 | pes_packet_length); | ||
573 | demuxer->data_size += pes_packet_length; | ||
574 | demuxer->raw_offset += pes_packet_length; | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | mpeg3packet_skip(demuxer, pes_packet_length); | ||
579 | } | ||
580 | } | ||
581 | else | ||
582 | if((stream_id >> 4) == 0xe) | ||
583 | { | ||
584 | /* Video data */ | ||
585 | /* Take first stream ID if -1 */ | ||
586 | if(!demuxer->do_audio && !demuxer->do_video) | ||
587 | demuxer->vstream_table[stream_id & 0x0f] = 1; | ||
588 | else | ||
589 | if(demuxer->vstream == -1) | ||
590 | demuxer->vstream = stream_id & 0x0f; | ||
591 | |||
592 | pes_packet_length -= demuxer->raw_offset - pes_packet_start; | ||
593 | if((stream_id & 0x0f) == demuxer->vstream && demuxer->do_video) | ||
594 | { | ||
595 | if(pts) demuxer->pes_video_time = pts; | ||
596 | |||
597 | memcpy(&demuxer->data_buffer[demuxer->data_size], | ||
598 | &demuxer->raw_data[demuxer->raw_offset], | ||
599 | pes_packet_length); | ||
600 | demuxer->data_size += pes_packet_length; | ||
601 | demuxer->raw_offset += pes_packet_length; | ||
602 | } | ||
603 | else | ||
604 | { | ||
605 | mpeg3packet_skip(demuxer, pes_packet_length); | ||
606 | } | ||
607 | } | ||
608 | else | ||
609 | if(stream_id == 0xbd && demuxer->raw_data[demuxer->raw_offset] != 0xff) | ||
610 | { | ||
611 | /* DVD audio data */ | ||
612 | /* Get the audio format */ | ||
613 | int format; | ||
614 | if((demuxer->raw_data[demuxer->raw_offset] & 0xf0) == 0xa0) | ||
615 | format = AUDIO_PCM; | ||
616 | else | ||
617 | format = AUDIO_AC3; | ||
618 | |||
619 | stream_id = demuxer->raw_data[demuxer->raw_offset] - 0x80; | ||
620 | |||
621 | /* Take first stream ID if not building TOC. */ | ||
622 | if(!demuxer->do_audio && !demuxer->do_video) | ||
623 | demuxer->astream_table[stream_id] = format; | ||
624 | else | ||
625 | if(demuxer->astream == -1) | ||
626 | demuxer->astream = stream_id; | ||
627 | |||
628 | if(stream_id == demuxer->astream && demuxer->do_audio) | ||
629 | { | ||
630 | demuxer->aformat = format; | ||
631 | if(pts) demuxer->pes_audio_time = pts; | ||
632 | mpeg3packet_read_int32(demuxer); | ||
633 | pes_packet_length -= demuxer->raw_offset - pes_packet_start; | ||
634 | |||
635 | memcpy(&demuxer->data_buffer[demuxer->data_size], | ||
636 | &demuxer->raw_data[demuxer->raw_offset], | ||
637 | pes_packet_length); | ||
638 | demuxer->data_size += pes_packet_length; | ||
639 | demuxer->raw_offset += pes_packet_length; | ||
640 | } | ||
641 | else | ||
642 | { | ||
643 | pes_packet_length -= demuxer->raw_offset - pes_packet_start; | ||
644 | mpeg3packet_skip(demuxer, pes_packet_length); | ||
645 | } | ||
646 | } | ||
647 | else | ||
648 | if(stream_id == 0xbc || 1) | ||
649 | { | ||
650 | pes_packet_length -= demuxer->raw_offset - pes_packet_start; | ||
651 | mpeg3packet_skip(demuxer, pes_packet_length); | ||
652 | } | ||
653 | } | ||
654 | else | ||
655 | if(stream_id == MPEG3_PRIVATE_STREAM_2 || stream_id == MPEG3_PADDING_STREAM) | ||
656 | { | ||
657 | pes_packet_length -= demuxer->raw_offset - pes_packet_start; | ||
658 | mpeg3packet_skip(demuxer, pes_packet_length); | ||
659 | } | ||
660 | |||
661 | while(demuxer->raw_offset + 4 < demuxer->raw_size) | ||
662 | { | ||
663 | *header = mpeg3packet_read_int32(demuxer); | ||
664 | if((*header >> 8) != MPEG3_PACKET_START_CODE_PREFIX) | ||
665 | demuxer->raw_offset -= 3; | ||
666 | else | ||
667 | break; | ||
668 | } | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | int mpeg3_read_program(mpeg3_demuxer_t *demuxer) | ||
674 | { | ||
675 | int result = 0, count = 0; | ||
676 | mpeg3_t *file = demuxer->file; | ||
677 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
678 | unsigned int header; | ||
679 | demuxer->raw_size = demuxer->packet_size; | ||
680 | demuxer->raw_offset = 0; | ||
681 | demuxer->data_size = 0; | ||
682 | |||
683 | /* Search backward for it. */ | ||
684 | header = mpeg3io_read_int32(title->fs); | ||
685 | result = mpeg3io_eof(title->fs); | ||
686 | |||
687 | if(!result) result = mpeg3io_seek_relative(title->fs, -4); | ||
688 | |||
689 | // Search backwards for header | ||
690 | while(header != MPEG3_PACK_START_CODE && !result && count < demuxer->packet_size) | ||
691 | { | ||
692 | result = mpeg3io_seek_relative(title->fs, -1); | ||
693 | if(!result) | ||
694 | { | ||
695 | header >>= 8; | ||
696 | header |= mpeg3io_read_char(title->fs) << 24; | ||
697 | result = mpeg3io_seek_relative(title->fs, -1); | ||
698 | } | ||
699 | count++; | ||
700 | } | ||
701 | |||
702 | if(result) | ||
703 | { | ||
704 | // couldn't find MPEG3_PACK_START_CODE | ||
705 | return 1; | ||
706 | } | ||
707 | |||
708 | result = mpeg3io_read_data(demuxer->raw_data, demuxer->packet_size, title->fs); | ||
709 | |||
710 | if(result) | ||
711 | { | ||
712 | perror("mpeg3_read_program"); | ||
713 | return 1; | ||
714 | } | ||
715 | |||
716 | header = mpeg3packet_read_int32(demuxer); | ||
717 | while(demuxer->raw_offset + 4 < demuxer->raw_size && !result) | ||
718 | { | ||
719 | if(header == MPEG3_PACK_START_CODE) | ||
720 | { | ||
721 | result = mpeg3_get_pack_header(demuxer, &header); | ||
722 | } | ||
723 | else | ||
724 | if((header >> 8) == MPEG3_PACKET_START_CODE_PREFIX) | ||
725 | { | ||
726 | result = mpeg3_get_ps_pes_packet(demuxer, &header); | ||
727 | } | ||
728 | } | ||
729 | return result; | ||
730 | } | ||
731 | |||
732 | double mpeg3_lookup_time_offset(mpeg3_demuxer_t *demuxer, long byte) | ||
733 | { | ||
734 | int i; | ||
735 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
736 | |||
737 | if(!title->timecode_table_size) return 0; | ||
738 | |||
739 | for(i = title->timecode_table_size - 1; | ||
740 | i >= 0 && title->timecode_table[i].start_byte > byte; | ||
741 | i--) | ||
742 | ; | ||
743 | if(i < 0) i = 0; | ||
744 | return title->timecode_table[i].absolute_start_time - title->timecode_table[i].start_time; | ||
745 | } | ||
746 | |||
747 | int mpeg3_advance_timecode(mpeg3_demuxer_t *demuxer, int reverse) | ||
748 | { | ||
749 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
750 | int result = 0; | ||
751 | int do_seek = 0; | ||
752 | |||
753 | /* Skip timecode advancing when constructing timecode table */ | ||
754 | if(!title->timecode_table || | ||
755 | !title->timecode_table_size || | ||
756 | demuxer->generating_timecode) return 0; | ||
757 | |||
758 | if(!reverse) | ||
759 | { | ||
760 | /* Get inside the current timecode */ | ||
761 | if(mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte) | ||
762 | { | ||
763 | mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); | ||
764 | } | ||
765 | |||
766 | /* Get the next timecode */ | ||
767 | while(!result && | ||
768 | (mpeg3io_tell(title->fs) >= title->timecode_table[demuxer->current_timecode].end_byte || | ||
769 | demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) | ||
770 | { | ||
771 | |||
772 | /* | ||
773 | * printf("mpeg3_advance_timecode %d %d %d %d\n", mpeg3io_tell(title->fs), title->timecode_table[demuxer->current_timecode].end_byte, | ||
774 | * demuxer->current_program, title->timecode_table[demuxer->current_timecode].program); | ||
775 | */ | ||
776 | |||
777 | demuxer->current_timecode++; | ||
778 | if(demuxer->current_timecode >= title->timecode_table_size) | ||
779 | { | ||
780 | demuxer->current_timecode = 0; | ||
781 | if(demuxer->current_title + 1 < demuxer->total_titles) | ||
782 | { | ||
783 | mpeg3demux_open_title(demuxer, demuxer->current_title + 1); | ||
784 | do_seek = 1; | ||
785 | } | ||
786 | else | ||
787 | { | ||
788 | mpeg3io_seek(title->fs, mpeg3io_total_bytes(title->fs)); | ||
789 | result = 1; | ||
790 | } | ||
791 | } | ||
792 | title = demuxer->titles[demuxer->current_title]; | ||
793 | } | ||
794 | |||
795 | if(!result && do_seek) | ||
796 | { | ||
797 | mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); | ||
798 | } | ||
799 | } | ||
800 | else | ||
801 | { | ||
802 | /* Get the previous timecode */ | ||
803 | while(!result && | ||
804 | (mpeg3io_tell(title->fs) < title->timecode_table[demuxer->current_timecode].start_byte || | ||
805 | demuxer->current_program != title->timecode_table[demuxer->current_timecode].program)) | ||
806 | { | ||
807 | /* | ||
808 | * if(demuxer->do_audio) printf("mpeg3_reverse_timecode %d %d %d %d\n", mpeg3io_tell(title->fs), title->timecode_table[demuxer->current_timecode].end_byte, | ||
809 | * demuxer->current_program, title->timecode_table[demuxer->current_timecode].program); | ||
810 | */ | ||
811 | demuxer->current_timecode--; | ||
812 | if(demuxer->current_timecode < 0) | ||
813 | { | ||
814 | if(demuxer->current_title > 0) | ||
815 | { | ||
816 | mpeg3demux_open_title(demuxer, demuxer->current_title - 1); | ||
817 | title = demuxer->titles[demuxer->current_title]; | ||
818 | demuxer->current_timecode = title->timecode_table_size - 1; | ||
819 | do_seek = 1; | ||
820 | } | ||
821 | else | ||
822 | { | ||
823 | mpeg3io_seek(title->fs, 0); | ||
824 | demuxer->current_timecode = 0; | ||
825 | result = 1; | ||
826 | } | ||
827 | } | ||
828 | } | ||
829 | |||
830 | if(!result && do_seek) | ||
831 | mpeg3io_seek(title->fs, title->timecode_table[demuxer->current_timecode].start_byte); | ||
832 | } | ||
833 | |||
834 | return result; | ||
835 | } | ||
836 | |||
837 | /* Read packet in the forward direction */ | ||
838 | int mpeg3_read_next_packet(mpeg3_demuxer_t *demuxer) | ||
839 | { | ||
840 | int result = 0; | ||
841 | long current_position; | ||
842 | mpeg3_t *file = demuxer->file; | ||
843 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
844 | demuxer->data_size = 0; | ||
845 | demuxer->data_position = 0; | ||
846 | |||
847 | /* Flip the file descriptor back to the end of the packet for forward */ | ||
848 | /* reading. */ | ||
849 | if(demuxer->reverse) | ||
850 | { | ||
851 | result = mpeg3io_seek_relative(title->fs, demuxer->packet_size); | ||
852 | demuxer->reverse = 0; | ||
853 | } | ||
854 | |||
855 | /* Read packets until the output buffer is full */ | ||
856 | if(!result) | ||
857 | { | ||
858 | do | ||
859 | { | ||
860 | result = mpeg3_advance_timecode(demuxer, 0); | ||
861 | |||
862 | if(!result) | ||
863 | { | ||
864 | demuxer->time_offset = mpeg3_lookup_time_offset(demuxer, mpeg3io_tell(title->fs)); | ||
865 | |||
866 | if(file->is_transport_stream) | ||
867 | { | ||
868 | result = mpeg3_read_transport(demuxer); | ||
869 | } | ||
870 | else | ||
871 | if(file->is_program_stream) | ||
872 | { | ||
873 | result = mpeg3_read_program(demuxer); | ||
874 | } | ||
875 | else | ||
876 | { | ||
877 | /* Read elementary stream. */ | ||
878 | result = mpeg3io_read_data(demuxer->data_buffer, demuxer->packet_size, title->fs); | ||
879 | if(!result) demuxer->data_size = demuxer->packet_size; | ||
880 | } | ||
881 | } | ||
882 | }while(!result && demuxer->data_size == 0 && (demuxer->do_audio || demuxer->do_video)); | ||
883 | } | ||
884 | |||
885 | return result; | ||
886 | } | ||
887 | |||
888 | /* Read the packet right before the packet we're currently on. */ | ||
889 | int mpeg3_read_prev_packet(mpeg3_demuxer_t *demuxer) | ||
890 | { | ||
891 | int result = 0; | ||
892 | mpeg3_t *file = demuxer->file; | ||
893 | long current_position; | ||
894 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
895 | |||
896 | demuxer->data_size = 0; | ||
897 | demuxer->data_position = 0; | ||
898 | |||
899 | do | ||
900 | { | ||
901 | /* Rewind to the start of the packet to be read. */ | ||
902 | result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); | ||
903 | |||
904 | if(!result) result = mpeg3_advance_timecode(demuxer, 1); | ||
905 | if(!result) demuxer->time_offset = mpeg3_lookup_time_offset(demuxer, mpeg3io_tell(title->fs)); | ||
906 | |||
907 | if(file->is_transport_stream && !result) | ||
908 | { | ||
909 | result = mpeg3_read_transport(demuxer); | ||
910 | if(!mpeg3io_bof(title->fs)) | ||
911 | /* if(!result) */result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); | ||
912 | } | ||
913 | else | ||
914 | if(file->is_program_stream && !result) | ||
915 | { | ||
916 | |||
917 | result = mpeg3_read_program(demuxer); | ||
918 | if(!mpeg3io_bof(title->fs)) | ||
919 | /* if(!result) */result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); | ||
920 | } | ||
921 | else | ||
922 | if(!result) | ||
923 | { | ||
924 | /* Elementary stream */ | ||
925 | /* Read the packet forwards and seek back to the start */ | ||
926 | result = mpeg3io_read_data(demuxer->data_buffer, demuxer->packet_size, title->fs); | ||
927 | if(!result) | ||
928 | { | ||
929 | demuxer->data_size = demuxer->packet_size; | ||
930 | result = mpeg3io_seek_relative(title->fs, -demuxer->packet_size); | ||
931 | } | ||
932 | } | ||
933 | }while(!result && demuxer->data_size == 0 && (demuxer->do_audio || demuxer->do_video)); | ||
934 | |||
935 | /* Remember that the file descriptor is at the beginning of the packet just read. */ | ||
936 | demuxer->reverse = 1; | ||
937 | demuxer->error_flag = result; | ||
938 | return result; | ||
939 | } | ||
940 | |||
941 | |||
942 | /* Used for audio */ | ||
943 | int mpeg3demux_read_data(mpeg3_demuxer_t *demuxer, | ||
944 | unsigned char *output, | ||
945 | long size) | ||
946 | { | ||
947 | long i; | ||
948 | int result = 0; | ||
949 | mpeg3_t *file = demuxer->file; | ||
950 | demuxer->error_flag = 0; | ||
951 | |||
952 | if(demuxer->data_position >= 0) | ||
953 | { | ||
954 | /* Read forwards */ | ||
955 | for(i = 0; i < size && !result; ) | ||
956 | { | ||
957 | int fragment_size = size - i; | ||
958 | if(fragment_size > demuxer->data_size - demuxer->data_position) | ||
959 | fragment_size = demuxer->data_size - demuxer->data_position; | ||
960 | memcpy(output + i, demuxer->data_buffer + demuxer->data_position, fragment_size); | ||
961 | demuxer->data_position += fragment_size; | ||
962 | i += fragment_size; | ||
963 | |||
964 | if(i < size) | ||
965 | { | ||
966 | result = mpeg3_read_next_packet(demuxer); | ||
967 | } | ||
968 | } | ||
969 | } | ||
970 | else | ||
971 | { | ||
972 | /* Read backwards a full packet. */ | ||
973 | /* Only good for reading less than the size of a full packet, but */ | ||
974 | /* this routine should only be used for searching for previous markers. */ | ||
975 | long current_position = demuxer->data_position; | ||
976 | result = mpeg3_read_prev_packet(demuxer); | ||
977 | if(!result) demuxer->data_position = demuxer->data_size + current_position; | ||
978 | memcpy(output, demuxer->data_buffer + demuxer->data_position, size); | ||
979 | demuxer->data_position += size; | ||
980 | } | ||
981 | |||
982 | demuxer->error_flag = result; | ||
983 | return result; | ||
984 | } | ||
985 | |||
986 | unsigned int mpeg3demux_read_char_packet(mpeg3_demuxer_t *demuxer) | ||
987 | { | ||
988 | demuxer->error_flag = 0; | ||
989 | if(demuxer->data_position >= demuxer->data_size) | ||
990 | demuxer->error_flag = mpeg3_read_next_packet(demuxer); | ||
991 | demuxer->next_char = demuxer->data_buffer[demuxer->data_position++]; | ||
992 | return demuxer->next_char; | ||
993 | } | ||
994 | |||
995 | unsigned int mpeg3demux_read_prev_char_packet(mpeg3_demuxer_t *demuxer) | ||
996 | { | ||
997 | demuxer->error_flag = 0; | ||
998 | demuxer->data_position--; | ||
999 | if(demuxer->data_position < 0) | ||
1000 | { | ||
1001 | demuxer->error_flag = mpeg3_read_prev_packet(demuxer); | ||
1002 | if(!demuxer->error_flag) demuxer->data_position = demuxer->data_size - 1; | ||
1003 | } | ||
1004 | demuxer->next_char = demuxer->data_buffer[demuxer->data_position]; | ||
1005 | return demuxer->next_char; | ||
1006 | } | ||
1007 | |||
1008 | mpeg3demux_timecode_t* mpeg3_append_timecode(mpeg3_demuxer_t *demuxer, | ||
1009 | mpeg3_title_t *title, | ||
1010 | long prev_byte, | ||
1011 | double prev_time, | ||
1012 | long next_byte, | ||
1013 | double next_time, | ||
1014 | int dont_store) | ||
1015 | { | ||
1016 | mpeg3demux_timecode_t *new_table; | ||
1017 | mpeg3demux_timecode_t *new_timecode, *old_timecode; | ||
1018 | long i; | ||
1019 | |||
1020 | if(!title->timecode_table || | ||
1021 | title->timecode_table_allocation <= title->timecode_table_size) | ||
1022 | { | ||
1023 | if(title->timecode_table_allocation == 0) | ||
1024 | title->timecode_table_allocation = 1; | ||
1025 | else | ||
1026 | title->timecode_table_allocation *= 2; | ||
1027 | |||
1028 | new_table = (mpeg3demux_timecode_t*)calloc(1, sizeof(mpeg3demux_timecode_t) * title->timecode_table_allocation); | ||
1029 | if(title->timecode_table) | ||
1030 | { | ||
1031 | for(i = 0; i < title->timecode_table_size; i++) | ||
1032 | { | ||
1033 | new_table[i] = title->timecode_table[i]; | ||
1034 | } | ||
1035 | |||
1036 | free(title->timecode_table); | ||
1037 | } | ||
1038 | title->timecode_table = new_table; | ||
1039 | } | ||
1040 | |||
1041 | if(!dont_store) | ||
1042 | { | ||
1043 | new_timecode = &title->timecode_table[title->timecode_table_size]; | ||
1044 | new_timecode->start_byte = next_byte; | ||
1045 | new_timecode->start_time = next_time; | ||
1046 | new_timecode->absolute_start_time = 0; | ||
1047 | |||
1048 | if(title->timecode_table_size > 0) | ||
1049 | { | ||
1050 | old_timecode = &title->timecode_table[title->timecode_table_size - 1]; | ||
1051 | old_timecode->end_byte = prev_byte; | ||
1052 | old_timecode->end_time = prev_time; | ||
1053 | new_timecode->absolute_start_time = | ||
1054 | prev_time - | ||
1055 | old_timecode->start_time + | ||
1056 | old_timecode->absolute_start_time; | ||
1057 | new_timecode->absolute_end_time = next_time; | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1061 | title->timecode_table_size++; | ||
1062 | return new_timecode; | ||
1063 | } | ||
1064 | |||
1065 | mpeg3demux_timecode_t* mpeg3demux_next_timecode(mpeg3_demuxer_t *demuxer, | ||
1066 | int *current_title, | ||
1067 | int *current_timecode, | ||
1068 | int current_program) | ||
1069 | { | ||
1070 | int done = 0; | ||
1071 | while(!done) | ||
1072 | { | ||
1073 | /* Increase timecode number */ | ||
1074 | if(*current_timecode < demuxer->titles[*current_title]->timecode_table_size - 1) | ||
1075 | { | ||
1076 | (*current_timecode)++; | ||
1077 | if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) | ||
1078 | return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); | ||
1079 | } | ||
1080 | else | ||
1081 | /* Increase title number */ | ||
1082 | if(*current_title < demuxer->total_titles - 1) | ||
1083 | { | ||
1084 | (*current_title)++; | ||
1085 | (*current_timecode) = 0; | ||
1086 | if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) | ||
1087 | return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); | ||
1088 | } | ||
1089 | else | ||
1090 | /* End of disk */ | ||
1091 | done = 1; | ||
1092 | } | ||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | mpeg3demux_timecode_t* mpeg3demux_prev_timecode(mpeg3_demuxer_t *demuxer, | ||
1097 | int *current_title, | ||
1098 | int *current_timecode, | ||
1099 | int current_program) | ||
1100 | { | ||
1101 | int done = 0; | ||
1102 | while(!done) | ||
1103 | { | ||
1104 | /* Increase timecode number */ | ||
1105 | if(*current_timecode > 0) | ||
1106 | { | ||
1107 | (*current_timecode)--; | ||
1108 | if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) | ||
1109 | return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); | ||
1110 | } | ||
1111 | else | ||
1112 | /* Increase title number */ | ||
1113 | if(*current_title > 0) | ||
1114 | { | ||
1115 | (*current_title)--; | ||
1116 | (*current_timecode) = demuxer->titles[*current_title]->timecode_table_size - 1; | ||
1117 | if(demuxer->titles[*current_title]->timecode_table[*current_timecode].program == current_program) | ||
1118 | return &(demuxer->titles[*current_title]->timecode_table[*current_timecode]); | ||
1119 | } | ||
1120 | else | ||
1121 | /* End of disk */ | ||
1122 | done = 1; | ||
1123 | |||
1124 | } | ||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | int mpeg3demux_open_title(mpeg3_demuxer_t *demuxer, int title_number) | ||
1129 | { | ||
1130 | mpeg3_title_t *title; | ||
1131 | |||
1132 | if(title_number < demuxer->total_titles) | ||
1133 | { | ||
1134 | if(demuxer->current_title >= 0) | ||
1135 | { | ||
1136 | mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs); | ||
1137 | demuxer->current_title = -1; | ||
1138 | } | ||
1139 | |||
1140 | title = demuxer->titles[title_number]; | ||
1141 | if(mpeg3io_open_file(title->fs)) | ||
1142 | { | ||
1143 | demuxer->error_flag = 1; | ||
1144 | perror("mpeg3demux_open_title"); | ||
1145 | } | ||
1146 | else | ||
1147 | { | ||
1148 | demuxer->current_title = title_number; | ||
1149 | } | ||
1150 | } | ||
1151 | |||
1152 | demuxer->current_timecode = 0; | ||
1153 | |||
1154 | return demuxer->error_flag; | ||
1155 | } | ||
1156 | |||
1157 | /* Assign program numbers to interleaved programs */ | ||
1158 | int mpeg3demux_assign_programs(mpeg3_demuxer_t *demuxer) | ||
1159 | { | ||
1160 | int current_program = 0; | ||
1161 | int current_title = 0, previous_title; | ||
1162 | int current_timecode = 0, previous_timecode; | ||
1163 | double current_time, current_length; | ||
1164 | int done = 0; | ||
1165 | int interleaved = 0; | ||
1166 | mpeg3demux_timecode_t *timecode1, *timecode2; | ||
1167 | double program_times[MPEG3_MAX_STREAMS]; | ||
1168 | int total_programs = 1; | ||
1169 | int i, j; | ||
1170 | int program_exists, last_program_assigned = 0; | ||
1171 | int total_timecodes; | ||
1172 | mpeg3_title_t **titles = demuxer->titles; | ||
1173 | |||
1174 | for(i = 0, total_timecodes = 0; i < demuxer->total_titles; i++) | ||
1175 | total_timecodes += demuxer->titles[i]->timecode_table_size; | ||
1176 | |||
1177 | //if(total_timecodes < 3) return 0; | ||
1178 | |||
1179 | /* | ||
1180 | * // Assign programs based on length of contiguous timecode | ||
1181 | * timecode1 = demuxer->titles[current_title]->timecode_table; | ||
1182 | * while(!done) | ||
1183 | * { | ||
1184 | * if(!timecode1) done = 1; | ||
1185 | * else | ||
1186 | * if(timecode1->end_time - timecode1->start_time < MPEG3_PROGRAM_THRESHOLD) | ||
1187 | * { | ||
1188 | * // Got interleaved section | ||
1189 | * interleaved = 1; | ||
1190 | * program_times[0] = timecode1->end_time; | ||
1191 | * | ||
1192 | * while(interleaved && !done) | ||
1193 | * { | ||
1194 | * timecode2 = mpeg3demux_next_timecode(demuxer, | ||
1195 | * ¤t_title, | ||
1196 | * ¤t_timecode, | ||
1197 | * 0); | ||
1198 | * | ||
1199 | * if(!timecode2) done = 1; | ||
1200 | * else | ||
1201 | * { | ||
1202 | * // Another segment of interleaved data | ||
1203 | * if(timecode2->end_time - timecode2->start_time < MPEG3_PROGRAM_THRESHOLD) | ||
1204 | * { | ||
1205 | * // Search program times for where the previous instance of the program left off | ||
1206 | * for(program_exists = 0, i = 0; | ||
1207 | * i < total_programs && !program_exists; | ||
1208 | * i++) | ||
1209 | * { | ||
1210 | * // Got a previous instance of the program | ||
1211 | * if(program_times[i] + 0.5 > timecode2->start_time && | ||
1212 | * program_times[i] - 0.5 < timecode2->start_time) | ||
1213 | * { | ||
1214 | * program_times[i] = timecode2->end_time; | ||
1215 | * timecode2->program = i; | ||
1216 | * program_exists = 1; | ||
1217 | * | ||
1218 | * // Programs must always start at 0 for an interleaved section | ||
1219 | * if(i < last_program_assigned && i != 0) | ||
1220 | * { | ||
1221 | * // Shift programs in the interleaved section down until they start at 0 | ||
1222 | * for(j = 0; j < total_programs - 1; j++) | ||
1223 | * program_times[j] = program_times[j + 1]; | ||
1224 | * | ||
1225 | * for(previous_title = current_title, previous_timecode = current_timecode; | ||
1226 | * titles[previous_title]->timecode_table[previous_timecode].program > 0 && | ||
1227 | * (previous_title >= 0 || previous_timecode >= 0); ) | ||
1228 | * { | ||
1229 | * titles[previous_title]->timecode_table[previous_timecode].program--; | ||
1230 | * previous_timecode--; | ||
1231 | * if(previous_timecode < 0 && previous_title > 0) | ||
1232 | * { | ||
1233 | * previous_title--; | ||
1234 | * previous_timecode = titles[previous_title]->timecode_table_size - 1; | ||
1235 | * } | ||
1236 | * } | ||
1237 | * } | ||
1238 | * } | ||
1239 | * } | ||
1240 | * | ||
1241 | * // Didn't get one | ||
1242 | * if(!program_exists) | ||
1243 | * { | ||
1244 | * program_times[total_programs] = timecode2->end_time; | ||
1245 | * timecode2->program = total_programs++; | ||
1246 | * } | ||
1247 | * last_program_assigned = timecode2->program; | ||
1248 | * } | ||
1249 | * // No more interleaved section | ||
1250 | * else | ||
1251 | * { | ||
1252 | * interleaved = 0; | ||
1253 | * // Restart program table from the beginning | ||
1254 | * total_programs = 1; | ||
1255 | * last_program_assigned = 0; | ||
1256 | * timecode1 = mpeg3demux_next_timecode(demuxer, | ||
1257 | * ¤t_title, | ||
1258 | * ¤t_timecode, | ||
1259 | * 0); | ||
1260 | * } | ||
1261 | * } | ||
1262 | * } | ||
1263 | * } | ||
1264 | * else | ||
1265 | * // Get next timecode | ||
1266 | * timecode1 = mpeg3demux_next_timecode(demuxer, | ||
1267 | * ¤t_title, | ||
1268 | * ¤t_timecode, | ||
1269 | * 0); | ||
1270 | * } | ||
1271 | * | ||
1272 | * demuxer->total_programs = total_programs; | ||
1273 | */ | ||
1274 | |||
1275 | /* Assign absolute timecodes in each program. */ | ||
1276 | for(current_program = 0; | ||
1277 | current_program < total_programs; | ||
1278 | current_program++) | ||
1279 | { | ||
1280 | current_time = 0; | ||
1281 | current_title = 0; | ||
1282 | current_timecode = -1; | ||
1283 | while(timecode1 = mpeg3demux_next_timecode(demuxer, | ||
1284 | ¤t_title, | ||
1285 | ¤t_timecode, | ||
1286 | current_program)) | ||
1287 | { | ||
1288 | timecode1->absolute_start_time = current_time; | ||
1289 | current_time += timecode1->end_time - timecode1->start_time; | ||
1290 | timecode1->absolute_end_time = current_time; | ||
1291 | } | ||
1292 | } | ||
1293 | //for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]); | ||
1294 | demuxer->current_program = 0; | ||
1295 | return 0; | ||
1296 | } | ||
1297 | |||
1298 | /* ==================================================================== */ | ||
1299 | /* Entry points */ | ||
1300 | /* ==================================================================== */ | ||
1301 | |||
1302 | mpeg3_demuxer_t* mpeg3_new_demuxer(mpeg3_t *file, int do_audio, int do_video, int stream_id) | ||
1303 | { | ||
1304 | mpeg3_demuxer_t *demuxer = (mpeg3_demuxer_t*)calloc(1, sizeof(mpeg3_demuxer_t)); | ||
1305 | int i; | ||
1306 | |||
1307 | /* The demuxer will change the default packet size for its own use. */ | ||
1308 | demuxer->file = file; | ||
1309 | demuxer->packet_size = file->packet_size; | ||
1310 | demuxer->do_audio = do_audio; | ||
1311 | demuxer->do_video = do_video; | ||
1312 | |||
1313 | /* Allocate buffer + padding */ | ||
1314 | demuxer->raw_data = (unsigned char*)calloc(1, MPEG3_MAX_PACKSIZE); | ||
1315 | demuxer->data_buffer = (unsigned char*)calloc(1, MPEG3_MAX_PACKSIZE); | ||
1316 | demuxer->data_allocated = MPEG3_MAX_PACKSIZE; | ||
1317 | /* System specific variables */ | ||
1318 | demuxer->audio_pid = stream_id; | ||
1319 | demuxer->video_pid = stream_id; | ||
1320 | demuxer->astream = stream_id; | ||
1321 | demuxer->vstream = stream_id; | ||
1322 | demuxer->current_title = -1; | ||
1323 | return demuxer; | ||
1324 | } | ||
1325 | |||
1326 | int mpeg3_delete_demuxer(mpeg3_demuxer_t *demuxer) | ||
1327 | { | ||
1328 | int i; | ||
1329 | |||
1330 | if(demuxer->current_title >= 0) | ||
1331 | { | ||
1332 | mpeg3io_close_file(demuxer->titles[demuxer->current_title]->fs); | ||
1333 | } | ||
1334 | |||
1335 | for(i = 0; i < demuxer->total_titles; i++) | ||
1336 | { | ||
1337 | mpeg3_delete_title(demuxer->titles[i]); | ||
1338 | } | ||
1339 | |||
1340 | if(demuxer->data_buffer) free(demuxer->data_buffer); | ||
1341 | free(demuxer->raw_data); | ||
1342 | free(demuxer); | ||
1343 | } | ||
1344 | |||
1345 | /* Create a title. */ | ||
1346 | /* Build a table of timecodes contained in the program stream. */ | ||
1347 | /* If toc is 0 just read the first and last timecode. */ | ||
1348 | int mpeg3demux_create_title(mpeg3_demuxer_t *demuxer, int timecode_search, FILE *toc) | ||
1349 | { | ||
1350 | int result = 0, done = 0, counter_start, counter; | ||
1351 | mpeg3_t *file = demuxer->file; | ||
1352 | long next_byte, prev_byte; | ||
1353 | double next_time, prev_time, absolute_time; | ||
1354 | long i; | ||
1355 | mpeg3_title_t *title; | ||
1356 | unsigned long test_header = 0; | ||
1357 | mpeg3demux_timecode_t *timecode = 0; | ||
1358 | |||
1359 | demuxer->error_flag = 0; | ||
1360 | demuxer->generating_timecode = 1; | ||
1361 | |||
1362 | /* Create a single title */ | ||
1363 | if(!demuxer->total_titles) | ||
1364 | { | ||
1365 | demuxer->titles[0] = mpeg3_new_title(file, file->fs->path); | ||
1366 | demuxer->total_titles = 1; | ||
1367 | mpeg3demux_open_title(demuxer, 0); | ||
1368 | } | ||
1369 | title = demuxer->titles[0]; | ||
1370 | title->total_bytes = mpeg3io_total_bytes(title->fs); | ||
1371 | |||
1372 | |||
1373 | /* Get the packet size from the file */ | ||
1374 | if(file->is_program_stream) | ||
1375 | { | ||
1376 | mpeg3io_seek(title->fs, 4); | ||
1377 | for(i = 0; i < MPEG3_MAX_PACKSIZE && | ||
1378 | test_header != MPEG3_PACK_START_CODE; i++) | ||
1379 | { | ||
1380 | test_header <<= 8; | ||
1381 | test_header |= mpeg3io_read_char(title->fs); | ||
1382 | } | ||
1383 | if(i < MPEG3_MAX_PACKSIZE) demuxer->packet_size = i; | ||
1384 | mpeg3io_seek(title->fs, 0); | ||
1385 | } | ||
1386 | else | ||
1387 | demuxer->packet_size = file->packet_size; | ||
1388 | |||
1389 | /* Get timecodes for the title */ | ||
1390 | if(file->is_transport_stream || file->is_program_stream) | ||
1391 | { | ||
1392 | mpeg3io_seek(title->fs, 0); | ||
1393 | while(!done && !result && !mpeg3io_eof(title->fs)) | ||
1394 | { | ||
1395 | next_byte = mpeg3io_tell(title->fs); | ||
1396 | result = mpeg3_read_next_packet(demuxer); | ||
1397 | |||
1398 | if(!result) | ||
1399 | { | ||
1400 | next_time = demuxer->time; | ||
1401 | //printf("%f %f\n", next_time, prev_time); | ||
1402 | if(next_time < prev_time || | ||
1403 | next_time - prev_time > MPEG3_CONTIGUOUS_THRESHOLD || | ||
1404 | !title->timecode_table_size) | ||
1405 | { | ||
1406 | /* Discontinuous */ | ||
1407 | timecode = mpeg3_append_timecode(demuxer, | ||
1408 | title, | ||
1409 | prev_byte, | ||
1410 | prev_time, | ||
1411 | next_byte, | ||
1412 | next_time, | ||
1413 | 0); | ||
1414 | /* | ||
1415 | * printf("timecode: %ld %ld %f %f\n", | ||
1416 | * timecode->start_byte, | ||
1417 | * timecode->end_byte, | ||
1418 | * timecode->start_time, | ||
1419 | * timecode->end_time); | ||
1420 | */ | ||
1421 | |||
1422 | counter_start = (int)next_time; | ||
1423 | } | ||
1424 | prev_time = next_time; | ||
1425 | prev_byte = next_byte; | ||
1426 | counter = (int)next_time; | ||
1427 | } | ||
1428 | |||
1429 | /* Just get the first bytes if not building a toc to get the stream ID's. */ | ||
1430 | if(next_byte > 0x100000 && | ||
1431 | (!timecode_search || !toc)) done = 1; | ||
1432 | } | ||
1433 | |||
1434 | /* Get the last timecode */ | ||
1435 | if(!toc || !timecode_search) | ||
1436 | { | ||
1437 | result = mpeg3io_seek(title->fs, title->total_bytes); | ||
1438 | if(!result) result = mpeg3_read_prev_packet(demuxer); | ||
1439 | } | ||
1440 | |||
1441 | if(title->timecode_table && timecode) | ||
1442 | { | ||
1443 | timecode->end_byte = title->total_bytes; | ||
1444 | // timecode->end_byte = mpeg3io_tell(title->fs)/* + demuxer->packet_size */; | ||
1445 | timecode->end_time = demuxer->time; | ||
1446 | timecode->absolute_end_time = timecode->end_time - timecode->start_time; | ||
1447 | } | ||
1448 | } | ||
1449 | |||
1450 | mpeg3io_seek(title->fs, 0); | ||
1451 | demuxer->generating_timecode = 0; | ||
1452 | return 0; | ||
1453 | } | ||
1454 | |||
1455 | int mpeg3demux_print_timecodes(mpeg3_title_t *title, FILE *output) | ||
1456 | { | ||
1457 | mpeg3demux_timecode_t *timecode; | ||
1458 | int i; | ||
1459 | |||
1460 | if(title->timecode_table) | ||
1461 | { | ||
1462 | for(i = 0; i < title->timecode_table_size; i++) | ||
1463 | { | ||
1464 | timecode = &title->timecode_table[i]; | ||
1465 | |||
1466 | fprintf(output, "REGION: %ld %ld %f %f\n", | ||
1467 | timecode->start_byte, | ||
1468 | timecode->end_byte, | ||
1469 | timecode->start_time, | ||
1470 | timecode->end_time); | ||
1471 | } | ||
1472 | } | ||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | /* Read the title information from a toc */ | ||
1477 | int mpeg3demux_read_titles(mpeg3_demuxer_t *demuxer) | ||
1478 | { | ||
1479 | char string1[MPEG3_STRLEN], string2[MPEG3_STRLEN]; | ||
1480 | long start_byte, end_byte; | ||
1481 | float start_time, end_time; | ||
1482 | mpeg3_title_t *title = 0; | ||
1483 | mpeg3_t *file = demuxer->file; | ||
1484 | |||
1485 | // Eventually use IFO file to generate titles | ||
1486 | while(!feof(file->fs->fd)) | ||
1487 | { | ||
1488 | fscanf(file->fs->fd, "%s %s %ld %f %f %f", | ||
1489 | string1, | ||
1490 | string2, | ||
1491 | &end_byte, | ||
1492 | &start_time, | ||
1493 | &end_time); | ||
1494 | |||
1495 | if(!strncasecmp(string1, "PATH:", 5)) | ||
1496 | { | ||
1497 | title = demuxer->titles[demuxer->total_titles++] = mpeg3_new_title(file, string2); | ||
1498 | |||
1499 | if(demuxer->current_title < 0) | ||
1500 | mpeg3demux_open_title(demuxer, 0); | ||
1501 | } | ||
1502 | else | ||
1503 | if(title) | ||
1504 | { | ||
1505 | start_byte = atol(string2); | ||
1506 | if(!strcasecmp(string1, "REGION:")) | ||
1507 | { | ||
1508 | mpeg3_append_timecode(demuxer, | ||
1509 | title, | ||
1510 | 0, | ||
1511 | 0, | ||
1512 | 0, | ||
1513 | 0, | ||
1514 | 1); | ||
1515 | title->timecode_table[title->timecode_table_size - 1].start_byte = start_byte; | ||
1516 | title->timecode_table[title->timecode_table_size - 1].end_byte = end_byte; | ||
1517 | title->timecode_table[title->timecode_table_size - 1].start_time = start_time; | ||
1518 | title->timecode_table[title->timecode_table_size - 1].end_time = end_time; | ||
1519 | } | ||
1520 | else | ||
1521 | if(!strcasecmp(string1, "ASTREAM:")) | ||
1522 | demuxer->astream_table[start_byte] = end_byte; | ||
1523 | else | ||
1524 | if(!strcasecmp(string1, "VSTREAM:")) | ||
1525 | demuxer->vstream_table[start_byte] = end_byte; | ||
1526 | else | ||
1527 | if(!strcasecmp(string1, "SIZE:")) | ||
1528 | title->total_bytes = start_byte; | ||
1529 | else | ||
1530 | if(!strcasecmp(string1, "PACKETSIZE:")) | ||
1531 | demuxer->packet_size = start_byte; | ||
1532 | } | ||
1533 | } | ||
1534 | |||
1535 | mpeg3demux_assign_programs(demuxer); | ||
1536 | return 0; | ||
1537 | } | ||
1538 | |||
1539 | int mpeg3demux_copy_titles(mpeg3_demuxer_t *dst, mpeg3_demuxer_t *src) | ||
1540 | { | ||
1541 | long i; | ||
1542 | mpeg3_t *file = dst->file; | ||
1543 | mpeg3_title_t *dst_title, *src_title; | ||
1544 | |||
1545 | dst->packet_size = src->packet_size; | ||
1546 | dst->total_titles = src->total_titles; | ||
1547 | dst->total_programs = src->total_programs; | ||
1548 | for(i = 0; i < MPEG3_MAX_STREAMS; i++) | ||
1549 | { | ||
1550 | dst->astream_table[i] = src->astream_table[i]; | ||
1551 | dst->vstream_table[i] = src->vstream_table[i]; | ||
1552 | } | ||
1553 | for(i = 0; i < src->total_titles; i++) | ||
1554 | { | ||
1555 | src_title = src->titles[i]; | ||
1556 | dst_title = dst->titles[i] = mpeg3_new_title(file, src->titles[i]->fs->path); | ||
1557 | mpeg3_copy_title(dst_title, src_title); | ||
1558 | } | ||
1559 | |||
1560 | mpeg3demux_open_title(dst, src->current_title); | ||
1561 | return 0; | ||
1562 | } | ||
1563 | |||
1564 | int mpeg3demux_print_streams(mpeg3_demuxer_t *demuxer, FILE *toc) | ||
1565 | { | ||
1566 | int i; | ||
1567 | /* Print the stream information */ | ||
1568 | for(i = 0; i < MPEG3_MAX_STREAMS; i++) | ||
1569 | { | ||
1570 | if(demuxer->astream_table[i]) | ||
1571 | fprintf(toc, "ASTREAM: %d %d\n", i, demuxer->astream_table[i]); | ||
1572 | |||
1573 | if(demuxer->vstream_table[i]) | ||
1574 | fprintf(toc, "VSTREAM: %d %d\n", i, demuxer->vstream_table[i]); | ||
1575 | } | ||
1576 | return 0; | ||
1577 | } | ||
1578 | |||
1579 | /* Need a timecode table to do this */ | ||
1580 | double mpeg3demux_length(mpeg3_demuxer_t *demuxer) | ||
1581 | { | ||
1582 | mpeg3_title_t *title; | ||
1583 | int i, j; | ||
1584 | double length; | ||
1585 | |||
1586 | for(i = demuxer->total_titles - 1; i >= 0; i--) | ||
1587 | { | ||
1588 | title = demuxer->titles[i]; | ||
1589 | for(j = title->timecode_table_size - 1; j >= 0; j--) | ||
1590 | { | ||
1591 | if(title->timecode_table[j].program == demuxer->current_program) | ||
1592 | { | ||
1593 | return title->timecode_table[j].end_time - | ||
1594 | title->timecode_table[j].start_time + | ||
1595 | title->timecode_table[j].absolute_start_time; | ||
1596 | } | ||
1597 | } | ||
1598 | } | ||
1599 | |||
1600 | return 1; | ||
1601 | } | ||
1602 | |||
1603 | int mpeg3demux_eof(mpeg3_demuxer_t *demuxer) | ||
1604 | { | ||
1605 | if(demuxer->current_title >= 0) | ||
1606 | { | ||
1607 | if(mpeg3io_eof(demuxer->titles[demuxer->current_title]->fs) && | ||
1608 | demuxer->current_title >= demuxer->total_titles - 1) | ||
1609 | return 1; | ||
1610 | } | ||
1611 | |||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | int mpeg3demux_bof(mpeg3_demuxer_t *demuxer) | ||
1616 | { | ||
1617 | if(demuxer->current_title >= 0) | ||
1618 | { | ||
1619 | if(mpeg3io_bof(demuxer->titles[demuxer->current_title]->fs) && | ||
1620 | demuxer->current_title <= 0) | ||
1621 | return 1; | ||
1622 | } | ||
1623 | return 0; | ||
1624 | } | ||
1625 | |||
1626 | |||
1627 | /* For elemental streams seek to a byte */ | ||
1628 | int mpeg3demux_seek_byte(mpeg3_demuxer_t *demuxer, long byte) | ||
1629 | { | ||
1630 | long current_position; | ||
1631 | mpeg3_t *file = demuxer->file; | ||
1632 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
1633 | |||
1634 | demuxer->data_position = 0; | ||
1635 | demuxer->data_size = 0; | ||
1636 | |||
1637 | demuxer->error_flag = mpeg3io_seek(title->fs, byte); | ||
1638 | |||
1639 | if(!demuxer->error_flag && (file->is_transport_stream || file->is_program_stream)) | ||
1640 | { | ||
1641 | /* Get on a packet boundary only for system streams. */ | ||
1642 | current_position = mpeg3io_tell(title->fs); | ||
1643 | if(byte % demuxer->packet_size) | ||
1644 | { | ||
1645 | demuxer->error_flag |= mpeg3io_seek(title->fs, current_position - (current_position % demuxer->packet_size)); | ||
1646 | } | ||
1647 | } | ||
1648 | return demuxer->error_flag; | ||
1649 | } | ||
1650 | |||
1651 | /* For programs streams and toc seek to a time */ | ||
1652 | int mpeg3demux_seek_time(mpeg3_demuxer_t *demuxer, double new_time) | ||
1653 | { | ||
1654 | int i, j, done = 0, result = 0; | ||
1655 | double byte_offset, new_byte_offset; | ||
1656 | double guess = 0, minimum = 65535; | ||
1657 | mpeg3_title_t *title; | ||
1658 | mpeg3demux_timecode_t *timecode; | ||
1659 | |||
1660 | demuxer->error_flag = 0; | ||
1661 | |||
1662 | i = 0; | ||
1663 | j = 0; | ||
1664 | title = demuxer->titles[i]; | ||
1665 | timecode = &title->timecode_table[j]; | ||
1666 | |||
1667 | /* Get the title and timecode of the new position */ | ||
1668 | while(!demuxer->error_flag && | ||
1669 | !(timecode->absolute_start_time <= new_time && | ||
1670 | timecode->absolute_end_time > new_time && | ||
1671 | timecode->program == demuxer->current_program)) | ||
1672 | { | ||
1673 | /* Next timecode */ | ||
1674 | j++; | ||
1675 | if(j >= title->timecode_table_size) | ||
1676 | { | ||
1677 | i++; | ||
1678 | j = 0; | ||
1679 | if(i >= demuxer->total_titles) | ||
1680 | { | ||
1681 | demuxer->error_flag = 1; | ||
1682 | return 1; | ||
1683 | } | ||
1684 | else | ||
1685 | { | ||
1686 | mpeg3demux_open_title(demuxer, i); | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | title = demuxer->titles[i]; | ||
1691 | timecode = &title->timecode_table[j]; | ||
1692 | } | ||
1693 | |||
1694 | /* Guess the new byte position */ | ||
1695 | demuxer->current_timecode = j; | ||
1696 | |||
1697 | byte_offset = ((new_time - timecode->absolute_start_time) / | ||
1698 | (timecode->absolute_end_time - timecode->absolute_start_time) * | ||
1699 | (timecode->end_byte - timecode->start_byte) + | ||
1700 | timecode->start_byte); | ||
1701 | //printf("mpeg3demux_seek_time %f %f\n", new_time, byte_offset); | ||
1702 | |||
1703 | while(!done && !result && byte_offset >= 0) | ||
1704 | { | ||
1705 | result = mpeg3demux_seek_byte(demuxer, (long)byte_offset); | ||
1706 | //printf("seek_time 0 byte %.0f want %f result %d\n", byte_offset, new_time, result); | ||
1707 | |||
1708 | if(!result) | ||
1709 | { | ||
1710 | result = mpeg3_read_next_packet(demuxer); | ||
1711 | // printf("seek_time 1 guess %f want %f\n", guess, new_time); | ||
1712 | guess = demuxer->time + demuxer->time_offset; | ||
1713 | |||
1714 | if(fabs(new_time - guess) >= fabs(minimum)) done = 1; | ||
1715 | else | ||
1716 | { | ||
1717 | minimum = guess - new_time; | ||
1718 | new_byte_offset = byte_offset + ((new_time - guess) / | ||
1719 | (timecode->end_time - timecode->start_time) * | ||
1720 | (timecode->end_byte - timecode->start_byte)); | ||
1721 | if(labs((long)new_byte_offset - (long)byte_offset) < demuxer->packet_size) done = 1; | ||
1722 | byte_offset = new_byte_offset; | ||
1723 | } | ||
1724 | } | ||
1725 | } | ||
1726 | |||
1727 | /* Get one packet before the packet just read */ | ||
1728 | if(!result && byte_offset > demuxer->packet_size && minimum > 0) | ||
1729 | { | ||
1730 | mpeg3_read_prev_packet(demuxer); | ||
1731 | mpeg3_read_prev_packet(demuxer); | ||
1732 | } | ||
1733 | //printf("seek_time %d %d %d\n", demuxer->current_title, demuxer->current_timecode, mpeg3demux_tell(demuxer)); | ||
1734 | demuxer->error_flag = result; | ||
1735 | return result; | ||
1736 | } | ||
1737 | |||
1738 | int mpeg3demux_seek_percentage(mpeg3_demuxer_t *demuxer, double percentage) | ||
1739 | { | ||
1740 | double total_bytes = 0; | ||
1741 | double absolute_position; | ||
1742 | long relative_position; | ||
1743 | int i, new_title; | ||
1744 | mpeg3_title_t *title; | ||
1745 | |||
1746 | demuxer->error_flag = 0; | ||
1747 | |||
1748 | /* Get the absolute byte position; */ | ||
1749 | for(i = 0; i < demuxer->total_titles; i++) | ||
1750 | total_bytes += demuxer->titles[i]->total_bytes; | ||
1751 | |||
1752 | absolute_position = percentage * total_bytes; | ||
1753 | |||
1754 | /* Get the title the byte is inside */ | ||
1755 | for(new_title = 0, total_bytes = 0; new_title < demuxer->total_titles; new_title++) | ||
1756 | { | ||
1757 | total_bytes += demuxer->titles[new_title]->total_bytes; | ||
1758 | if(absolute_position < total_bytes) break; | ||
1759 | } | ||
1760 | |||
1761 | if(new_title >= demuxer->total_titles) | ||
1762 | { | ||
1763 | new_title = demuxer->total_titles - 1; | ||
1764 | } | ||
1765 | |||
1766 | /* Got a title */ | ||
1767 | title = demuxer->titles[new_title]; | ||
1768 | total_bytes -= title->total_bytes; | ||
1769 | relative_position = (long)(absolute_position - total_bytes); | ||
1770 | |||
1771 | /* Get the timecode the byte is inside */ | ||
1772 | for(demuxer->current_timecode = 0; | ||
1773 | demuxer->current_timecode < title->timecode_table_size; | ||
1774 | demuxer->current_timecode++) | ||
1775 | { | ||
1776 | if(title->timecode_table[demuxer->current_timecode].start_byte <= relative_position && | ||
1777 | title->timecode_table[demuxer->current_timecode].end_byte > relative_position) | ||
1778 | { | ||
1779 | break; | ||
1780 | } | ||
1781 | } | ||
1782 | |||
1783 | if(demuxer->current_timecode >= title->timecode_table_size) | ||
1784 | demuxer->current_timecode = title->timecode_table_size - 1; | ||
1785 | |||
1786 | /* Get the nearest timecode in the same program */ | ||
1787 | while(demuxer->current_timecode < title->timecode_table_size - 1 && | ||
1788 | title->timecode_table[demuxer->current_timecode].program != demuxer->current_program) | ||
1789 | { | ||
1790 | demuxer->current_timecode++; | ||
1791 | } | ||
1792 | |||
1793 | /* Open the new title and seek to the correct byte */ | ||
1794 | if(new_title != demuxer->current_title) | ||
1795 | { | ||
1796 | demuxer->error_flag = mpeg3demux_open_title(demuxer, new_title); | ||
1797 | } | ||
1798 | |||
1799 | if(!demuxer->error_flag) | ||
1800 | demuxer->error_flag = mpeg3io_seek(title->fs, relative_position); | ||
1801 | |||
1802 | return demuxer->error_flag; | ||
1803 | } | ||
1804 | |||
1805 | double mpeg3demux_tell_percentage(mpeg3_demuxer_t *demuxer) | ||
1806 | { | ||
1807 | double total_bytes = 0; | ||
1808 | double position = 0; | ||
1809 | int i; | ||
1810 | |||
1811 | demuxer->error_flag = 0; | ||
1812 | position = mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs); | ||
1813 | for(i = 0; i < demuxer->total_titles; i++) | ||
1814 | { | ||
1815 | if(i == demuxer->current_title) | ||
1816 | { | ||
1817 | position += total_bytes; | ||
1818 | } | ||
1819 | total_bytes += demuxer->titles[i]->total_bytes; | ||
1820 | } | ||
1821 | return position / total_bytes; | ||
1822 | } | ||
1823 | |||
1824 | double mpeg3demux_get_time(mpeg3_demuxer_t *demuxer) | ||
1825 | { | ||
1826 | return demuxer->time; | ||
1827 | } | ||
1828 | |||
1829 | long mpeg3demux_tell(mpeg3_demuxer_t *demuxer) | ||
1830 | { | ||
1831 | return mpeg3io_tell(demuxer->titles[demuxer->current_title]->fs); | ||
1832 | } | ||
1833 | |||
1834 | long mpeg3demuxer_total_bytes(mpeg3_demuxer_t *demuxer) | ||
1835 | { | ||
1836 | mpeg3_title_t *title = demuxer->titles[demuxer->current_title]; | ||
1837 | return title->total_bytes; | ||
1838 | } | ||
1839 | |||
1840 | mpeg3_demuxer_t* mpeg3_get_demuxer(mpeg3_t *file) | ||
1841 | { | ||
1842 | if(file->is_program_stream || file->is_transport_stream) | ||
1843 | { | ||
1844 | if(file->has_audio) return file->atrack[0]->demuxer; | ||
1845 | else | ||
1846 | if(file->has_video) return file->vtrack[0]->demuxer; | ||
1847 | } | ||
1848 | return 0; | ||
1849 | } | ||