summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/import/demuxer.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/demuxer.c')
-rw-r--r--debian/transcode/transcode-1.1.7/import/demuxer.c998
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;
+}
+