diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/scan_pes.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/scan_pes.c | 1369 |
1 files changed, 1369 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/scan_pes.c b/debian/transcode/transcode-1.1.7/import/scan_pes.c new file mode 100644 index 00000000..ed53b9c7 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/scan_pes.c @@ -0,0 +1,1369 @@ +/* + * scan_pes.c + * + * Copyright (C) Thomas Oestreich - June 2001 + * + * This file is part of transcode, a video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "transcode.h" +#include "tcinfo.h" +#include "ioaux.h" +#include "tc.h" +#include "aux_pes.h" +#include "mpg123.h" +#include "ac3scan.h" +#include "demuxer.h" +#include "libtc/libtc.h" +#include "libtc/ratiocodes.h" + +#define BUFFER_SIZE 262144 +static uint8_t buffer[BUFFER_SIZE]; + +static seq_info_t si; + +static int mpeg_version=0; + +static int unit_ctr=0, seq_ctr=0; + +static uint16_t id; + +static uint32_t stream[256], track[TC_MAX_AUD_TRACKS], attr[TC_MAX_AUD_TRACKS]; + +static int tot_seq_ctr=0, tot_unit_ctr=0; +static unsigned int tot_bitrate=0, min_bitrate=(unsigned int)-1, max_bitrate=0; + +//count packs for each presntation unit +static uint32_t unit_pack_cnt[256], unit_pack_cnt_index=0; + +static int ref_pts=0; + +static int show_seq_info=0, show_ext_info=0; + +static int cmp_32_bits(char *buf, long x) +{ + + if ((uint8_t)buf[0] != ((x >> 24) & 0xff)) + return 0; + if ((uint8_t)buf[1] != ((x >> 16) & 0xff)) + return 0; + if ((uint8_t)buf[2] != ((x >> 8) & 0xff)) + return 0; + if ((uint8_t)buf[3] != ((x ) & 0xff)) + return 0; + + // OK found it + return 1; +} + +static int probe_sequence(uint8_t *buffer, ProbeInfo *probe_info) +{ + + int horizontal_size; + int vertical_size; + int aspect_ratio_information; + int frame_rate_code; + int bit_rate_value; + int vbv_buffer_size_value; + int constrained_parameters_flag; + int load_intra_quantizer_matrix; + int load_non_intra_quantizer_matrix; + + vertical_size = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; + horizontal_size = ((vertical_size >> 12) + 15) & ~15; + vertical_size = ((vertical_size & 0xfff) + 15) & ~15; + + aspect_ratio_information = buffer[3] >> 4; + frame_rate_code = buffer[3] & 15; + bit_rate_value = (buffer[4] << 10) | (buffer[5] << 2) | (buffer[6] >> 6); + vbv_buffer_size_value = ((buffer[6] << 5) | (buffer[7] >> 3)) & 0x3ff; + constrained_parameters_flag = buffer[7] & 4; + load_intra_quantizer_matrix = buffer[7] & 2; + if (load_intra_quantizer_matrix) + buffer += 64; + load_non_intra_quantizer_matrix = buffer[7] & 1; + + //set some defaults, if invalid: + if(aspect_ratio_information < 0 || aspect_ratio_information>15) aspect_ratio_information=0; + + if(frame_rate_code < 0 || frame_rate_code>15) frame_rate_code=0; + + //fill out user structure + + probe_info->width = horizontal_size; + probe_info->height = vertical_size; + probe_info->asr = aspect_ratio_information; + probe_info->frc = frame_rate_code; + probe_info->bitrate = bit_rate_value * 400.0 / 1000.0; + tc_frc_code_to_value(frame_rate_code, &probe_info->fps); + + return(0); + +} + +static int probe_extension(uint8_t *buffer, ProbeInfo *probe_info) +{ + + int intra_dc_precision; + int picture_structure; + int top_field_first; + int frame_pred_frame_dct; + int concealment_motion_vectors; + int q_scale_type; + int intra_vlc_format; + int alternate_scan; + int repeat_first_field; + int progressive_frame; + + intra_dc_precision = (buffer[2] >> 2) & 3; + picture_structure = buffer[2] & 3; + top_field_first = buffer[3] >> 7; + frame_pred_frame_dct = (buffer[3] >> 6) & 1; + concealment_motion_vectors = (buffer[3] >> 5) & 1; + q_scale_type = (buffer[3] >> 4) & 1; + intra_vlc_format = (buffer[3] >> 3) & 1; + alternate_scan = (buffer[3] >> 2) & 1; + repeat_first_field = (buffer[3] >> 1) & 1; + progressive_frame = buffer[4] >> 7; + + //get infos + probe_info->ext_attributes[2] = progressive_frame; + probe_info->ext_attributes[3] = alternate_scan; + + if(top_field_first == 1 && repeat_first_field == 0) return(1); + + return(0); +} + +static void unit_summary(void) +{ + int n; + + int pes_total=0; + + tc_log_msg(__FILE__, "------------- presentation unit [%d] ---------------", unit_ctr); + + for(n=0; n<256; ++n) { + if(stream[n] && n != 0xba) + tc_log_msg(__FILE__, "stream id [0x%x] %6d", n, stream[n]); + + if(n != 0xba) pes_total+=stream[n]; + stream[n]=0; //reset or next unit + } + + tc_log_msg(__FILE__, "%d packetized elementary stream(s) PES packets found", pes_total); + + tc_log_msg(__FILE__, "presentation unit PU [%d] contains %d MPEG video sequence(s)", unit_ctr, seq_ctr); + if (seq_ctr) { + tc_log_msg(__FILE__, "Average Bitrate is %u. Min Bitrate is %u, max is %u (%s)", + ((tot_bitrate*400)/1000)/seq_ctr, min_bitrate*400/1000, max_bitrate*400/1000, + (max_bitrate==min_bitrate)?"CBR":"VBR"); + } + + ++tot_unit_ctr; + tot_seq_ctr+=seq_ctr; + + tc_log_msg(__FILE__, "---------------------------------------------------"); + + //reset counters + seq_ctr=0; + show_seq_info=0; + + fflush(stdout); +} + +static int mpeg1_skip_table[16] = { + 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +/*------------------------------------------------------------------ + * + * full source scan mode: + * + *------------------------------------------------------------------*/ + +/* + * helper. Ok, that's no much more than a crude movement from + * probe_stream. Isn't really a big leap forward. Yet. + */ +static void adjust_info(info_t *ipipe) +{ + switch(ipipe->magic) { + case TC_MAGIC_CDXA: + ipipe->probe_info->attributes |= TC_INFO_NO_DEMUX; + break; + + case TC_MAGIC_MPEG_PS: /* MPEG Program Stream */ + case TC_MAGIC_VOB: /* backward compatibility fallback */ + /* NTSC video/film check */ + if (verbose >= TC_DEBUG) { + tc_log_msg(__FILE__, "att0=%d, att1=%d", + ipipe->probe_info->ext_attributes[0], + ipipe->probe_info->ext_attributes[1]); + } + if (ipipe->probe_info->codec == TC_CODEC_MPEG2 + && ipipe->probe_info->height == 480 + && ipipe->probe_info->width == 720) { + if (ipipe->probe_info->ext_attributes[0] > 2 * ipipe->probe_info->ext_attributes[1] + || ipipe->probe_info->ext_attributes[1] == 0) { + ipipe->probe_info->is_video = 1; + } + + if (ipipe->probe_info->is_video) { + ipipe->probe_info->fps = NTSC_VIDEO; + ipipe->probe_info->frc = 4; + } else { + ipipe->probe_info->fps = NTSC_FILM; + ipipe->probe_info->frc = 1; + } + } + + if (ipipe->probe_info->codec == TC_CODEC_MPEG1) { + ipipe->probe_info->magic = TC_MAGIC_MPEG_PS; + } + + /* + * check for need of special import module, + * that does not rely on 2k packs + */ + if (ipipe->probe_info->attributes & TC_INFO_NO_DEMUX) { + ipipe->probe_info->codec = TC_CODEC_MPEG; + ipipe->probe_info->magic = TC_MAGIC_MPEG_PS; /* XXX: doubtful */ + } + break; + + case TC_MAGIC_MPEG_ES: /* MPEG Elementary Stream */ + case TC_MAGIC_M2V: /* backward compatibility fallback */ + /* make sure not to use the demuxer */ + ipipe->probe_info->codec = TC_CODEC_MPEG; + ipipe->probe_info->magic = TC_MAGIC_MPEG_ES; + break; + + case TC_MAGIC_MPEG_PES:/* MPEG Packetized Elementary Stream */ + case TC_MAGIC_MPEG: /* backward compatibility fallback */ + ipipe->probe_info->attributes |= TC_INFO_NO_DEMUX; + break; + } + return; +} + + + + +void scan_pes(int verbose, FILE *in_file) +{ + int n, has_pts_dts=0; + unsigned long i_pts, i_dts; + + uint8_t * buf; + uint8_t * end; + uint8_t * tmp1=NULL; + uint8_t * tmp2=NULL; + int complain_loudly; + + long int pack_header_last=0, pack_header_ctr=0, pack_header_pos=0, pack_header_inc=0; + + char scan_buf[256]; + + complain_loudly = 1; + buf = buffer; + + for(n=0; n<256; ++n) stream[n]=0; + + do { + end = buf + fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file); + buf = buffer; + + //scan buffer + while (buf + 4 <= end) { + + // check for valid start code + if (buf[0] || buf[1] || (buf[2] != 0x01)) { + if (complain_loudly) { + + tc_log_warn(__FILE__, "missing start code at %#lx", + ftell (in_file) - (end - buf)); + if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0)) + tc_log_warn(__FILE__, "incorrect zero-byte padding detected - ignored"); + + complain_loudly = 0; + } + buf++; + continue; + }// check for valid start code + + + id = buf[3] & 0xff; + + + switch (buf[3]) { + + case 0xb9: /* program end code */ + + tc_log_msg(__FILE__, "found program end code [0x%x]", buf[3] & 0xff); + + goto summary; + + case 0xba: /* pack header */ + + pack_header_pos = ftell (in_file) - (end - buf); + pack_header_inc = pack_header_pos - pack_header_last; + + if (pack_header_inc==0) { + tc_log_msg(__FILE__, "found first packet header at stream offset 0x%#x", 0); + } else { + if((pack_header_inc-((pack_header_inc>>11)<<11))) + tc_log_msg(__FILE__, "pack header out of sequence at %#lx (+%#lx)", pack_header_ctr, pack_header_inc); + } + + pack_header_last=pack_header_pos; + ++pack_header_ctr; + ++stream[id]; + + /* skip */ + if ((buf[4] & 0xc0) == 0x40) /* mpeg2 */ + tmp1 = buf + 14 + (buf[13] & 7); + else if ((buf[4] & 0xf0) == 0x20) /* mpeg1 */ + tmp1 = buf + 12; + else if (buf + 5 > end) + goto copy; + else { + tc_log_error(__FILE__, "weird pack header"); + import_exit(1); + } + + if (tmp1 > end) + goto copy; + buf = tmp1; + break; + + + case 0xbd: /* private stream 1 */ + + if(!stream[id]) tc_log_msg(__FILE__, "found %s stream [0x%x]", "private_stream_1", buf[3] & 0xff); + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + else { /* mpeg1 */ + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + if(verbose & TC_DEBUG) + tc_log_msg(__FILE__, "[0x%x] (sub_id=0x%02x)", buf[3] & 0xff, *tmp1); + + if((*tmp1-0x80) >= 0 && (*tmp1-0x80)<TC_MAX_AUD_TRACKS && !track[*tmp1-0x80] ) { + tc_log_msg(__FILE__, "found AC3 audio track %d [0x%x]", *tmp1-0x80, *tmp1); + track[*tmp1-0x80]=1; + } else if (*tmp1 == 0xFF && memcmp(tmp1+4,"SShd",4) == 0) { + tc_log_msg(__FILE__, "found VAG audio track [0x%x]", *tmp1); + track[0]=1; + } + + buf = tmp2; + + break; + + case 0xbf: + + if(!stream[id]) + tc_log_msg(__FILE__, "found %s [0x%x]", "navigation pack", buf[3] & 0xff); + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + + buf = tmp2; + + break; + + case 0xbe: + + if(!stream[id]) + tc_log_msg(__FILE__, "found %s stream [0x%x]", "padding", buf[3] & 0xff); + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + + buf = tmp2; + + break; + + case 0xbb: + + if(!stream[id]) + tc_log_msg(__FILE__, "found %s stream [0x%x]", "unknown", buf[3] & 0xff); + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + + buf = tmp2; + + break; + + + //MPEG audio, maybe more??? + + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + + if(!stream[id]) + 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); + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + else { /* mpeg1 */ + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + buf = tmp2; + + break; + + case 0xe0: /* video */ + case 0xe1: /* video */ + case 0xe2: /* video */ + case 0xe3: /* video */ + case 0xe4: /* video */ + case 0xe5: /* video */ + case 0xe6: /* video */ + case 0xe7: /* video */ + case 0xe8: /* video */ + case 0xe9: /* video */ + + id = buf[3] & 0xff; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) { + /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + + if(!stream[id]) + tc_log_msg(__FILE__, "found %s stream [0x%x]", "ISO/IEC 13818-2 or 11172-2 MPEG video", buf[3] & 0xff); + ++stream[id]; + + mpeg_version=2; + + // get pts time stamp: + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + + if(has_pts_dts) { + + if(!show_seq_info) { + for(n=0; n<100; ++n) { + + if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) { + stats_sequence(buf+n+4, &si); + show_seq_info=1; + break; + } + } + } + for(n=0; n<100; ++n) { + if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) { + stats_sequence_silent(buf+n+4, &si); + if (si.brv>max_bitrate) max_bitrate=si.brv; + if (si.brv<min_bitrate) min_bitrate=si.brv; + tot_bitrate += si.brv; + break; + } + } + + if( ref_pts != 0 && i_pts < ref_pts) { + + unit_summary(); + unit_ctr++; + } + ref_pts=i_pts; + ++seq_ctr; + } + + } else { + /* mpeg1 */ + + if(!stream[id]) + tc_log_msg(__FILE__, "found %s stream [0x%x]", "MPEG-1 video", buf[3] & 0xff); + ++stream[id]; + + mpeg_version=1; + + if(!show_seq_info) { + for(n=0; n<100; ++n) { + + if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) { + stats_sequence(buf+n+4, &si); + show_seq_info=1; + } + } + } + + // get pts time stamp: + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + + if(has_pts_dts) { + + if( ref_pts != 0 && i_pts < ref_pts) { + + //unit_summary(); + unit_ctr++; + } + ref_pts=i_pts; + + ++seq_ctr; + } + + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + buf = tmp2; + break; + + + case 0xb3: + + tc_log_msg(__FILE__, "found MPEG sequence start code [0x%x]", buf[3] & 0xff); + tc_log_warn(__FILE__, "looks like an elementary stream - not program stream"); + + stats_sequence(&buf[4], &si); + + return; + + break; + + + default: + if (buf[3] < 0xb9) { + tc_log_warn(__FILE__, "looks like an elementary stream - not program stream"); + + return; + } + + /* skip */ + tmp1 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp1 > end) + goto copy; + buf = tmp1; + break; + + } //start code selection + } //scan buffer + + if (buf < end) { + copy: + /* we only pass here for mpeg1 ps streams */ + memmove (buffer, buf, end - buf); + } + buf = buffer + (end - buf); + + } while (end == buffer + BUFFER_SIZE); + + tc_log_msg(__FILE__, "end of stream reached"); + + summary: + + unit_summary(); + + 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); + +} + +/*------------------------------------------------------------------ + * + * probe only mode: + * + *------------------------------------------------------------------*/ + + +void probe_pes(info_t *ipipe) +{ + + int n, num, has_pts_dts=0; + int aid, ret, initial_sync=0, has_audio=0; + + unsigned long i_pts, i_dts; + long probe_bytes=0, total_bytes=0; + + uint8_t * buf; + uint8_t * end; + uint8_t * tmp1=NULL; + uint8_t * tmp2=NULL; + + long pack_pts_1=0, pack_pts_2=0, pack_pts_3=0; + + long int pack_header_last=0, pack_header_ctr=0, pack_header_pos=0, pack_header_inc=0; + + char scan_buf[256]; + + double pack_ppp=0; + + FILE *in_file = fdopen(ipipe->fd_in, "r"); + + buf = buffer; + + for(n=0; n<256; ++n) stream[n]=unit_pack_cnt[n]=0; + + do { + + probe_bytes = fread (buf, 1, buffer + BUFFER_SIZE - buf, in_file); + + if(probe_bytes<0) { + ipipe->error=1; + return; + } + + total_bytes += probe_bytes; + + //limit amount of search stream bytes + if(total_bytes > TC_MAX_SEEK_BYTES * ipipe->factor) return; + + end = buf + probe_bytes; + buf = buffer; + + //scan buffer + while (buf + 4 <= end) { + + // check for valid start code + if (buf[0] || buf[1] || (buf[2] != 0x01)) { + + if (ipipe->verbose & TC_DEBUG) { + tc_log_warn(__FILE__, "missing start code at %#lx", + ftell (in_file) - (end - buf)); + if ((buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0)) + tc_log_warn(__FILE__, "incorrect zero-byte padding detected - ignored"); + } + ipipe->probe_info->attributes=TC_INFO_NO_DEMUX; + buf++; + continue; + }// check for valid start code + + id = buf[3] & 0xff; + + switch (buf[3]) { + + //------------------------------ + // + // packet header start/end code + // + //------------------------------ + + case 0xb9: /* program end code */ + return; + break; + + case 0xba: /* pack header */ + + pack_header_pos = ftell (in_file) - (end - buf); + pack_header_inc = pack_header_pos - pack_header_last; + + if((pack_header_inc-((pack_header_inc>>11)<<11))) + ipipe->probe_info->attributes=TC_INFO_NO_DEMUX|TC_INFO_MPEG_PS; + + pack_header_last=pack_header_pos; + + ++pack_header_ctr; + ++stream[id]; + + /* skip */ + if ((buf[4] & 0xc0) == 0x40) { /* mpeg2 */ + tmp1 = buf + 14 + (buf[13] & 7); + ipipe->probe_info->codec=TC_CODEC_MPEG2; + } else if ((buf[4] & 0xf0) == 0x20) { /* mpeg1 */ + tmp1 = buf + 12; + ipipe->probe_info->codec=TC_CODEC_MPEG1; + } else if (buf + 5 > end) + goto copy; + else { + tc_log_error(__FILE__, "weird pack header"); + import_exit(1); + } + + // get PPP - starts + + ac_memcpy(scan_buf, &buf[4], 16); + pack_pts_2 = read_time_stamp_long(scan_buf); + pack_ppp = read_time_stamp(scan_buf); + + if(pack_pts_2 == pack_pts_1) + if(ipipe->verbose & TC_DEBUG) + 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); + + if(pack_pts_2 < pack_pts_1) { + + pack_pts_3 += pack_pts_1; + + if(ipipe->verbose & TC_DEBUG) + 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); + + ++unit_pack_cnt_index; + + //reset all video/audio information at this point - start + + memset(ipipe->probe_info, 0, sizeof(ProbeInfo)); + for(n=0; n<256; ++n) stream[n]=0; + for(n=0; n<TC_MAX_AUD_TRACKS; ++n) track[n]=attr[n]=0; + show_seq_info=0; + //reset - ends + + ipipe->probe_info->unit_cnt=unit_pack_cnt_index; + } + + ++unit_pack_cnt[unit_pack_cnt_index]; + pack_pts_1 = pack_pts_2; + + // get PPP - ends + + if (tmp1 > end) + goto copy; + buf = tmp1; + + break; + + //------------------------ + // + // MPEG video + // + //------------------------ + + case 0xe0: /* video */ + case 0xe1: /* video */ + case 0xe2: /* video */ + case 0xe3: /* video */ + case 0xe4: /* video */ + case 0xe5: /* video */ + case 0xe6: /* video */ + case 0xe7: /* video */ + case 0xe8: /* video */ + case 0xe9: /* video */ + + id = buf[3] & 0xff; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) { + /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + + ++stream[id]; + + mpeg_version=2; + ipipe->probe_info->codec=TC_CODEC_MPEG2; + + // get pts time stamp: + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + + if(has_pts_dts) { + + /* + I have no idea why the has_audio==0 is there. It seems to + cause problems at least for: + http://lists.exit1.org/pipermail/transcode-devel/2003-October/000004.html + I'll remove it until someone complains -- tibit + */ +#if 0 + if(ipipe->probe_info->pts_start==0 || has_audio==0) { +#else + if(ipipe->probe_info->pts_start==0) { +#endif + ipipe->probe_info->pts_start=(double)i_pts/90000.0; + initial_sync=1; + } + + if(!show_seq_info) { + + for(n=0; n<128; ++n) { + + if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) { + probe_sequence(buf+n+4, ipipe->probe_info); + show_seq_info=1; + } + } + } // probe sequence header + } + + + if(!show_ext_info) { + + int ret_code=-1; + int bb=tmp2-tmp1; + + if(bb<0 || bb>2048) bb=2048; + + for(n=0; n<bb; ++n) { + + if(cmp_32_bits(buf+n, TC_MAGIC_PICEXT) + && (buf[n+4]>>4)==8) { + + ret_code = probe_extension(buf+n+4, ipipe->probe_info); + + //ret_code + //-1 = invalid header + // 1 = (TFF=1,RFF=0) + // 0 else + + if(ret_code==1) ++ipipe->probe_info->ext_attributes[0]; + if(ret_code==0) ++ipipe->probe_info->ext_attributes[1]; + + } + } // probe extension header + + ref_pts=i_pts; + ++seq_ctr; + } + + } else { + /* mpeg1 */ + + ++stream[id]; + + mpeg_version=1; + + //MPEG1 may have audio but no time stamps + initial_sync=1; + ipipe->probe_info->codec=TC_CODEC_MPEG1; + + if(!show_seq_info) { + for(n=0; n<100; ++n) { + + if(cmp_32_bits(buf+n, TC_MAGIC_M2V)) { + probe_sequence(buf+n+4, ipipe->probe_info); + show_seq_info=1; + } + } + } + + // get pts time stamp: + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + + if(has_pts_dts) { + + if( ref_pts != 0 && i_pts < ref_pts) unit_ctr++; + + ref_pts=i_pts; + + ++seq_ctr; + + if(ipipe->probe_info->pts_start==0 || has_audio==0) { + ipipe->probe_info->pts_start=(double)i_pts/90000.0; + } + + } + + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + buf = tmp2; + break; + + + //---------------------------------- + // + // private stream 1 + // + //---------------------------------- + + + case 0xbd: + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + else { /* mpeg1 */ + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + aid = *tmp1; + + //------------- + // + //subtitle + // + //------------- + + if((aid >= 0x20) && (aid <= 0x3F)) { + + num=aid-0x20; + + if(!(attr[num] & PACKAGE_SUBTITLE)) { + + if(!track[num]) { + ++ipipe->probe_info->num_tracks; + track[num]=1; + ipipe->probe_info->track[num].tid=num; + } + + if(!(ipipe->probe_info->track[num].attribute & + PACKAGE_SUBTITLE)&& initial_sync) { + ipipe->probe_info->track[num].attribute |= PACKAGE_SUBTITLE; + + // get pts time stamp: + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + } + } + } + + //------------- + // + //AC3 audio + // + //------------- + + if(((aid >= 0x80 && aid <= 0x88)) || (aid>=0x90 && aid<=0x9f)) { + num=aid-0x80; + + if(!(attr[num] & PACKAGE_AUDIO_AC3) && initial_sync) { + + if(!track[num]) { + ++ipipe->probe_info->num_tracks; + track[num]=1; + ipipe->probe_info->track[num].tid=num; + } + + if(!(ipipe->probe_info->track[num].attribute & + PACKAGE_AUDIO_AC3)) { + + tmp1 +=4; + + //need to scan payload for more AC3 audio info + ret = buf_probe_ac3(tmp1, tmp2-tmp1, &ipipe->probe_info->track[num]); + if(ret==0) { + ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_AC3; + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.; + has_audio=1; + } + } + } + } + + //------------- + // + // DTS audio + // + //------------- + + if((aid >= 0x89) && (aid <= 0x8f)) { + num=aid-0x80; + + if(!(attr[num] & PACKAGE_AUDIO_DTS) && initial_sync) { + + if(!track[num]) { + ++ipipe->probe_info->num_tracks; + track[num]=1; + ipipe->probe_info->track[num].tid=num; + } + + if(!(ipipe->probe_info->track[num].attribute & + PACKAGE_AUDIO_DTS)) { + + tmp1+=4; + + //need to scan payload for more DTS audio info + ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_DTS; + buf_probe_dts(tmp1, tmp2-tmp1, &ipipe->probe_info->track[num]); + + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.; + has_audio=1; + } + } + } + //------------- + // + //AC3 audio + // + //------------- + + if((aid >= 0x80) && (aid <= 0x88)) { + num=aid-0x80; + + if(!(attr[num] & PACKAGE_AUDIO_AC3) && initial_sync) { + + if(!track[num]) { + ++ipipe->probe_info->num_tracks; + track[num]=1; + ipipe->probe_info->track[num].tid=num; + } + + if(!(ipipe->probe_info->track[num].attribute & + PACKAGE_AUDIO_AC3)) { + + tmp1 +=4; + + //need to scan payload for more AC3 audio info + ret = buf_probe_ac3(tmp1, tmp2-tmp1, &ipipe->probe_info->track[num]); + if(ret==0) { + ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_AC3; + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.; + has_audio=1; + } + } + } + } + + //------------- + // + //LPCM audio + // + //------------- + + if((aid >= 0xA0) && (aid <= 0xBF)) { + num=aid-0xA0; + + if(!(attr[num] & PACKAGE_AUDIO_PCM) && initial_sync) { + + if(!track[num]) { + ++ipipe->probe_info->num_tracks; + track[num]=1; + ipipe->probe_info->track[num].tid=num; + } + + if(!(ipipe->probe_info->track[num].attribute & + PACKAGE_AUDIO_PCM)) { + + tmp1 += 4; + + ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_PCM; + + switch ((tmp1[1] >> 4) & 3) { + case 0: ipipe->probe_info->track[num].samplerate = 48000; + break; + case 1: ipipe->probe_info->track[num].samplerate = 96000; + break; + case 2: ipipe->probe_info->track[num].samplerate = 44100; + break; + case 3: ipipe->probe_info->track[num].samplerate = 32000; + break; + } + switch ((tmp1[1] >> 6) & 3) { + case 0: ipipe->probe_info->track[num].bits = 16; + break; + case 1: ipipe->probe_info->track[num].bits = 20; + break; + case 2: ipipe->probe_info->track[num].bits = 24; + break; + default: tc_log_error(__FILE__, "unknown LPCM quantization"); + import_exit (1); + } + ipipe->probe_info->track[num].chan = 1 + (tmp1[1] & 7); + ipipe->probe_info->track[num].bitrate + = ipipe->probe_info->track[num].samplerate + * ipipe->probe_info->track[num].bits + * ipipe->probe_info->track[num].chan / 1000; + ipipe->probe_info->track[num].format=CODEC_LPCM; + + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.; + has_audio=1; + //ipipe->probe_info->track[num].pts_start=pack_ppp; + } + } + } + + //------------- + // + //VAG audio + // + //------------- + + if(aid == 0xFF && memcmp(tmp1+4,"SShd",4) == 0) { + num=0; + + if(!(attr[num] & PACKAGE_AUDIO_VAG) && initial_sync) { + + if(!track[num]) { + ++ipipe->probe_info->num_tracks; + track[num]=1; + ipipe->probe_info->track[num].tid=num; + } + + if(!(ipipe->probe_info->track[num].attribute & + PACKAGE_AUDIO_VAG)) { + + tmp1 += 4; // skip MPEG data + tmp1 += 4; // skip "SShd" header tag + tmp1 += 4; // skip file (data+header) size (int32_le) + ipipe->probe_info->track[num].bits = *tmp1; + tmp1 += 4; + ipipe->probe_info->track[num].samplerate = tmp1[0]|tmp1[1]<<8; + tmp1 += 4; + ipipe->probe_info->track[num].chan = *tmp1; + tmp1 += 4; + // next 4 bytes are stereo quantization size + // next 8 bytes are unused? + // next 8 bytes are data block header "SSbd" and int32_le size + + ipipe->probe_info->track[num].attribute |= PACKAGE_AUDIO_VAG; + ipipe->probe_info->track[num].bitrate + = ipipe->probe_info->track[num].samplerate + * ipipe->probe_info->track[num].chan + * 4 /* bits per sample, encoded */ + * 16 / 14 /* overhead ratio */ + / 1000; + ipipe->probe_info->track[num].format = CODEC_VAG; + + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.; + has_audio=1; + //ipipe->probe_info->track[num].pts_start=pack_ppp; + } + } + } + + buf = tmp2; + + break; + + + //------------------------ + // + // MPEG audio + // + //------------------------ + + case 0xc0: + case 0xc1: + case 0xc2: + case 0xc3: + case 0xc4: + case 0xc5: + case 0xc6: + case 0xc7: + case 0xc8: + case 0xc9: + case 0xca: + case 0xcb: + case 0xcc: + case 0xcd: + case 0xce: + case 0xcf: + case 0xd0: + case 0xd1: + case 0xd2: + case 0xd3: + case 0xd4: + case 0xd5: + case 0xd6: + case 0xd7: + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + + ++stream[id]; + + tmp2 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp2 > end) + goto copy; + if ((buf[6] & 0xc0) == 0x80) /* mpeg2 */ + tmp1 = buf + 9 + buf[8]; + else { /* mpeg1 */ + for (tmp1 = buf + 6; *tmp1 == 0xff; tmp1++) + if (tmp1 == buf + 6 + 16) { + tc_log_warn(__FILE__, "too much stuffing"); + buf = tmp2; + break; + } + if ((*tmp1 & 0xc0) == 0x40) + tmp1 += 2; + tmp1 += mpeg1_skip_table [*tmp1 >> 4]; + } + + //add found track + //need to scan payload for more MPEG audio info + + num=(buf[3] & 0xff) - 0xc0; + + if(num >= 0 && !track[num] && num<TC_MAX_AUD_TRACKS && initial_sync) { + + ++ipipe->probe_info->num_tracks; + +#ifdef HAVE_LAME + //need to scan payload for more MPEG audio info + if(end-buf>0) buf_probe_mp3(buf, end-buf, &ipipe->probe_info->track[num]); +#else + //all we know for now + ipipe->probe_info->track[num].format=CODEC_MP3; + ipipe->probe_info->track[num].tid=num; +#endif + + ac_memcpy(scan_buf, &buf[6], 16); + has_pts_dts=get_pts_dts(scan_buf, &i_pts, &i_dts); + + if(has_pts_dts) { + ipipe->probe_info->track[num].pts_start=(double) i_pts/90000.; + track[num]=1; + } + + has_audio=1; + } + + buf = tmp2; + break; + + case 0xb3: + + //MPEG video ES + probe_sequence(&buf[4], ipipe->probe_info); + + ipipe->probe_info->codec=TC_CODEC_MPEG; + if ((buf[6] & 0xc0) == 0x80) ipipe->probe_info->codec=TC_CODEC_MPEG2; + + return; + break; + + default: + if (buf[3] < 0xb9) { + tc_log_warn(__FILE__, "looks like an elementary stream - not program stream"); + ipipe->probe_info->codec=TC_CODEC_MPEG; + if ((buf[6] & 0xc0) == 0x80) ipipe->probe_info->codec=TC_CODEC_MPEG2; + return; + } + + /* skip */ + + tmp1 = buf + 6 + (buf[4] << 8) + buf[5]; + if (tmp1 > end) + goto copy; + buf = tmp1; + break; + + } //start code selection + } //scan buffer + + if (buf < end) { + copy: + /* we only pass here for mpeg1 ps streams */ + memmove (buffer, buf, end - buf); + } + buf = buffer + (end - buf); + + } while (end == buffer + BUFFER_SIZE); + + adjust_info(ipipe); + return; +} |
