diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/src/split.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/src/split.c | 319 |
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); +} |
