diff options
| author | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
|---|---|---|
| committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2020-09-11 14:38:47 +0900 |
| commit | 884c8093d63402a1ad0b502244b791e3c6782be3 (patch) | |
| tree | a600d4ab0d431a2bdfe4c15b70df43c14fbd8dd0 /debian/transcode/transcode-1.1.7/src/frame_threads.c | |
| parent | 14e1aa2006796f147f3f4811fb908a6b01e79253 (diff) | |
| download | extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.tar.gz extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.zip | |
Added debian extra dependency packages.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'debian/transcode/transcode-1.1.7/src/frame_threads.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/src/frame_threads.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/src/frame_threads.c b/debian/transcode/transcode-1.1.7/src/frame_threads.c new file mode 100644 index 00000000..95a7ef7e --- /dev/null +++ b/debian/transcode/transcode-1.1.7/src/frame_threads.c @@ -0,0 +1,376 @@ +/* + * frame_threads.c -- implementation of transcode multithreaded filter + * processing code. + * + * Copyright (C) Thomas Oestreich - June 2001 + * updates and partial rewrite: + * Copyright (C) Francesco Romani - October 2007 + * + * 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 <pthread.h> + +#include "transcode.h" +#include "encoder-common.h" +#include "framebuffer.h" +#include "video_trans.h" +#include "audio_trans.h" +#include "decoder.h" +#include "filter.h" + +#include "frame_threads.h" + +/*************************************************************************/ + +typedef struct tcframethreaddata_ TCFrameThreadData; +struct tcframethreaddata_ { + pthread_t threads[TC_FRAME_THREADS_MAX]; /* thread pool */ + int count; /* how many workers? */ + + pthread_mutex_t lock; + volatile int running; /* _pool_ running flag */ +}; + +TCFrameThreadData audio_threads = { + .count = 0, + .lock = PTHREAD_MUTEX_INITIALIZER, + .running = TC_FALSE, +}; + +TCFrameThreadData video_threads = { + .count = 0, + .lock = PTHREAD_MUTEX_INITIALIZER, + .running = TC_FALSE, +}; + +/*************************************************************************/ + +/* + * tc_frame_threads_stop (Thread safe): + * set the stop flag for a thread pool. + * + * Parameters: + * data: thread pool descriptor. + * Return Value: + * None. + */ +static void tc_frame_threads_stop(TCFrameThreadData *data) +{ + pthread_mutex_lock(&data->lock); + data->running = TC_FALSE; + pthread_mutex_unlock(&data->lock); +} + +/* + * tc_frame_threads_are_active (Thread safe): + * verify if there is a pending stop request for given thread pool. + * + * Parameters: + * data: thread pool descriptor. + * Return Value: + * !0: there is pending pool stop request. + * 0: otherwise. + */ +static int tc_frame_threads_are_active(TCFrameThreadData *data) +{ + int ret; + pthread_mutex_lock(&data->lock); + ret = data->running; + pthread_mutex_unlock(&data->lock); + return ret; +} + +/* + * stop_requested: verify if the pool thread has to stop. + * First thread in the pool notifying the core has to stop must + * set the flag to notify the others. + * + * Parameters: + * data: thread pool descriptor. + * Return Value: + * !0: thread pool has to halt as soon as is possible. + * 0: thread pool can continue to run. + */ +static int stop_requested(TCFrameThreadData *data) +{ + return (!tc_running() || !tc_frame_threads_are_active(data)); +} + + +/*************************************************************************/ +/* frame processing core threads */ +/*************************************************************************/ + + +#define DUP_vptr_if_cloned(vptr) do { \ + if(vptr->attributes & TC_FRAME_IS_CLONED) { \ + vframe_list_t *tmptr = vframe_dup(vptr); \ + \ + /* ptr was successfully cloned */ \ + /* delete clone flag */ \ + tmptr->attributes &= ~TC_FRAME_IS_CLONED; \ + vptr->attributes &= ~TC_FRAME_IS_CLONED; \ + \ + /* set info for filters */ \ + tmptr->attributes |= TC_FRAME_WAS_CLONED; \ + \ + /* this frame is to be processed _after_ the current one */ \ + /* so put it back into the queue */ \ + vframe_push_next(tmptr, TC_FRAME_WAIT); \ + \ + } \ +} while (0) + + + +#define DUP_aptr_if_cloned(aptr) do { \ + if(aptr->attributes & TC_FRAME_IS_CLONED) { \ + aframe_list_t *tmptr = aframe_dup(aptr); \ + \ + /* ptr was successfully cloned */ \ + \ + /* delete clone flag */ \ + tmptr->attributes &= ~TC_FRAME_IS_CLONED; \ + aptr->attributes &= ~TC_FRAME_IS_CLONED; \ + \ + /* set info for filters */ \ + tmptr->attributes |= TC_FRAME_WAS_CLONED; \ + \ + /* this frame is to be processed _after_ the current one */ \ + /* so put it back into the queue */ \ + aframe_push_next(tmptr, TC_FRAME_WAIT); \ + \ + } \ +} while (0) + + +#define SET_STOP_FLAG(DATAP, MSG) do { \ + if (verbose >= TC_CLEANUP) \ + tc_log_msg(__FILE__, "%s", (MSG)); \ + tc_frame_threads_stop((DATAP)); \ +} while (0) + +static void *process_video_frame(void *_vob) +{ + static int res = 0; // XXX + vframe_list_t *ptr = NULL; + vob_t *vob = _vob; + + while (!stop_requested(&video_threads)) { + ptr = vframe_reserve(); + if (ptr == NULL) { + SET_STOP_FLAG(&video_threads, "video interrupted: exiting!"); + res = 1; + break; + } + if (ptr->attributes & TC_FRAME_IS_END_OF_STREAM) { + SET_STOP_FLAG(&video_threads, "video stream end: marking!"); + } + + if (ptr->attributes & TC_FRAME_IS_SKIPPED) { + vframe_remove(ptr); /* release frame buffer memory */ + continue; + } + + if (TC_FRAME_NEED_PROCESSING(ptr)) { + // external plugin pre-processing + ptr->tag = TC_VIDEO|TC_PRE_M_PROCESS; + tc_filter_process((frame_list_t *)ptr); + + if (ptr->attributes & TC_FRAME_IS_SKIPPED) { + vframe_remove(ptr); /* release frame buffer memory */ + continue; + } + + // clone if the filter told us to do so. + DUP_vptr_if_cloned(ptr); + + // internal processing of video + ptr->tag = TC_VIDEO; + process_vid_frame(vob, ptr); + + // external plugin post-processing + ptr->tag = TC_VIDEO|TC_POST_M_PROCESS; + tc_filter_process((frame_list_t *)ptr); + + if (ptr->attributes & TC_FRAME_IS_SKIPPED) { + vframe_remove(ptr); /* release frame buffer memory */ + continue; + } + } + + vframe_push_next(ptr, TC_FRAME_READY); + } + if (verbose >= TC_CLEANUP) + tc_log_msg(__FILE__, "video stream end: got, so exiting!"); + + pthread_exit(&res); + return NULL; +} + + +static void *process_audio_frame(void *_vob) +{ + static int res = 0; // XXX + aframe_list_t *ptr = NULL; + vob_t *vob = _vob; + + while (!stop_requested(&audio_threads)) { + ptr = aframe_reserve(); + if (ptr == NULL) { + SET_STOP_FLAG(&audio_threads, "audio interrupted: exiting!"); + break; + res = 1; + } + if (ptr->attributes & TC_FRAME_IS_END_OF_STREAM) { + SET_STOP_FLAG(&audio_threads, "audio stream end: marking!"); + } + + if (ptr->attributes & TC_FRAME_IS_SKIPPED) { + aframe_remove(ptr); /* release frame buffer memory */ + continue; + } + + if (TC_FRAME_NEED_PROCESSING(ptr)) { + // external plugin pre-processing + ptr->tag = TC_AUDIO|TC_PRE_M_PROCESS; + tc_filter_process((frame_list_t *)ptr); + + DUP_aptr_if_cloned(ptr); + + if (ptr->attributes & TC_FRAME_IS_SKIPPED) { + aframe_remove(ptr); /* release frame buffer memory */ + continue; + } + + // internal processing of audio + ptr->tag = TC_AUDIO; + process_aud_frame(vob, ptr); + + // external plugin post-processing + ptr->tag = TC_AUDIO|TC_POST_M_PROCESS; + tc_filter_process((frame_list_t *)ptr); + + if (ptr->attributes & TC_FRAME_IS_SKIPPED) { + aframe_remove(ptr); /* release frame buffer memory */ + continue; + } + } + + aframe_push_next(ptr, TC_FRAME_READY); + } + if (verbose >= TC_CLEANUP) + tc_log_msg(__FILE__, "audio stream end: got, so exiting!"); + + pthread_exit(&res); + return NULL; +} + +/*************************************************************************/ + + +int tc_frame_threads_have_video_workers(void) +{ + return (video_threads.count > 0); +} + +int tc_frame_threads_have_audio_workers(void) +{ + return (audio_threads.count > 0); +} + + +void tc_frame_threads_init(vob_t *vob, int vworkers, int aworkers) +{ + int n = 0; + + if (vworkers > 0 && !video_threads.running) { + video_threads.count = vworkers; + video_threads.running = TC_TRUE; /* enforce, needed when restarting */ + + if (verbose >= TC_DEBUG) + tc_log_info(__FILE__, "starting %i video frame" + " processing thread(s)", vworkers); + + // start the thread pool + for (n = 0; n < vworkers; n++) { + if (pthread_create(&video_threads.threads[n], NULL, + process_video_frame, vob) != 0) + tc_error("failed to start video frame processing thread"); + } + } + + if (aworkers > 0 && !audio_threads.running) { + audio_threads.count = aworkers; + audio_threads.running = TC_TRUE; /* enforce, needed when restarting */ + + if (verbose >= TC_DEBUG) + tc_log_info(__FILE__, "starting %i audio frame" + " processing thread(s)", aworkers); + + // start the thread pool + for (n = 0; n < aworkers; n++) { + if (pthread_create(&audio_threads.threads[n], NULL, + process_audio_frame, vob) != 0) + tc_error("failed to start audio frame processing thread"); + } + } + return; +} + +void tc_frame_threads_close(void) +{ + void *status = NULL; + int n = 0; + + if (audio_threads.count > 0) { + tc_frame_threads_stop(&audio_threads); + if (verbose >= TC_CLEANUP) + tc_log_msg(__FILE__, "wait for %i audio frame processing threads", + audio_threads.count); + for (n = 0; n < audio_threads.count; n++) + pthread_join(audio_threads.threads[n], &status); + if (verbose >= TC_CLEANUP) + tc_log_msg(__FILE__, "audio frame processing threads canceled"); + } + + if (video_threads.count > 0) { + tc_frame_threads_stop(&video_threads); + if (verbose >= TC_CLEANUP) + tc_log_msg(__FILE__, "wait for %i video frame processing threads", + video_threads.count); + for (n = 0; n < video_threads.count; n++) + pthread_join(video_threads.threads[n], &status); + if (verbose >= TC_CLEANUP) + tc_log_msg(__FILE__, "video frame processing threads canceled"); + } +} + + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ |
