Commit 6e643239 authored by Paul B Mahol's avatar Paul B Mahol

pngdec: frame multithreading support

Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent f903b426
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "internal.h" #include "internal.h"
#include "png.h" #include "png.h"
#include "pngdsp.h" #include "pngdsp.h"
#include "thread.h"
/* TODO: /* TODO:
* - add 16 bit depth support * - add 16 bit depth support
...@@ -40,7 +41,8 @@ typedef struct PNGDecContext { ...@@ -40,7 +41,8 @@ typedef struct PNGDecContext {
AVCodecContext *avctx; AVCodecContext *avctx;
GetByteContext gb; GetByteContext gb;
AVFrame *prev; ThreadFrame last_picture;
ThreadFrame picture;
int state; int state;
int width, height; int width, height;
...@@ -505,13 +507,17 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -505,13 +507,17 @@ static int decode_frame(AVCodecContext *avctx,
PNGDecContext * const s = avctx->priv_data; PNGDecContext * const s = avctx->priv_data;
const uint8_t *buf = avpkt->data; const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size; int buf_size = avpkt->size;
AVFrame *p = data; AVFrame *p;
AVDictionary *metadata = NULL; AVDictionary *metadata = NULL;
uint8_t *crow_buf_base = NULL; uint8_t *crow_buf_base = NULL;
uint32_t tag, length; uint32_t tag, length;
int64_t sig; int64_t sig;
int ret; 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); bytestream2_init(&s->gb, buf, buf_size);
/* check signature */ /* check signature */
...@@ -635,8 +641,10 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -635,8 +641,10 @@ static int decode_frame(AVCodecContext *avctx,
goto fail; 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; goto fail;
ff_thread_finish_setup(avctx);
p->pict_type = AV_PICTURE_TYPE_I; p->pict_type = AV_PICTURE_TYPE_I;
p->key_frame = 1; p->key_frame = 1;
p->interlaced_frame = !!s->interlace_type; p->interlaced_frame = !!s->interlace_type;
...@@ -820,16 +828,17 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -820,16 +828,17 @@ static int decode_frame(AVCodecContext *avctx,
} }
/* handle p-frames only if a predecessor frame is available */ /* 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") if ( !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG")
&& s->prev->width == p->width && s->last_picture.f->width == p->width
&& s->prev->height== p->height && s->last_picture.f->height== p->height
&& s->prev->format== p->format && s->last_picture.f->format== p->format
) { ) {
int i, j; int i, j;
uint8_t *pd = p->data[0]; 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 (j = 0; j < s->height; j++) {
for (i = 0; i < s->width * s->bpp; i++) { for (i = 0; i < s->width * s->bpp; i++) {
pd[i] += pd_last[i]; pd[i] += pd_last[i];
...@@ -839,13 +848,13 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -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); av_frame_set_metadata(p, metadata);
metadata = NULL; metadata = NULL;
av_frame_unref(s->prev); if ((ret = av_frame_ref(data, s->picture.f)) < 0)
if ((ret = av_frame_ref(s->prev, p)) < 0) return ret;
goto fail;
*got_frame = 1; *got_frame = 1;
...@@ -860,20 +869,39 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -860,20 +869,39 @@ static int decode_frame(AVCodecContext *avctx,
fail: fail:
av_dict_free(&metadata); av_dict_free(&metadata);
ret = AVERROR_INVALIDDATA; ret = AVERROR_INVALIDDATA;
ff_thread_release_buffer(avctx, &s->picture);
goto the_end; 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) static av_cold int png_dec_init(AVCodecContext *avctx)
{ {
PNGDecContext *s = avctx->priv_data; PNGDecContext *s = avctx->priv_data;
s->prev = av_frame_alloc(); s->avctx = avctx;
if (!s->prev) s->last_picture.f = av_frame_alloc();
s->picture.f = av_frame_alloc();
if (!s->last_picture.f || !s->picture.f)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
ff_pngdsp_init(&s->dsp); if (!avctx->internal->is_copy) {
avctx->internal->allocate_progress = 1;
s->avctx = avctx; ff_pngdsp_init(&s->dsp);
}
return 0; return 0;
} }
...@@ -882,7 +910,10 @@ static av_cold int png_dec_end(AVCodecContext *avctx) ...@@ -882,7 +910,10 @@ static av_cold int png_dec_end(AVCodecContext *avctx)
{ {
PNGDecContext *s = avctx->priv_data; 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; return 0;
} }
...@@ -895,6 +926,8 @@ AVCodec ff_png_decoder = { ...@@ -895,6 +926,8 @@ AVCodec ff_png_decoder = {
.init = png_dec_init, .init = png_dec_init,
.close = png_dec_end, .close = png_dec_end,
.decode = decode_frame, .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"), .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"),
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment