[FFmpeg-devel] [PATCH] ffmpeg: make reading packets from thread blocking.

Nicolas George george at nsup.org
Fri Oct 25 11:33:00 CEST 2013


If a packet is not ready on the input selected by ffmpeg,
it will read from another input instead. If that happens
repeatedly, frames will accumulate somewhere later in the
processing to ensure streams synchronization. It can happen
in particular when reading from a slow medium or an
expensive lavfi filter graph.

Make reading from normal demuxers on non-streamed data and
from the lavfi pseudo-device blocking to avoid that.

Should fix trac ticket #3079.

Signed-off-by: Nicolas George <george at nsup.org>
---
 ffmpeg.c | 17 +++++++++++++++--
 ffmpeg.h |  1 +
 2 files changed, 16 insertions(+), 2 deletions(-)


Note: the non_blocking flag can be later made an option. But I am in fact
rather convinced that the blocking mode should be made the default even for
devices, possibly enlarging the size of the FIFO at the same time.


diff --git a/ffmpeg.c b/ffmpeg.c
index 001e5c1..ff717d5 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2795,6 +2795,7 @@ static void *input_thread(void *arg)
 
         av_dup_packet(&pkt);
         av_fifo_generic_write(f->fifo, &pkt, sizeof(pkt), NULL);
+        pthread_cond_signal(&f->fifo_cond);
 
         pthread_mutex_unlock(&f->fifo_lock);
     }
@@ -2851,6 +2852,10 @@ static int init_input_threads(void)
         if (!(f->fifo = av_fifo_alloc(8*sizeof(AVPacket))))
             return AVERROR(ENOMEM);
 
+        if (f->ctx->pb ? !f->ctx->pb->seekable :
+            strcmp(f->ctx->iformat->name, "lavfi"))
+            f->non_blocking = 1;
+
         pthread_mutex_init(&f->fifo_lock, NULL);
         pthread_cond_init (&f->fifo_cond, NULL);
 
@@ -2866,14 +2871,22 @@ static int get_input_packet_mt(InputFile *f, AVPacket *pkt)
 
     pthread_mutex_lock(&f->fifo_lock);
 
+    while (1) {
     if (av_fifo_size(f->fifo)) {
         av_fifo_generic_read(f->fifo, pkt, sizeof(*pkt), NULL);
         pthread_cond_signal(&f->fifo_cond);
+        break;
     } else {
-        if (f->finished)
+        if (f->finished) {
             ret = AVERROR_EOF;
-        else
+            break;
+        }
+        if (f->non_blocking) {
             ret = AVERROR(EAGAIN);
+            break;
+        }
+        pthread_cond_wait(&f->fifo_cond, &f->fifo_lock);
+    }
     }
 
     pthread_mutex_unlock(&f->fifo_lock);
diff --git a/ffmpeg.h b/ffmpeg.h
index 054e718..4dc10ff 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -293,6 +293,7 @@ typedef struct InputFile {
 
 #if HAVE_PTHREADS
     pthread_t thread;           /* thread reading from this file */
+    int non_blocking;           /* reading packets from the thread should not block */
     int finished;               /* the thread has exited */
     int joined;                 /* the thread has been joined */
     pthread_mutex_t fifo_lock;  /* lock for access to fifo */
-- 
1.8.4.rc3



More information about the ffmpeg-devel mailing list