X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fqpeg.c;h=829e08aba1a962936ccadea4ed431c43cee78c03;hb=2606c48391377681541111263de41c79adeffa49;hp=d4195c5f0b7f145e7bbbf28dc894c8e0bed4b9ab;hpb=5c363d3e595a9e5b7c42897b7aab91b91b154ac1;p=ffmpeg diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c index d4195c5f0b7..829e08aba1a 100644 --- a/libavcodec/qpeg.c +++ b/libavcodec/qpeg.c @@ -26,11 +26,12 @@ #include "avcodec.h" #include "bytestream.h" +#include "decode.h" #include "internal.h" typedef struct QpegContext{ AVCodecContext *avctx; - AVFrame *pic, *ref; + AVFrame *ref; uint32_t pal[256]; GetByteContext buffer; } QpegContext; @@ -101,8 +102,11 @@ static void qpeg_decode_intra(QpegContext *qctx, uint8_t *dst, } else { if (bytestream2_get_bytes_left(&qctx->buffer) < copy) copy = bytestream2_get_bytes_left(&qctx->buffer); - for(i = 0; i < copy; i++) { - dst[filled++] = bytestream2_get_byte(&qctx->buffer); + while (copy > 0) { + int step = FFMIN(copy, width - filled); + bytestream2_get_bufferu(&qctx->buffer, dst + filled, step); + filled += step; + copy -= step; if (filled >= width) { filled = 0; dst -= stride; @@ -115,9 +119,9 @@ static void qpeg_decode_intra(QpegContext *qctx, uint8_t *dst, } } -static const int qpeg_table_h[16] = +static const uint8_t qpeg_table_h[16] = { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04}; -static const int qpeg_table_w[16] = +static const uint8_t qpeg_table_w[16] = { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04}; /* Decodes delta frames */ @@ -267,12 +271,10 @@ static int decode_frame(AVCodecContext *avctx, { uint8_t ctable[128]; QpegContext * const a = avctx->priv_data; - AVFrame * const p = a->pic; + AVFrame * const p = data; AVFrame * const ref = a->ref; uint8_t* outdata; - int delta, ret; - int pal_size; - const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &pal_size); + int delta, intra, ret; if (avpkt->size < 0x86) { av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); @@ -281,9 +283,6 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_init(&a->buffer, avpkt->data, avpkt->size); - av_frame_unref(ref); - av_frame_move_ref(ref, p); - if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; outdata = p->data[0]; @@ -292,24 +291,24 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_skip(&a->buffer, 1); delta = bytestream2_get_byte(&a->buffer); - if(delta == 0x10) { + intra = delta == 0x10; + if (intra) { qpeg_decode_intra(a, outdata, p->linesize[0], avctx->width, avctx->height); } else { qpeg_decode_inter(a, outdata, p->linesize[0], avctx->width, avctx->height, delta, ctable, ref->data[0]); } /* make the palette available on the way out */ - if (pal && pal_size == AVPALETTE_SIZE) { - p->palette_has_changed = 1; - memcpy(a->pal, pal, AVPALETTE_SIZE); - } else if (pal) { - av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", pal_size); - } + p->palette_has_changed = ff_copy_palette(a->pal, avpkt, avctx); memcpy(p->data[1], a->pal, AVPALETTE_SIZE); - if ((ret = av_frame_ref(data, p)) < 0) + av_frame_unref(ref); + if ((ret = av_frame_ref(ref, p)) < 0) return ret; + p->key_frame = intra; + p->pict_type = intra ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; + *got_frame = 1; return avpkt->size; @@ -320,6 +319,8 @@ static void decode_flush(AVCodecContext *avctx){ int i, pal_size; const uint8_t *pal_src; + av_frame_unref(a->ref); + pal_size = FFMIN(1024U, avctx->extradata_size); pal_src = avctx->extradata + avctx->extradata_size - pal_size; @@ -331,7 +332,6 @@ static av_cold int decode_end(AVCodecContext *avctx) { QpegContext * const a = avctx->priv_data; - av_frame_free(&a->pic); av_frame_free(&a->ref); return 0; @@ -343,19 +343,16 @@ static av_cold int decode_init(AVCodecContext *avctx){ a->avctx = avctx; avctx->pix_fmt= AV_PIX_FMT_PAL8; - decode_flush(avctx); - - a->pic = av_frame_alloc(); a->ref = av_frame_alloc(); - if (!a->pic || !a->ref) { - decode_end(avctx); + if (!a->ref) return AVERROR(ENOMEM); - } + + decode_flush(avctx); return 0; } -AVCodec ff_qpeg_decoder = { +const AVCodec ff_qpeg_decoder = { .name = "qpeg", .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), .type = AVMEDIA_TYPE_VIDEO, @@ -366,4 +363,6 @@ AVCodec ff_qpeg_decoder = { .decode = decode_frame, .flush = decode_flush, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, };