[FFmpeg-devel] [PATCH] pngdec: frame multithreading support
Paul B Mahol
onemda at gmail.com
Wed Aug 21 01:04:58 CEST 2013
Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
libavcodec/pngdec.c | 71 +++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 53 insertions(+), 18 deletions(-)
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index 1358ac5..dcdbb2f 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -28,6 +28,7 @@
#include "internal.h"
#include "png.h"
#include "pngdsp.h"
+#include "thread.h"
/* TODO:
* - add 16 bit depth support
@@ -40,7 +41,8 @@ typedef struct PNGDecContext {
AVCodecContext *avctx;
GetByteContext gb;
- AVFrame *prev;
+ ThreadFrame last_picture;
+ ThreadFrame picture;
int state;
int width, height;
@@ -505,13 +507,18 @@ static int decode_frame(AVCodecContext *avctx,
PNGDecContext * const s = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
- AVFrame *p = data;
+ AVFrame *p;
AVDictionary *metadata = NULL;
uint8_t *crow_buf_base = NULL;
uint32_t tag, length;
int64_t sig;
int ret;
+ if (s->last_picture.f)
+ ff_thread_release_buffer(avctx, &s->last_picture);
+ FFSWAP(ThreadFrame, s->picture, s->last_picture);
+ p = s->picture.f;
+
bytestream2_init(&s->gb, buf, buf_size);
/* check signature */
@@ -635,8 +642,10 @@ static int decode_frame(AVCodecContext *avctx,
goto fail;
}
- if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0)
+ if (ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF) < 0)
goto fail;
+ ff_thread_finish_setup(avctx);
+
p->pict_type = AV_PICTURE_TYPE_I;
p->key_frame = 1;
p->interlaced_frame = !!s->interlace_type;
@@ -820,16 +829,17 @@ static int decode_frame(AVCodecContext *avctx,
}
/* handle p-frames only if a predecessor frame is available */
- if (s->prev->data[0]) {
+ if (s->last_picture.f->data[0]) {
if ( !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG")
- && s->prev->width == p->width
- && s->prev->height== p->height
- && s->prev->format== p->format
+ && s->last_picture.f->width == p->width
+ && s->last_picture.f->height== p->height
+ && s->last_picture.f->format== p->format
) {
int i, j;
uint8_t *pd = p->data[0];
- uint8_t *pd_last = s->prev->data[0];
+ uint8_t *pd_last = s->last_picture.f->data[0];
+ ff_thread_await_progress(&s->last_picture, INT_MAX, 0);
for (j = 0; j < s->height; j++) {
for (i = 0; i < s->width * s->bpp; i++) {
pd[i] += pd_last[i];
@@ -839,13 +849,13 @@ static int decode_frame(AVCodecContext *avctx,
}
}
}
+ ff_thread_report_progress(&s->picture, INT_MAX, 0);
av_frame_set_metadata(p, metadata);
metadata = NULL;
- av_frame_unref(s->prev);
- if ((ret = av_frame_ref(s->prev, p)) < 0)
- goto fail;
+ if ((ret = av_frame_ref(data, s->picture.f)) < 0)
+ return ret;
*got_frame = 1;
@@ -863,17 +873,35 @@ static int decode_frame(AVCodecContext *avctx,
goto the_end;
}
+static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
+{
+ PNGDecContext *psrc = src->priv_data;
+ PNGDecContext *pdst = dst->priv_data;
+
+ if (dst == src)
+ return 0;
+
+ ff_thread_release_buffer(dst, &pdst->picture);
+ if (psrc->picture.f->data[0])
+ return ff_thread_ref_frame(&pdst->picture, &psrc->picture);
+
+ return 0;
+}
+
static av_cold int png_dec_init(AVCodecContext *avctx)
{
PNGDecContext *s = avctx->priv_data;
- s->prev = av_frame_alloc();
- if (!s->prev)
+ s->avctx = avctx;
+ s->last_picture.f = av_frame_alloc();
+ s->picture.f = av_frame_alloc();
+ if (!s->last_picture.f || !s->picture.f)
return AVERROR(ENOMEM);
- ff_pngdsp_init(&s->dsp);
-
- s->avctx = avctx;
+ if (!avctx->internal->is_copy) {
+ avctx->internal->allocate_progress = 1;
+ ff_pngdsp_init(&s->dsp);
+ }
return 0;
}
@@ -882,7 +910,12 @@ static av_cold int png_dec_end(AVCodecContext *avctx)
{
PNGDecContext *s = avctx->priv_data;
- av_frame_free(&s->prev);
+ if (s->last_picture.f)
+ ff_thread_release_buffer(avctx, &s->last_picture);
+ av_frame_free(&s->last_picture.f);
+ if (s->picture.f)
+ ff_thread_release_buffer(avctx, &s->picture);
+ av_frame_free(&s->picture.f);
return 0;
}
@@ -895,6 +928,8 @@ AVCodec ff_png_decoder = {
.init = png_dec_init,
.close = png_dec_end,
.decode = decode_frame,
- .capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
+ .init_thread_copy = ONLY_IF_THREADS_ENABLED(png_dec_init),
+ .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
+ .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
.long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"),
};
--
1.7.11.2
More information about the ffmpeg-devel
mailing list