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