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