[FFmpeg-devel] [PATCH 1/4] libavcodec: new API for frame threading by step

Christophe Gisquet christophe.gisquet at gmail.com
Wed Jul 23 21:13:43 CEST 2014


The new _progress3 functions allow reporting the x,y position in
decoding.

ff_thread_report_progress3_raster_end allows signaling the end of
a raster line and updates unconditionally the position to the
start of next raster line.

ff_thread_report_progress3_increment tries to increment position
if it lies on the same raster line as current position.
---
 libavcodec/pthread_frame.c | 68 ++++++++++++++++++++++++++++++++++++++++++++--
 libavcodec/thread.h        | 24 ++++++++++++++++
 2 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 2a67f4d..9896bba 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -488,6 +488,51 @@ void ff_thread_report_progress(ThreadFrame *f, int n, int field)
     pthread_mutex_unlock(&p->progress_mutex);
 }
 
+void ff_thread_report_progress3_raster_end(ThreadFrame *f, int y)
+{
+    PerThreadContext *p;
+    volatile int *progress = f->progress ? (int*)f->progress->data : NULL;
+
+    if (!progress || progress[0] > y || progress[1] > y )
+        return;
+
+    p = f->owner->internal->thread_ctx;
+
+    if (f->owner->debug&FF_DEBUG_THREADS)
+        av_log(f->owner, AV_LOG_DEBUG, "%p finished line %d\n", progress, y);
+
+    pthread_mutex_lock(&p->progress_mutex);
+    progress[0] = y;
+    progress[1] = y;
+    progress[2] = 0;
+    pthread_cond_broadcast(&p->progress_cond);
+    pthread_mutex_unlock(&p->progress_mutex);
+}
+
+void ff_thread_report_progress3_increment(ThreadFrame *f, int x, int y, int step)
+{
+    PerThreadContext *p;
+    volatile int *progress = f->progress ? (int*)f->progress->data : NULL;
+
+    if (!progress || (progress[0]!=-1 && y != progress[0])) return;
+    // Until a line is completed, increments on x from next line are ignored,
+    // therefore allow horizontal jumps in case they are on the expect line
+    if (progress[0] != progress[1] && progress[2]+step != x) return;
+
+    p = f->owner->internal->thread_ctx;
+
+    if (f->owner->debug&FF_DEBUG_THREADS)
+        av_log(f->owner, AV_LOG_DEBUG, "%p finished up to (%d,%d)/%d\n",
+               progress, x, y, step);
+
+    pthread_mutex_lock(&p->progress_mutex);
+    progress[0] = y;
+    progress[1] = y + step;
+    progress[2] = x;
+    pthread_cond_broadcast(&p->progress_cond);
+    pthread_mutex_unlock(&p->progress_mutex);
+}
+
 void ff_thread_await_progress(ThreadFrame *f, int n, int field)
 {
     PerThreadContext *p;
@@ -506,6 +551,25 @@ void ff_thread_await_progress(ThreadFrame *f, int n, int field)
     pthread_mutex_unlock(&p->progress_mutex);
 }
 
+void ff_thread_await_progress3(ThreadFrame *f, int x, int y)
+{
+    PerThreadContext *p;
+    volatile int *progress = f->progress ? (int*)f->progress->data : NULL;
+
+    if (!progress || progress[0] >= y ||
+        (progress[2] >= x && progress[1] >= y)) return;
+
+    p = f->owner->internal->thread_ctx;
+
+    if (f->owner->debug&FF_DEBUG_THREADS)
+        av_log(f->owner, AV_LOG_DEBUG, "thread awaiting (%d,%d) point in %p\n", x, y, progress);
+
+    pthread_mutex_lock(&p->progress_mutex);
+    while (progress[0] < y && (progress[2] < x || progress[1] < y))
+        pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
+    pthread_mutex_unlock(&p->progress_mutex);
+}
+
 void ff_thread_finish_setup(AVCodecContext *avctx) {
     PerThreadContext *p = avctx->internal->thread_ctx;
 
@@ -766,13 +830,13 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
 
     if (avctx->internal->allocate_progress) {
         int *progress;
-        f->progress = av_buffer_alloc(2 * sizeof(int));
+        f->progress = av_buffer_alloc(3 * sizeof(int));
         if (!f->progress) {
             return AVERROR(ENOMEM);
         }
         progress = (int*)f->progress->data;
 
-        progress[0] = progress[1] = -1;
+        progress[0] = progress[1] = progress[2] = -1;
     }
 
     pthread_mutex_lock(&p->parent->buffer_mutex);
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index c848d7a..ca1bf81 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -140,4 +140,28 @@ void ff_reset_entries(AVCodecContext *avctx);
 void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n);
 void ff_thread_await_progress2(AVCodecContext *avctx,  int field, int thread, int shift);
 
+/**
+ * Report end of a line in raster order: change current raster line and refresh
+ * position.
+ * @param f     The picture being decoded.
+ * @param y     Ordinate of the finished line.
+ */
+void ff_thread_report_progress3_raster_end(ThreadFrame *f, int y);
+/**
+ * Report progress inside a raster line. If the progress does not correspond to
+ * an increment, it is ignored.
+ * @param f     The picture being decoded.
+ * @param x     Abscissa of the progress
+ * @param y     Ordinate of the progress
+ * @param step  Allowed increment
+ */
+void ff_thread_report_progress3_increment(ThreadFrame *f, int x, int y, int step);
+/**
+ * Wait for point to be in the decoded area.
+ * @param f     The picture being decoded.
+ * @param x     First coordinate.
+ * @param y     Second coordinate.
+ */
+void ff_thread_await_progress3(ThreadFrame *f, int x, int y);
+
 #endif /* AVCODEC_THREAD_H */
-- 
1.9.2.msysgit.0



More information about the ffmpeg-devel mailing list