summaryrefslogtreecommitdiff
path: root/src/xine-engine/demux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/demux.c')
-rw-r--r--src/xine-engine/demux.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c
index 59339f0e2..1fb4dac2c 100644
--- a/src/xine-engine/demux.c
+++ b/src/xine-engine/demux.c
@@ -23,10 +23,16 @@
* $id$
*/
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
#include "xine_internal.h"
#include "demuxers/demux.h"
#include "buffer.h"
+#define LOG
+
+
/* internal use only - called from demuxers on seek/stop
* warning: after clearing decoders fifos an absolute discontinuity
* indication must be sent. relative discontinuities are likely
@@ -121,3 +127,120 @@ void xine_demux_control_end( xine_stream_t *stream, uint32_t flags ) {
stream->audio_fifo->put (stream->audio_fifo, buf);
}
}
+
+static void *demux_loop (void *stream_gen) {
+
+ xine_stream_t *stream = (xine_stream_t *)stream_gen;
+ int status;
+
+#ifdef LOG
+ printf ("demux: loop starting...\n");
+#endif
+
+ pthread_mutex_lock( &stream->demux_lock );
+
+ /* do-while needed to seek after demux finished */
+ do {
+
+ /* main demuxer loop */
+ status = stream->demux_plugin->get_status(stream->demux_plugin);
+ while(status == DEMUX_OK && stream->demux_thread_running) {
+
+ status = stream->demux_plugin->send_chunk(stream->demux_plugin);
+
+ /* someone may want to interrupt us */
+ pthread_mutex_unlock( &stream->demux_lock );
+ pthread_mutex_lock( &stream->demux_lock );
+ }
+
+#ifdef LOG
+ printf ("demux: main demuxer loop finished (status: %d)\n", status);
+#endif
+ /* wait before sending end buffers: user might want to do a new seek */
+ while(stream->demux_thread_running &&
+ (!stream->video_fifo || stream->video_fifo->size(stream->video_fifo)) &&
+ (!stream->audio_fifo || stream->audio_fifo->size(stream->audio_fifo)) &&
+ status != DEMUX_OK ){
+ pthread_mutex_unlock( &stream->demux_lock );
+ xine_usec_sleep(100000);
+ pthread_mutex_lock( &stream->demux_lock );
+ status = stream->demux_plugin->get_status(stream->demux_plugin);
+ }
+
+ } while( status == DEMUX_OK && stream->demux_thread_running );
+
+#ifdef LOG
+ printf ("demux: loop finished (status: %d)\n", status);
+#endif
+
+ /* demux_thread_running is zero is demux loop has being stopped by user */
+ if (stream->demux_thread_running) {
+ xine_demux_control_end(stream, BUF_FLAG_END_STREAM);
+ } else {
+ xine_demux_control_end(stream, BUF_FLAG_END_USER);
+ }
+
+ stream->demux_thread_running = 0;
+ pthread_mutex_unlock( &stream->demux_lock );
+
+ pthread_exit(NULL);
+
+ return NULL;
+}
+
+int xine_demux_start_thread (xine_stream_t *stream) {
+
+ int err;
+
+#ifdef LOG
+ printf ("demux: start thread called\n");
+#endif
+
+ pthread_mutex_lock( &stream->demux_lock );
+
+ if( !stream->demux_thread_running ) {
+
+ stream->demux_thread_running = 1;
+ if ((err = pthread_create (&stream->demux_thread,
+ NULL, demux_loop, (void *)stream)) != 0) {
+ printf ("demux: can't create new thread (%s)\n",
+ strerror(err));
+ abort();
+ }
+ }
+
+ pthread_mutex_unlock( &stream->demux_lock );
+ return 0;
+}
+
+int xine_demux_stop_thread (xine_stream_t *stream) {
+
+ void *p;
+
+#ifdef LOG
+ printf ("demux: stop thread called\n");
+#endif
+
+ pthread_mutex_lock( &stream->demux_lock );
+ stream->demux_thread_running = 0;
+ pthread_mutex_unlock( &stream->demux_lock );
+
+#ifdef LOG
+ printf ("demux: joining thread %d\n", stream->demux_thread );
+#endif
+
+ /* FIXME: counter_lock isn't meant to protect demux_thread update.
+ however we can't use demux_lock here. should we create a new lock? */
+ pthread_mutex_lock (&stream->counter_lock);
+
+ /* <join; demux_thread = 0;> must be atomic */
+ if( stream->demux_thread )
+ pthread_join (stream->demux_thread, &p);
+ stream->demux_thread = 0;
+
+ pthread_mutex_unlock (&stream->counter_lock);
+
+ xine_demux_flush_engine(stream);
+
+ return 0;
+}