1 /*
2 * scan_pes.c
3 *
4 * Copyright (C) Thomas Oestreich - June 2001
5 *
6 * This file is part of transcode, a video stream processing tool
7 *
8 * transcode is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * transcode is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Make; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "transcode.h"
25 #include "tcinfo.h"
26 #include "ioaux.h"
27 #include "tc.h"
28 #include "aux_pes.h"
29 #include "mpg123.h"
30 #include "ac3scan.h"
31 #include "demuxer.h"
32 #include "libtc/libtc.h"
33 #include "libtc/ratiocodes.h"
34
35 #define BUFFER_SIZE 262144
36 static uint8_t buffer[BUFFER_SIZE];
37
38 static seq_info_t si;
39
40 static int mpeg_version=0;
41
42 static int unit_ctr=0, seq_ctr=0;
43
44 static uint16_t id;
45
46 static uint32_t stream[256], track[TC_MAX_AUD_TRACKS], attr[TC_MAX_AUD_TRACKS];
47
48 static int tot_seq_ctr=0, tot_unit_ctr=0;
49 static unsigned int tot_bitrate=0, min_bitrate=(unsigned int)-1, max_bitrate=0;
50
51 //count packs for each presntation unit
52 static uint32_t unit_pack_cnt[256], unit_pack_cnt_index=0;
53
54 static int ref_pts=0;
55
56 static int show_seq_info=0, show_ext_info=0;
57
cmp_32_bits(char * buf,long x)58 static int cmp_32_bits(char *buf, long x)
59 {
60
61 if ((uint8_t)buf[0] != ((x >> 24) & 0xff))
62 return 0;
63 if ((uint8_t)buf[1] != ((x >> 16) & 0xff))
64 return 0;
65 if ((uint8_t)buf[2] != ((x >> 8) & 0xff))
66 return 0;
67 if ((uint8_t)buf[3] != ((x ) & 0xff))
68 return 0;
69
70 // OK found it
71 return 1;
72 }
73
probe_sequence(uint8_t * buffer,ProbeInfo * probe_info)74 static int probe_sequence(uint8_t *buffer, ProbeInfo *probe_info)
75 {
76
77 int horizontal_size;
78 int vertical_size;
79 int aspect_ratio_information;
80 int frame_rate_code;
81 int bit_rate_value;
82 int vbv_buffer_size_value;
83 int constrained_parameters_flag;
84 int load_intra_quantizer_matrix;
85 int load_non_intra_quantizer_matrix;
86
87 vertical_size = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
88 horizontal_size = ((vertical_size >> 12) + 15) & ~15;
89 vertical_size = ((vertical_size & 0xfff) + 15) & ~15;
90
91 aspect_ratio_information = buffer[3] >> 4;
92 frame_rate_code = buffer[3] & 15;
93 bit_rate_value = (buffer[4] << 10) | (buffer[5] << 2) | (buffer[6] >> 6);
94 vbv_buffer_size_value = ((buffer[6] << 5) | (buffer[7] >> 3)) & 0x3ff;
95 constrained_parameters_flag = buffer[7] & 4;
96 load_intra_quantizer_matrix = buffer[7] & 2;
97 if (load_intra_quantizer_matrix)
98 buffer += 64;
99 load_non_intra_quantizer_matrix = buffer[7] & 1;
100
101 //set some defaults, if invalid:
102 if(aspect_ratio_information < 0 || aspect_ratio_information>15) aspect_ratio_information=0;
103
104 if(frame_rate_code < 0 || frame_rate_code>15) frame_rate_code=0;
105
106 //fill out user structure
107
108 probe_info->width = horizontal_size;
109 probe_info->height = vertical_size;
110 probe_info->asr = aspect_ratio_information;
111 probe_info->frc = frame_rate_code;
112 probe_info->bitrate = bit_rate_value * 400.0 / 1000.0;
113 tc_frc_code_to_value(frame_rate_code, &probe_info->fps);
114
115 return(0);
116
117 }
118
probe_extension(uint8_t * buffer,ProbeInfo * probe_info)119 static int probe_extension(uint8_t *buffer, ProbeInfo *probe_info)
120 {
121
122 int intra_dc_precision;
123 int picture_structure;
124 int top_field_first;
125 int frame_pred_frame_dct;
126 int concealment_motion_vectors;
127 int q_scale_type;
128 int intra_vlc_format;
129 int alternate_scan;
130 int repeat_first_field;
131 int progressive_frame;
132
133 intra_dc_precision = (buffer[2] >> 2) & 3;
134 picture_structure = buffer[2] & 3;
135 top_field_first = buffer[3] >> 7;
136 frame_pred_frame_dct = (buffer[3] >> 6) & 1;
137 concealment_motion_vectors = (buffer[3] >> 5) & 1;
138 q_scale_type = (buffer[3] >> 4) & 1;
139 intra_vlc_format = (buffer[3] >> 3) & 1;
140 alternate_scan = (buffer[3] >> 2) & 1;
141 repeat_first_field = (buffer[3] >> 1) & 1;
142 progressive_frame = buffer[4] >> 7;
143
144 //get infos
145 probe_info->ext_attributes[2] = progressive_frame;
146 probe_info->ext_attributes[3] = alternate_scan;
147
148 if(top_field_first == 1 && repeat_first_field == 0) return(1);
149
150 return(0);
151 }
152
unit_summary(void)153 static void unit_summary(void)
154 {
155 int n;
156
157 int pes_total=0;
158
159 tc_log_msg(__FILE__, "------------- presentation unit [%d] ---------------", unit_ctr);
160
161 for(n=0; n<256; ++n) {
162 if(stream[n] && n != 0xba)
163 tc_log_msg(__FILE__, "stream id [0x%x] %6d", n, stream[n]);
164
165 if(n != 0xba) pes_total+=stream[n];
166 stream[n]=0; //reset or next unit
167 }
168
169 tc_log_msg(__FILE__, "%d packetized elementary stream(s) PES packets found", pes_total);
170
171 tc_log_msg(__FILE__, "presentation unit PU [%d] contains %d MPEG video sequence(s)", unit_ctr, seq_ctr);
172 if (seq_ctr) {
173 tc_log_msg(__FILE__, "Average Bitrate is %u. Min Bitrate is %u, max is %u (%s)",
174 ((tot_bitrate*400)/1000)/seq_ctr, min_bitrate*400/1000, max_bitrate*400/1000,
175 (max_bitrate==min_bitrate)?"CBR":"VBR");
176 }
177
178 ++tot_unit_ctr;
179 tot_seq_ctr+=seq_ctr;
180
181 tc_log_msg(__FILE__, "---------------------------------------------------");
182
183 //reset counters
184 seq_ctr=0;
185 show_seq_info=0;
186
187 fflush(stdout);
188 }
189
190 static int mpeg1_skip_table[16] = {
191 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
192 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
193 };
194
195 /*------------------------------------------------------------------
196 *
197 * full source scan mode:
198 *
199 *------------------------------------------------------------------*/
200
201 /*
202 * helper. Ok, that's no much more than a crude movement from
203 * probe_stream. Isn't really a big leap forward. Yet.
204 */
adjust_info(info_t * ipipe)205 static void adjust_info(info_t *ipipe)
206 {
207 switch(ipipe->magic) {
208 case TC_MAGIC_CDXA:
209 ipipe->probe_info->attributes |= TC_INFO_NO_DEMUX;
210 break;
211
212 case TC_MAGIC_MPEG_PS: /* MPEG Program Stream */
213 case TC_MAGIC_VOB: /* backward compatibility fallback */
214 /* NTSC video/film check */
215 if (verbose >= TC_DEBUG) {
216 tc_log_msg(__FILE__, "att0=%d, att1=%d",
217 ipipe->probe_info->ext_attributes[0],
218 ipipe->probe_info->ext_attributes[1]);
219 }
220 if (ipipe->probe_info->codec == TC_CODEC_MPEG2
221 && ipipe->probe_info->height == 480
222 && ipipe->probe_info->width == 720) {
223 if (ipipe->probe_info->ext_attributes[0] > 2 * ipipe->probe_info->ext_attributes[1]
224 || ipipe->probe_info->ext_attributes[1] == 0) {
225 ipipe->probe_info->is_video = 1;
226 }
227
228 if (ipipe->probe_info->is_video) {
229 ipipe->probe_info->fps = NTSC_VIDEO;
230 ipipe->probe_info->frc = 4;
231 } else {
232 ipipe->probe_info->fps = NTSC_FILM;
233 ipipe->probe_info->frc = 1;
234 }
235 }
236
237 if (ipipe->probe_info->codec == TC_CODEC_MPEG1) {
238 ipipe->probe_info->magic = TC_MAGIC_MPEG_PS;
239 }
240
241 /*
242 * check for need of special import module,
243 * that does not rely on 2k packs
244 */
245 if (ipipe->probe_info->attributes & TC_INFO_NO_DEMUX) {
246 ipipe->probe_info->codec = TC_CODEC_MPEG;
247 ipipe->probe_info->magic = TC_MAGIC_MPEG_PS; /* XXX: doubtful */
248 }
249 break;
250
251 case TC_MAGIC_MPEG_ES: /* MPEG Elementary Stream */
252 case TC_MAGIC_M2V: /* backward compatibility fallback */
253 /* make sure not to use the demuxer */
254 ipipe->probe_info->codec = TC_CODEC_MPEG;
255 ipipe->probe_info->magic = TC_MAGIC_MPEG_ES;
256 break;
257
258 case TC_MAGIC_MPEG_PES:/* MPEG Packetized Elementary Stream */
259 case TC_MAGIC_MPEG: /* backward compatibility fallback */
260 ipipe->probe_info->attributes |= TC_INFO_NO_DEMUX;
261 break;
262 }
263 return;
264 }
265
266
267
268
scan_pes(int verbose,FILE * in_file)269 void scan_pes(int verbose, FILE *in_file)
270 {
271 int n, has_pts_dts=0;
272 unsigned long i_pts, i_dts;
273
274 uint8_t * buf;
275 uint8_t * end;
276 uint8_t * tmp1=NULL;
277 uint8_t * tmp2=NULL;
278 int complain_loudly;
279
280 long int pack_header_last=0, pack_header_ctr=0, pack_header_pos=0, pack_header_inc=0;
281
282 char scan_buf[256];
283
284 complain_loudly = 1;
285 buf = buffer;
286
287 for(n=0; n<256; ++n) stream[n]=0;
288
289 do {
290 end = buf + fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file);
291 buf = buffer;
292
293 //scan buffer
294 while (buf + 4 <= end) {
295
296 // check for valid start code
297 if (buf[0] || buf[1] || (buf[2] != 0x01)) {
298 if (complain_loudly) {
299
300 tc_log_warn(__FILE__, "missing start code at %#lx",
301 ftell (in_file) - (end - buf));
302 if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0))
303 tc_log_warn(__FILE__, "incorrect zero-byte padding detected - ignored");
304
305 complain_loudly = 0;
306 }
307 buf++;
308 continue;
309 }// check for valid start code
310
311
312 id = buf[3] & 0xff;
313
314
315 switch (buf[3]) {
316
317 case 0xb9: /* program end code */
318
319 tc_log_msg(__FILE__, "found program end code [0x%x]", buf[3] & 0xff);
320
321 goto summary;
322
323 case 0xba: /* pack header */
324
325 pack_header_pos = ftell (in_file) - (end - buf);
326 pack_header_inc = pack_header_pos - pack_header_last;
327
328 if (pack_header_inc==0) {
329 tc_log_msg(__FILE__, "found first packet header at stream offset 0x%#x", 0);
330 } else {
331 if((pack_header_inc-((pack_header_inc>>11)<<11)))
332 tc_log_msg(__FILE__, "pack header out of sequence at %#lx (+%#lx)", pack_header_ctr, pack_header_inc);
333 }
334
335 pack_header_last=pack_header_pos;
336 ++pack_header_ctr;
337 ++stream[id];
338
339 /* skip */
340 if ((buf[4] & 0xc0) == 0x40) /* mpeg2 */
341 tmp1 = buf + 14 + (buf[13] & 7);
342 else if ((buf[4] & 0xf0) == 0x20) /* mpeg1 */
343 tmp1 = buf + 12;
344 else if (buf + 5 > end)
345 goto copy;
346 else {
347 tc_log_error(__FILE__, "weird pack header");
348 import_exit(1);
349 }
350
351 if (tmp1 > end)
352 goto copy;
353 buf = tmp1;
354 break;
355
356
357 case 0xbd: /* private stream 1 */
358
359 if(!stream[id]) tc_log_msg(__FILE__, "found %s stream [0x%x]", "private_stream_1", buf[3] & 0xff);
360
361 ++stream[id];
362
363 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
364 if (tmp2 > end)
365 goto copy;
366 if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */
367 tmp1 = buf + 9 + buf[8];
368 else { /* mpeg1 */
369 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
370 if (tmp1 == buf + 6 + 16) {
371 tc_log_warn(__FILE__, "too much stuffing");
372 buf = tmp2;
373 break;
374 }
375 if ((*tmp1 & 0xc0) == 0x40)
376 tmp1 += 2;
377 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
378 }
379
380 if(verbose & TC_DEBUG)
381 tc_log_msg(__FILE__, "[0x%x] (sub_id=0x%02x)", buf[3] & 0xff, *tmp1);
382
383 if((*tmp1-0x80) >= 0 && (*tmp1-0x80)<TC_MAX_AUD_TRACKS && !track[*tmp1-0x80] ) {
384 tc_log_msg(__FILE__, "found AC3 audio track %d [0x%x]", *tmp1-0x80, *tmp1);
385 track[*tmp1-0x80]=1;
386 } else if (*tmp1 == 0xFF && memcmp(tmp1+4,"SShd",4) == 0) {
387 tc_log_msg(__FILE__, "found VAG audio track [0x%x]", *tmp1);
388 track[0]=1;
389 }
390
391 buf = tmp2;
392
393 break;
394
395 case 0xbf:
396
397 if(!stream[id])
398 tc_log_msg(__FILE__, "found %s [0x%x]", "navigation pack", buf[3] & 0xff);
399
400 ++stream[id];
401
402 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
403 if (tmp2 > end)
404 goto copy;
405
406 buf = tmp2;
407
408 break;
409
410 case 0xbe:
411
412 if(!stream[id])
413 tc_log_msg(__FILE__, "found %s stream [0x%x]", "padding", buf[3] & 0xff);
414
415 ++stream[id];
416
417 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
418 if (tmp2 > end)
419 goto copy;
420
421 buf = tmp2;
422
423 break;
424
425 case 0xbb:
426
427 if(!stream[id])
428 tc_log_msg(__FILE__, "found %s stream [0x%x]", "unknown", buf[3] & 0xff);
429
430 ++stream[id];
431
432 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
433 if (tmp2 > end)
434 goto copy;
435
436 buf = tmp2;
437
438 break;
439
440
441 //MPEG audio, maybe more???
442
443 case 0xc0:
444 case 0xc1:
445 case 0xc2:
446 case 0xc3:
447 case 0xc4:
448 case 0xc5:
449 case 0xc6:
450 case 0xc7:
451 case 0xc8:
452 case 0xc9:
453 case 0xca:
454 case 0xcb:
455 case 0xcc:
456 case 0xcd:
457 case 0xce:
458 case 0xcf:
459 case 0xd0:
460 case 0xd1:
461 case 0xd2:
462 case 0xd3:
463 case 0xd4:
464 case 0xd5:
465 case 0xd6:
466 case 0xd7:
467 case 0xd8:
468 case 0xd9:
469 case 0xda:
470 case 0xdb:
471 case 0xdc:
472 case 0xdd:
473 case 0xde:
474 case 0xdf:
475
476 if(!stream[id])
477 tc_log_msg(__FILE__, "found %s track %d [0x%x]", "ISO/IEC 13818-3 or 11172-3 MPEG audio", (buf[3] & 0xff) - 0xc0, buf[3] & 0xff);
478
479 ++stream[id];
480
481 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
482 if (tmp2 > end)
483 goto copy;
484 if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */
485 tmp1 = buf + 9 + buf[8];
486 else { /* mpeg1 */
487 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
488 if (tmp1 == buf + 6 + 16) {
489 tc_log_warn(__FILE__, "too much stuffing");
490 buf = tmp2;
491 break;
492 }
493 if ((*tmp1 & 0xc0) == 0x40)
494 tmp1 += 2;
495 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
496 }
497
498 buf = tmp2;
499
500 break;
501
502 case 0xe0: /* video */
503 case 0xe1: /* video */
504 case 0xe2: /* video */
505 case 0xe3: /* video */
506 case 0xe4: /* video */
507 case 0xe5: /* video */
508 case 0xe6: /* video */
509 case 0xe7: /* video */
510 case 0xe8: /* video */
511 case 0xe9: /* video */
512
513 id = buf[3] & 0xff;
514
515 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
516 if (tmp2 > end)
517 goto copy;
518 if ((buf[6] & 0xc0) == 0x80) {
519 /* mpeg2 */
520 tmp1 = buf + 9 + buf[8];
521
522 if(!stream[id])
523 tc_log_msg(__FILE__, "found %s stream [0x%x]", "ISO/IEC 13818-2 or 11172-2 MPEG video", buf[3] & 0xff);
524 ++stream[id];
525
526 mpeg_version=2;
527
528 // get pts time stamp:
529 ac_memcpy(scan_buf, &buf[6], 16);
530 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
531
532 if(has_pts_dts) {
533
534 if(!show_seq_info) {
535 for(n=0; n<100; ++n) {
536
537 if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) {
538 stats_sequence(buf+n+4, &si);
539 show_seq_info=1;
540 break;
541 }
542 }
543 }
544 for(n=0; n<100; ++n) {
545 if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) {
546 stats_sequence_silent(buf+n+4, &si);
547 if (si.brv>max_bitrate) max_bitrate=si.brv;
548 if (si.brv<min_bitrate) min_bitrate=si.brv;
549 tot_bitrate += si.brv;
550 break;
551 }
552 }
553
554 if( ref_pts != 0 && i_pts < ref_pts) {
555
556 unit_summary();
557 unit_ctr++;
558 }
559 ref_pts=i_pts;
560 ++seq_ctr;
561 }
562
563 } else {
564 /* mpeg1 */
565
566 if(!stream[id])
567 tc_log_msg(__FILE__, "found %s stream [0x%x]", "MPEG-1 video", buf[3] & 0xff);
568 ++stream[id];
569
570 mpeg_version=1;
571
572 if(!show_seq_info) {
573 for(n=0; n<100; ++n) {
574
575 if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) {
576 stats_sequence(buf+n+4, &si);
577 show_seq_info=1;
578 }
579 }
580 }
581
582 // get pts time stamp:
583 ac_memcpy(scan_buf, &buf[6], 16);
584 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
585
586 if(has_pts_dts) {
587
588 if( ref_pts != 0 && i_pts < ref_pts) {
589
590 //unit_summary();
591 unit_ctr++;
592 }
593 ref_pts=i_pts;
594
595 ++seq_ctr;
596 }
597
598 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
599 if (tmp1 == buf + 6 + 16) {
600 tc_log_warn(__FILE__, "too much stuffing");
601 buf = tmp2;
602 break;
603 }
604 if ((*tmp1 & 0xc0) == 0x40)
605 tmp1 += 2;
606 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
607 }
608
609 buf = tmp2;
610 break;
611
612
613 case 0xb3:
614
615 tc_log_msg(__FILE__, "found MPEG sequence start code [0x%x]", buf[3] & 0xff);
616 tc_log_warn(__FILE__, "looks like an elementary stream - not program stream");
617
618 stats_sequence(&buf[4], &si);
619
620 return;
621
622 break;
623
624
625 default:
626 if (buf[3] < 0xb9) {
627 tc_log_warn(__FILE__, "looks like an elementary stream - not program stream");
628
629 return;
630 }
631
632 /* skip */
633 tmp1 = buf + 6 + (buf[4] << 8) + buf[5];
634 if (tmp1 > end)
635 goto copy;
636 buf = tmp1;
637 break;
638
639 } //start code selection
640 } //scan buffer
641
642 if (buf < end) {
643 copy:
644 /* we only pass here for mpeg1 ps streams */
645 memmove (buffer, buf, end - buf);
646 }
647 buf = buffer + (end - buf);
648
649 } while (end == buffer + BUFFER_SIZE);
650
651 tc_log_msg(__FILE__, "end of stream reached");
652
653 summary:
654
655 unit_summary();
656
657 tc_log_msg(__FILE__, "(%s) detected a total of %d presentation unit(s) PU and %d sequence(s)", __FILE__, tot_unit_ctr, tot_seq_ctr);
658
659 }
660
661 /*------------------------------------------------------------------
662 *
663 * probe only mode:
664 *
665 *------------------------------------------------------------------*/
666
667
probe_pes(info_t * ipipe)668 void probe_pes(info_t *ipipe)
669 {
670
671 int n, num, has_pts_dts=0;
672 int aid, ret, initial_sync=0, has_audio=0;
673
674 unsigned long i_pts, i_dts;
675 long probe_bytes=0, total_bytes=0;
676
677 uint8_t * buf;
678 uint8_t * end;
679 uint8_t * tmp1=NULL;
680 uint8_t * tmp2=NULL;
681
682 long pack_pts_1=0, pack_pts_2=0, pack_pts_3=0;
683
684 long int pack_header_last=0, pack_header_ctr=0, pack_header_pos=0, pack_header_inc=0;
685
686 char scan_buf[256];
687
688 double pack_ppp=0;
689
690 FILE *in_file = fdopen(ipipe->fd_in, "r");
691
692 buf = buffer;
693
694 for(n=0; n<256; ++n) stream[n]=unit_pack_cnt[n]=0;
695
696 do {
697
698 probe_bytes = fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file);
699
700 if(probe_bytes<0) {
701 ipipe->error=1;
702 return;
703 }
704
705 total_bytes += probe_bytes;
706
707 //limit amount of search stream bytes
708 if(total_bytes > TC_MAX_SEEK_BYTES * ipipe->factor) return;
709
710 end = buf + probe_bytes;
711 buf = buffer;
712
713 //scan buffer
714 while (buf + 4 <= end) {
715
716 // check for valid start code
717 if (buf[0] || buf[1] || (buf[2] != 0x01)) {
718
719 if (ipipe->verbose & TC_DEBUG) {
720 tc_log_warn(__FILE__, "missing start code at %#lx",
721 ftell (in_file) - (end - buf));
722 if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0))
723 tc_log_warn(__FILE__, "incorrect zero-byte padding detected - ignored");
724 }
725 ipipe->probe_info->attributes=TC_INFO_NO_DEMUX;
726 buf++;
727 continue;
728 }// check for valid start code
729
730 id = buf[3] & 0xff;
731
732 switch (buf[3]) {
733
734 //------------------------------
735 //
736 // packet header start/end code
737 //
738 //------------------------------
739
740 case 0xb9: /* program end code */
741 return;
742 break;
743
744 case 0xba: /* pack header */
745
746 pack_header_pos = ftell (in_file) - (end - buf);
747 pack_header_inc = pack_header_pos - pack_header_last;
748
749 if((pack_header_inc-((pack_header_inc>>11)<<11)))
750 ipipe->probe_info->attributes=TC_INFO_NO_DEMUX|TC_INFO_MPEG_PS;
751
752 pack_header_last=pack_header_pos;
753
754 ++pack_header_ctr;
755 ++stream[id];
756
757 /* skip */
758 if ((buf[4] & 0xc0) == 0x40) { /* mpeg2 */
759 tmp1 = buf + 14 + (buf[13] & 7);
760 ipipe->probe_info->codec=TC_CODEC_MPEG2;
761 } else if ((buf[4] & 0xf0) == 0x20) { /* mpeg1 */
762 tmp1 = buf + 12;
763 ipipe->probe_info->codec=TC_CODEC_MPEG1;
764 } else if (buf + 5 > end)
765 goto copy;
766 else {
767 tc_log_error(__FILE__, "weird pack header");
768 import_exit(1);
769 }
770
771 // get PPP - starts
772
773 ac_memcpy(scan_buf, &buf[4], 16);
774 pack_pts_2 = read_time_stamp_long(scan_buf);
775 pack_ppp = read_time_stamp(scan_buf);
776
777 if(pack_pts_2 == pack_pts_1)
778 if(ipipe->verbose & TC_DEBUG)
779 tc_log_msg(__FILE__, "SCR=%8ld (%8ld) unit=%d @ offset %10.4f (sec)", pack_pts_2, pack_pts_1, ipipe->probe_info->unit_cnt, pack_pts_1/90000.0);
780
781 if(pack_pts_2 < pack_pts_1) {
782
783 pack_pts_3 += pack_pts_1;
784
785 if(ipipe->verbose & TC_DEBUG)
786 tc_log_msg(__FILE__, "SCR=%8ld (%8ld) unit=%d @ offset %10.4f (sec)", pack_pts_2, pack_pts_1, ipipe->probe_info->unit_cnt+1, pack_pts_3/90000.0);
787
788 ++unit_pack_cnt_index;
789
790 //reset all video/audio information at this point - start
791
792 memset(ipipe->probe_info, 0, sizeof(ProbeInfo));
793 for(n=0; n<256; ++n) stream[n]=0;
794 for(n=0; n<TC_MAX_AUD_TRACKS; ++n) track[n]=attr[n]=0;
795 show_seq_info=0;
796 //reset - ends
797
798 ipipe->probe_info->unit_cnt=unit_pack_cnt_index;
799 }
800
801 ++unit_pack_cnt[unit_pack_cnt_index];
802 pack_pts_1 = pack_pts_2;
803
804 // get PPP - ends
805
806 if (tmp1 > end)
807 goto copy;
808 buf = tmp1;
809
810 break;
811
812 //------------------------
813 //
814 // MPEG video
815 //
816 //------------------------
817
818 case 0xe0: /* video */
819 case 0xe1: /* video */
820 case 0xe2: /* video */
821 case 0xe3: /* video */
822 case 0xe4: /* video */
823 case 0xe5: /* video */
824 case 0xe6: /* video */
825 case 0xe7: /* video */
826 case 0xe8: /* video */
827 case 0xe9: /* video */
828
829 id = buf[3] & 0xff;
830
831 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
832 if (tmp2 > end)
833 goto copy;
834 if ((buf[6] & 0xc0) == 0x80) {
835 /* mpeg2 */
836 tmp1 = buf + 9 + buf[8];
837
838 ++stream[id];
839
840 mpeg_version=2;
841 ipipe->probe_info->codec=TC_CODEC_MPEG2;
842
843 // get pts time stamp:
844 ac_memcpy(scan_buf, &buf[6], 16);
845 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
846
847 if(has_pts_dts) {
848
849 /*
850 I have no idea why the has_audio==0 is there. It seems to
851 cause problems at least for:
852 http://lists.exit1.org/pipermail/transcode-devel/2003-October/000004.html
853 I'll remove it until someone complains -- tibit
854 */
855 #if 0
856 if(ipipe->probe_info->pts_start==0 || has_audio==0) {
857 #else
858 if(ipipe->probe_info->pts_start==0) {
859 #endif
860 ipipe->probe_info->pts_start=(double)i_pts/90000.0;
861 initial_sync=1;
862 }
863
864 if(!show_seq_info) {
865
866 for(n=0; n<128; ++n) {
867
868 if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) {
869 probe_sequence(buf+n+4, ipipe->probe_info);
870 show_seq_info=1;
871 }
872 }
873 } // probe sequence header
874 }
875
876
877 if(!show_ext_info) {
878
879 int ret_code=-1;
880 int bb=tmp2-tmp1;
881
882 if(bb<0 || bb>2048) bb=2048;
883
884 for(n=0; n<bb; ++n) {
885
886 if(cmp_32_bits(buf+n, TC_MAGIC_PICEXT)
887 && (buf[n+4]>>4)==8) {
888
889 ret_code = probe_extension(buf+n+4, ipipe->probe_info);
890
891 //ret_code
892 //-1 = invalid header
893 // 1 = (TFF=1,RFF=0)
894 // 0 else
895
896 if(ret_code==1) ++ipipe->probe_info->ext_attributes[0];
897 if(ret_code==0) ++ipipe->probe_info->ext_attributes[1];
898
899 }
900 } // probe extension header
901
902 ref_pts=i_pts;
903 ++seq_ctr;
904 }
905
906 } else {
907 /* mpeg1 */
908
909 ++stream[id];
910
911 mpeg_version=1;
912
913 //MPEG1 may have audio but no time stamps
914 initial_sync=1;
915 ipipe->probe_info->codec=TC_CODEC_MPEG1;
916
917 if(!show_seq_info) {
918 for(n=0; n<100; ++n) {
919
920 if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) {
921 probe_sequence(buf+n+4, ipipe->probe_info);
922 show_seq_info=1;
923 }
924 }
925 }
926
927 // get pts time stamp:
928 ac_memcpy(scan_buf, &buf[6], 16);
929 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
930
931 if(has_pts_dts) {
932
933 if( ref_pts != 0 && i_pts < ref_pts) unit_ctr++;
934
935 ref_pts=i_pts;
936
937 ++seq_ctr;
938
939 if(ipipe->probe_info->pts_start==0 || has_audio==0) {
940 ipipe->probe_info->pts_start=(double)i_pts/90000.0;
941 }
942
943 }
944
945 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
946 if (tmp1 == buf + 6 + 16) {
947 tc_log_warn(__FILE__, "too much stuffing");
948 buf = tmp2;
949 break;
950 }
951 if ((*tmp1 & 0xc0) == 0x40)
952 tmp1 += 2;
953 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
954 }
955
956 buf = tmp2;
957 break;
958
959
960 //----------------------------------
961 //
962 // private stream 1
963 //
964 //----------------------------------
965
966
967 case 0xbd:
968
969 ++stream[id];
970
971 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
972 if (tmp2 > end)
973 goto copy;
974 if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */
975 tmp1 = buf + 9 + buf[8];
976 else { /* mpeg1 */
977 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
978 if (tmp1 == buf + 6 + 16) {
979 tc_log_warn(__FILE__, "too much stuffing");
980 buf = tmp2;
981 break;
982 }
983 if ((*tmp1 & 0xc0) == 0x40)
984 tmp1 += 2;
985 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
986 }
987
988 aid = *tmp1;
989
990 //-------------
991 //
992 //subtitle
993 //
994 //-------------
995
996 if((aid >= 0x20) && (aid <= 0x3F)) {
997
998 num=aid-0x20;
999
1000 if(!(attr[num] & PACKAGE_SUBTITLE)) {
1001
1002 if(!track[num]) {
1003 ++ipipe->probe_info->num_tracks;
1004 track[num]=1;
1005 ipipe->probe_info->track[num].tid=num;
1006 }
1007
1008 if(!(ipipe->probe_info->track[num].attribute &
1009 PACKAGE_SUBTITLE)&& initial_sync) {
1010 ipipe->probe_info->track[num].attribute |= PACKAGE_SUBTITLE;
1011
1012 // get pts time stamp:
1013 ac_memcpy(scan_buf, &buf[6], 16);
1014 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1015 }
1016 }
1017 }
1018
1019 //-------------
1020 //
1021 //AC3 audio
1022 //
1023 //-------------
1024
1025 if(((aid >= 0x80 && aid <= 0x88)) || (aid>=0x90 && aid<=0x9f)) {
1026 num=aid-0x80;
1027
1028 if(!(attr[num] & PACKAGE_AUDIO_AC3) && initial_sync) {
1029
1030 if(!track[num]) {
1031 ++ipipe->probe_info->num_tracks;
1032 track[num]=1;
1033 ipipe->probe_info->track[num].tid=num;
1034 }
1035
1036 if(!(ipipe->probe_info->track[num].attribute &
1037 PACKAGE_AUDIO_AC3)) {
1038
1039 tmp1 +=4;
1040
1041 //need to scan payload for more AC3 audio info
1042 ret = buf_probe_ac3(tmp1, tmp2-tmp1, &ipipe->probe_info->track[num]);
1043 if(ret==0) {
1044 ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_AC3;
1045 ac_memcpy(scan_buf, &buf[6], 16);
1046 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1047 ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.;
1048 has_audio=1;
1049 }
1050 }
1051 }
1052 }
1053
1054 //-------------
1055 //
1056 // DTS audio
1057 //
1058 //-------------
1059
1060 if((aid >= 0x89) && (aid <= 0x8f)) {
1061 num=aid-0x80;
1062
1063 if(!(attr[num] & PACKAGE_AUDIO_DTS) && initial_sync) {
1064
1065 if(!track[num]) {
1066 ++ipipe->probe_info->num_tracks;
1067 track[num]=1;
1068 ipipe->probe_info->track[num].tid=num;
1069 }
1070
1071 if(!(ipipe->probe_info->track[num].attribute &
1072 PACKAGE_AUDIO_DTS)) {
1073
1074 tmp1+=4;
1075
1076 //need to scan payload for more DTS audio info
1077 ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_DTS;
1078 buf_probe_dts(tmp1, tmp2-tmp1, &ipipe->probe_info->track[num]);
1079
1080 ac_memcpy(scan_buf, &buf[6], 16);
1081 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1082 ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.;
1083 has_audio=1;
1084 }
1085 }
1086 }
1087 //-------------
1088 //
1089 //AC3 audio
1090 //
1091 //-------------
1092
1093 if((aid >= 0x80) && (aid <= 0x88)) {
1094 num=aid-0x80;
1095
1096 if(!(attr[num] & PACKAGE_AUDIO_AC3) && initial_sync) {
1097
1098 if(!track[num]) {
1099 ++ipipe->probe_info->num_tracks;
1100 track[num]=1;
1101 ipipe->probe_info->track[num].tid=num;
1102 }
1103
1104 if(!(ipipe->probe_info->track[num].attribute &
1105 PACKAGE_AUDIO_AC3)) {
1106
1107 tmp1 +=4;
1108
1109 //need to scan payload for more AC3 audio info
1110 ret = buf_probe_ac3(tmp1, tmp2-tmp1, &ipipe->probe_info->track[num]);
1111 if(ret==0) {
1112 ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_AC3;
1113 ac_memcpy(scan_buf, &buf[6], 16);
1114 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1115 ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.;
1116 has_audio=1;
1117 }
1118 }
1119 }
1120 }
1121
1122 //-------------
1123 //
1124 //LPCM audio
1125 //
1126 //-------------
1127
1128 if((aid >= 0xA0) && (aid <= 0xBF)) {
1129 num=aid-0xA0;
1130
1131 if(!(attr[num] & PACKAGE_AUDIO_PCM) && initial_sync) {
1132
1133 if(!track[num]) {
1134 ++ipipe->probe_info->num_tracks;
1135 track[num]=1;
1136 ipipe->probe_info->track[num].tid=num;
1137 }
1138
1139 if(!(ipipe->probe_info->track[num].attribute &
1140 PACKAGE_AUDIO_PCM)) {
1141
1142 tmp1 += 4;
1143
1144 ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_PCM;
1145
1146 switch ((tmp1[1] >> 4) & 3) {
1147 case 0: ipipe->probe_info->track[num].samplerate = 48000;
1148 break;
1149 case 1: ipipe->probe_info->track[num].samplerate = 96000;
1150 break;
1151 case 2: ipipe->probe_info->track[num].samplerate = 44100;
1152 break;
1153 case 3: ipipe->probe_info->track[num].samplerate = 32000;
1154 break;
1155 }
1156 switch ((tmp1[1] >> 6) & 3) {
1157 case 0: ipipe->probe_info->track[num].bits = 16;
1158 break;
1159 case 1: ipipe->probe_info->track[num].bits = 20;
1160 break;
1161 case 2: ipipe->probe_info->track[num].bits = 24;
1162 break;
1163 default: tc_log_error(__FILE__, "unknown LPCM quantization");
1164 import_exit (1);
1165 }
1166 ipipe->probe_info->track[num].chan = 1 + (tmp1[1] & 7);
1167 ipipe->probe_info->track[num].bitrate
1168 = ipipe->probe_info->track[num].samplerate
1169 * ipipe->probe_info->track[num].bits
1170 * ipipe->probe_info->track[num].chan / 1000;
1171 ipipe->probe_info->track[num].format=CODEC_LPCM;
1172
1173 ac_memcpy(scan_buf, &buf[6], 16);
1174 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1175 ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.;
1176 has_audio=1;
1177 //ipipe->probe_info->track[num].pts_start=pack_ppp;
1178 }
1179 }
1180 }
1181
1182 //-------------
1183 //
1184 //VAG audio
1185 //
1186 //-------------
1187
1188 if(aid == 0xFF && memcmp(tmp1+4,"SShd",4) == 0) {
1189 num=0;
1190
1191 if(!(attr[num] & PACKAGE_AUDIO_VAG) && initial_sync) {
1192
1193 if(!track[num]) {
1194 ++ipipe->probe_info->num_tracks;
1195 track[num]=1;
1196 ipipe->probe_info->track[num].tid=num;
1197 }
1198
1199 if(!(ipipe->probe_info->track[num].attribute &
1200 PACKAGE_AUDIO_VAG)) {
1201
1202 tmp1 += 4; // skip MPEG data
1203 tmp1 += 4; // skip "SShd" header tag
1204 tmp1 += 4; // skip file (data+header) size (int32_le)
1205 ipipe->probe_info->track[num].bits = *tmp1;
1206 tmp1 += 4;
1207 ipipe->probe_info->track[num].samplerate = tmp1[0]|tmp1[1]<<8;
1208 tmp1 += 4;
1209 ipipe->probe_info->track[num].chan = *tmp1;
1210 tmp1 += 4;
1211 // next 4 bytes are stereo quantization size
1212 // next 8 bytes are unused?
1213 // next 8 bytes are data block header "SSbd" and int32_le size
1214
1215 ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_VAG;
1216 ipipe->probe_info->track[num].bitrate
1217 = ipipe->probe_info->track[num].samplerate
1218 * ipipe->probe_info->track[num].chan
1219 * 4 /* bits per sample, encoded */
1220 * 16 / 14 /* overhead ratio */
1221 / 1000;
1222 ipipe->probe_info->track[num].format = CODEC_VAG;
1223
1224 ac_memcpy(scan_buf, &buf[6], 16);
1225 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1226 ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.;
1227 has_audio=1;
1228 //ipipe->probe_info->track[num].pts_start=pack_ppp;
1229 }
1230 }
1231 }
1232
1233 buf = tmp2;
1234
1235 break;
1236
1237
1238 //------------------------
1239 //
1240 // MPEG audio
1241 //
1242 //------------------------
1243
1244 case 0xc0:
1245 case 0xc1:
1246 case 0xc2:
1247 case 0xc3:
1248 case 0xc4:
1249 case 0xc5:
1250 case 0xc6:
1251 case 0xc7:
1252 case 0xc8:
1253 case 0xc9:
1254 case 0xca:
1255 case 0xcb:
1256 case 0xcc:
1257 case 0xcd:
1258 case 0xce:
1259 case 0xcf:
1260 case 0xd0:
1261 case 0xd1:
1262 case 0xd2:
1263 case 0xd3:
1264 case 0xd4:
1265 case 0xd5:
1266 case 0xd6:
1267 case 0xd7:
1268 case 0xd8:
1269 case 0xd9:
1270 case 0xda:
1271 case 0xdb:
1272 case 0xdc:
1273 case 0xdd:
1274 case 0xde:
1275 case 0xdf:
1276
1277 ++stream[id];
1278
1279 tmp2 = buf + 6 + (buf[4] << 8) + buf[5];
1280 if (tmp2 > end)
1281 goto copy;
1282 if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */
1283 tmp1 = buf + 9 + buf[8];
1284 else { /* mpeg1 */
1285 for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++)
1286 if (tmp1 == buf + 6 + 16) {
1287 tc_log_warn(__FILE__, "too much stuffing");
1288 buf = tmp2;
1289 break;
1290 }
1291 if ((*tmp1 & 0xc0) == 0x40)
1292 tmp1 += 2;
1293 tmp1 += mpeg1_skip_table [*tmp1 >> 4];
1294 }
1295
1296 //add found track
1297 //need to scan payload for more MPEG audio info
1298
1299 num=(buf[3] & 0xff) - 0xc0;
1300
1301 if(num >= 0 && !track[num] && num<TC_MAX_AUD_TRACKS && initial_sync) {
1302
1303 ++ipipe->probe_info->num_tracks;
1304
1305 #ifdef HAVE_LAME
1306 //need to scan payload for more MPEG audio info
1307 if(end-buf>0) buf_probe_mp3(buf, end-buf, &ipipe->probe_info->track[num]);
1308 #else
1309 //all we know for now
1310 ipipe->probe_info->track[num].format=CODEC_MP3;
1311 ipipe->probe_info->track[num].tid=num;
1312 #endif
1313
1314 ac_memcpy(scan_buf, &buf[6], 16);
1315 has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts);
1316
1317 if(has_pts_dts) {
1318 ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.;
1319 track[num]=1;
1320 }
1321
1322 has_audio=1;
1323 }
1324
1325 buf = tmp2;
1326 break;
1327
1328 case 0xb3:
1329
1330 //MPEG video ES
1331 probe_sequence(&buf[4], ipipe->probe_info);
1332
1333 ipipe->probe_info->codec=TC_CODEC_MPEG;
1334 if ((buf[6] & 0xc0) == 0x80) ipipe->probe_info->codec=TC_CODEC_MPEG2;
1335
1336 return;
1337 break;
1338
1339 default:
1340 if (buf[3] < 0xb9) {
1341 tc_log_warn(__FILE__, "looks like an elementary stream - not program stream");
1342 ipipe->probe_info->codec=TC_CODEC_MPEG;
1343 if ((buf[6] & 0xc0) == 0x80) ipipe->probe_info->codec=TC_CODEC_MPEG2;
1344 return;
1345 }
1346
1347 /* skip */
1348
1349 tmp1 = buf + 6 + (buf[4] << 8) + buf[5];
1350 if (tmp1 > end)
1351 goto copy;
1352 buf = tmp1;
1353 break;
1354
1355 } //start code selection
1356 } //scan buffer
1357
1358 if (buf < end) {
1359 copy:
1360 /* we only pass here for mpeg1 ps streams */
1361 memmove (buffer, buf, end - buf);
1362 }
1363 buf = buffer + (end - buf);
1364
1365 } while (end == buffer + BUFFER_SIZE);
1366
1367 adjust_info(ipipe);
1368 return;
1369 }
1370