diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/clone.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/clone.c | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/clone.c b/debian/transcode/transcode-1.1.7/import/clone.c new file mode 100644 index 00000000..54dafe84 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/clone.c @@ -0,0 +1,398 @@ +/* + * clone.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. + * + */ + +//undef if you experience lock ups! +#define USE_FIFO_LOGFILE 1 + +#include "transcode.h" +#include "libtc/libtc.h" +#include "encoder.h" +#include "clone.h" +#include "seqinfo.h" /* for sync_type_t */ +#include "ivtc.h" + +#include "frame_info.h" + +static FILE *pfd=NULL; + +static int clone_ctr=0, sync_disabled_flag=0; + +static int width, height, vcodec; + +static char *video_buffer=NULL, *pulldown_buffer=NULL; + +static int sync_ctr=0, frame_ctr=0, drop_ctr=0, seq_dis=-1; + +static char *logfile; + +static int sfd=0; + +static double fps; + +static pthread_t thread=(pthread_t)0; + +static int clone_read_thread_flag=0; + +static pthread_mutex_t buffer_fill_lock=PTHREAD_MUTEX_INITIALIZER; +static int buffer_fill_ctr; +static pthread_cond_t buffer_fill_cv=PTHREAD_COND_INITIALIZER; + + +int clone_init(FILE *fd) +{ + + vob_t *vob; + + // copy file pointer + pfd=fd; + + vob = tc_get_vob(); + fps = vob->fps; + width = vob->im_v_width; + height = vob->im_v_height; + vcodec = vob->im_v_codec; + + //sync log file + + if((sfd = open(logfile, O_RDONLY, 0666))<0) { + tc_log_perror(__FILE__, "open file"); + return(-1); + } + + if(verbose & TC_DEBUG) + tc_log_msg(__FILE__, "reading video frame sync data from %s", logfile); + + // allocate space, assume max buffer size + + if((video_buffer = tc_zalloc(width*height*3))==NULL) { + tc_log_error(__FILE__, "out of memory"); + sync_disabled_flag=1; + return(-1); + } + + // allocate space, assume max buffer size + + if((pulldown_buffer = tc_zalloc(width*height*3))==NULL) { + tc_log_error(__FILE__, "out of memory"); + sync_disabled_flag=1; + return(-1); + } + + //basic operational flags + clone_read_thread_flag=1; + sync_disabled_flag=0; + + if(pthread_create(&thread, NULL, (void *) clone_read_thread, NULL)!=0) { + tc_log_error(__FILE__, "failed to start frame processing thread"); + sync_disabled_flag=1; + return(-1); + } + + return(0); +} + + +static frame_info_list_t *fiptr=NULL; + +static int buffered_p_read(char *s) +{ + + pthread_mutex_lock(&buffer_fill_lock); + + //exit + if(buffer_fill_ctr <= 0 && clone_read_thread_flag==0) { + pthread_mutex_unlock(&buffer_fill_lock); + return(0); + } + + if(verbose & TC_SYNC) + tc_log_msg(__FILE__, "WAIT (%d)", buffer_fill_ctr); + + while(buffer_fill_ctr == 0) { + pthread_cond_wait(&buffer_fill_cv, &buffer_fill_lock); +#ifdef BROKEN_PTHREADS // Used to be MacOSX specific; kernel 2.6 as well? + pthread_testcancel(); +#endif + } + + --buffer_fill_ctr; + + pthread_mutex_unlock(&buffer_fill_lock); + + fiptr=frame_info_retrieve(); + + ac_memcpy(s, fiptr->sync_info, sizeof(sync_info_t)); + + return(sizeof(sync_info_t)); +} + +static int get_next_frame(char *buffer, int size) +{ + + int clone_flag; + + int i, ret=0; + + double drift=0; + + sync_info_t ptr; + + // read next log file entry: + + //default + clone_flag=1; + + if(sync_disabled_flag) goto read_only; + + if(verbose & TC_SYNC) + tc_log_msg(__FILE__, "----------------- reading syncinfo (%d)", sync_ctr); + + if((i=buffered_p_read((char *) &ptr)) != sizeof(sync_info_t)) { + + if(verbose & TC_DEBUG) { + tc_log_msg(__FILE__, "read error (%d/%ld)", i, (long)sizeof(sync_info_t)); + } + + //no more frames? + sync_disabled_flag=1; + + return(-1); + } + + //only relevant information + clone_flag = ptr.adj_frame; + + // infos: + + if(verbose & TC_COUNTER) { + if(ptr.sequence != seq_dis) { + + drift = ptr.dec_fps - fps; + + tc_log_msg(__FILE__, "frame=%6ld seq=%4ld adj=%4d AV=%8.4f [fps] ratio= %.4f PTS= %.2f", + ptr.enc_frame, ptr.sequence, drop_ctr, drift, + ((fps>0)?ptr.enc_fps/fps:0.0f), ptr.pts); + if(ptr.drop_seq) { + tc_log_msg(__FILE__, "MPEG sequence (%ld) dropped for AV sync correction", + ptr.sequence); + } + seq_dis=ptr.sequence; + } + } + + drop_ctr += (clone_flag-1); + tc_update_frames_dropped(clone_flag-1); + + ++sync_ctr; + + read_only: + + if(verbose & TC_SYNC) + tc_log_msg(__FILE__, "reading frame (%d)", frame_ctr); + ret = fread(buffer, size, 1, pfd); + + if(ret!=1) { + sync_disabled_flag=1; + return(-1); + } + ++frame_ctr; + + + // this number determines the number of frame copies, including master + // frame + + // ---------------------------------------------------------------- + // + // new: reverse 3:2 pulldown (inverse telecine) + // currently, only a few number of hardcoded sequences + // indicated by pulldown flag, are supported, s. below: + + if(ptr.pulldown > 0) + ivtc(&clone_flag, ptr.pulldown, buffer, pulldown_buffer, width, height, size, vcodec, verbose); + + //free frame info buffer + frame_info_remove(fiptr); + fiptr=NULL; + + return(clone_flag); +} + +//import API +int clone_frame(char *buffer, int size) +{ + + int i=0; + + if(clone_ctr) { + + //copy already buffered frame + + ac_memcpy(buffer, video_buffer, size); + + --clone_ctr; + return(0); + } + + //we loop until we have a valid frame; + + for (;;) { + + i=get_next_frame(buffer, size); + + //error or eos + if(i==-1) return(-1); + + if(i==1) return(0); //unique frame, already loaded in buffer + + if(i>1) { + + //frame will be cloned. We need to get a copy first + + ac_memcpy(video_buffer, buffer, size); + + clone_ctr=i-1; + return(0); + } + //frame dropped, get next one + } + + return(0); +} + +void clone_close() +{ + void *status; + + // cancel the thread + if (thread) { + pthread_cancel(thread); +#ifdef BROKEN_PTHREADS // Used to be MacOSX specific; kernel 2.6 as well? + pthread_cond_signal(&buffer_fill_cv); +#endif + pthread_join(thread, &status); + thread = (pthread_t)0; + } + + //reentrance safe + + if(video_buffer != NULL) free(video_buffer); + video_buffer=NULL; + + if(pulldown_buffer != NULL) free(pulldown_buffer); + pulldown_buffer=NULL; + + if(sfd>0) { + + close(sfd); + unlink(logfile); + + free(logfile); + sfd=0; + } + + if (pfd) pclose(pfd); + pfd = NULL; +} + +char *clone_fifo() +{ + + char *name, *a, b[PATH_MAX]; + + //need to create a pipe here + if ((a = getenv("TMPDIR")) != NULL) + tc_snprintf(b, PATH_MAX, "%s/%s", a, "fileXXXXXX"); + else + tc_snprintf(b, PATH_MAX, "%s/%s", "/tmp", "fileXXXXXX"); + + name = mktemp(b); + + logfile=tc_strdup(name); + +#ifdef USE_FIFO_LOGFILE + if(mkfifo(logfile, 0666)<0) { + tc_log_perror(__FILE__, "create FIFO"); + return(NULL); + } +#endif + + return(logfile); +} + +void clone_read_thread() +{ + frame_info_list_t *ptr = NULL; + + int i=0, j=0; + + for(;;) { + + if((ptr = frame_info_register(i))==NULL) { + + tc_log_error(__FILE__, "could not allocate a frame info buffer"); + + pthread_mutex_lock(&buffer_fill_lock); + clone_read_thread_flag=0; + pthread_mutex_unlock(&buffer_fill_lock); + pthread_exit(0); + return; + } + + if((ptr->sync_info = tc_zalloc(sizeof(sync_info_t)))==NULL) { + tc_log_error(__FILE__, "out of memory"); + pthread_mutex_lock(&buffer_fill_lock); + clone_read_thread_flag=0; + pthread_mutex_unlock(&buffer_fill_lock); + pthread_exit(0); + } + + if(verbose & TC_SYNC) + tc_log_msg(__FILE__, "READ (%d)", i); + + if((j=tc_pread(sfd, (uint8_t *) ptr->sync_info, sizeof(sync_info_t))) != sizeof(sync_info_t)) { + + if(verbose & TC_DEBUG) + tc_log_msg(__FILE__, "tc_pread error (%d/%ld)", j, (long)sizeof(sync_info_t)); + pthread_mutex_lock(&buffer_fill_lock); + clone_read_thread_flag=0; + pthread_mutex_unlock(&buffer_fill_lock); + pthread_exit(0); + } + + // ready for encoding + frame_info_set_status(ptr, FRAME_INFO_READY); + + pthread_mutex_lock(&buffer_fill_lock); + ++buffer_fill_ctr; + //tc_log_msg(__FILE__, "fill (%d)", buffer_fill_ctr); + //notify import thread + pthread_cond_signal(&buffer_fill_cv); + pthread_mutex_unlock(&buffer_fill_lock); + + + ++i; + } + + return; +} + |
