diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/demuxer.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/demuxer.c | 998 |
1 files changed, 998 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/demuxer.c b/debian/transcode/transcode-1.1.7/import/demuxer.c new file mode 100644 index 00000000..a442fbd0 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/demuxer.c @@ -0,0 +1,998 @@ +/* + * demuxer.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 "libtc/libtc.h" +#include "tcinfo.h" + +#include "ioaux.h" +#include "aux_pes.h" +#include "seqinfo.h" +#include "demuxer.h" +#include "packets.h" + +#include <math.h> + +static int demux_mode=TC_DEMUX_SEQ_ADJUST; + +int gop, gop_pts, gop_cnt; + +typedef struct timecode_struc /* Time_code Struktur laut MPEG */ +{ unsigned long msb; /* fuer SCR, DTS, PTS */ + unsigned long lsb; + unsigned long reference_ext; + unsigned long negative; /* for delays when doing multiple files */ +} Timecode_struc; + +#define MAX_FFFFFFFF 4294967295.0 /* = 0xffffffff in hex. */ + +/* ------------------------------------------------------------ + * + * support code (scr_rewrite()) moved from aux_pes.c + * + * ------------------------------------------------------------*/ + +static void make_timecode (double timestamp, Timecode_struc *pointer) +{ + double temp_ts; + + if (timestamp < 0.0) { + pointer->negative = 1; + timestamp = -timestamp; + } else + pointer->negative = 0; + + temp_ts = floor(timestamp / 300.0); + + if (temp_ts > MAX_FFFFFFFF) { + pointer->msb=1; + temp_ts -= MAX_FFFFFFFF; + pointer->lsb=(unsigned long)temp_ts; + } else { + pointer->msb=0; + pointer->lsb=(unsigned long)temp_ts; + } + + pointer->reference_ext = (unsigned long)(timestamp - (floor(timestamp / 300.0) * 300.0)); + +} + +#define MPEG2_MARKER_SCR 1 /* MPEG2 Marker SCR */ + +/************************************************************************* + Kopiert einen TimeCode in einen Bytebuffer. Dabei wird er nach + MPEG-Verfahren in bits aufgesplittet. + + Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields + according to MPEG-System +*************************************************************************/ + +static void buffer_timecode_scr (Timecode_struc *pointer, unsigned char **buffer) +{ + + unsigned char temp; + unsigned char marker=MPEG2_MARKER_SCR; + + + temp = (marker << 6) | (pointer->msb << 5) | + ((pointer->lsb >> 27) & 0x18) | 0x4 | ((pointer->lsb >> 28) & 0x3); + *((*buffer)++)=temp; + temp = (pointer->lsb & 0x0ff00000) >> 20; + *((*buffer)++)=temp; + temp = ((pointer->lsb & 0x000f8000) >> 12) | 0x4 | + ((pointer->lsb & 0x00006000) >> 13); + *((*buffer)++)=temp; + temp = (pointer->lsb & 0x00001fe0) >> 5; + *((*buffer)++)=temp; + temp = ((pointer->lsb & 0x0000001f) << 3) | 0x4 | + ((pointer->reference_ext & 0x00000180) >> 7); + *((*buffer)++)=temp; + temp = ((pointer->reference_ext & 0x0000007F) << 1) | 1; + *((*buffer)++)=temp; + +} + +static void scr_rewrite(char *buf, uint32_t pts) +{ + Timecode_struc timecode; + unsigned char * ucbuf = (unsigned char *)buf; + + timecode.msb = 0; + timecode.lsb = 0; + timecode.reference_ext = 0; + timecode.negative = 0; + + make_timecode((double) pts, &timecode); + + buffer_timecode_scr(&timecode, &ucbuf); +} + +/* ------------------------------------------------------------ + * + * demuxer / synchronization thread + * + * ------------------------------------------------------------*/ + +void tcdemux_thread(info_t *ipipe) +{ + + int k, id=0, zz=0; + + int j, i, bytes, filesize; + char *buffer=NULL; + + int payload_id=0, select=PACKAGE_ALL; + + double pts=0.0f, ref_pts=0.0f, resync_pts=-1.0f, pts_diff=0.0f, track_initial_pts=0.0f; + double av_fine_pts1=-1.0f, av_fine_pts2=-1.0f, av_fine_diff=0.0f; + + uint32_t frame_based_lpts=0; + + int unit_seek=0, unit, track=0, is_track=0; + + int resync_seq1=0, resync_seq2=INT_MAX, seq_dump, seq_seek; + int keep_seq = 0; + int hard_fps = 0; + + int has_pts_dts=0, demux_video=0, demux_audio=0; + + int flag_flush = 0; + int flag_force = 0; + int flag_eos = 0; + int flag_has_audio = 0; + int flag_append_audio = 0; + int flag_notify = 1; + int flag_avsync = 1; + int flag_skip = 0; + int flag_sync_reset = 0; + int flag_sync_active = 0; + int flag_loop_all = 0; + int flag_av_fine_tune = 0; + int flag_rewrite_scr = 0; + int flag_field_encoded= 0; + + //for demux_mode=2 + int seq_picture_ctr=0, pack_picture_ctr=0, sequence_ctr=0, packet_ctr=0; + + char buf[256]; + const char *logfile; + unsigned long i_pts, i_dts; + unsigned int packet_size=VOB_PACKET_SIZE; + seq_list_t *ptr=NULL; + double fps; + + + // allocate space + if((buffer = tc_zalloc(packet_size))==NULL) { + tc_log_perror(__FILE__, "out of memory"); + exit(1); + } + + // copy info parameter to local variables + + unit_seek = ipipe->ps_unit; + resync_seq1 = ipipe->ps_seq1; + resync_seq2 = ipipe->ps_seq2; + track = ipipe->track; + + //map track on substream id + + switch(ipipe->codec) { + + case TC_CODEC_SUB: + track+=0x20; + flag_rewrite_scr=1; + break; + case TC_CODEC_AC3: + track+=0x80; + break; + case TC_CODEC_PCM: + track+=0xA0; + break; + case TC_CODEC_MP3: + track+=0xC0; + break; + case TC_CODEC_MPEG2: + // for MPEG2 video, use this substream id for sync adjustment + track=ipipe->subid; + demux_video=1; + break; + } + + //0.6.0pre4 + if(demux_video==0) { + + if(ipipe->demux == TC_DEMUX_SEQ_FSYNC) + ipipe->demux=TC_DEMUX_SEQ_ADJUST; + + if(ipipe->demux == TC_DEMUX_SEQ_FSYNC2) + ipipe->demux=TC_DEMUX_SEQ_ADJUST2; + + //substream synchonized with video in "force frame rate" mode + demux_audio=1; + } + + if(ipipe->demux == TC_DEMUX_SEQ_FSYNC || ipipe->demux == TC_DEMUX_SEQ_FSYNC2 || ipipe->demux == TC_DEMUX_SEQ_LIST) { + + //allocate buffer + if(flush_buffer_init(ipipe->fd_out, ipipe->verbose)<0) { + tc_log_error(__FILE__, "flush buffer facility init failed"); + exit(1); + } + + //need to open the logfile + if(seq_init(ipipe->name, ipipe->fd_log, ipipe->fps, ipipe->verbose)<0) { + tc_log_error(__FILE__, "sync mode init failed"); + exit(1); + } + } + + + //new default behaving: + // if(unit_seek==0 && resync_seq1==0 && resync_seq2 == INT_MAX) flag_loop_all=1; + //changes 0.6.0pre3: + //tcprobe selects start unit --> switch to flag_loop_all always true + // for any given unit + if(resync_seq1==0 && resync_seq2 == INT_MAX) flag_loop_all=1; + + demux_mode = ipipe->demux; + select = ipipe->select; + fps = ipipe->fps; + logfile = ipipe->name; + keep_seq = ipipe->keep_seq; + hard_fps = ipipe->hard_fps_flag; + + j=0; //packet counter + i=0; //skipped packets counter + k=0; //unit counter + + // will be switched on as soon start of sequences to flush is reached + flag_flush=0; + + flag_notify=1; + + flag_avsync=0; + flag_append_audio=0; + + if(keep_seq) flag_sync_active=1; + + unit=unit_seek; + + seq_seek = resync_seq1; + seq_dump = resync_seq2 - resync_seq1; + + ++unit_seek; + ++seq_seek; + + if(!flag_loop_all) { + tc_log_msg(__FILE__, "seeking to sequence %d:%d ...", unit, resync_seq1); + } + + filesize = 0; + for(;;) { + + /* ------------------------------------------------------------ + * + * (I) read a 2048k block + * + * ------------------------------------------------------------*/ + + if((bytes=tc_pread(ipipe->fd_in, buffer, packet_size)) != packet_size) { + + //program end code? + if(bytes==4) { + if(scan_pack_header(buffer, MPEG_PROGRAM_END_CODE)) { + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "(pid=%d) program stream end code detected", + getpid()); + break; + } + } + + if(bytes) + tc_log_warn(__FILE__, "invalid program stream packet size (%d/%d)", + bytes, packet_size); + + break; + } + filesize += bytes; + + // do not make any tests in pass-through mode + if(demux_mode==TC_DEMUX_OFF) goto flush_packet; + + /* ------------------------------------------------------------ + * + * (II) packet header ok? + * + * ------------------------------------------------------------*/ + + + if(!scan_pack_header(buffer, TC_MAGIC_VOB)) { + + if(flag_notify && (ipipe->verbose & TC_DEBUG)) + tc_log_warn(__FILE__, "(pid=%d) invalid packet header detected", + getpid()); + + // something else? + + if(scan_pack_header(buffer, MPEG_VIDEO) | scan_pack_header(buffer, MPEG_AUDIO)) { + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "(pid=%d) MPEG system stream detected", + getpid()); + + if(scan_pack_header(buffer, MPEG_VIDEO)) payload_id=PACKAGE_VIDEO; + if(scan_pack_header(buffer, MPEG_AUDIO)) payload_id=PACKAGE_AUDIO_MP3; + + // no further processing + goto flush_packet; + } else { + + tc_log_warn(__FILE__, "(pid=%d) '0x%02x%02x%02x%02x' not yet supported", + getpid(), buffer[0] & 0xff, buffer[1] & 0xff, + buffer[2] & 0xff, buffer[3] & 0xff); + break; + } + } else { + + //MPEG1? + if ((buffer[4] & 0xf0) == 0x20) { + + payload_id=PACKAGE_MPEG1; + flag_flush=1; + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "(pid=%d) MPEG-1 video stream detected", + getpid()); + + // no further processing + goto flush_packet; + } + } + + + /* ------------------------------------------------------------ + * + * (III) analyze packet contents + * + * ------------------------------------------------------------*/ + + + // proceed with a valid package, assume defaults + + flag_skip=0; //do not skip + has_pts_dts=0; //no pts_dts stamp + payload_id=0; //payload unknown + flag_sync_reset=0; //no reset of syncinfo + + id = buffer[17] & 0xff; //payload id byte + + //MPEG 2? + if ((buffer[4] & 0xc0) == 0x40) { + + // do not change any flags + + if(ipipe->verbose & TC_STATS) { + //display info only once + tc_log_msg(__FILE__, "(pid=%d) MPEG-2 video stream detected", + getpid()); + } + } else { + + //MPEG1 + if ((buffer[4] & 0xf0) == 0x20) { + + payload_id=PACKAGE_MPEG1; + + if(ipipe->verbose & TC_STATS) { + //display info only once + tc_log_msg(__FILE__, "(pid=%d) MPEG-1 video stream detected", + getpid()); + } + } else { + + payload_id=PACKAGE_PASS; + + if(ipipe->verbose & TC_DEBUG) + tc_log_warn(__FILE__, "(pid=%d) unknown stream packet id detected", + getpid()); + } + + //flush all MPEG1 stuff + goto flush_packet; + } + + /* ------------------------------------------------------------ + * + * (IV) audio payload + * + * ------------------------------------------------------------*/ + + // check payload id + // process this audio packet? + + // sync to AC3 audio mode? + if(id == P_ID_AC3) payload_id = PACKAGE_PRIVATE_STREAM; + + // sync to MP3 audio mode? + if(id >= 0xc0 && id <= 0xdf) payload_id = PACKAGE_AUDIO_MP3; + + // are we dealing with the right track? + // check here: + + is_track=0; + + if(payload_id == PACKAGE_PRIVATE_STREAM) { + + //position of track code + uint8_t *_buf=buffer+14; + uint8_t *_tmp=_buf + 9 + _buf[8]; + + is_track = ((*_tmp) == track) ? 1:0; + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "substream [0x%x] %d", *_tmp, is_track); + + if(is_track==0) { + flag_skip=1; //drop this packet + } else { + flag_skip=0; + goto sync_track; + } + } + + if(payload_id & PACKAGE_AUDIO_MP3) { + + is_track = ((id) == track) ? 1:0; + if(is_track==0) flag_skip=1; //drop this packet + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "MPEG audio track [0x%x] %d", id, is_track); + } + + sync_track: + + if(is_track) { + + + if(flag_sync_active==0) { + + //first valid audio packet! + + // get pts time stamp: + ac_memcpy(buf, &buffer[20], 16); + has_pts_dts=get_pts_dts(buf, &i_pts, &i_dts); + + if(has_pts_dts) { + track_initial_pts=(double)i_pts/90000.; + } else { + //fallback to scr time stamp: + ac_memcpy(buf, &buffer[4], 6); + track_initial_pts = read_time_stamp(buf); + } + + if(resync_pts<0) { + pts_diff = track_initial_pts; + } else { + pts_diff = track_initial_pts - resync_pts; + } + + //pts_diff<0 is OK, the packets will be dropped to establish sync + //pts_diff>0 is not so simple, since we need to drop video + //packets, already submitted to flush buffer + + //enable sync mode, check for PTS giant leap???? + if(pts_diff < TC_DEMUX_MIN_PTS || pts_diff > TC_DEMUX_CRIT_PTS) + flag_sync_active = 1; + + //0.6.0pre5: frame dropping handled by transcode + flag_sync_active=1; + + //unless this flag is on, the video sequence is dropped + //in TC_DEMUX_SEQ_FSYNC mode + } + + + // sync now, if requested: + + if(!unit_seek) flag_has_audio=1; //unit has audio packets + + + // need to find the time difference of two audio packets + // for fine-tuning AV sync. + + if(flag_av_fine_tune == 0) { + // get pts time stamp: + ac_memcpy(buf, &buffer[20], 16); + has_pts_dts=get_pts_dts(buf, &i_pts, &i_dts); + + if(av_fine_pts1<0) { + av_fine_pts1 = (double)i_pts/90000.; + } else { + av_fine_pts2 = (double)i_pts/90000.; + flag_av_fine_tune=1; + } + + //diff: + if(flag_av_fine_tune==1) { + av_fine_diff=av_fine_pts2-av_fine_pts1; + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "AV fine-tuning: %d ms", + (int)(av_fine_diff*1000)); + } + + //sanity check: + if(av_fine_diff<0) av_fine_diff=0.0f; + + } + + //Pre-processing: check if we need to re-sync? + + if(demux_mode == TC_DEMUX_SEQ_FSYNC2 || demux_mode == TC_DEMUX_SEQ_ADJUST2) { + //new demux modes let transcode handle audio sync shift + flag_avsync=0; + flag_skip=0; + } + + if(flag_avsync) { + + // get pts time stamp: + ac_memcpy(buf, &buffer[20], 16); + has_pts_dts=get_pts_dts(buf, &i_pts, &i_dts); + + if(has_pts_dts) { + pts=(double)i_pts/90000.; + } else { + //fallback to scr time stamp: + ac_memcpy(buf, &buffer[4], 6); + pts = read_time_stamp(buf); + } + + pts_diff = pts - resync_pts; + + //correction + //FIXME + pts_diff += av_fine_diff; + + if(pts_diff<0) { + flag_skip=1; + + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "(pid=%d) audio packet %06d for PU [%d] skipped (%.4f)", + getpid(), j, ((k==0)? 0:k-1), pts-resync_pts); + } else { + //reset + flag_skip=0; + flag_avsync=0; + if(ipipe->verbose) + tc_log_msg(__FILE__, "(pid=%d) AV sync established for PU [%d] at PTS=%.4f (%.4f)", + getpid(), k-1, pts, pts-resync_pts); + } + } + + //Post-processing: more audio packets? + + if(flag_append_audio) { + + //need to flush a few audio packets, if video ahead + + // get pts time stamp: + ac_memcpy(buf, &buffer[20], 16); + has_pts_dts=get_pts_dts(buf, &i_pts, &i_dts); + + if(has_pts_dts) { + pts=(double)i_pts/90000.; + } else { + //fallback to scr time stamp: + ac_memcpy(buf, &buffer[4], 6); + pts = read_time_stamp(buf); + } + + pts_diff = pts - resync_pts; + + if(pts_diff<0) { + + //append this packet + flag_skip=0; + + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "(pid=%d) audio packet %06d for PU [%d] appended (%.4f)", + getpid(), j, ((k==0)? 0:k-1), pts-resync_pts); + } else { + //abort - all done + flag_eos=1; + if(ipipe->verbose) + tc_log_msg(__FILE__, "(pid=%d) AV sync abandoned for PU [%d] at PTS=%.4f (%.4f)", + getpid(), k-1, pts, pts-resync_pts); + } + } + } + + //only go for audio in this phase + if(flag_append_audio) goto flush_packet; + + /* ------------------------------------------------------------ + * + * (V) misc payload + * + * ------------------------------------------------------------*/ + + + if(id == P_ID_PROG || id == P_ID_PADD) { + + payload_id=PACKAGE_NAV; + + // get pts time stamp: + ac_memcpy(buf, &buffer[20], 16); + has_pts_dts=get_pts_dts(buf, &i_pts, &i_dts); + + if(has_pts_dts) { + pts=(double)i_pts/90000.; + } else { + //fallback to scr time stamp: + ac_memcpy(buf, &buffer[4], 6); + pts = read_time_stamp(buf); + } + + //do not dump this packet + flag_skip=1; + } + + /* ------------------------------------------------------------ + * + * (VI) video payload + * + * ------------------------------------------------------------*/ + + + if(id == P_ID_MPEG) { + + payload_id = PACKAGE_VIDEO; + + // get pts time stamp: + ac_memcpy(buf, &buffer[4], 6); + pts = read_time_stamp(buf); + + //read full packet header + ac_memcpy(buf, &buffer[20], 16); + has_pts_dts=get_pts_dts(buf, &i_pts, &i_dts); + + //need frame/field encoding information + zz=scan_pack_ext(buffer); + if(zz>0) flag_field_encoded=zz; + + //need precise number of pics in this sequence + pack_picture_ctr = scan_pack_pics(buffer); + + seq_picture_ctr += pack_picture_ctr; + + frame_based_lpts = (seq_picture_ctr-1); + + //need this pack for subtitle PTS information + if(flag_rewrite_scr && has_pts_dts) flag_force=1; + + // only process packets with pts/dts time stamp, since + // they (all?) have a sequence start code + + if(has_pts_dts) { + + if (ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "(pid=%d) PTS-DTS detected in packet [%06d]", + getpid(), j); + + // default first(=0) unit ? + if(k==0) { + + --unit_seek; + flag_sync_reset=1; + + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "(pid=%d) MPEG sequence start code in packet %06d for PU [0]", + getpid(), j); + + k++; + } + + + if(pts<ref_pts) { + + --unit_seek; + flag_sync_reset=1; + + // past next unit - abort + // or process all following units? + + if(unit_seek<0 && flag_loop_all==0) flag_eos=1; + + //experimental: try to resync + //flag_avsync = 1; + + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "(pid=%d) PTS reset (%.3f->%.3f) in packet %06d for PU [%d]", + getpid(), ref_pts, pts, j, k); + + k++; + } + + + // only decrement sequence counter in right unit, i.e. + // unit_seek=0; + if(!unit_seek) --seq_seek; + + // flush all sequences until the end of the unit + // or end of stream + // or resync_seq2 is reached + + if(seq_seek==0) { + + //re read packet header + ac_memcpy(buf, &buffer[20], 16); + get_pts_dts(buf, &i_pts, &i_dts); + + resync_pts = (double) i_pts / 90000; + + if(!flag_flush) { + + // need to dump requested seq_dump sequences + seq_seek=seq_dump; + flag_flush = 1; + + flag_avsync = 1; + + // may be a useful info for the user + if(ipipe->verbose) + tc_log_msg(__FILE__, "(pid=%d) processing PU [%d], on at PTS=%.4f sec", + getpid(), k-1, resync_pts); + + } else { + // finished, all sequences flushed, switch + // to audio packets post processing + flag_append_audio = 1; + flag_skip = 1; //flush mode on, but do not write this one + + // may be a useful info for the user + if(ipipe->verbose) + tc_log_msg(__FILE__, "(pid=%d) processing PU [%d], off at PTS=%.4f sec", + getpid(), k-1, resync_pts); + } + } + + //--------------------------------------------------- + //gather information on the sequences before flushing + //--------------------------------------------------- + + if((demux_mode == TC_DEMUX_SEQ_FSYNC || demux_mode == TC_DEMUX_SEQ_FSYNC2) && flag_flush) { + + ptr = seq_register(sequence_ctr); + + zz=(flag_field_encoded==3)?(seq_picture_ctr-pack_picture_ctr): + (seq_picture_ctr-pack_picture_ctr)/2; + + if(sequence_ctr) seq_update(ptr->prev, i_pts, zz, packet_ctr, flag_sync_active, hard_fps); + + //init sequence information structure for current sequence + + ptr->pts = i_pts; + ptr->dts = i_dts; + ptr->pics_first_packet = pack_picture_ctr; + ptr->sync_reset = flag_sync_reset; + + //reset/update + seq_picture_ctr = 0; + packet_ctr = 0; + ++sequence_ctr; + + //shift resync_pts, since sequence is dropped + if(flag_sync_active==0) resync_pts=(double) i_pts / 90000; + + } //end TC_DEMUX_SEQ_FSYNC mode + + //--------------------------------------------------- + //print out sequence information for frame navigation + //--------------------------------------------------- + + if((demux_mode == TC_DEMUX_SEQ_LIST) && flag_flush) { + + ptr = seq_register(sequence_ctr); + + zz=(flag_field_encoded==3)?(seq_picture_ctr-pack_picture_ctr): + (seq_picture_ctr-pack_picture_ctr)/2; + + if(sequence_ctr) seq_list(ptr->prev, i_pts, zz, packet_ctr, flag_sync_active); + + //init sequence information structure for current sequence + + ptr->pts = i_pts; + ptr->dts = i_dts; + ptr->pics_first_packet = pack_picture_ctr; + ptr->sync_reset = flag_sync_reset; + ptr->packet_ctr=j; + + //reset/update + seq_picture_ctr = 0; + packet_ctr = 0; + ++sequence_ctr; + + //shift resync_pts, since sequence is dropped + if(flag_sync_active==0) resync_pts=(double) i_pts / 90000; + + } //end TC_DEMUX_SEQ_LIST mode + + //reset sync pts, if no audio/substream has been found (0.6.0pre4) + if(flag_sync_active==0 && demux_audio) { + resync_pts=(double) i_pts / 90000; + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "new initial PTS=%f", resync_pts); + } + + }// PTS-DTS flag yes + + ref_pts=pts; + + }// MPEG video packet + + /* ------------------------------------------------------------ + * + * (VII) evaluate scan results - flush packet + * + * ------------------------------------------------------------*/ + + flush_packet: + + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "INFO: j=%05d, i=%05d, skip=%d, flush=%d, force=%d, pay=%3d, sid=0x%02x, eos=%d", + j, i, flag_skip, flag_flush, flag_force, payload_id, id, flag_eos); + + //need to rewrite SCR pack header entry based on + //frame_based_pts information for transcode: + if(flag_rewrite_scr) scr_rewrite(&buffer[4], ((flag_field_encoded==3)?frame_based_lpts:frame_based_lpts/2)); + + //flush here: + + switch(demux_mode) { + + case TC_DEMUX_DEBUG: + if((flag_flush && !flag_skip && (payload_id & select)) + || flag_force) scan_pack_payload(buffer, packet_size, j, ipipe->verbose); + break; + + case TC_DEMUX_DEBUG_ALL: + scan_pack_payload(buffer, packet_size, j, ipipe->verbose); + break; + + case TC_DEMUX_SEQ_FSYNC: + case TC_DEMUX_SEQ_FSYNC2: + + if((flag_flush && !flag_skip && (payload_id & select)) || flag_force) { + + //count current sequence packets to be flushed + ++packet_ctr; + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "flushing packet (%d/%d)", sequence_ctr, j); + + if(flush_buffer_write(ipipe->fd_out, buffer, packet_size) != packet_size) { + tc_log_perror(__FILE__, "write program stream packet"); + exit(1); + } + + //reset + flag_force=0; + } + + break; + + case TC_DEMUX_SEQ_ADJUST: + case TC_DEMUX_SEQ_ADJUST2: + + if((flag_flush && !flag_skip && (payload_id & select)) || flag_force) { + + if(tc_pwrite(ipipe->fd_out, buffer, packet_size) != packet_size) { + tc_log_perror(__FILE__, "write program stream packet"); + exit(1); + } + + //reset + flag_force=0; + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "writing packet %d", j); + + } else { + + ++i; + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "skipping packet %d", j); + } + + break; + + + case TC_DEMUX_SEQ_LIST: + + //count packs + ++packet_ctr; + + // nothing to do + break; + + case TC_DEMUX_OFF: + + if(tc_pwrite(ipipe->fd_out, buffer, packet_size) != packet_size) { + tc_log_perror(__FILE__, "write program stream packet"); + exit(1); + } + + if(ipipe->verbose & TC_STATS) + tc_log_msg(__FILE__, "writing packet %d", j); + + break; + } + + //aborting? + if(flag_eos) break; + + //total packs (2k each) counter + ++j; + + } // process next packet/block + + if(ipipe->verbose & TC_SYNC) + tc_log_msg(__FILE__, "EOS - flushing packet buffer"); + + //post processing + + if(demux_mode == TC_DEMUX_SEQ_FSYNC || demux_mode == TC_DEMUX_SEQ_FSYNC2) { + seq_close(); + flush_buffer_close(); + } + + if(demux_mode == TC_DEMUX_SEQ_LIST) { + + ptr = seq_register(sequence_ctr); + + zz=(flag_field_encoded==3)?(seq_picture_ctr-pack_picture_ctr): + (seq_picture_ctr-pack_picture_ctr)/2; + + if(ptr!=NULL && ptr->id) seq_list(ptr->prev, ref_pts, zz, packet_ctr, flag_sync_active); + + fflush(stdout); + + //summary + seq_list_frames(); + + seq_close(); + flush_buffer_close(); + + } + + //summary + if(ipipe->verbose & TC_DEBUG) + tc_log_msg(__FILE__, "(pid=%d) %d/%d packets discarded", getpid(), i, j); + + if(buffer!=NULL) free(buffer); + + return; +} + |
