[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