2014-07-23 21:20 GMT+02:00 Christophe Gisquet <christophe.gisq...@gmail.com>:
> Didn't refresh the patch with update documentation. Here it is.

It didn't contain dummy functions in libavcodec/utils.c.

The attached patch should fix failures to build with pthread disabled.

-- 
Christophe
From 4a144438e5dcd66be173b2d23f310bb4eacec24d Mon Sep 17 00:00:00 2001
From: Christophe Gisquet <christophe.gisq...@gmail.com>
Date: Fri, 18 Jul 2014 19:19:06 +0200
Subject: [PATCH 04/15] libavcodec: new API for frame threading by step

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.
---
 doc/multithreading.txt     |   23 ++++++++++++++-
 libavcodec/pthread_frame.c |   68 ++++++++++++++++++++++++++++++++++++++++++-
 libavcodec/thread.h        |   24 +++++++++++++++
 libavcodec/utils.c         |   12 ++++++++
 4 files changed, 124 insertions(+), 3 deletions(-)

diff --git a/doc/multithreading.txt b/doc/multithreading.txt
index 2b992fc..30e7219 100644
--- a/doc/multithreading.txt
+++ b/doc/multithreading.txt
@@ -1,7 +1,7 @@
 FFmpeg multithreading methods
 ==============================================
 
-FFmpeg provides two methods for multithreading codecs.
+FFmpeg provides three methods for multithreading codecs.
 
 Slice threading decodes multiple parts of a frame at the same time, using
 AVCodecContext execute() and execute2().
@@ -11,6 +11,9 @@ It accepts N future frames and delays decoded pictures by N-1 frames.
 The later frames are decoded in separate threads while the user is
 displaying the current one.
 
+Frame step threading is similar to frame threading except the progress is
+measured in a finer way.
+
 Restrictions on clients
 ==============================================
 
@@ -26,6 +29,9 @@ Frame threading -
   Clients must be able to handle this; the pkt_dts and pkt_pts fields in
   AVFrame will work as usual.
 
+Frame step threading -
+* Same as frame threading
+
 Restrictions on codec implementations
 ==============================================
 
@@ -42,6 +48,10 @@ Frame threading -
 * The contents of buffers must not be written to after ff_thread_report_progress()
   has been called on them. This includes draw_edges().
 
+Frame step threadin -
+* The progress must be in raster scan.
+* Raster lines must be reported in order.
+
 Porting codecs to frame threading
 ==============================================
 
@@ -68,3 +78,14 @@ called anywhere, as it's useful too and the implementation is trivial when you'r
 doing this. Note that draw_edges() needs to be called before reporting progress.
 
 Before accessing a reference frame or its MVs, call ff_thread_await_progress().
+
+Porting codecs to frame step threading
+==============================================
+
+Instead of using {report,await}_progress() with the ordinate:
+- You can signal a raster line end by passing the line ordinate to
+  ff_thread_report_progress3_raster_end;
+- You should signal intermediate progress by passing the x,y progress
+  as well as the expected step since last progress to
+  ff_thread_report_progress3_increment;
+- ff_thread_await_progress3 now takes x,y parameters.
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 */
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 6071380..31d240a 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -3556,6 +3556,18 @@ void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, in
 {
 }
 
+void ff_thread_report_progress3_raster_end(ThreadFrame *f, int y)
+{
+}
+
+void ff_thread_report_progress3_increment(ThreadFrame *f, int x, int y, int step);
+{
+}
+
+void ff_thread_await_progress3(ThreadFrame *f, int x, int y)
+{
+}
+
 #endif
 
 enum AVMediaType avcodec_get_type(enum AVCodecID codec_id)
-- 
1.7.7.6

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to