1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Electronic Arts Madcow Video Decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2007-2009 Peter Ross 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Electronic Arts Madcow Video Decoder 25cabdff1aSopenharmony_ci * @author Peter Ross <pross@xvid.org> 26cabdff1aSopenharmony_ci * 27cabdff1aSopenharmony_ci * @see technical details at 28cabdff1aSopenharmony_ci * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_MAD 29cabdff1aSopenharmony_ci */ 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h" 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci#include "avcodec.h" 34cabdff1aSopenharmony_ci#include "blockdsp.h" 35cabdff1aSopenharmony_ci#include "bytestream.h" 36cabdff1aSopenharmony_ci#include "bswapdsp.h" 37cabdff1aSopenharmony_ci#include "codec_internal.h" 38cabdff1aSopenharmony_ci#include "get_bits.h" 39cabdff1aSopenharmony_ci#include "aandcttab.h" 40cabdff1aSopenharmony_ci#include "eaidct.h" 41cabdff1aSopenharmony_ci#include "idctdsp.h" 42cabdff1aSopenharmony_ci#include "internal.h" 43cabdff1aSopenharmony_ci#include "mpeg12data.h" 44cabdff1aSopenharmony_ci#include "mpeg12vlc.h" 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci#define EA_PREAMBLE_SIZE 8 47cabdff1aSopenharmony_ci#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD I-frame */ 48cabdff1aSopenharmony_ci#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD P-frame */ 49cabdff1aSopenharmony_ci#define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_citypedef struct MadContext { 52cabdff1aSopenharmony_ci AVCodecContext *avctx; 53cabdff1aSopenharmony_ci BlockDSPContext bdsp; 54cabdff1aSopenharmony_ci BswapDSPContext bbdsp; 55cabdff1aSopenharmony_ci IDCTDSPContext idsp; 56cabdff1aSopenharmony_ci AVFrame *last_frame; 57cabdff1aSopenharmony_ci GetBitContext gb; 58cabdff1aSopenharmony_ci void *bitstream_buf; 59cabdff1aSopenharmony_ci unsigned int bitstream_buf_size; 60cabdff1aSopenharmony_ci DECLARE_ALIGNED(32, int16_t, block)[64]; 61cabdff1aSopenharmony_ci ScanTable scantable; 62cabdff1aSopenharmony_ci uint16_t quant_matrix[64]; 63cabdff1aSopenharmony_ci int mb_x; 64cabdff1aSopenharmony_ci int mb_y; 65cabdff1aSopenharmony_ci} MadContext; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx) 68cabdff1aSopenharmony_ci{ 69cabdff1aSopenharmony_ci MadContext *s = avctx->priv_data; 70cabdff1aSopenharmony_ci s->avctx = avctx; 71cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV420P; 72cabdff1aSopenharmony_ci ff_blockdsp_init(&s->bdsp, avctx); 73cabdff1aSopenharmony_ci ff_bswapdsp_init(&s->bbdsp); 74cabdff1aSopenharmony_ci ff_idctdsp_init(&s->idsp, avctx); 75cabdff1aSopenharmony_ci ff_init_scantable_permutation(s->idsp.idct_permutation, FF_IDCT_PERM_NONE); 76cabdff1aSopenharmony_ci ff_init_scantable(s->idsp.idct_permutation, &s->scantable, ff_zigzag_direct); 77cabdff1aSopenharmony_ci ff_mpeg12_init_vlcs(); 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci s->last_frame = av_frame_alloc(); 80cabdff1aSopenharmony_ci if (!s->last_frame) 81cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci return 0; 84cabdff1aSopenharmony_ci} 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_cistatic inline void comp(unsigned char *dst, ptrdiff_t dst_stride, 87cabdff1aSopenharmony_ci unsigned char *src, ptrdiff_t src_stride, int add) 88cabdff1aSopenharmony_ci{ 89cabdff1aSopenharmony_ci int j, i; 90cabdff1aSopenharmony_ci for (j=0; j<8; j++) 91cabdff1aSopenharmony_ci for (i=0; i<8; i++) 92cabdff1aSopenharmony_ci dst[j*dst_stride + i] = av_clip_uint8(src[j*src_stride + i] + add); 93cabdff1aSopenharmony_ci} 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_cistatic inline void comp_block(MadContext *t, AVFrame *frame, 96cabdff1aSopenharmony_ci int mb_x, int mb_y, 97cabdff1aSopenharmony_ci int j, int mv_x, int mv_y, int add) 98cabdff1aSopenharmony_ci{ 99cabdff1aSopenharmony_ci if (j < 4) { 100cabdff1aSopenharmony_ci unsigned offset = (mb_y*16 + ((j&2)<<2) + mv_y)*t->last_frame->linesize[0] + mb_x*16 + ((j&1)<<3) + mv_x; 101cabdff1aSopenharmony_ci if (offset >= (t->avctx->height - 7) * t->last_frame->linesize[0] - 7) 102cabdff1aSopenharmony_ci return; 103cabdff1aSopenharmony_ci comp(frame->data[0] + (mb_y*16 + ((j&2)<<2))*frame->linesize[0] + mb_x*16 + ((j&1)<<3), 104cabdff1aSopenharmony_ci frame->linesize[0], 105cabdff1aSopenharmony_ci t->last_frame->data[0] + offset, 106cabdff1aSopenharmony_ci t->last_frame->linesize[0], add); 107cabdff1aSopenharmony_ci } else if (!(t->avctx->flags & AV_CODEC_FLAG_GRAY)) { 108cabdff1aSopenharmony_ci int index = j - 3; 109cabdff1aSopenharmony_ci unsigned offset = (mb_y * 8 + (mv_y/2))*t->last_frame->linesize[index] + mb_x * 8 + (mv_x/2); 110cabdff1aSopenharmony_ci if (offset >= (t->avctx->height/2 - 7) * t->last_frame->linesize[index] - 7) 111cabdff1aSopenharmony_ci return; 112cabdff1aSopenharmony_ci comp(frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x * 8, 113cabdff1aSopenharmony_ci frame->linesize[index], 114cabdff1aSopenharmony_ci t->last_frame->data[index] + offset, 115cabdff1aSopenharmony_ci t->last_frame->linesize[index], add); 116cabdff1aSopenharmony_ci } 117cabdff1aSopenharmony_ci} 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_cistatic inline void idct_put(MadContext *t, AVFrame *frame, int16_t *block, 120cabdff1aSopenharmony_ci int mb_x, int mb_y, int j) 121cabdff1aSopenharmony_ci{ 122cabdff1aSopenharmony_ci if (j < 4) { 123cabdff1aSopenharmony_ci ff_ea_idct_put_c( 124cabdff1aSopenharmony_ci frame->data[0] + (mb_y*16 + ((j&2)<<2))*frame->linesize[0] + mb_x*16 + ((j&1)<<3), 125cabdff1aSopenharmony_ci frame->linesize[0], block); 126cabdff1aSopenharmony_ci } else if (!(t->avctx->flags & AV_CODEC_FLAG_GRAY)) { 127cabdff1aSopenharmony_ci int index = j - 3; 128cabdff1aSopenharmony_ci ff_ea_idct_put_c( 129cabdff1aSopenharmony_ci frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x*8, 130cabdff1aSopenharmony_ci frame->linesize[index], block); 131cabdff1aSopenharmony_ci } 132cabdff1aSopenharmony_ci} 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_cistatic inline int decode_block_intra(MadContext *s, int16_t * block) 135cabdff1aSopenharmony_ci{ 136cabdff1aSopenharmony_ci int level, i, j, run; 137cabdff1aSopenharmony_ci RLTable *rl = &ff_rl_mpeg1; 138cabdff1aSopenharmony_ci const uint8_t *scantable = s->scantable.permutated; 139cabdff1aSopenharmony_ci int16_t *quant_matrix = s->quant_matrix; 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci block[0] = (128 + get_sbits(&s->gb, 8)) * quant_matrix[0]; 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci /* The RL decoder is derived from mpeg1_decode_block_intra; 144cabdff1aSopenharmony_ci Escaped level and run values a decoded differently */ 145cabdff1aSopenharmony_ci i = 0; 146cabdff1aSopenharmony_ci { 147cabdff1aSopenharmony_ci OPEN_READER(re, &s->gb); 148cabdff1aSopenharmony_ci /* now quantify & encode AC coefficients */ 149cabdff1aSopenharmony_ci for (;;) { 150cabdff1aSopenharmony_ci UPDATE_CACHE(re, &s->gb); 151cabdff1aSopenharmony_ci GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci if (level == 127) { 154cabdff1aSopenharmony_ci break; 155cabdff1aSopenharmony_ci } else if (level != 0) { 156cabdff1aSopenharmony_ci i += run; 157cabdff1aSopenharmony_ci if (i > 63) { 158cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, 159cabdff1aSopenharmony_ci "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); 160cabdff1aSopenharmony_ci return -1; 161cabdff1aSopenharmony_ci } 162cabdff1aSopenharmony_ci j = scantable[i]; 163cabdff1aSopenharmony_ci level = (level*quant_matrix[j]) >> 4; 164cabdff1aSopenharmony_ci level = (level-1)|1; 165cabdff1aSopenharmony_ci level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); 166cabdff1aSopenharmony_ci LAST_SKIP_BITS(re, &s->gb, 1); 167cabdff1aSopenharmony_ci } else { 168cabdff1aSopenharmony_ci /* escape */ 169cabdff1aSopenharmony_ci UPDATE_CACHE(re, &s->gb); 170cabdff1aSopenharmony_ci level = SHOW_SBITS(re, &s->gb, 10); SKIP_BITS(re, &s->gb, 10); 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci UPDATE_CACHE(re, &s->gb); 173cabdff1aSopenharmony_ci run = SHOW_UBITS(re, &s->gb, 6)+1; LAST_SKIP_BITS(re, &s->gb, 6); 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci i += run; 176cabdff1aSopenharmony_ci if (i > 63) { 177cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, 178cabdff1aSopenharmony_ci "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); 179cabdff1aSopenharmony_ci return -1; 180cabdff1aSopenharmony_ci } 181cabdff1aSopenharmony_ci j = scantable[i]; 182cabdff1aSopenharmony_ci if (level < 0) { 183cabdff1aSopenharmony_ci level = -level; 184cabdff1aSopenharmony_ci level = (level*quant_matrix[j]) >> 4; 185cabdff1aSopenharmony_ci level = (level-1)|1; 186cabdff1aSopenharmony_ci level = -level; 187cabdff1aSopenharmony_ci } else { 188cabdff1aSopenharmony_ci level = (level*quant_matrix[j]) >> 4; 189cabdff1aSopenharmony_ci level = (level-1)|1; 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci } 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci block[j] = level; 194cabdff1aSopenharmony_ci } 195cabdff1aSopenharmony_ci CLOSE_READER(re, &s->gb); 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci return 0; 198cabdff1aSopenharmony_ci} 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_cistatic int decode_motion(GetBitContext *gb) 201cabdff1aSopenharmony_ci{ 202cabdff1aSopenharmony_ci int value = 0; 203cabdff1aSopenharmony_ci if (get_bits1(gb)) { 204cabdff1aSopenharmony_ci if (get_bits1(gb)) 205cabdff1aSopenharmony_ci value = -17; 206cabdff1aSopenharmony_ci value += get_bits(gb, 4) + 1; 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci return value; 209cabdff1aSopenharmony_ci} 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_cistatic int decode_mb(MadContext *s, AVFrame *frame, int inter) 212cabdff1aSopenharmony_ci{ 213cabdff1aSopenharmony_ci int mv_map = 0; 214cabdff1aSopenharmony_ci int av_uninit(mv_x), av_uninit(mv_y); 215cabdff1aSopenharmony_ci int j; 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci if (inter) { 218cabdff1aSopenharmony_ci int v = decode210(&s->gb); 219cabdff1aSopenharmony_ci if (v < 2) { 220cabdff1aSopenharmony_ci mv_map = v ? get_bits(&s->gb, 6) : 63; 221cabdff1aSopenharmony_ci mv_x = decode_motion(&s->gb); 222cabdff1aSopenharmony_ci mv_y = decode_motion(&s->gb); 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci } 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci for (j=0; j<6; j++) { 227cabdff1aSopenharmony_ci if (mv_map & (1<<j)) { // mv_x and mv_y are guarded by mv_map 228cabdff1aSopenharmony_ci int add = 2*decode_motion(&s->gb); 229cabdff1aSopenharmony_ci if (s->last_frame->data[0]) 230cabdff1aSopenharmony_ci comp_block(s, frame, s->mb_x, s->mb_y, j, mv_x, mv_y, add); 231cabdff1aSopenharmony_ci } else { 232cabdff1aSopenharmony_ci s->bdsp.clear_block(s->block); 233cabdff1aSopenharmony_ci if(decode_block_intra(s, s->block) < 0) 234cabdff1aSopenharmony_ci return -1; 235cabdff1aSopenharmony_ci idct_put(s, frame, s->block, s->mb_x, s->mb_y, j); 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci } 238cabdff1aSopenharmony_ci return 0; 239cabdff1aSopenharmony_ci} 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_cistatic void calc_quant_matrix(MadContext *s, int qscale) 242cabdff1aSopenharmony_ci{ 243cabdff1aSopenharmony_ci int i; 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci s->quant_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0]) >> 11; 246cabdff1aSopenharmony_ci for (i=1; i<64; i++) 247cabdff1aSopenharmony_ci s->quant_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32) >> 10; 248cabdff1aSopenharmony_ci} 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *frame, 251cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 252cabdff1aSopenharmony_ci{ 253cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 254cabdff1aSopenharmony_ci int buf_size = avpkt->size; 255cabdff1aSopenharmony_ci MadContext *s = avctx->priv_data; 256cabdff1aSopenharmony_ci GetByteContext gb; 257cabdff1aSopenharmony_ci int width, height; 258cabdff1aSopenharmony_ci int chunk_type; 259cabdff1aSopenharmony_ci int inter, ret; 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci bytestream2_init(&gb, buf, buf_size); 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci chunk_type = bytestream2_get_le32(&gb); 264cabdff1aSopenharmony_ci inter = (chunk_type == MADm_TAG || chunk_type == MADe_TAG); 265cabdff1aSopenharmony_ci bytestream2_skip(&gb, 10); 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci av_reduce(&avctx->framerate.den, &avctx->framerate.num, 268cabdff1aSopenharmony_ci bytestream2_get_le16(&gb), 1000, 1<<30); 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci width = bytestream2_get_le16(&gb); 271cabdff1aSopenharmony_ci height = bytestream2_get_le16(&gb); 272cabdff1aSopenharmony_ci bytestream2_skip(&gb, 1); 273cabdff1aSopenharmony_ci calc_quant_matrix(s, bytestream2_get_byte(&gb)); 274cabdff1aSopenharmony_ci bytestream2_skip(&gb, 2); 275cabdff1aSopenharmony_ci 276cabdff1aSopenharmony_ci if (bytestream2_get_bytes_left(&gb) < 2) { 277cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Input data too small\n"); 278cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 279cabdff1aSopenharmony_ci } 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ci if (width < 16 || height < 16) { 282cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Dimensions too small\n"); 283cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 284cabdff1aSopenharmony_ci } 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ci if (avctx->width != width || avctx->height != height) { 287cabdff1aSopenharmony_ci av_frame_unref(s->last_frame); 288cabdff1aSopenharmony_ci if((width * (int64_t)height)/2048*7 > bytestream2_get_bytes_left(&gb)) 289cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 290cabdff1aSopenharmony_ci if ((ret = ff_set_dimensions(avctx, width, height)) < 0) 291cabdff1aSopenharmony_ci return ret; 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) 295cabdff1aSopenharmony_ci return ret; 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci if (inter && !s->last_frame->data[0]) { 298cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Missing reference frame.\n"); 299cabdff1aSopenharmony_ci ret = ff_get_buffer(avctx, s->last_frame, AV_GET_BUFFER_FLAG_REF); 300cabdff1aSopenharmony_ci if (ret < 0) 301cabdff1aSopenharmony_ci return ret; 302cabdff1aSopenharmony_ci memset(s->last_frame->data[0], 0, s->last_frame->height * 303cabdff1aSopenharmony_ci s->last_frame->linesize[0]); 304cabdff1aSopenharmony_ci memset(s->last_frame->data[1], 0x80, s->last_frame->height / 2 * 305cabdff1aSopenharmony_ci s->last_frame->linesize[1]); 306cabdff1aSopenharmony_ci memset(s->last_frame->data[2], 0x80, s->last_frame->height / 2 * 307cabdff1aSopenharmony_ci s->last_frame->linesize[2]); 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci 310cabdff1aSopenharmony_ci av_fast_padded_malloc(&s->bitstream_buf, &s->bitstream_buf_size, 311cabdff1aSopenharmony_ci bytestream2_get_bytes_left(&gb)); 312cabdff1aSopenharmony_ci if (!s->bitstream_buf) 313cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 314cabdff1aSopenharmony_ci s->bbdsp.bswap16_buf(s->bitstream_buf, (const uint16_t *)(buf + bytestream2_tell(&gb)), 315cabdff1aSopenharmony_ci bytestream2_get_bytes_left(&gb) / 2); 316cabdff1aSopenharmony_ci memset((uint8_t*)s->bitstream_buf + bytestream2_get_bytes_left(&gb), 0, AV_INPUT_BUFFER_PADDING_SIZE); 317cabdff1aSopenharmony_ci init_get_bits(&s->gb, s->bitstream_buf, 8*(bytestream2_get_bytes_left(&gb))); 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_ci for (s->mb_y=0; s->mb_y < (avctx->height+15)/16; s->mb_y++) 320cabdff1aSopenharmony_ci for (s->mb_x=0; s->mb_x < (avctx->width +15)/16; s->mb_x++) 321cabdff1aSopenharmony_ci if(decode_mb(s, frame, inter) < 0) 322cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 323cabdff1aSopenharmony_ci 324cabdff1aSopenharmony_ci *got_frame = 1; 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_ci if (chunk_type != MADe_TAG) { 327cabdff1aSopenharmony_ci av_frame_unref(s->last_frame); 328cabdff1aSopenharmony_ci if ((ret = av_frame_ref(s->last_frame, frame)) < 0) 329cabdff1aSopenharmony_ci return ret; 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci return buf_size; 333cabdff1aSopenharmony_ci} 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx) 336cabdff1aSopenharmony_ci{ 337cabdff1aSopenharmony_ci MadContext *t = avctx->priv_data; 338cabdff1aSopenharmony_ci av_frame_free(&t->last_frame); 339cabdff1aSopenharmony_ci av_freep(&t->bitstream_buf); 340cabdff1aSopenharmony_ci return 0; 341cabdff1aSopenharmony_ci} 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ciconst FFCodec ff_eamad_decoder = { 344cabdff1aSopenharmony_ci .p.name = "eamad", 345cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Madcow Video"), 346cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 347cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_MAD, 348cabdff1aSopenharmony_ci .priv_data_size = sizeof(MadContext), 349cabdff1aSopenharmony_ci .init = decode_init, 350cabdff1aSopenharmony_ci .close = decode_end, 351cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 352cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 353cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, 354cabdff1aSopenharmony_ci}; 355