summaryrefslogtreecommitdiff
path: root/libavcodec/eatgv.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2012-11-21 21:34:46 +0100
committerAnton Khirnov <anton@khirnov.net>2013-03-08 07:38:30 +0100
commit759001c534287a96dc96d1e274665feb7059145d (patch)
tree6ace9560c20aa30db92067c5b45d7bd86e458d10 /libavcodec/eatgv.c
parent6e7b50b4270116ded8b874d76cb7c5b1a0341827 (diff)
downloadffmpeg-759001c534287a96dc96d1e274665feb7059145d.tar.gz
lavc decoders: work with refcounted frames.
Diffstat (limited to 'libavcodec/eatgv.c')
-rw-r--r--libavcodec/eatgv.c74
1 files changed, 34 insertions, 40 deletions
diff --git a/libavcodec/eatgv.c b/libavcodec/eatgv.c
index 792eaf708e..1e0ec60bc5 100644
--- a/libavcodec/eatgv.c
+++ b/libavcodec/eatgv.c
@@ -31,6 +31,7 @@
#include "avcodec.h"
#define BITSTREAM_READER_LE
#include "get_bits.h"
+#include "internal.h"
#include "libavutil/imgutils.h"
#include "libavutil/mem.h"
@@ -39,8 +40,8 @@
typedef struct TgvContext {
AVCodecContext *avctx;
- AVFrame frame;
AVFrame last_frame;
+ uint8_t *frame_buffer;
int width,height;
uint32_t palette[AVPALETTE_COUNT];
@@ -138,8 +139,8 @@ static int unpack(const uint8_t *src, const uint8_t *src_end,
* Decode inter-frame
* @return 0 on success, -1 on critical buffer underflow
*/
-static int tgv_decode_inter(TgvContext *s, const uint8_t *buf,
- const uint8_t *buf_end)
+static int tgv_decode_inter(TgvContext *s, AVFrame *frame,
+ const uint8_t *buf, const uint8_t *buf_end)
{
int num_mvs;
int num_blocks_raw;
@@ -237,22 +238,13 @@ static int tgv_decode_inter(TgvContext *s, const uint8_t *buf,
for (j = 0; j < 4; j++)
for (i = 0; i < 4; i++)
- s->frame.data[0][(y * 4 + j) * s->frame.linesize[0] + (x * 4 + i)] =
+ frame->data[0][(y * 4 + j) * frame->linesize[0] + (x * 4 + i)] =
src[j * src_stride + i];
}
return 0;
}
-/** release AVFrame buffers if allocated */
-static void cond_release_buffer(AVFrame *pic)
-{
- if (pic->data[0]) {
- av_freep(&pic->data[0]);
- av_free(pic->data[1]);
- }
-}
-
static int tgv_decode_frame(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
@@ -261,6 +253,7 @@ static int tgv_decode_frame(AVCodecContext *avctx,
int buf_size = avpkt->size;
TgvContext *s = avctx->priv_data;
const uint8_t *buf_end = buf + buf_size;
+ AVFrame *frame = data;
int chunk_type, ret;
chunk_type = AV_RL32(&buf[0]);
@@ -277,8 +270,8 @@ static int tgv_decode_frame(AVCodecContext *avctx,
s->height = AV_RL16(&buf[2]);
if (s->avctx->width != s->width || s->avctx->height != s->height) {
avcodec_set_dimensions(s->avctx, s->width, s->height);
- cond_release_buffer(&s->frame);
- cond_release_buffer(&s->last_frame);
+ av_freep(&s->frame_buffer);
+ av_frame_unref(&s->last_frame);
}
pal_count = AV_RL16(&buf[6]);
@@ -292,46 +285,46 @@ static int tgv_decode_frame(AVCodecContext *avctx,
if ((ret = av_image_check_size(s->width, s->height, 0, avctx)) < 0)
return ret;
- /* shuffle */
- FFSWAP(AVFrame, s->frame, s->last_frame);
- if (!s->frame.data[0]) {
- s->frame.reference = 1;
- s->frame.buffer_hints = FF_BUFFER_HINTS_VALID;
- s->frame.linesize[0] = s->width;
+ if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
+ return ret;
- s->frame.data[0] = av_malloc(s->width * s->height);
- if (!s->frame.data[0])
- return AVERROR(ENOMEM);
- s->frame.data[1] = av_malloc(AVPALETTE_SIZE);
- if (!s->frame.data[1]) {
- av_freep(&s->frame.data[0]);
- return AVERROR(ENOMEM);
- }
- }
- memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
+ memcpy(frame->data[1], s->palette, AVPALETTE_SIZE);
if (chunk_type == kVGT_TAG) {
- s->frame.key_frame = 1;
- s->frame.pict_type = AV_PICTURE_TYPE_I;
- if (unpack(buf, buf_end, s->frame.data[0], s->avctx->width, s->avctx->height) < 0) {
+ int y;
+ frame->key_frame = 1;
+ frame->pict_type = AV_PICTURE_TYPE_I;
+
+ if (!s->frame_buffer &&
+ !(s->frame_buffer = av_malloc(s->width * s->height)))
+ return AVERROR(ENOMEM);
+
+ if (unpack(buf, buf_end, s->frame_buffer, s->avctx->width, s->avctx->height) < 0) {
av_log(avctx, AV_LOG_WARNING, "truncated intra frame\n");
return AVERROR_INVALIDDATA;
}
+ for (y = 0; y < s->height; y++)
+ memcpy(frame->data[0] + y * frame->linesize[0],
+ s->frame_buffer + y * s->width,
+ s->width);
} else {
if (!s->last_frame.data[0]) {
av_log(avctx, AV_LOG_WARNING, "inter frame without corresponding intra frame\n");
return buf_size;
}
- s->frame.key_frame = 0;
- s->frame.pict_type = AV_PICTURE_TYPE_P;
- if (tgv_decode_inter(s, buf, buf_end) < 0) {
+ frame->key_frame = 0;
+ frame->pict_type = AV_PICTURE_TYPE_P;
+ if (tgv_decode_inter(s, frame, buf, buf_end) < 0) {
av_log(avctx, AV_LOG_WARNING, "truncated inter frame\n");
return AVERROR_INVALIDDATA;
}
}
+ av_frame_unref(&s->last_frame);
+ if ((ret = av_frame_ref(&s->last_frame, frame)) < 0)
+ return ret;
+
*got_frame = 1;
- *(AVFrame*)data = s->frame;
return buf_size;
}
@@ -339,8 +332,8 @@ static int tgv_decode_frame(AVCodecContext *avctx,
static av_cold int tgv_decode_end(AVCodecContext *avctx)
{
TgvContext *s = avctx->priv_data;
- cond_release_buffer(&s->frame);
- cond_release_buffer(&s->last_frame);
+ av_frame_unref(&s->last_frame);
+ av_freep(&s->frame_buffer);
av_free(s->mv_codebook);
av_free(s->block_codebook);
return 0;
@@ -355,4 +348,5 @@ AVCodec ff_eatgv_decoder = {
.close = tgv_decode_end,
.decode = tgv_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"),
+ .capabilities = CODEC_CAP_DR1,
};