summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/src/split.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/src/split.c')
-rw-r--r--debian/transcode/transcode-1.1.7/src/split.c319
1 files changed, 319 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/src/split.c b/debian/transcode/transcode-1.1.7/src/split.c
new file mode 100644
index 00000000..9d5b1a8b
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/src/split.c
@@ -0,0 +1,319 @@
+/*
+ * split.c
+ *
+ * Copyright (C) Thomas Oestreich - January 2002
+ *
+ * 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 "split.h"
+
+#define PMAX_BUF 1024
+char split_cmd_buf[PMAX_BUF];
+
+static int entries;
+
+typedef struct seq_s {
+
+ int unit;
+ long frame;
+ int seq;
+ int pseq;
+ long offset;
+ int foffset;
+} seq_t;
+
+static seq_t **seq=NULL;
+
+#define MAX_UNITS 128
+
+static long uframe[MAX_UNITS];
+static long unit_offset[MAX_UNITS];
+
+#define debug_return {return(-1);}
+
+static int split_stream_core(const char *file, const char *source)
+{
+
+ FILE *fd;
+ FILE *tmp;
+ char buffer[256];
+
+ int n=-1;
+
+ if(file == NULL) {
+
+ if(tc_snprintf(split_cmd_buf, PMAX_BUF, "tccat -i %s | tcdemux -W 2>/dev/null", source)<0) debug_return;
+ // popen
+ if((fd = popen(split_cmd_buf, "r"))== NULL) debug_return;
+
+ tc_log_info(__FILE__, "generating auto-split information from file \"%s\"", source);
+
+ // open temp. file
+ tmp = tmpfile();
+
+ while ( fgets (buffer, 256, fd) ) {
+ ++n;
+ if ( fputs (buffer, tmp) < 0 ) debug_return;
+ }
+
+ pclose(fd);
+ fd = tmp;
+
+ } else {
+
+ if((fd = fopen(file, "r"))==NULL) debug_return;
+
+ tc_log_info(__FILE__, "reading auto-split information from file \"%s\"", file);
+
+ // determine number of lines
+
+ while (fgets (buffer, 256, fd)) { ++n; }
+ }
+
+ // need n+2 pointers????
+ seq = (seq_t **) malloc( (n+2) * sizeof(seq_t*));
+ if ( seq == NULL ) debug_return;
+
+ n=-1;
+ fseek (fd, 0, SEEK_SET);
+
+ do {
+ ++n;
+
+ if((seq[n] = (seq_t *) malloc(sizeof(seq_t))) == NULL) debug_return;
+
+ } while((fscanf(fd, "%d %ld %d %d %ld %d", &seq[n]->unit, &seq[n]->frame, &seq[n]->seq, &seq[n]->pseq, &seq[n]->offset, &seq[n]->foffset)!=EOF));
+
+ entries=n;
+
+ if(seq[n]!=NULL) seq[n] = (seq_t *) malloc(sizeof(seq_t));
+
+ //add fake closing entry
+ seq[n]->unit=seq[n-1]->unit+1;
+ seq[n]->frame=seq[n-1]->frame=0;
+ seq[n]->seq=seq[n-1]->seq+1;
+
+ fclose(fd);
+
+ return(0);
+}
+
+
+static long get_frame_index(int unit, long frame_inc)
+{
+ //first entry is unique
+
+ long n;
+ int m;
+
+ if(frame_inc==0) return(unit_offset[unit]);
+
+ n=unit_offset[unit] + frame_inc;
+ m=seq[n]->seq;
+
+ while(seq[n]->unit == unit && n < entries && seq[n]->seq == m ) ++n;
+
+ return(n);
+}
+
+//----------------------------------------------
+//
+// main routine
+//
+//----------------------------------------------
+
+
+int split_stream(vob_t *vob, const char *file, int this_unit, int *fa, int *fb, int opt_flag)
+{
+
+ int n, unit_ctr=-1, last_unit=-1;
+
+ int s1, s2, video=1;
+
+ long max_frames=-1;
+ int unit=0, foff=0;
+
+ long _fa, _fb;
+
+ long _n, frame_inc=0, poff=0;
+
+ int startc, chunks;
+
+ if(split_stream_core(file, ((vob->vob_chunk == vob->vob_chunk_max) ? vob->audio_in_file:vob->video_in_file))<0) {
+ tc_log_error(__FILE__, "failed to read VOB navigation file %s", file);
+ return(-1);
+ }
+
+ tc_log_info(__FILE__, "done reading %d entries", entries);
+
+ //analyze data:
+
+ for(n=0; n<MAX_UNITS; ++n) uframe[n]=0;
+
+ // (I) determine presentation units and number of frames
+
+ for(n=0; n<entries; ++n) {
+
+ if(last_unit != seq[n]->unit) {
+ last_unit=seq[n]->unit;
+ ++unit_ctr;
+ unit_offset[unit_ctr]=n;
+ }
+
+ ++uframe[unit_ctr];
+ }
+
+ for(n=0; n<=unit_ctr; ++n) {
+ if(max_frames<=uframe[n]) {
+ unit = n;
+ max_frames = uframe[n];
+ }
+
+ if(this_unit > unit_ctr) {
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "invalid PSU %s", file);
+ return(-1);
+ }
+
+ if(-1 < this_unit) unit = this_unit;
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "unit=%d, frames=%ld, offset=%ld (%d)", n, uframe[n], unit_offset[n], vob->ps_unit);
+ }
+
+ // (II) determine largest (main) presentation unit
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "selecting unit %d, frames=%ld, offset=%ld", unit, uframe[unit], unit_offset[unit]);
+
+
+ // video or audio mode ?
+
+ if((vob->vob_percentage) ? (vob->vob_chunk==vob->vob_chunk_max && vob->vob_chunk_max==100 ) : (vob->vob_chunk == vob->vob_chunk_max)) video=0;
+
+ //check user error
+ if(vob->vob_chunk_num2>vob->vob_chunk_max) vob->vob_chunk_num2=vob->vob_chunk_max;
+ if(vob->vob_chunk_num1>vob->vob_chunk_max) vob->vob_chunk_num1=0;
+
+ // determine number of chunks to process: (0.6.0pre5)
+
+ if(video) {
+ chunks = (vob->vob_percentage || vob->vob_chunk_num2==0) ? 1:vob->vob_chunk_num2-vob->vob_chunk_num1;
+ startc = (vob->vob_percentage || vob->vob_chunk_num2==0) ? vob->vob_chunk:vob->vob_chunk_num1;
+ } else {
+ chunks = (vob->vob_percentage || vob->vob_chunk_num2==0) ? vob->vob_chunk_max:vob->vob_chunk_num2-vob->vob_chunk_num1;
+ startc = (vob->vob_percentage || vob->vob_chunk_num2==0) ? 0:vob->vob_chunk_num1;
+ }
+
+ //---------------------------------------------------------------------
+
+ // (III) determine pack offset for given number of VOB chunks
+ // Modified by CARON Dominique <domi@lpm.univ-monp2.fr> to optimize the
+ // cluster mode
+ // vob->vob_chunk = percentage of frames to skip before frames to encode
+ // vob->vob_chunk_max = percentage of frames to encode
+
+
+ frame_inc = (vob->vob_percentage) ? (long) ((startc * uframe[unit])/100) : (long) ((startc * uframe[unit])/vob->vob_chunk_max);
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "estimated chunk offset = %ld", frame_inc);
+
+ _n = get_frame_index(unit, frame_inc);
+
+ poff = seq[_n]->offset;
+ foff = seq[_n]->foffset;
+
+ _fa = seq[_n]->frame;
+
+ // parameter for option "-c"
+ *fa = foff;
+ *fb = foff - seq[_n]->frame;
+
+ s1 = seq[_n]->seq;
+
+ if(verbose &TC_DEBUG) tc_log_msg(__FILE__, "chunk %d starts at frame %ld, pack offset %ld, finc=%d", startc, _n, poff, foff);
+
+
+ // (IV) determine end of chunk(s)
+ // Modified by CARON Dominique <domi@lpm.univ-monp2.fr> to optimize the
+ // cluster mode
+
+ frame_inc = (vob->vob_percentage) ? (long) (((vob->vob_chunk+vob->vob_chunk_max) * uframe[unit])/100) : (long) (((startc+chunks) * uframe[unit])/vob->vob_chunk_max);
+
+ _n = get_frame_index(unit, frame_inc);
+
+ _fb = seq[_n]->frame;
+
+ s2 = seq[_n]->seq;
+
+ if(_fb==0) {
+ _fb = uframe[unit];
+ *fb += uframe[unit];
+ } else {
+ *fb += seq[_n]->frame;
+ }
+
+ // (V) set vob parameter
+
+ vob->vob_offset = poff;
+ vob->ps_unit = 0;
+
+ vob->ps_seq1 = 0;
+ vob->ps_seq2 = (s2==0 && _n) ? seq[_n-1]->seq-s1+3 : s2-s1+2;
+
+ tc_log_msg(__FILE__, "chunk %d/%d PU=%d (-L 0 -c %ld-%ld) mapped onto (-L %ld -c %d-%d)", vob->vob_chunk, vob->vob_chunk_max-1, unit, _fa, _fb, poff, *fa, *fb);
+
+
+ //---------------------------------------------------------------------
+
+ if(opt_flag==1) { //cluster mode
+
+ if(video) {
+
+ // no sound
+ vob->amod_probed="null";
+ vob->has_audio=0;
+
+ tc_log_info(__FILE__, "video mode");
+
+ } else {
+
+ // no video
+ vob->vmod_probed="null";
+ vob->has_video=0;
+
+ vob->vob_offset = poff;
+ vob->ps_unit = 0;
+
+ tc_log_info(__FILE__, "audio mode");
+ }
+ }
+
+ //---------------------------------------------------------------------
+
+ if(seq != NULL) {
+
+ // seq array not needed anymore
+ for (n=0; n < entries+1; ++n) {
+ free(seq[n]);
+ }
+
+ free(seq);
+ }
+
+ return(0);
+}