1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Duck/ON2 TrueMotion 2 Decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2005 Konstantin Shishkov 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 Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Duck TrueMotion2 decoder. 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <inttypes.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "avcodec.h" 30cabdff1aSopenharmony_ci#include "bswapdsp.h" 31cabdff1aSopenharmony_ci#include "bytestream.h" 32cabdff1aSopenharmony_ci#include "codec_internal.h" 33cabdff1aSopenharmony_ci#include "get_bits.h" 34cabdff1aSopenharmony_ci#include "internal.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#define TM2_ESCAPE 0x80000000 37cabdff1aSopenharmony_ci#define TM2_DELTAS 64 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci/* Huffman-coded streams of different types of blocks */ 40cabdff1aSopenharmony_cienum TM2_STREAMS { 41cabdff1aSopenharmony_ci TM2_C_HI = 0, 42cabdff1aSopenharmony_ci TM2_C_LO, 43cabdff1aSopenharmony_ci TM2_L_HI, 44cabdff1aSopenharmony_ci TM2_L_LO, 45cabdff1aSopenharmony_ci TM2_UPD, 46cabdff1aSopenharmony_ci TM2_MOT, 47cabdff1aSopenharmony_ci TM2_TYPE, 48cabdff1aSopenharmony_ci TM2_NUM_STREAMS 49cabdff1aSopenharmony_ci}; 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ci/* Block types */ 52cabdff1aSopenharmony_cienum TM2_BLOCKS { 53cabdff1aSopenharmony_ci TM2_HI_RES = 0, 54cabdff1aSopenharmony_ci TM2_MED_RES, 55cabdff1aSopenharmony_ci TM2_LOW_RES, 56cabdff1aSopenharmony_ci TM2_NULL_RES, 57cabdff1aSopenharmony_ci TM2_UPDATE, 58cabdff1aSopenharmony_ci TM2_STILL, 59cabdff1aSopenharmony_ci TM2_MOTION 60cabdff1aSopenharmony_ci}; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_citypedef struct TM2Context { 63cabdff1aSopenharmony_ci AVCodecContext *avctx; 64cabdff1aSopenharmony_ci AVFrame *pic; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci GetBitContext gb; 67cabdff1aSopenharmony_ci int error; 68cabdff1aSopenharmony_ci BswapDSPContext bdsp; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci uint8_t *buffer; 71cabdff1aSopenharmony_ci int buffer_size; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci /* TM2 streams */ 74cabdff1aSopenharmony_ci int *tokens[TM2_NUM_STREAMS]; 75cabdff1aSopenharmony_ci int tok_lens[TM2_NUM_STREAMS]; 76cabdff1aSopenharmony_ci int tok_ptrs[TM2_NUM_STREAMS]; 77cabdff1aSopenharmony_ci int deltas[TM2_NUM_STREAMS][TM2_DELTAS]; 78cabdff1aSopenharmony_ci /* for blocks decoding */ 79cabdff1aSopenharmony_ci int D[4]; 80cabdff1aSopenharmony_ci int CD[4]; 81cabdff1aSopenharmony_ci int *last; 82cabdff1aSopenharmony_ci int *clast; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci /* data for current and previous frame */ 85cabdff1aSopenharmony_ci int *Y_base, *UV_base; 86cabdff1aSopenharmony_ci int *Y1, *U1, *V1, *Y2, *U2, *V2; 87cabdff1aSopenharmony_ci int y_stride, uv_stride; 88cabdff1aSopenharmony_ci int cur; 89cabdff1aSopenharmony_ci} TM2Context; 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci/** 92cabdff1aSopenharmony_ci* Huffman codes for each of streams 93cabdff1aSopenharmony_ci*/ 94cabdff1aSopenharmony_citypedef struct TM2Codes { 95cabdff1aSopenharmony_ci VLC vlc; ///< table for FFmpeg bitstream reader 96cabdff1aSopenharmony_ci int bits; 97cabdff1aSopenharmony_ci int *recode; ///< table for converting from code indexes to values 98cabdff1aSopenharmony_ci int length; 99cabdff1aSopenharmony_ci} TM2Codes; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci/** 102cabdff1aSopenharmony_ci* structure for gathering Huffman codes information 103cabdff1aSopenharmony_ci*/ 104cabdff1aSopenharmony_citypedef struct TM2Huff { 105cabdff1aSopenharmony_ci int val_bits; ///< length of literal 106cabdff1aSopenharmony_ci int max_bits; ///< maximum length of code 107cabdff1aSopenharmony_ci int min_bits; ///< minimum length of code 108cabdff1aSopenharmony_ci int nodes; ///< total number of nodes in tree 109cabdff1aSopenharmony_ci int num; ///< current number filled 110cabdff1aSopenharmony_ci int max_num; ///< total number of codes 111cabdff1aSopenharmony_ci int *nums; ///< literals 112cabdff1aSopenharmony_ci uint8_t *lens; ///< codelengths 113cabdff1aSopenharmony_ci} TM2Huff; 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci/** 116cabdff1aSopenharmony_ci * 117cabdff1aSopenharmony_ci * @returns the length of the longest code or an AVERROR code 118cabdff1aSopenharmony_ci */ 119cabdff1aSopenharmony_cistatic int tm2_read_tree(TM2Context *ctx, int length, TM2Huff *huff) 120cabdff1aSopenharmony_ci{ 121cabdff1aSopenharmony_ci int ret, ret2; 122cabdff1aSopenharmony_ci if (length > huff->max_bits) { 123cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Tree exceeded its given depth (%i)\n", 124cabdff1aSopenharmony_ci huff->max_bits); 125cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 126cabdff1aSopenharmony_ci } 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci if (!get_bits1(&ctx->gb)) { /* literal */ 129cabdff1aSopenharmony_ci if (length == 0) { 130cabdff1aSopenharmony_ci length = 1; 131cabdff1aSopenharmony_ci } 132cabdff1aSopenharmony_ci if (huff->num >= huff->max_num) { 133cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_DEBUG, "Too many literals\n"); 134cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci huff->nums[huff->num] = get_bits_long(&ctx->gb, huff->val_bits); 137cabdff1aSopenharmony_ci huff->lens[huff->num] = length; 138cabdff1aSopenharmony_ci huff->num++; 139cabdff1aSopenharmony_ci return length; 140cabdff1aSopenharmony_ci } else { /* non-terminal node */ 141cabdff1aSopenharmony_ci if ((ret2 = tm2_read_tree(ctx, length + 1, huff)) < 0) 142cabdff1aSopenharmony_ci return ret2; 143cabdff1aSopenharmony_ci if ((ret = tm2_read_tree(ctx, length + 1, huff)) < 0) 144cabdff1aSopenharmony_ci return ret; 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci return FFMAX(ret, ret2); 147cabdff1aSopenharmony_ci} 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_cistatic int tm2_build_huff_table(TM2Context *ctx, TM2Codes *code) 150cabdff1aSopenharmony_ci{ 151cabdff1aSopenharmony_ci TM2Huff huff; 152cabdff1aSopenharmony_ci int res = 0; 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci huff.val_bits = get_bits(&ctx->gb, 5); 155cabdff1aSopenharmony_ci huff.max_bits = get_bits(&ctx->gb, 5); 156cabdff1aSopenharmony_ci huff.min_bits = get_bits(&ctx->gb, 5); 157cabdff1aSopenharmony_ci huff.nodes = get_bits(&ctx->gb, 17); 158cabdff1aSopenharmony_ci huff.num = 0; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci /* check for correct codes parameters */ 161cabdff1aSopenharmony_ci if ((huff.val_bits < 1) || (huff.val_bits > 32) || 162cabdff1aSopenharmony_ci (huff.max_bits < 0) || (huff.max_bits > 25)) { 163cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect tree parameters - literal " 164cabdff1aSopenharmony_ci "length: %i, max code length: %i\n", huff.val_bits, huff.max_bits); 165cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci if ((huff.nodes <= 0) || (huff.nodes > 0x10000)) { 168cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of Huffman tree " 169cabdff1aSopenharmony_ci "nodes: %i\n", huff.nodes); 170cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci /* one-node tree */ 173cabdff1aSopenharmony_ci if (huff.max_bits == 0) 174cabdff1aSopenharmony_ci huff.max_bits = 1; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci /* allocate space for codes - it is exactly ceil(nodes / 2) entries */ 177cabdff1aSopenharmony_ci huff.max_num = (huff.nodes + 1) >> 1; 178cabdff1aSopenharmony_ci huff.nums = av_calloc(huff.max_num, sizeof(int)); 179cabdff1aSopenharmony_ci huff.lens = av_mallocz(huff.max_num); 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_ci if (!huff.nums || !huff.lens) { 182cabdff1aSopenharmony_ci res = AVERROR(ENOMEM); 183cabdff1aSopenharmony_ci goto out; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci res = tm2_read_tree(ctx, 0, &huff); 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci if (res >= 0 && res != huff.max_bits) { 189cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Got less bits than expected: %i of %i\n", 190cabdff1aSopenharmony_ci res, huff.max_bits); 191cabdff1aSopenharmony_ci res = AVERROR_INVALIDDATA; 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci if (huff.num != huff.max_num) { 194cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Got less codes than expected: %i of %i\n", 195cabdff1aSopenharmony_ci huff.num, huff.max_num); 196cabdff1aSopenharmony_ci res = AVERROR_INVALIDDATA; 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci /* convert codes to vlc_table */ 200cabdff1aSopenharmony_ci if (res >= 0) { 201cabdff1aSopenharmony_ci res = ff_init_vlc_from_lengths(&code->vlc, huff.max_bits, huff.max_num, 202cabdff1aSopenharmony_ci huff.lens, sizeof(huff.lens[0]), 203cabdff1aSopenharmony_ci NULL, 0, 0, 0, 0, ctx->avctx); 204cabdff1aSopenharmony_ci if (res < 0) 205cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); 206cabdff1aSopenharmony_ci else { 207cabdff1aSopenharmony_ci code->bits = huff.max_bits; 208cabdff1aSopenharmony_ci code->length = huff.max_num; 209cabdff1aSopenharmony_ci code->recode = huff.nums; 210cabdff1aSopenharmony_ci huff.nums = NULL; 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ciout: 215cabdff1aSopenharmony_ci /* free allocated memory */ 216cabdff1aSopenharmony_ci av_free(huff.nums); 217cabdff1aSopenharmony_ci av_free(huff.lens); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci return res; 220cabdff1aSopenharmony_ci} 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_cistatic void tm2_free_codes(TM2Codes *code) 223cabdff1aSopenharmony_ci{ 224cabdff1aSopenharmony_ci av_free(code->recode); 225cabdff1aSopenharmony_ci if (code->vlc.table) 226cabdff1aSopenharmony_ci ff_free_vlc(&code->vlc); 227cabdff1aSopenharmony_ci} 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_cistatic inline int tm2_get_token(GetBitContext *gb, TM2Codes *code) 230cabdff1aSopenharmony_ci{ 231cabdff1aSopenharmony_ci int val; 232cabdff1aSopenharmony_ci val = get_vlc2(gb, code->vlc.table, code->bits, 1); 233cabdff1aSopenharmony_ci if(val<0) 234cabdff1aSopenharmony_ci return -1; 235cabdff1aSopenharmony_ci return code->recode[val]; 236cabdff1aSopenharmony_ci} 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci#define TM2_OLD_HEADER_MAGIC 0x00000100 239cabdff1aSopenharmony_ci#define TM2_NEW_HEADER_MAGIC 0x00000101 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_cistatic inline int tm2_read_header(TM2Context *ctx, const uint8_t *buf) 242cabdff1aSopenharmony_ci{ 243cabdff1aSopenharmony_ci uint32_t magic = AV_RL32(buf); 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci switch (magic) { 246cabdff1aSopenharmony_ci case TM2_OLD_HEADER_MAGIC: 247cabdff1aSopenharmony_ci avpriv_request_sample(ctx->avctx, "Old TM2 header"); 248cabdff1aSopenharmony_ci return 0; 249cabdff1aSopenharmony_ci case TM2_NEW_HEADER_MAGIC: 250cabdff1aSopenharmony_ci return 0; 251cabdff1aSopenharmony_ci default: 252cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Not a TM2 header: 0x%08"PRIX32"\n", 253cabdff1aSopenharmony_ci magic); 254cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 255cabdff1aSopenharmony_ci } 256cabdff1aSopenharmony_ci} 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_cistatic int tm2_read_deltas(TM2Context *ctx, int stream_id) 259cabdff1aSopenharmony_ci{ 260cabdff1aSopenharmony_ci int d, mb; 261cabdff1aSopenharmony_ci int i, v; 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci d = get_bits(&ctx->gb, 9); 264cabdff1aSopenharmony_ci mb = get_bits(&ctx->gb, 5); 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci av_assert2(mb < 32); 267cabdff1aSopenharmony_ci if ((d < 1) || (d > TM2_DELTAS) || (mb < 1)) { 268cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect delta table: %i deltas x %i bits\n", d, mb); 269cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 270cabdff1aSopenharmony_ci } 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_ci for (i = 0; i < d; i++) { 273cabdff1aSopenharmony_ci v = get_bits_long(&ctx->gb, mb); 274cabdff1aSopenharmony_ci if (v & (1 << (mb - 1))) 275cabdff1aSopenharmony_ci ctx->deltas[stream_id][i] = v - (1U << mb); 276cabdff1aSopenharmony_ci else 277cabdff1aSopenharmony_ci ctx->deltas[stream_id][i] = v; 278cabdff1aSopenharmony_ci } 279cabdff1aSopenharmony_ci for (; i < TM2_DELTAS; i++) 280cabdff1aSopenharmony_ci ctx->deltas[stream_id][i] = 0; 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci return 0; 283cabdff1aSopenharmony_ci} 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_cistatic int tm2_read_stream(TM2Context *ctx, const uint8_t *buf, int stream_id, int buf_size) 286cabdff1aSopenharmony_ci{ 287cabdff1aSopenharmony_ci int i, ret; 288cabdff1aSopenharmony_ci int skip = 0; 289cabdff1aSopenharmony_ci int len, toks, pos; 290cabdff1aSopenharmony_ci TM2Codes codes; 291cabdff1aSopenharmony_ci GetByteContext gb; 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci if (buf_size < 4) { 294cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "not enough space for len left\n"); 295cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci /* get stream length in dwords */ 299cabdff1aSopenharmony_ci bytestream2_init(&gb, buf, buf_size); 300cabdff1aSopenharmony_ci len = bytestream2_get_be32(&gb); 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_ci if (len == 0) 303cabdff1aSopenharmony_ci return 4; 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci if (len >= INT_MAX / 4 - 1 || len < 0 || len * 4 + 4 > buf_size) { 306cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Error, invalid stream size.\n"); 307cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci skip = len * 4 + 4; 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci toks = bytestream2_get_be32(&gb); 312cabdff1aSopenharmony_ci if (toks & 1) { 313cabdff1aSopenharmony_ci len = bytestream2_get_be32(&gb); 314cabdff1aSopenharmony_ci if (len == TM2_ESCAPE) { 315cabdff1aSopenharmony_ci len = bytestream2_get_be32(&gb); 316cabdff1aSopenharmony_ci } 317cabdff1aSopenharmony_ci if (len > 0) { 318cabdff1aSopenharmony_ci pos = bytestream2_tell(&gb); 319cabdff1aSopenharmony_ci if (skip <= pos) 320cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 321cabdff1aSopenharmony_ci init_get_bits(&ctx->gb, buf + pos, (skip - pos) * 8); 322cabdff1aSopenharmony_ci if ((ret = tm2_read_deltas(ctx, stream_id)) < 0) 323cabdff1aSopenharmony_ci return ret; 324cabdff1aSopenharmony_ci bytestream2_skip(&gb, ((get_bits_count(&ctx->gb) + 31) >> 5) << 2); 325cabdff1aSopenharmony_ci } 326cabdff1aSopenharmony_ci } 327cabdff1aSopenharmony_ci /* skip unused fields */ 328cabdff1aSopenharmony_ci len = bytestream2_get_be32(&gb); 329cabdff1aSopenharmony_ci if (len == TM2_ESCAPE) { /* some unknown length - could be escaped too */ 330cabdff1aSopenharmony_ci bytestream2_skip(&gb, 8); /* unused by decoder */ 331cabdff1aSopenharmony_ci } else { 332cabdff1aSopenharmony_ci bytestream2_skip(&gb, 4); /* unused by decoder */ 333cabdff1aSopenharmony_ci } 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci pos = bytestream2_tell(&gb); 336cabdff1aSopenharmony_ci if (skip <= pos) 337cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 338cabdff1aSopenharmony_ci init_get_bits(&ctx->gb, buf + pos, (skip - pos) * 8); 339cabdff1aSopenharmony_ci if ((ret = tm2_build_huff_table(ctx, &codes)) < 0) 340cabdff1aSopenharmony_ci return ret; 341cabdff1aSopenharmony_ci bytestream2_skip(&gb, ((get_bits_count(&ctx->gb) + 31) >> 5) << 2); 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci toks >>= 1; 344cabdff1aSopenharmony_ci /* check if we have sane number of tokens */ 345cabdff1aSopenharmony_ci if ((toks < 0) || (toks > 0xFFFFFF)) { 346cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of tokens: %i\n", toks); 347cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 348cabdff1aSopenharmony_ci goto end; 349cabdff1aSopenharmony_ci } 350cabdff1aSopenharmony_ci ret = av_reallocp_array(&ctx->tokens[stream_id], toks, sizeof(int)); 351cabdff1aSopenharmony_ci if (ret < 0) { 352cabdff1aSopenharmony_ci ctx->tok_lens[stream_id] = 0; 353cabdff1aSopenharmony_ci goto end; 354cabdff1aSopenharmony_ci } 355cabdff1aSopenharmony_ci ctx->tok_lens[stream_id] = toks; 356cabdff1aSopenharmony_ci len = bytestream2_get_be32(&gb); 357cabdff1aSopenharmony_ci if (len > 0) { 358cabdff1aSopenharmony_ci pos = bytestream2_tell(&gb); 359cabdff1aSopenharmony_ci if (skip <= pos) { 360cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 361cabdff1aSopenharmony_ci goto end; 362cabdff1aSopenharmony_ci } 363cabdff1aSopenharmony_ci init_get_bits(&ctx->gb, buf + pos, (skip - pos) * 8); 364cabdff1aSopenharmony_ci for (i = 0; i < toks; i++) { 365cabdff1aSopenharmony_ci if (get_bits_left(&ctx->gb) <= 0) { 366cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Incorrect number of tokens: %i\n", toks); 367cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 368cabdff1aSopenharmony_ci goto end; 369cabdff1aSopenharmony_ci } 370cabdff1aSopenharmony_ci ctx->tokens[stream_id][i] = tm2_get_token(&ctx->gb, &codes); 371cabdff1aSopenharmony_ci if (stream_id <= TM2_MOT && ctx->tokens[stream_id][i] >= TM2_DELTAS || ctx->tokens[stream_id][i]<0) { 372cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Invalid delta token index %d for type %d, n=%d\n", 373cabdff1aSopenharmony_ci ctx->tokens[stream_id][i], stream_id, i); 374cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 375cabdff1aSopenharmony_ci goto end; 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci } 378cabdff1aSopenharmony_ci } else { 379cabdff1aSopenharmony_ci if (len < 0) { 380cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 381cabdff1aSopenharmony_ci goto end; 382cabdff1aSopenharmony_ci } 383cabdff1aSopenharmony_ci for (i = 0; i < toks; i++) { 384cabdff1aSopenharmony_ci ctx->tokens[stream_id][i] = codes.recode[0]; 385cabdff1aSopenharmony_ci if (stream_id <= TM2_MOT && ctx->tokens[stream_id][i] >= TM2_DELTAS) { 386cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Invalid delta token index %d for type %d, n=%d\n", 387cabdff1aSopenharmony_ci ctx->tokens[stream_id][i], stream_id, i); 388cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 389cabdff1aSopenharmony_ci goto end; 390cabdff1aSopenharmony_ci } 391cabdff1aSopenharmony_ci } 392cabdff1aSopenharmony_ci } 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci ret = skip; 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ciend: 397cabdff1aSopenharmony_ci tm2_free_codes(&codes); 398cabdff1aSopenharmony_ci return ret; 399cabdff1aSopenharmony_ci} 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_cistatic inline int GET_TOK(TM2Context *ctx,int type) 402cabdff1aSopenharmony_ci{ 403cabdff1aSopenharmony_ci if (ctx->tok_ptrs[type] >= ctx->tok_lens[type]) { 404cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Read token from stream %i out of bounds (%i>=%i)\n", type, ctx->tok_ptrs[type], ctx->tok_lens[type]); 405cabdff1aSopenharmony_ci ctx->error = 1; 406cabdff1aSopenharmony_ci return 0; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci if (type <= TM2_MOT) { 409cabdff1aSopenharmony_ci if (ctx->tokens[type][ctx->tok_ptrs[type]] >= TM2_DELTAS) { 410cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "token %d is too large\n", ctx->tokens[type][ctx->tok_ptrs[type]]); 411cabdff1aSopenharmony_ci return 0; 412cabdff1aSopenharmony_ci } 413cabdff1aSopenharmony_ci return ctx->deltas[type][ctx->tokens[type][ctx->tok_ptrs[type]++]]; 414cabdff1aSopenharmony_ci } 415cabdff1aSopenharmony_ci return ctx->tokens[type][ctx->tok_ptrs[type]++]; 416cabdff1aSopenharmony_ci} 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci/* blocks decoding routines */ 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci/* common Y, U, V pointers initialisation */ 421cabdff1aSopenharmony_ci#define TM2_INIT_POINTERS() \ 422cabdff1aSopenharmony_ci int *last, *clast; \ 423cabdff1aSopenharmony_ci int *Y, *U, *V;\ 424cabdff1aSopenharmony_ci int Ystride, Ustride, Vstride;\ 425cabdff1aSopenharmony_ci\ 426cabdff1aSopenharmony_ci Ystride = ctx->y_stride;\ 427cabdff1aSopenharmony_ci Vstride = ctx->uv_stride;\ 428cabdff1aSopenharmony_ci Ustride = ctx->uv_stride;\ 429cabdff1aSopenharmony_ci Y = (ctx->cur?ctx->Y2:ctx->Y1) + by * 4 * Ystride + bx * 4;\ 430cabdff1aSopenharmony_ci V = (ctx->cur?ctx->V2:ctx->V1) + by * 2 * Vstride + bx * 2;\ 431cabdff1aSopenharmony_ci U = (ctx->cur?ctx->U2:ctx->U1) + by * 2 * Ustride + bx * 2;\ 432cabdff1aSopenharmony_ci last = ctx->last + bx * 4;\ 433cabdff1aSopenharmony_ci clast = ctx->clast + bx * 4; 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_ci#define TM2_INIT_POINTERS_2() \ 436cabdff1aSopenharmony_ci unsigned *Yo, *Uo, *Vo;\ 437cabdff1aSopenharmony_ci int oYstride, oUstride, oVstride;\ 438cabdff1aSopenharmony_ci\ 439cabdff1aSopenharmony_ci TM2_INIT_POINTERS();\ 440cabdff1aSopenharmony_ci oYstride = Ystride;\ 441cabdff1aSopenharmony_ci oVstride = Vstride;\ 442cabdff1aSopenharmony_ci oUstride = Ustride;\ 443cabdff1aSopenharmony_ci Yo = (ctx->cur?ctx->Y1:ctx->Y2) + by * 4 * oYstride + bx * 4;\ 444cabdff1aSopenharmony_ci Vo = (ctx->cur?ctx->V1:ctx->V2) + by * 2 * oVstride + bx * 2;\ 445cabdff1aSopenharmony_ci Uo = (ctx->cur?ctx->U1:ctx->U2) + by * 2 * oUstride + bx * 2; 446cabdff1aSopenharmony_ci 447cabdff1aSopenharmony_ci/* recalculate last and delta values for next blocks */ 448cabdff1aSopenharmony_ci#define TM2_RECALC_BLOCK(CHR, stride, last, CD) {\ 449cabdff1aSopenharmony_ci CD[0] = (unsigned)CHR[ 1] - (unsigned)last[1];\ 450cabdff1aSopenharmony_ci CD[1] = (unsigned)CHR[stride + 1] - (unsigned) CHR[1];\ 451cabdff1aSopenharmony_ci last[0] = (int)CHR[stride + 0];\ 452cabdff1aSopenharmony_ci last[1] = (int)CHR[stride + 1];} 453cabdff1aSopenharmony_ci 454cabdff1aSopenharmony_ci/* common operations - add deltas to 4x4 block of luma or 2x2 blocks of chroma */ 455cabdff1aSopenharmony_cistatic inline void tm2_apply_deltas(TM2Context *ctx, int* Y, int stride, int *deltas, int *last) 456cabdff1aSopenharmony_ci{ 457cabdff1aSopenharmony_ci unsigned ct, d; 458cabdff1aSopenharmony_ci int i, j; 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci for (j = 0; j < 4; j++){ 461cabdff1aSopenharmony_ci ct = ctx->D[j]; 462cabdff1aSopenharmony_ci for (i = 0; i < 4; i++){ 463cabdff1aSopenharmony_ci d = deltas[i + j * 4]; 464cabdff1aSopenharmony_ci ct += d; 465cabdff1aSopenharmony_ci last[i] += ct; 466cabdff1aSopenharmony_ci Y[i] = av_clip_uint8(last[i]); 467cabdff1aSopenharmony_ci } 468cabdff1aSopenharmony_ci Y += stride; 469cabdff1aSopenharmony_ci ctx->D[j] = ct; 470cabdff1aSopenharmony_ci } 471cabdff1aSopenharmony_ci} 472cabdff1aSopenharmony_ci 473cabdff1aSopenharmony_cistatic inline void tm2_high_chroma(int *data, int stride, int *last, unsigned *CD, int *deltas) 474cabdff1aSopenharmony_ci{ 475cabdff1aSopenharmony_ci int i, j; 476cabdff1aSopenharmony_ci for (j = 0; j < 2; j++) { 477cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) { 478cabdff1aSopenharmony_ci CD[j] += deltas[i + j * 2]; 479cabdff1aSopenharmony_ci last[i] += CD[j]; 480cabdff1aSopenharmony_ci data[i] = last[i]; 481cabdff1aSopenharmony_ci } 482cabdff1aSopenharmony_ci data += stride; 483cabdff1aSopenharmony_ci } 484cabdff1aSopenharmony_ci} 485cabdff1aSopenharmony_ci 486cabdff1aSopenharmony_cistatic inline void tm2_low_chroma(int *data, int stride, int *clast, unsigned *CD, int *deltas, int bx) 487cabdff1aSopenharmony_ci{ 488cabdff1aSopenharmony_ci int t; 489cabdff1aSopenharmony_ci int l; 490cabdff1aSopenharmony_ci int prev; 491cabdff1aSopenharmony_ci 492cabdff1aSopenharmony_ci if (bx > 0) 493cabdff1aSopenharmony_ci prev = clast[-3]; 494cabdff1aSopenharmony_ci else 495cabdff1aSopenharmony_ci prev = 0; 496cabdff1aSopenharmony_ci t = (int)(CD[0] + CD[1]) >> 1; 497cabdff1aSopenharmony_ci l = (int)(prev - CD[0] - CD[1] + clast[1]) >> 1; 498cabdff1aSopenharmony_ci CD[1] = CD[0] + CD[1] - t; 499cabdff1aSopenharmony_ci CD[0] = t; 500cabdff1aSopenharmony_ci clast[0] = l; 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_ci tm2_high_chroma(data, stride, clast, CD, deltas); 503cabdff1aSopenharmony_ci} 504cabdff1aSopenharmony_ci 505cabdff1aSopenharmony_cistatic inline void tm2_hi_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 506cabdff1aSopenharmony_ci{ 507cabdff1aSopenharmony_ci int i; 508cabdff1aSopenharmony_ci int deltas[16]; 509cabdff1aSopenharmony_ci TM2_INIT_POINTERS(); 510cabdff1aSopenharmony_ci 511cabdff1aSopenharmony_ci /* hi-res chroma */ 512cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 513cabdff1aSopenharmony_ci deltas[i] = GET_TOK(ctx, TM2_C_HI); 514cabdff1aSopenharmony_ci deltas[i + 4] = GET_TOK(ctx, TM2_C_HI); 515cabdff1aSopenharmony_ci } 516cabdff1aSopenharmony_ci tm2_high_chroma(U, Ustride, clast, ctx->CD, deltas); 517cabdff1aSopenharmony_ci tm2_high_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas + 4); 518cabdff1aSopenharmony_ci 519cabdff1aSopenharmony_ci /* hi-res luma */ 520cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) 521cabdff1aSopenharmony_ci deltas[i] = GET_TOK(ctx, TM2_L_HI); 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci tm2_apply_deltas(ctx, Y, Ystride, deltas, last); 524cabdff1aSopenharmony_ci} 525cabdff1aSopenharmony_ci 526cabdff1aSopenharmony_cistatic inline void tm2_med_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 527cabdff1aSopenharmony_ci{ 528cabdff1aSopenharmony_ci int i; 529cabdff1aSopenharmony_ci int deltas[16]; 530cabdff1aSopenharmony_ci TM2_INIT_POINTERS(); 531cabdff1aSopenharmony_ci 532cabdff1aSopenharmony_ci /* low-res chroma */ 533cabdff1aSopenharmony_ci deltas[0] = GET_TOK(ctx, TM2_C_LO); 534cabdff1aSopenharmony_ci deltas[1] = deltas[2] = deltas[3] = 0; 535cabdff1aSopenharmony_ci tm2_low_chroma(U, Ustride, clast, ctx->CD, deltas, bx); 536cabdff1aSopenharmony_ci 537cabdff1aSopenharmony_ci deltas[0] = GET_TOK(ctx, TM2_C_LO); 538cabdff1aSopenharmony_ci deltas[1] = deltas[2] = deltas[3] = 0; 539cabdff1aSopenharmony_ci tm2_low_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas, bx); 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_ci /* hi-res luma */ 542cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) 543cabdff1aSopenharmony_ci deltas[i] = GET_TOK(ctx, TM2_L_HI); 544cabdff1aSopenharmony_ci 545cabdff1aSopenharmony_ci tm2_apply_deltas(ctx, Y, Ystride, deltas, last); 546cabdff1aSopenharmony_ci} 547cabdff1aSopenharmony_ci 548cabdff1aSopenharmony_cistatic inline void tm2_low_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 549cabdff1aSopenharmony_ci{ 550cabdff1aSopenharmony_ci int i; 551cabdff1aSopenharmony_ci int t1, t2; 552cabdff1aSopenharmony_ci int deltas[16]; 553cabdff1aSopenharmony_ci TM2_INIT_POINTERS(); 554cabdff1aSopenharmony_ci 555cabdff1aSopenharmony_ci /* low-res chroma */ 556cabdff1aSopenharmony_ci deltas[0] = GET_TOK(ctx, TM2_C_LO); 557cabdff1aSopenharmony_ci deltas[1] = deltas[2] = deltas[3] = 0; 558cabdff1aSopenharmony_ci tm2_low_chroma(U, Ustride, clast, ctx->CD, deltas, bx); 559cabdff1aSopenharmony_ci 560cabdff1aSopenharmony_ci deltas[0] = GET_TOK(ctx, TM2_C_LO); 561cabdff1aSopenharmony_ci deltas[1] = deltas[2] = deltas[3] = 0; 562cabdff1aSopenharmony_ci tm2_low_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas, bx); 563cabdff1aSopenharmony_ci 564cabdff1aSopenharmony_ci /* low-res luma */ 565cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) 566cabdff1aSopenharmony_ci deltas[i] = 0; 567cabdff1aSopenharmony_ci 568cabdff1aSopenharmony_ci deltas[ 0] = GET_TOK(ctx, TM2_L_LO); 569cabdff1aSopenharmony_ci deltas[ 2] = GET_TOK(ctx, TM2_L_LO); 570cabdff1aSopenharmony_ci deltas[ 8] = GET_TOK(ctx, TM2_L_LO); 571cabdff1aSopenharmony_ci deltas[10] = GET_TOK(ctx, TM2_L_LO); 572cabdff1aSopenharmony_ci 573cabdff1aSopenharmony_ci if (bx > 0) 574cabdff1aSopenharmony_ci last[0] = (int)((unsigned)last[-1] - ctx->D[0] - ctx->D[1] - ctx->D[2] - ctx->D[3] + last[1]) >> 1; 575cabdff1aSopenharmony_ci else 576cabdff1aSopenharmony_ci last[0] = (int)((unsigned)last[1] - ctx->D[0] - ctx->D[1] - ctx->D[2] - ctx->D[3])>> 1; 577cabdff1aSopenharmony_ci last[2] = (int)((unsigned)last[1] + last[3]) >> 1; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci t1 = ctx->D[0] + (unsigned)ctx->D[1]; 580cabdff1aSopenharmony_ci ctx->D[0] = t1 >> 1; 581cabdff1aSopenharmony_ci ctx->D[1] = t1 - (t1 >> 1); 582cabdff1aSopenharmony_ci t2 = ctx->D[2] + (unsigned)ctx->D[3]; 583cabdff1aSopenharmony_ci ctx->D[2] = t2 >> 1; 584cabdff1aSopenharmony_ci ctx->D[3] = t2 - (t2 >> 1); 585cabdff1aSopenharmony_ci 586cabdff1aSopenharmony_ci tm2_apply_deltas(ctx, Y, Ystride, deltas, last); 587cabdff1aSopenharmony_ci} 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_cistatic inline void tm2_null_res_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 590cabdff1aSopenharmony_ci{ 591cabdff1aSopenharmony_ci int i; 592cabdff1aSopenharmony_ci int ct; 593cabdff1aSopenharmony_ci unsigned left, right; 594cabdff1aSopenharmony_ci int diff; 595cabdff1aSopenharmony_ci int deltas[16]; 596cabdff1aSopenharmony_ci TM2_INIT_POINTERS(); 597cabdff1aSopenharmony_ci 598cabdff1aSopenharmony_ci /* null chroma */ 599cabdff1aSopenharmony_ci deltas[0] = deltas[1] = deltas[2] = deltas[3] = 0; 600cabdff1aSopenharmony_ci tm2_low_chroma(U, Ustride, clast, ctx->CD, deltas, bx); 601cabdff1aSopenharmony_ci 602cabdff1aSopenharmony_ci deltas[0] = deltas[1] = deltas[2] = deltas[3] = 0; 603cabdff1aSopenharmony_ci tm2_low_chroma(V, Vstride, clast + 2, ctx->CD + 2, deltas, bx); 604cabdff1aSopenharmony_ci 605cabdff1aSopenharmony_ci /* null luma */ 606cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) 607cabdff1aSopenharmony_ci deltas[i] = 0; 608cabdff1aSopenharmony_ci 609cabdff1aSopenharmony_ci ct = (unsigned)ctx->D[0] + ctx->D[1] + ctx->D[2] + ctx->D[3]; 610cabdff1aSopenharmony_ci 611cabdff1aSopenharmony_ci if (bx > 0) 612cabdff1aSopenharmony_ci left = last[-1] - (unsigned)ct; 613cabdff1aSopenharmony_ci else 614cabdff1aSopenharmony_ci left = 0; 615cabdff1aSopenharmony_ci 616cabdff1aSopenharmony_ci right = last[3]; 617cabdff1aSopenharmony_ci diff = right - left; 618cabdff1aSopenharmony_ci last[0] = left + (diff >> 2); 619cabdff1aSopenharmony_ci last[1] = left + (diff >> 1); 620cabdff1aSopenharmony_ci last[2] = right - (diff >> 2); 621cabdff1aSopenharmony_ci last[3] = right; 622cabdff1aSopenharmony_ci { 623cabdff1aSopenharmony_ci unsigned tp = left; 624cabdff1aSopenharmony_ci 625cabdff1aSopenharmony_ci ctx->D[0] = (tp + (ct >> 2)) - left; 626cabdff1aSopenharmony_ci left += ctx->D[0]; 627cabdff1aSopenharmony_ci ctx->D[1] = (tp + (ct >> 1)) - left; 628cabdff1aSopenharmony_ci left += ctx->D[1]; 629cabdff1aSopenharmony_ci ctx->D[2] = ((tp + ct) - (ct >> 2)) - left; 630cabdff1aSopenharmony_ci left += ctx->D[2]; 631cabdff1aSopenharmony_ci ctx->D[3] = (tp + ct) - left; 632cabdff1aSopenharmony_ci } 633cabdff1aSopenharmony_ci tm2_apply_deltas(ctx, Y, Ystride, deltas, last); 634cabdff1aSopenharmony_ci} 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_cistatic inline void tm2_still_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 637cabdff1aSopenharmony_ci{ 638cabdff1aSopenharmony_ci int i, j; 639cabdff1aSopenharmony_ci TM2_INIT_POINTERS_2(); 640cabdff1aSopenharmony_ci 641cabdff1aSopenharmony_ci /* update chroma */ 642cabdff1aSopenharmony_ci for (j = 0; j < 2; j++) { 643cabdff1aSopenharmony_ci for (i = 0; i < 2; i++){ 644cabdff1aSopenharmony_ci U[i] = Uo[i]; 645cabdff1aSopenharmony_ci V[i] = Vo[i]; 646cabdff1aSopenharmony_ci } 647cabdff1aSopenharmony_ci U += Ustride; V += Vstride; 648cabdff1aSopenharmony_ci Uo += oUstride; Vo += oVstride; 649cabdff1aSopenharmony_ci } 650cabdff1aSopenharmony_ci U -= Ustride * 2; 651cabdff1aSopenharmony_ci V -= Vstride * 2; 652cabdff1aSopenharmony_ci TM2_RECALC_BLOCK(U, Ustride, clast, ctx->CD); 653cabdff1aSopenharmony_ci TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); 654cabdff1aSopenharmony_ci 655cabdff1aSopenharmony_ci /* update deltas */ 656cabdff1aSopenharmony_ci ctx->D[0] = Yo[3] - last[3]; 657cabdff1aSopenharmony_ci ctx->D[1] = Yo[3 + oYstride] - Yo[3]; 658cabdff1aSopenharmony_ci ctx->D[2] = Yo[3 + oYstride * 2] - Yo[3 + oYstride]; 659cabdff1aSopenharmony_ci ctx->D[3] = Yo[3 + oYstride * 3] - Yo[3 + oYstride * 2]; 660cabdff1aSopenharmony_ci 661cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) { 662cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 663cabdff1aSopenharmony_ci Y[i] = Yo[i]; 664cabdff1aSopenharmony_ci last[i] = Yo[i]; 665cabdff1aSopenharmony_ci } 666cabdff1aSopenharmony_ci Y += Ystride; 667cabdff1aSopenharmony_ci Yo += oYstride; 668cabdff1aSopenharmony_ci } 669cabdff1aSopenharmony_ci} 670cabdff1aSopenharmony_ci 671cabdff1aSopenharmony_cistatic inline void tm2_update_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 672cabdff1aSopenharmony_ci{ 673cabdff1aSopenharmony_ci int i, j; 674cabdff1aSopenharmony_ci unsigned d; 675cabdff1aSopenharmony_ci TM2_INIT_POINTERS_2(); 676cabdff1aSopenharmony_ci 677cabdff1aSopenharmony_ci /* update chroma */ 678cabdff1aSopenharmony_ci for (j = 0; j < 2; j++) { 679cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) { 680cabdff1aSopenharmony_ci U[i] = Uo[i] + GET_TOK(ctx, TM2_UPD); 681cabdff1aSopenharmony_ci V[i] = Vo[i] + GET_TOK(ctx, TM2_UPD); 682cabdff1aSopenharmony_ci } 683cabdff1aSopenharmony_ci U += Ustride; 684cabdff1aSopenharmony_ci V += Vstride; 685cabdff1aSopenharmony_ci Uo += oUstride; 686cabdff1aSopenharmony_ci Vo += oVstride; 687cabdff1aSopenharmony_ci } 688cabdff1aSopenharmony_ci U -= Ustride * 2; 689cabdff1aSopenharmony_ci V -= Vstride * 2; 690cabdff1aSopenharmony_ci TM2_RECALC_BLOCK(U, Ustride, clast, ctx->CD); 691cabdff1aSopenharmony_ci TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci /* update deltas */ 694cabdff1aSopenharmony_ci ctx->D[0] = Yo[3] - last[3]; 695cabdff1aSopenharmony_ci ctx->D[1] = Yo[3 + oYstride] - Yo[3]; 696cabdff1aSopenharmony_ci ctx->D[2] = Yo[3 + oYstride * 2] - Yo[3 + oYstride]; 697cabdff1aSopenharmony_ci ctx->D[3] = Yo[3 + oYstride * 3] - Yo[3 + oYstride * 2]; 698cabdff1aSopenharmony_ci 699cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) { 700cabdff1aSopenharmony_ci d = last[3]; 701cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 702cabdff1aSopenharmony_ci Y[i] = Yo[i] + (unsigned)GET_TOK(ctx, TM2_UPD); 703cabdff1aSopenharmony_ci last[i] = Y[i]; 704cabdff1aSopenharmony_ci } 705cabdff1aSopenharmony_ci ctx->D[j] = last[3] - d; 706cabdff1aSopenharmony_ci Y += Ystride; 707cabdff1aSopenharmony_ci Yo += oYstride; 708cabdff1aSopenharmony_ci } 709cabdff1aSopenharmony_ci} 710cabdff1aSopenharmony_ci 711cabdff1aSopenharmony_cistatic inline void tm2_motion_block(TM2Context *ctx, AVFrame *pic, int bx, int by) 712cabdff1aSopenharmony_ci{ 713cabdff1aSopenharmony_ci int i, j; 714cabdff1aSopenharmony_ci int mx, my; 715cabdff1aSopenharmony_ci TM2_INIT_POINTERS_2(); 716cabdff1aSopenharmony_ci 717cabdff1aSopenharmony_ci mx = GET_TOK(ctx, TM2_MOT); 718cabdff1aSopenharmony_ci my = GET_TOK(ctx, TM2_MOT); 719cabdff1aSopenharmony_ci mx = av_clip(mx, -(bx * 4 + 4), ctx->avctx->width - bx * 4); 720cabdff1aSopenharmony_ci my = av_clip(my, -(by * 4 + 4), ctx->avctx->height - by * 4); 721cabdff1aSopenharmony_ci 722cabdff1aSopenharmony_ci if (4*bx+mx<0 || 4*by+my<0 || 4*bx+mx+4 > ctx->avctx->width || 4*by+my+4 > ctx->avctx->height) { 723cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "MV out of picture\n"); 724cabdff1aSopenharmony_ci return; 725cabdff1aSopenharmony_ci } 726cabdff1aSopenharmony_ci 727cabdff1aSopenharmony_ci Yo += my * oYstride + mx; 728cabdff1aSopenharmony_ci Uo += (my >> 1) * oUstride + (mx >> 1); 729cabdff1aSopenharmony_ci Vo += (my >> 1) * oVstride + (mx >> 1); 730cabdff1aSopenharmony_ci 731cabdff1aSopenharmony_ci /* copy chroma */ 732cabdff1aSopenharmony_ci for (j = 0; j < 2; j++) { 733cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) { 734cabdff1aSopenharmony_ci U[i] = Uo[i]; 735cabdff1aSopenharmony_ci V[i] = Vo[i]; 736cabdff1aSopenharmony_ci } 737cabdff1aSopenharmony_ci U += Ustride; 738cabdff1aSopenharmony_ci V += Vstride; 739cabdff1aSopenharmony_ci Uo += oUstride; 740cabdff1aSopenharmony_ci Vo += oVstride; 741cabdff1aSopenharmony_ci } 742cabdff1aSopenharmony_ci U -= Ustride * 2; 743cabdff1aSopenharmony_ci V -= Vstride * 2; 744cabdff1aSopenharmony_ci TM2_RECALC_BLOCK(U, Ustride, clast, ctx->CD); 745cabdff1aSopenharmony_ci TM2_RECALC_BLOCK(V, Vstride, (clast + 2), (ctx->CD + 2)); 746cabdff1aSopenharmony_ci 747cabdff1aSopenharmony_ci /* copy luma */ 748cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) { 749cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 750cabdff1aSopenharmony_ci Y[i] = Yo[i]; 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci Y += Ystride; 753cabdff1aSopenharmony_ci Yo += oYstride; 754cabdff1aSopenharmony_ci } 755cabdff1aSopenharmony_ci /* calculate deltas */ 756cabdff1aSopenharmony_ci Y -= Ystride * 4; 757cabdff1aSopenharmony_ci ctx->D[0] = (unsigned)Y[3] - last[3]; 758cabdff1aSopenharmony_ci ctx->D[1] = (unsigned)Y[3 + Ystride] - Y[3]; 759cabdff1aSopenharmony_ci ctx->D[2] = (unsigned)Y[3 + Ystride * 2] - Y[3 + Ystride]; 760cabdff1aSopenharmony_ci ctx->D[3] = (unsigned)Y[3 + Ystride * 3] - Y[3 + Ystride * 2]; 761cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 762cabdff1aSopenharmony_ci last[i] = Y[i + Ystride * 3]; 763cabdff1aSopenharmony_ci} 764cabdff1aSopenharmony_ci 765cabdff1aSopenharmony_cistatic int tm2_decode_blocks(TM2Context *ctx, AVFrame *p) 766cabdff1aSopenharmony_ci{ 767cabdff1aSopenharmony_ci int i, j; 768cabdff1aSopenharmony_ci int w = ctx->avctx->width, h = ctx->avctx->height, bw = w >> 2, bh = h >> 2, cw = w >> 1; 769cabdff1aSopenharmony_ci int type; 770cabdff1aSopenharmony_ci int keyframe = 1; 771cabdff1aSopenharmony_ci int *Y, *U, *V; 772cabdff1aSopenharmony_ci uint8_t *dst; 773cabdff1aSopenharmony_ci 774cabdff1aSopenharmony_ci for (i = 0; i < TM2_NUM_STREAMS; i++) 775cabdff1aSopenharmony_ci ctx->tok_ptrs[i] = 0; 776cabdff1aSopenharmony_ci 777cabdff1aSopenharmony_ci if (ctx->tok_lens[TM2_TYPE]<bw*bh) { 778cabdff1aSopenharmony_ci av_log(ctx->avctx,AV_LOG_ERROR,"Got %i tokens for %i blocks\n",ctx->tok_lens[TM2_TYPE],bw*bh); 779cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 780cabdff1aSopenharmony_ci } 781cabdff1aSopenharmony_ci 782cabdff1aSopenharmony_ci memset(ctx->last, 0, 4 * bw * sizeof(int)); 783cabdff1aSopenharmony_ci memset(ctx->clast, 0, 4 * bw * sizeof(int)); 784cabdff1aSopenharmony_ci 785cabdff1aSopenharmony_ci for (j = 0; j < bh; j++) { 786cabdff1aSopenharmony_ci memset(ctx->D, 0, 4 * sizeof(int)); 787cabdff1aSopenharmony_ci memset(ctx->CD, 0, 4 * sizeof(int)); 788cabdff1aSopenharmony_ci for (i = 0; i < bw; i++) { 789cabdff1aSopenharmony_ci type = GET_TOK(ctx, TM2_TYPE); 790cabdff1aSopenharmony_ci switch(type) { 791cabdff1aSopenharmony_ci case TM2_HI_RES: 792cabdff1aSopenharmony_ci tm2_hi_res_block(ctx, p, i, j); 793cabdff1aSopenharmony_ci break; 794cabdff1aSopenharmony_ci case TM2_MED_RES: 795cabdff1aSopenharmony_ci tm2_med_res_block(ctx, p, i, j); 796cabdff1aSopenharmony_ci break; 797cabdff1aSopenharmony_ci case TM2_LOW_RES: 798cabdff1aSopenharmony_ci tm2_low_res_block(ctx, p, i, j); 799cabdff1aSopenharmony_ci break; 800cabdff1aSopenharmony_ci case TM2_NULL_RES: 801cabdff1aSopenharmony_ci tm2_null_res_block(ctx, p, i, j); 802cabdff1aSopenharmony_ci break; 803cabdff1aSopenharmony_ci case TM2_UPDATE: 804cabdff1aSopenharmony_ci tm2_update_block(ctx, p, i, j); 805cabdff1aSopenharmony_ci keyframe = 0; 806cabdff1aSopenharmony_ci break; 807cabdff1aSopenharmony_ci case TM2_STILL: 808cabdff1aSopenharmony_ci tm2_still_block(ctx, p, i, j); 809cabdff1aSopenharmony_ci keyframe = 0; 810cabdff1aSopenharmony_ci break; 811cabdff1aSopenharmony_ci case TM2_MOTION: 812cabdff1aSopenharmony_ci tm2_motion_block(ctx, p, i, j); 813cabdff1aSopenharmony_ci keyframe = 0; 814cabdff1aSopenharmony_ci break; 815cabdff1aSopenharmony_ci default: 816cabdff1aSopenharmony_ci av_log(ctx->avctx, AV_LOG_ERROR, "Skipping unknown block type %i\n", type); 817cabdff1aSopenharmony_ci } 818cabdff1aSopenharmony_ci if (ctx->error) 819cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 820cabdff1aSopenharmony_ci } 821cabdff1aSopenharmony_ci } 822cabdff1aSopenharmony_ci 823cabdff1aSopenharmony_ci /* copy data from our buffer to AVFrame */ 824cabdff1aSopenharmony_ci Y = (ctx->cur?ctx->Y2:ctx->Y1); 825cabdff1aSopenharmony_ci U = (ctx->cur?ctx->U2:ctx->U1); 826cabdff1aSopenharmony_ci V = (ctx->cur?ctx->V2:ctx->V1); 827cabdff1aSopenharmony_ci dst = p->data[0]; 828cabdff1aSopenharmony_ci for (j = 0; j < h; j++) { 829cabdff1aSopenharmony_ci for (i = 0; i < w; i++) { 830cabdff1aSopenharmony_ci unsigned y = Y[i], u = U[i >> 1], v = V[i >> 1]; 831cabdff1aSopenharmony_ci dst[3*i+0] = av_clip_uint8(y + v); 832cabdff1aSopenharmony_ci dst[3*i+1] = av_clip_uint8(y); 833cabdff1aSopenharmony_ci dst[3*i+2] = av_clip_uint8(y + u); 834cabdff1aSopenharmony_ci } 835cabdff1aSopenharmony_ci 836cabdff1aSopenharmony_ci /* horizontal edge extension */ 837cabdff1aSopenharmony_ci Y[-4] = Y[-3] = Y[-2] = Y[-1] = Y[0]; 838cabdff1aSopenharmony_ci Y[w + 3] = Y[w + 2] = Y[w + 1] = Y[w] = Y[w - 1]; 839cabdff1aSopenharmony_ci 840cabdff1aSopenharmony_ci /* vertical edge extension */ 841cabdff1aSopenharmony_ci if (j == 0) { 842cabdff1aSopenharmony_ci memcpy(Y - 4 - 1 * ctx->y_stride, Y - 4, ctx->y_stride); 843cabdff1aSopenharmony_ci memcpy(Y - 4 - 2 * ctx->y_stride, Y - 4, ctx->y_stride); 844cabdff1aSopenharmony_ci memcpy(Y - 4 - 3 * ctx->y_stride, Y - 4, ctx->y_stride); 845cabdff1aSopenharmony_ci memcpy(Y - 4 - 4 * ctx->y_stride, Y - 4, ctx->y_stride); 846cabdff1aSopenharmony_ci } else if (j == h - 1) { 847cabdff1aSopenharmony_ci memcpy(Y - 4 + 1 * ctx->y_stride, Y - 4, ctx->y_stride); 848cabdff1aSopenharmony_ci memcpy(Y - 4 + 2 * ctx->y_stride, Y - 4, ctx->y_stride); 849cabdff1aSopenharmony_ci memcpy(Y - 4 + 3 * ctx->y_stride, Y - 4, ctx->y_stride); 850cabdff1aSopenharmony_ci memcpy(Y - 4 + 4 * ctx->y_stride, Y - 4, ctx->y_stride); 851cabdff1aSopenharmony_ci } 852cabdff1aSopenharmony_ci 853cabdff1aSopenharmony_ci Y += ctx->y_stride; 854cabdff1aSopenharmony_ci if (j & 1) { 855cabdff1aSopenharmony_ci /* horizontal edge extension */ 856cabdff1aSopenharmony_ci U[-2] = U[-1] = U[0]; 857cabdff1aSopenharmony_ci V[-2] = V[-1] = V[0]; 858cabdff1aSopenharmony_ci U[cw + 1] = U[cw] = U[cw - 1]; 859cabdff1aSopenharmony_ci V[cw + 1] = V[cw] = V[cw - 1]; 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_ci /* vertical edge extension */ 862cabdff1aSopenharmony_ci if (j == 1) { 863cabdff1aSopenharmony_ci memcpy(U - 2 - 1 * ctx->uv_stride, U - 2, ctx->uv_stride); 864cabdff1aSopenharmony_ci memcpy(V - 2 - 1 * ctx->uv_stride, V - 2, ctx->uv_stride); 865cabdff1aSopenharmony_ci memcpy(U - 2 - 2 * ctx->uv_stride, U - 2, ctx->uv_stride); 866cabdff1aSopenharmony_ci memcpy(V - 2 - 2 * ctx->uv_stride, V - 2, ctx->uv_stride); 867cabdff1aSopenharmony_ci } else if (j == h - 1) { 868cabdff1aSopenharmony_ci memcpy(U - 2 + 1 * ctx->uv_stride, U - 2, ctx->uv_stride); 869cabdff1aSopenharmony_ci memcpy(V - 2 + 1 * ctx->uv_stride, V - 2, ctx->uv_stride); 870cabdff1aSopenharmony_ci memcpy(U - 2 + 2 * ctx->uv_stride, U - 2, ctx->uv_stride); 871cabdff1aSopenharmony_ci memcpy(V - 2 + 2 * ctx->uv_stride, V - 2, ctx->uv_stride); 872cabdff1aSopenharmony_ci } 873cabdff1aSopenharmony_ci 874cabdff1aSopenharmony_ci U += ctx->uv_stride; 875cabdff1aSopenharmony_ci V += ctx->uv_stride; 876cabdff1aSopenharmony_ci } 877cabdff1aSopenharmony_ci dst += p->linesize[0]; 878cabdff1aSopenharmony_ci } 879cabdff1aSopenharmony_ci 880cabdff1aSopenharmony_ci return keyframe; 881cabdff1aSopenharmony_ci} 882cabdff1aSopenharmony_ci 883cabdff1aSopenharmony_cistatic const int tm2_stream_order[TM2_NUM_STREAMS] = { 884cabdff1aSopenharmony_ci TM2_C_HI, TM2_C_LO, TM2_L_HI, TM2_L_LO, TM2_UPD, TM2_MOT, TM2_TYPE 885cabdff1aSopenharmony_ci}; 886cabdff1aSopenharmony_ci 887cabdff1aSopenharmony_ci#define TM2_HEADER_SIZE 40 888cabdff1aSopenharmony_ci 889cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *rframe, 890cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 891cabdff1aSopenharmony_ci{ 892cabdff1aSopenharmony_ci TM2Context * const l = avctx->priv_data; 893cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 894cabdff1aSopenharmony_ci int buf_size = avpkt->size & ~3; 895cabdff1aSopenharmony_ci AVFrame * const p = l->pic; 896cabdff1aSopenharmony_ci int offset = TM2_HEADER_SIZE; 897cabdff1aSopenharmony_ci int i, t, ret; 898cabdff1aSopenharmony_ci 899cabdff1aSopenharmony_ci l->error = 0; 900cabdff1aSopenharmony_ci 901cabdff1aSopenharmony_ci av_fast_padded_malloc(&l->buffer, &l->buffer_size, buf_size); 902cabdff1aSopenharmony_ci if (!l->buffer) { 903cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); 904cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 905cabdff1aSopenharmony_ci } 906cabdff1aSopenharmony_ci 907cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, p, 0)) < 0) 908cabdff1aSopenharmony_ci return ret; 909cabdff1aSopenharmony_ci 910cabdff1aSopenharmony_ci l->bdsp.bswap_buf((uint32_t *) l->buffer, (const uint32_t *) buf, 911cabdff1aSopenharmony_ci buf_size >> 2); 912cabdff1aSopenharmony_ci 913cabdff1aSopenharmony_ci if ((ret = tm2_read_header(l, l->buffer)) < 0) { 914cabdff1aSopenharmony_ci return ret; 915cabdff1aSopenharmony_ci } 916cabdff1aSopenharmony_ci 917cabdff1aSopenharmony_ci for (i = 0; i < TM2_NUM_STREAMS; i++) { 918cabdff1aSopenharmony_ci if (offset >= buf_size) { 919cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "no space for tm2_read_stream\n"); 920cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 921cabdff1aSopenharmony_ci } 922cabdff1aSopenharmony_ci 923cabdff1aSopenharmony_ci t = tm2_read_stream(l, l->buffer + offset, tm2_stream_order[i], 924cabdff1aSopenharmony_ci buf_size - offset); 925cabdff1aSopenharmony_ci if (t < 0) { 926cabdff1aSopenharmony_ci int j = tm2_stream_order[i]; 927cabdff1aSopenharmony_ci if (l->tok_lens[j]) 928cabdff1aSopenharmony_ci memset(l->tokens[j], 0, sizeof(**l->tokens) * l->tok_lens[j]); 929cabdff1aSopenharmony_ci return t; 930cabdff1aSopenharmony_ci } 931cabdff1aSopenharmony_ci offset += t; 932cabdff1aSopenharmony_ci } 933cabdff1aSopenharmony_ci p->key_frame = tm2_decode_blocks(l, p); 934cabdff1aSopenharmony_ci if (p->key_frame) 935cabdff1aSopenharmony_ci p->pict_type = AV_PICTURE_TYPE_I; 936cabdff1aSopenharmony_ci else 937cabdff1aSopenharmony_ci p->pict_type = AV_PICTURE_TYPE_P; 938cabdff1aSopenharmony_ci 939cabdff1aSopenharmony_ci l->cur = !l->cur; 940cabdff1aSopenharmony_ci *got_frame = 1; 941cabdff1aSopenharmony_ci ret = av_frame_ref(rframe, l->pic); 942cabdff1aSopenharmony_ci 943cabdff1aSopenharmony_ci return (ret < 0) ? ret : buf_size; 944cabdff1aSopenharmony_ci} 945cabdff1aSopenharmony_ci 946cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx) 947cabdff1aSopenharmony_ci{ 948cabdff1aSopenharmony_ci TM2Context * const l = avctx->priv_data; 949cabdff1aSopenharmony_ci int w = avctx->width, h = avctx->height; 950cabdff1aSopenharmony_ci 951cabdff1aSopenharmony_ci if ((avctx->width & 3) || (avctx->height & 3)) { 952cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Width and height must be multiple of 4\n"); 953cabdff1aSopenharmony_ci return AVERROR(EINVAL); 954cabdff1aSopenharmony_ci } 955cabdff1aSopenharmony_ci 956cabdff1aSopenharmony_ci l->avctx = avctx; 957cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_BGR24; 958cabdff1aSopenharmony_ci 959cabdff1aSopenharmony_ci l->pic = av_frame_alloc(); 960cabdff1aSopenharmony_ci if (!l->pic) 961cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 962cabdff1aSopenharmony_ci 963cabdff1aSopenharmony_ci ff_bswapdsp_init(&l->bdsp); 964cabdff1aSopenharmony_ci 965cabdff1aSopenharmony_ci l->last = av_malloc_array(w, 2 * sizeof(*l->last)); 966cabdff1aSopenharmony_ci if (!l->last) 967cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 968cabdff1aSopenharmony_ci l->clast = l->last + w; 969cabdff1aSopenharmony_ci 970cabdff1aSopenharmony_ci w += 8; 971cabdff1aSopenharmony_ci h += 8; 972cabdff1aSopenharmony_ci l->Y_base = av_calloc(w * h, 2 * sizeof(*l->Y_base)); 973cabdff1aSopenharmony_ci if (!l->Y_base) 974cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 975cabdff1aSopenharmony_ci l->y_stride = w; 976cabdff1aSopenharmony_ci l->Y1 = l->Y_base + l->y_stride * 4 + 4; 977cabdff1aSopenharmony_ci l->Y2 = l->Y1 + w * h; 978cabdff1aSopenharmony_ci w = (w + 1) >> 1; 979cabdff1aSopenharmony_ci h = (h + 1) >> 1; 980cabdff1aSopenharmony_ci l->UV_base = av_calloc(w * h, 4 * sizeof(*l->UV_base)); 981cabdff1aSopenharmony_ci if (!l->UV_base) 982cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 983cabdff1aSopenharmony_ci l->uv_stride = w; 984cabdff1aSopenharmony_ci l->U1 = l->UV_base + l->uv_stride * 2 + 2; 985cabdff1aSopenharmony_ci l->U2 = l->U1 + w * h; 986cabdff1aSopenharmony_ci l->V1 = l->U2 + w * h; 987cabdff1aSopenharmony_ci l->V2 = l->V1 + w * h; 988cabdff1aSopenharmony_ci 989cabdff1aSopenharmony_ci return 0; 990cabdff1aSopenharmony_ci} 991cabdff1aSopenharmony_ci 992cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx) 993cabdff1aSopenharmony_ci{ 994cabdff1aSopenharmony_ci TM2Context * const l = avctx->priv_data; 995cabdff1aSopenharmony_ci int i; 996cabdff1aSopenharmony_ci 997cabdff1aSopenharmony_ci av_freep(&l->last); 998cabdff1aSopenharmony_ci for (i = 0; i < TM2_NUM_STREAMS; i++) 999cabdff1aSopenharmony_ci av_freep(&l->tokens[i]); 1000cabdff1aSopenharmony_ci 1001cabdff1aSopenharmony_ci av_freep(&l->Y_base); 1002cabdff1aSopenharmony_ci av_freep(&l->UV_base); 1003cabdff1aSopenharmony_ci av_freep(&l->buffer); 1004cabdff1aSopenharmony_ci l->buffer_size = 0; 1005cabdff1aSopenharmony_ci 1006cabdff1aSopenharmony_ci av_frame_free(&l->pic); 1007cabdff1aSopenharmony_ci 1008cabdff1aSopenharmony_ci return 0; 1009cabdff1aSopenharmony_ci} 1010cabdff1aSopenharmony_ci 1011cabdff1aSopenharmony_ciconst FFCodec ff_truemotion2_decoder = { 1012cabdff1aSopenharmony_ci .p.name = "truemotion2", 1013cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0"), 1014cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 1015cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_TRUEMOTION2, 1016cabdff1aSopenharmony_ci .priv_data_size = sizeof(TM2Context), 1017cabdff1aSopenharmony_ci .init = decode_init, 1018cabdff1aSopenharmony_ci .close = decode_end, 1019cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(decode_frame), 1020cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 1021cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, 1022cabdff1aSopenharmony_ci}; 1023