From 6e643239d9956ce32888d87451706ee7c8757afa Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 12 Aug 2013 10:56:20 +0000 Subject: [PATCH] pngdec: frame multithreading support Signed-off-by: Paul B Mahol --- libavcodec/pngdec.c | 69 +++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 1358ac5c5c..16225db277 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,17 @@ 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; + 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 +641,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 +828,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 +848,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; @@ -860,20 +869,39 @@ static int decode_frame(AVCodecContext *avctx, fail: av_dict_free(&metadata); ret = AVERROR_INVALIDDATA; + ff_thread_release_buffer(avctx, &s->picture); 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,10 @@ static av_cold int png_dec_end(AVCodecContext *avctx) { PNGDecContext *s = avctx->priv_data; - av_frame_free(&s->prev); + ff_thread_release_buffer(avctx, &s->last_picture); + av_frame_free(&s->last_picture.f); + ff_thread_release_buffer(avctx, &s->picture); + av_frame_free(&s->picture.f); return 0; } @@ -895,6 +926,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"), };