mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
pngdec: frame multithreading support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
f903b42663
commit
6e643239d9
@ -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"),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user