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