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