1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * 4XM codec
3cabdff1aSopenharmony_ci * Copyright (c) 2003 Michael Niedermayer
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 * 4XM codec.
25cabdff1aSopenharmony_ci */
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include <inttypes.h>
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
30cabdff1aSopenharmony_ci#include "libavutil/frame.h"
31cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
32cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
33cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h"
34cabdff1aSopenharmony_ci#include "libavutil/thread.h"
35cabdff1aSopenharmony_ci#include "avcodec.h"
36cabdff1aSopenharmony_ci#include "blockdsp.h"
37cabdff1aSopenharmony_ci#include "bswapdsp.h"
38cabdff1aSopenharmony_ci#include "bytestream.h"
39cabdff1aSopenharmony_ci#include "codec_internal.h"
40cabdff1aSopenharmony_ci#include "get_bits.h"
41cabdff1aSopenharmony_ci#include "internal.h"
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci#define BLOCK_TYPE_VLC_BITS 5
45cabdff1aSopenharmony_ci#define ACDC_VLC_BITS 9
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci#define CFRAME_BUFFER_COUNT 100
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_cistatic const uint8_t block_type_tab[2][4][8][2] = {
50cabdff1aSopenharmony_ci    {
51cabdff1aSopenharmony_ci        {    // { 8, 4, 2 } x { 8, 4, 2}
52cabdff1aSopenharmony_ci            { 0, 1 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 30, 5 }, { 31, 5 }, { 0, 0 }
53cabdff1aSopenharmony_ci        }, { // { 8, 4 } x 1
54cabdff1aSopenharmony_ci            { 0, 1 }, { 0, 0 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 }, { 0, 0 }
55cabdff1aSopenharmony_ci        }, { // 1 x { 8, 4 }
56cabdff1aSopenharmony_ci            { 0, 1 }, { 2, 2 }, { 0, 0 }, { 6, 3 }, { 14, 4 }, { 15, 4 }, { 0, 0 }
57cabdff1aSopenharmony_ci        }, { // 1 x 2, 2 x 1
58cabdff1aSopenharmony_ci            { 0, 1 }, { 0, 0 }, { 0, 0 }, { 2, 2 }, { 6, 3 }, { 14, 4 }, { 15, 4 }
59cabdff1aSopenharmony_ci        }
60cabdff1aSopenharmony_ci    }, {
61cabdff1aSopenharmony_ci        {   // { 8, 4, 2 } x { 8, 4, 2}
62cabdff1aSopenharmony_ci            { 1, 2 }, { 4, 3 }, { 5, 3 }, { 0, 2 }, { 6, 3 }, { 7, 3 }, { 0, 0 }
63cabdff1aSopenharmony_ci        }, {// { 8, 4 } x 1
64cabdff1aSopenharmony_ci            { 1, 2 }, { 0, 0 }, { 2, 2 }, { 0, 2 }, { 6, 3 }, { 7, 3 }, { 0, 0 }
65cabdff1aSopenharmony_ci        }, {// 1 x { 8, 4 }
66cabdff1aSopenharmony_ci            { 1, 2 }, { 2, 2 }, { 0, 0 }, { 0, 2 }, { 6, 3 }, { 7, 3 }, { 0, 0 }
67cabdff1aSopenharmony_ci        }, {// 1 x 2, 2 x 1
68cabdff1aSopenharmony_ci            { 1, 2 }, { 0, 0 }, { 0, 0 }, { 0, 2 }, { 2, 2 }, { 6, 3 }, { 7, 3 }
69cabdff1aSopenharmony_ci      }
70cabdff1aSopenharmony_ci    }
71cabdff1aSopenharmony_ci};
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_cistatic const uint8_t size2index[4][4] = {
74cabdff1aSopenharmony_ci    { -1, 3, 1, 1 },
75cabdff1aSopenharmony_ci    {  3, 0, 0, 0 },
76cabdff1aSopenharmony_ci    {  2, 0, 0, 0 },
77cabdff1aSopenharmony_ci    {  2, 0, 0, 0 },
78cabdff1aSopenharmony_ci};
79cabdff1aSopenharmony_ci
80cabdff1aSopenharmony_cistatic const int8_t mv[256][2] = {
81cabdff1aSopenharmony_ci    {   0,   0 }, {   0,  -1 }, {  -1,   0 }, {   1,   0 }, {   0,   1 }, {  -1,  -1 }, {   1,  -1 }, {  -1,   1 },
82cabdff1aSopenharmony_ci    {   1,   1 }, {   0,  -2 }, {  -2,   0 }, {   2,   0 }, {   0,   2 }, {  -1,  -2 }, {   1,  -2 }, {  -2,  -1 },
83cabdff1aSopenharmony_ci    {   2,  -1 }, {  -2,   1 }, {   2,   1 }, {  -1,   2 }, {   1,   2 }, {  -2,  -2 }, {   2,  -2 }, {  -2,   2 },
84cabdff1aSopenharmony_ci    {   2,   2 }, {   0,  -3 }, {  -3,   0 }, {   3,   0 }, {   0,   3 }, {  -1,  -3 }, {   1,  -3 }, {  -3,  -1 },
85cabdff1aSopenharmony_ci    {   3,  -1 }, {  -3,   1 }, {   3,   1 }, {  -1,   3 }, {   1,   3 }, {  -2,  -3 }, {   2,  -3 }, {  -3,  -2 },
86cabdff1aSopenharmony_ci    {   3,  -2 }, {  -3,   2 }, {   3,   2 }, {  -2,   3 }, {   2,   3 }, {   0,  -4 }, {  -4,   0 }, {   4,   0 },
87cabdff1aSopenharmony_ci    {   0,   4 }, {  -1,  -4 }, {   1,  -4 }, {  -4,  -1 }, {   4,  -1 }, {   4,   1 }, {  -1,   4 }, {   1,   4 },
88cabdff1aSopenharmony_ci    {  -3,  -3 }, {  -3,   3 }, {   3,   3 }, {  -2,  -4 }, {  -4,  -2 }, {   4,  -2 }, {  -4,   2 }, {  -2,   4 },
89cabdff1aSopenharmony_ci    {   2,   4 }, {  -3,  -4 }, {   3,  -4 }, {   4,  -3 }, {  -5,   0 }, {  -4,   3 }, {  -3,   4 }, {   3,   4 },
90cabdff1aSopenharmony_ci    {  -1,  -5 }, {  -5,  -1 }, {  -5,   1 }, {  -1,   5 }, {  -2,  -5 }, {   2,  -5 }, {   5,  -2 }, {   5,   2 },
91cabdff1aSopenharmony_ci    {  -4,  -4 }, {  -4,   4 }, {  -3,  -5 }, {  -5,  -3 }, {  -5,   3 }, {   3,   5 }, {  -6,   0 }, {   0,   6 },
92cabdff1aSopenharmony_ci    {  -6,  -1 }, {  -6,   1 }, {   1,   6 }, {   2,  -6 }, {  -6,   2 }, {   2,   6 }, {  -5,  -4 }, {   5,   4 },
93cabdff1aSopenharmony_ci    {   4,   5 }, {  -6,  -3 }, {   6,   3 }, {  -7,   0 }, {  -1,  -7 }, {   5,  -5 }, {  -7,   1 }, {  -1,   7 },
94cabdff1aSopenharmony_ci    {   4,  -6 }, {   6,   4 }, {  -2,  -7 }, {  -7,   2 }, {  -3,  -7 }, {   7,  -3 }, {   3,   7 }, {   6,  -5 },
95cabdff1aSopenharmony_ci    {   0,  -8 }, {  -1,  -8 }, {  -7,  -4 }, {  -8,   1 }, {   4,   7 }, {   2,  -8 }, {  -2,   8 }, {   6,   6 },
96cabdff1aSopenharmony_ci    {  -8,   3 }, {   5,  -7 }, {  -5,   7 }, {   8,  -4 }, {   0,  -9 }, {  -9,  -1 }, {   1,   9 }, {   7,  -6 },
97cabdff1aSopenharmony_ci    {  -7,   6 }, {  -5,  -8 }, {  -5,   8 }, {  -9,   3 }, {   9,  -4 }, {   7,  -7 }, {   8,  -6 }, {   6,   8 },
98cabdff1aSopenharmony_ci    {  10,   1 }, { -10,   2 }, {   9,  -5 }, {  10,  -3 }, {  -8,  -7 }, { -10,  -4 }, {   6,  -9 }, { -11,   0 },
99cabdff1aSopenharmony_ci    {  11,   1 }, { -11,  -2 }, {  -2,  11 }, {   7,  -9 }, {  -7,   9 }, {  10,   6 }, {  -4,  11 }, {   8,  -9 },
100cabdff1aSopenharmony_ci    {   8,   9 }, {   5,  11 }, {   7, -10 }, {  12,  -3 }, {  11,   6 }, {  -9,  -9 }, {   8,  10 }, {   5,  12 },
101cabdff1aSopenharmony_ci    { -11,   7 }, {  13,   2 }, {   6, -12 }, {  10,   9 }, { -11,   8 }, {  -7,  12 }, {   0,  14 }, {  14,  -2 },
102cabdff1aSopenharmony_ci    {  -9,  11 }, {  -6,  13 }, { -14,  -4 }, {  -5, -14 }, {   5,  14 }, { -15,  -1 }, { -14,  -6 }, {   3, -15 },
103cabdff1aSopenharmony_ci    {  11, -11 }, {  -7,  14 }, {  -5,  15 }, {   8, -14 }, {  15,   6 }, {   3,  16 }, {   7, -15 }, { -16,   5 },
104cabdff1aSopenharmony_ci    {   0,  17 }, { -16,  -6 }, { -10,  14 }, { -16,   7 }, {  12,  13 }, { -16,   8 }, { -17,   6 }, { -18,   3 },
105cabdff1aSopenharmony_ci    {  -7,  17 }, {  15,  11 }, {  16,  10 }, {   2, -19 }, {   3, -19 }, { -11, -16 }, { -18,   8 }, { -19,  -6 },
106cabdff1aSopenharmony_ci    {   2, -20 }, { -17, -11 }, { -10, -18 }, {   8,  19 }, { -21,  -1 }, { -20,   7 }, {  -4,  21 }, {  21,   5 },
107cabdff1aSopenharmony_ci    {  15,  16 }, {   2, -22 }, { -10, -20 }, { -22,   5 }, {  20, -11 }, {  -7, -22 }, { -12,  20 }, {  23,  -5 },
108cabdff1aSopenharmony_ci    {  13, -20 }, {  24,  -2 }, { -15,  19 }, { -11,  22 }, {  16,  19 }, {  23, -10 }, { -18, -18 }, {  -9, -24 },
109cabdff1aSopenharmony_ci    {  24, -10 }, {  -3,  26 }, { -23,  13 }, { -18, -20 }, {  17,  21 }, {  -4,  27 }, {  27,   6 }, {   1, -28 },
110cabdff1aSopenharmony_ci    { -11,  26 }, { -17, -23 }, {   7,  28 }, {  11, -27 }, {  29,   5 }, { -23, -19 }, { -28, -11 }, { -21,  22 },
111cabdff1aSopenharmony_ci    { -30,   7 }, { -17,  26 }, { -27,  16 }, {  13,  29 }, {  19, -26 }, {  10, -31 }, { -14, -30 }, {  20, -27 },
112cabdff1aSopenharmony_ci    { -29,  18 }, { -16, -31 }, { -28, -22 }, {  21, -30 }, { -25,  28 }, {  26, -29 }, {  25, -32 }, { -32, -32 }
113cabdff1aSopenharmony_ci};
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci/* This is simply the scaled down elementwise product of the standard JPEG
116cabdff1aSopenharmony_ci * quantizer table and the AAN premul table. */
117cabdff1aSopenharmony_cistatic const uint8_t dequant_table[64] = {
118cabdff1aSopenharmony_ci    16, 15, 13, 19, 24, 31, 28, 17,
119cabdff1aSopenharmony_ci    17, 23, 25, 31, 36, 63, 45, 21,
120cabdff1aSopenharmony_ci    18, 24, 27, 37, 52, 59, 49, 20,
121cabdff1aSopenharmony_ci    16, 28, 34, 40, 60, 80, 51, 20,
122cabdff1aSopenharmony_ci    18, 31, 48, 66, 68, 86, 56, 21,
123cabdff1aSopenharmony_ci    19, 38, 56, 59, 64, 64, 48, 20,
124cabdff1aSopenharmony_ci    27, 48, 55, 55, 56, 51, 35, 15,
125cabdff1aSopenharmony_ci    20, 35, 34, 32, 31, 22, 15,  8,
126cabdff1aSopenharmony_ci};
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_cistatic VLC block_type_vlc[2][4];
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_citypedef struct CFrameBuffer {
132cabdff1aSopenharmony_ci    unsigned int allocated_size;
133cabdff1aSopenharmony_ci    unsigned int size;
134cabdff1aSopenharmony_ci    int id;
135cabdff1aSopenharmony_ci    uint8_t *data;
136cabdff1aSopenharmony_ci} CFrameBuffer;
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_citypedef struct FourXContext {
139cabdff1aSopenharmony_ci    AVCodecContext *avctx;
140cabdff1aSopenharmony_ci    BlockDSPContext bdsp;
141cabdff1aSopenharmony_ci    BswapDSPContext bbdsp;
142cabdff1aSopenharmony_ci    uint16_t *frame_buffer;
143cabdff1aSopenharmony_ci    uint16_t *last_frame_buffer;
144cabdff1aSopenharmony_ci    GetBitContext pre_gb;          ///< ac/dc prefix
145cabdff1aSopenharmony_ci    GetBitContext gb;
146cabdff1aSopenharmony_ci    GetByteContext g;
147cabdff1aSopenharmony_ci    GetByteContext g2;
148cabdff1aSopenharmony_ci    int mv[256];
149cabdff1aSopenharmony_ci    VLC pre_vlc;
150cabdff1aSopenharmony_ci    int last_dc;
151cabdff1aSopenharmony_ci    DECLARE_ALIGNED(32, int16_t, block)[6][64];
152cabdff1aSopenharmony_ci    void *bitstream_buffer;
153cabdff1aSopenharmony_ci    unsigned int bitstream_buffer_size;
154cabdff1aSopenharmony_ci    int version;
155cabdff1aSopenharmony_ci    CFrameBuffer cfrm[CFRAME_BUFFER_COUNT];
156cabdff1aSopenharmony_ci} FourXContext;
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci
159cabdff1aSopenharmony_ci#define FIX_1_082392200  70936
160cabdff1aSopenharmony_ci#define FIX_1_414213562  92682
161cabdff1aSopenharmony_ci#define FIX_1_847759065 121095
162cabdff1aSopenharmony_ci#define FIX_2_613125930 171254
163cabdff1aSopenharmony_ci
164cabdff1aSopenharmony_ci#define MULTIPLY(var, const) ((int)((var) * (unsigned)(const)) >> 16)
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_cistatic void idct(int16_t block[64])
167cabdff1aSopenharmony_ci{
168cabdff1aSopenharmony_ci    int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
169cabdff1aSopenharmony_ci    int tmp10, tmp11, tmp12, tmp13;
170cabdff1aSopenharmony_ci    int z5, z10, z11, z12, z13;
171cabdff1aSopenharmony_ci    int i;
172cabdff1aSopenharmony_ci    int temp[64];
173cabdff1aSopenharmony_ci
174cabdff1aSopenharmony_ci    for (i = 0; i < 8; i++) {
175cabdff1aSopenharmony_ci        tmp10 = block[8 * 0 + i] + block[8 * 4 + i];
176cabdff1aSopenharmony_ci        tmp11 = block[8 * 0 + i] - block[8 * 4 + i];
177cabdff1aSopenharmony_ci
178cabdff1aSopenharmony_ci        tmp13 = block[8 * 2 + i] + block[8 * 6 + i];
179cabdff1aSopenharmony_ci        tmp12 = MULTIPLY(block[8 * 2 + i] - block[8 * 6 + i], FIX_1_414213562) - tmp13;
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci        tmp0 = tmp10 + tmp13;
182cabdff1aSopenharmony_ci        tmp3 = tmp10 - tmp13;
183cabdff1aSopenharmony_ci        tmp1 = tmp11 + tmp12;
184cabdff1aSopenharmony_ci        tmp2 = tmp11 - tmp12;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci        z13 = block[8 * 5 + i] + block[8 * 3 + i];
187cabdff1aSopenharmony_ci        z10 = block[8 * 5 + i] - block[8 * 3 + i];
188cabdff1aSopenharmony_ci        z11 = block[8 * 1 + i] + block[8 * 7 + i];
189cabdff1aSopenharmony_ci        z12 = block[8 * 1 + i] - block[8 * 7 + i];
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci        tmp7  =          z11 + z13;
192cabdff1aSopenharmony_ci        tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562);
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_ci        z5    = MULTIPLY(z10 + z12, FIX_1_847759065);
195cabdff1aSopenharmony_ci        tmp10 = MULTIPLY(z12,  FIX_1_082392200) - z5;
196cabdff1aSopenharmony_ci        tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5;
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_ci        tmp6 = tmp12 - tmp7;
199cabdff1aSopenharmony_ci        tmp5 = tmp11 - tmp6;
200cabdff1aSopenharmony_ci        tmp4 = tmp10 + tmp5;
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci        temp[8 * 0 + i] = tmp0 + tmp7;
203cabdff1aSopenharmony_ci        temp[8 * 7 + i] = tmp0 - tmp7;
204cabdff1aSopenharmony_ci        temp[8 * 1 + i] = tmp1 + tmp6;
205cabdff1aSopenharmony_ci        temp[8 * 6 + i] = tmp1 - tmp6;
206cabdff1aSopenharmony_ci        temp[8 * 2 + i] = tmp2 + tmp5;
207cabdff1aSopenharmony_ci        temp[8 * 5 + i] = tmp2 - tmp5;
208cabdff1aSopenharmony_ci        temp[8 * 4 + i] = tmp3 + tmp4;
209cabdff1aSopenharmony_ci        temp[8 * 3 + i] = tmp3 - tmp4;
210cabdff1aSopenharmony_ci    }
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci    for (i = 0; i < 8 * 8; i += 8) {
213cabdff1aSopenharmony_ci        tmp10 = temp[0 + i] + temp[4 + i];
214cabdff1aSopenharmony_ci        tmp11 = temp[0 + i] - temp[4 + i];
215cabdff1aSopenharmony_ci
216cabdff1aSopenharmony_ci        tmp13 = temp[2 + i] + temp[6 + i];
217cabdff1aSopenharmony_ci        tmp12 = MULTIPLY(temp[2 + i] - temp[6 + i], FIX_1_414213562) - tmp13;
218cabdff1aSopenharmony_ci
219cabdff1aSopenharmony_ci        tmp0 = tmp10 + tmp13;
220cabdff1aSopenharmony_ci        tmp3 = tmp10 - tmp13;
221cabdff1aSopenharmony_ci        tmp1 = tmp11 + tmp12;
222cabdff1aSopenharmony_ci        tmp2 = tmp11 - tmp12;
223cabdff1aSopenharmony_ci
224cabdff1aSopenharmony_ci        z13 = temp[5 + i] + temp[3 + i];
225cabdff1aSopenharmony_ci        z10 = temp[5 + i] - temp[3 + i];
226cabdff1aSopenharmony_ci        z11 = temp[1 + i] + temp[7 + i];
227cabdff1aSopenharmony_ci        z12 = temp[1 + i] - temp[7 + i];
228cabdff1aSopenharmony_ci
229cabdff1aSopenharmony_ci        tmp7  = z11 + z13;
230cabdff1aSopenharmony_ci        tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562);
231cabdff1aSopenharmony_ci
232cabdff1aSopenharmony_ci        z5    = MULTIPLY(z10 + z12, FIX_1_847759065);
233cabdff1aSopenharmony_ci        tmp10 = MULTIPLY(z12,  FIX_1_082392200) - z5;
234cabdff1aSopenharmony_ci        tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5;
235cabdff1aSopenharmony_ci
236cabdff1aSopenharmony_ci        tmp6 = tmp12 - tmp7;
237cabdff1aSopenharmony_ci        tmp5 = tmp11 - tmp6;
238cabdff1aSopenharmony_ci        tmp4 = tmp10 + tmp5;
239cabdff1aSopenharmony_ci
240cabdff1aSopenharmony_ci        block[0 + i] = (tmp0 + tmp7) >> 6;
241cabdff1aSopenharmony_ci        block[7 + i] = (tmp0 - tmp7) >> 6;
242cabdff1aSopenharmony_ci        block[1 + i] = (tmp1 + tmp6) >> 6;
243cabdff1aSopenharmony_ci        block[6 + i] = (tmp1 - tmp6) >> 6;
244cabdff1aSopenharmony_ci        block[2 + i] = (tmp2 + tmp5) >> 6;
245cabdff1aSopenharmony_ci        block[5 + i] = (tmp2 - tmp5) >> 6;
246cabdff1aSopenharmony_ci        block[4 + i] = (tmp3 + tmp4) >> 6;
247cabdff1aSopenharmony_ci        block[3 + i] = (tmp3 - tmp4) >> 6;
248cabdff1aSopenharmony_ci    }
249cabdff1aSopenharmony_ci}
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_cistatic av_cold void init_vlcs(void)
252cabdff1aSopenharmony_ci{
253cabdff1aSopenharmony_ci    static VLCElem table[2][4][32];
254cabdff1aSopenharmony_ci    int i, j;
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++) {
257cabdff1aSopenharmony_ci        for (j = 0; j < 4; j++) {
258cabdff1aSopenharmony_ci            block_type_vlc[i][j].table           = table[i][j];
259cabdff1aSopenharmony_ci            block_type_vlc[i][j].table_allocated = 32;
260cabdff1aSopenharmony_ci            init_vlc(&block_type_vlc[i][j], BLOCK_TYPE_VLC_BITS, 7,
261cabdff1aSopenharmony_ci                     &block_type_tab[i][j][0][1], 2, 1,
262cabdff1aSopenharmony_ci                     &block_type_tab[i][j][0][0], 2, 1,
263cabdff1aSopenharmony_ci                     INIT_VLC_USE_NEW_STATIC);
264cabdff1aSopenharmony_ci        }
265cabdff1aSopenharmony_ci    }
266cabdff1aSopenharmony_ci}
267cabdff1aSopenharmony_ci
268cabdff1aSopenharmony_cistatic void init_mv(FourXContext *f, int linesize)
269cabdff1aSopenharmony_ci{
270cabdff1aSopenharmony_ci    int i;
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_ci    for (i = 0; i < 256; i++) {
273cabdff1aSopenharmony_ci        if (f->version > 1)
274cabdff1aSopenharmony_ci            f->mv[i] = mv[i][0] + mv[i][1] * linesize / 2;
275cabdff1aSopenharmony_ci        else
276cabdff1aSopenharmony_ci            f->mv[i] = (i & 15) - 8 + ((i >> 4) - 8) * linesize / 2;
277cabdff1aSopenharmony_ci    }
278cabdff1aSopenharmony_ci}
279cabdff1aSopenharmony_ci
280cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN
281cabdff1aSopenharmony_ci#define LE_CENTRIC_MUL(dst, src, scale, dc)             \
282cabdff1aSopenharmony_ci    {                                                   \
283cabdff1aSopenharmony_ci        unsigned tmpval = AV_RN32(src);                 \
284cabdff1aSopenharmony_ci        tmpval = (tmpval << 16) | (tmpval >> 16);       \
285cabdff1aSopenharmony_ci        tmpval = tmpval * (scale) + (dc);               \
286cabdff1aSopenharmony_ci        tmpval = (tmpval << 16) | (tmpval >> 16);       \
287cabdff1aSopenharmony_ci        AV_WN32A(dst, tmpval);                          \
288cabdff1aSopenharmony_ci    }
289cabdff1aSopenharmony_ci#else
290cabdff1aSopenharmony_ci#define LE_CENTRIC_MUL(dst, src, scale, dc)              \
291cabdff1aSopenharmony_ci    {                                                    \
292cabdff1aSopenharmony_ci        unsigned tmpval = AV_RN32(src) * (scale) + (dc); \
293cabdff1aSopenharmony_ci        AV_WN32A(dst, tmpval);                           \
294cabdff1aSopenharmony_ci    }
295cabdff1aSopenharmony_ci#endif
296cabdff1aSopenharmony_ci
297cabdff1aSopenharmony_cistatic inline void mcdc(uint16_t *dst, const uint16_t *src, int log2w,
298cabdff1aSopenharmony_ci                        int h, int stride, int scale, unsigned dc)
299cabdff1aSopenharmony_ci{
300cabdff1aSopenharmony_ci    int i;
301cabdff1aSopenharmony_ci    dc *= 0x10001;
302cabdff1aSopenharmony_ci
303cabdff1aSopenharmony_ci    switch (log2w) {
304cabdff1aSopenharmony_ci    case 0:
305cabdff1aSopenharmony_ci        for (i = 0; i < h; i++) {
306cabdff1aSopenharmony_ci            dst[0] = scale * src[0] + dc;
307cabdff1aSopenharmony_ci            if (scale)
308cabdff1aSopenharmony_ci                src += stride;
309cabdff1aSopenharmony_ci            dst += stride;
310cabdff1aSopenharmony_ci        }
311cabdff1aSopenharmony_ci        break;
312cabdff1aSopenharmony_ci    case 1:
313cabdff1aSopenharmony_ci        for (i = 0; i < h; i++) {
314cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst, src, scale, dc);
315cabdff1aSopenharmony_ci            if (scale)
316cabdff1aSopenharmony_ci                src += stride;
317cabdff1aSopenharmony_ci            dst += stride;
318cabdff1aSopenharmony_ci        }
319cabdff1aSopenharmony_ci        break;
320cabdff1aSopenharmony_ci    case 2:
321cabdff1aSopenharmony_ci        for (i = 0; i < h; i++) {
322cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst, src, scale, dc);
323cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst + 2, src + 2, scale, dc);
324cabdff1aSopenharmony_ci            if (scale)
325cabdff1aSopenharmony_ci                src += stride;
326cabdff1aSopenharmony_ci            dst += stride;
327cabdff1aSopenharmony_ci        }
328cabdff1aSopenharmony_ci        break;
329cabdff1aSopenharmony_ci    case 3:
330cabdff1aSopenharmony_ci        for (i = 0; i < h; i++) {
331cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst,     src,     scale, dc);
332cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst + 2, src + 2, scale, dc);
333cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst + 4, src + 4, scale, dc);
334cabdff1aSopenharmony_ci            LE_CENTRIC_MUL(dst + 6, src + 6, scale, dc);
335cabdff1aSopenharmony_ci            if (scale)
336cabdff1aSopenharmony_ci                src += stride;
337cabdff1aSopenharmony_ci            dst += stride;
338cabdff1aSopenharmony_ci        }
339cabdff1aSopenharmony_ci        break;
340cabdff1aSopenharmony_ci    default:
341cabdff1aSopenharmony_ci        av_assert0(0);
342cabdff1aSopenharmony_ci    }
343cabdff1aSopenharmony_ci}
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_cistatic int decode_p_block(FourXContext *f, uint16_t *dst, const uint16_t *src,
346cabdff1aSopenharmony_ci                          int log2w, int log2h, int stride)
347cabdff1aSopenharmony_ci{
348cabdff1aSopenharmony_ci    int index, h, code, ret, scale = 1;
349cabdff1aSopenharmony_ci    uint16_t *start, *end;
350cabdff1aSopenharmony_ci    unsigned dc = 0;
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci    av_assert0(log2w >= 0 && log2h >= 0);
353cabdff1aSopenharmony_ci
354cabdff1aSopenharmony_ci    index = size2index[log2h][log2w];
355cabdff1aSopenharmony_ci    av_assert0(index >= 0);
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    if (get_bits_left(&f->gb) < 1)
358cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
359cabdff1aSopenharmony_ci    h     = 1 << log2h;
360cabdff1aSopenharmony_ci    code  = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index].table,
361cabdff1aSopenharmony_ci                     BLOCK_TYPE_VLC_BITS, 1);
362cabdff1aSopenharmony_ci    av_assert0(code >= 0 && code <= 6);
363cabdff1aSopenharmony_ci
364cabdff1aSopenharmony_ci    start = f->last_frame_buffer;
365cabdff1aSopenharmony_ci    end   = start + stride * (f->avctx->height - h + 1) - (1 << log2w);
366cabdff1aSopenharmony_ci
367cabdff1aSopenharmony_ci    if (code == 1) {
368cabdff1aSopenharmony_ci        log2h--;
369cabdff1aSopenharmony_ci        if ((ret = decode_p_block(f, dst, src, log2w, log2h, stride)) < 0)
370cabdff1aSopenharmony_ci            return ret;
371cabdff1aSopenharmony_ci        return decode_p_block(f, dst + (stride << log2h),
372cabdff1aSopenharmony_ci                              src + (stride << log2h),
373cabdff1aSopenharmony_ci                              log2w, log2h, stride);
374cabdff1aSopenharmony_ci    } else if (code == 2) {
375cabdff1aSopenharmony_ci        log2w--;
376cabdff1aSopenharmony_ci        if ((ret = decode_p_block(f, dst , src, log2w, log2h, stride)) < 0)
377cabdff1aSopenharmony_ci            return ret;
378cabdff1aSopenharmony_ci        return decode_p_block(f, dst + (1 << log2w),
379cabdff1aSopenharmony_ci                              src + (1 << log2w),
380cabdff1aSopenharmony_ci                              log2w, log2h, stride);
381cabdff1aSopenharmony_ci    } else if (code == 6) {
382cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(&f->g2) < 4) {
383cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
384cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
385cabdff1aSopenharmony_ci        }
386cabdff1aSopenharmony_ci        if (log2w) {
387cabdff1aSopenharmony_ci            dst[0]      = bytestream2_get_le16u(&f->g2);
388cabdff1aSopenharmony_ci            dst[1]      = bytestream2_get_le16u(&f->g2);
389cabdff1aSopenharmony_ci        } else {
390cabdff1aSopenharmony_ci            dst[0]      = bytestream2_get_le16u(&f->g2);
391cabdff1aSopenharmony_ci            dst[stride] = bytestream2_get_le16u(&f->g2);
392cabdff1aSopenharmony_ci        }
393cabdff1aSopenharmony_ci        return 0;
394cabdff1aSopenharmony_ci    }
395cabdff1aSopenharmony_ci
396cabdff1aSopenharmony_ci    if ((code&3)==0 && bytestream2_get_bytes_left(&f->g) < 1) {
397cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "bytestream overread\n");
398cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
399cabdff1aSopenharmony_ci    }
400cabdff1aSopenharmony_ci
401cabdff1aSopenharmony_ci    if (code == 0) {
402cabdff1aSopenharmony_ci        src  += f->mv[bytestream2_get_byte(&f->g)];
403cabdff1aSopenharmony_ci    } else if (code == 3 && f->version >= 2) {
404cabdff1aSopenharmony_ci        return 0;
405cabdff1aSopenharmony_ci    } else if (code == 4) {
406cabdff1aSopenharmony_ci        src  += f->mv[bytestream2_get_byte(&f->g)];
407cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(&f->g2) < 2){
408cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
409cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
410cabdff1aSopenharmony_ci        }
411cabdff1aSopenharmony_ci        dc    = bytestream2_get_le16(&f->g2);
412cabdff1aSopenharmony_ci    } else if (code == 5) {
413cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(&f->g2) < 2){
414cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "wordstream overread\n");
415cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
416cabdff1aSopenharmony_ci        }
417cabdff1aSopenharmony_ci        av_assert0(start <= src && src <= end);
418cabdff1aSopenharmony_ci        scale = 0;
419cabdff1aSopenharmony_ci        dc    = bytestream2_get_le16(&f->g2);
420cabdff1aSopenharmony_ci    }
421cabdff1aSopenharmony_ci
422cabdff1aSopenharmony_ci    if (start > src || src > end) {
423cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
424cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
425cabdff1aSopenharmony_ci    }
426cabdff1aSopenharmony_ci
427cabdff1aSopenharmony_ci    mcdc(dst, src, log2w, h, stride, scale, dc);
428cabdff1aSopenharmony_ci
429cabdff1aSopenharmony_ci    return 0;
430cabdff1aSopenharmony_ci}
431cabdff1aSopenharmony_ci
432cabdff1aSopenharmony_cistatic int decode_p_frame(FourXContext *f, const uint8_t *buf, int length)
433cabdff1aSopenharmony_ci{
434cabdff1aSopenharmony_ci    int x, y;
435cabdff1aSopenharmony_ci    const int width  = f->avctx->width;
436cabdff1aSopenharmony_ci    const int height = f->avctx->height;
437cabdff1aSopenharmony_ci    uint16_t *dst    = f->frame_buffer;
438cabdff1aSopenharmony_ci    uint16_t *src;
439cabdff1aSopenharmony_ci    unsigned int bitstream_size, bytestream_size, wordstream_size, extra,
440cabdff1aSopenharmony_ci                 bytestream_offset, wordstream_offset;
441cabdff1aSopenharmony_ci    int ret;
442cabdff1aSopenharmony_ci
443cabdff1aSopenharmony_ci    src = f->last_frame_buffer;
444cabdff1aSopenharmony_ci
445cabdff1aSopenharmony_ci    if (f->version > 1) {
446cabdff1aSopenharmony_ci        extra           = 20;
447cabdff1aSopenharmony_ci        if (length < extra)
448cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
449cabdff1aSopenharmony_ci        bitstream_size  = AV_RL32(buf + 8);
450cabdff1aSopenharmony_ci        wordstream_size = AV_RL32(buf + 12);
451cabdff1aSopenharmony_ci        bytestream_size = AV_RL32(buf + 16);
452cabdff1aSopenharmony_ci    } else {
453cabdff1aSopenharmony_ci        extra           = 0;
454cabdff1aSopenharmony_ci        bitstream_size  = AV_RL16(buf - 4);
455cabdff1aSopenharmony_ci        wordstream_size = AV_RL16(buf - 2);
456cabdff1aSopenharmony_ci        bytestream_size = FFMAX(length - bitstream_size - wordstream_size, 0);
457cabdff1aSopenharmony_ci    }
458cabdff1aSopenharmony_ci
459cabdff1aSopenharmony_ci    if (bitstream_size > length || bitstream_size >= INT_MAX/8 ||
460cabdff1aSopenharmony_ci        bytestream_size > length - bitstream_size ||
461cabdff1aSopenharmony_ci        wordstream_size > length - bytestream_size - bitstream_size ||
462cabdff1aSopenharmony_ci        extra > length - bytestream_size - bitstream_size - wordstream_size) {
463cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size,
464cabdff1aSopenharmony_ci        bitstream_size+ bytestream_size+ wordstream_size - length);
465cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
466cabdff1aSopenharmony_ci    }
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci    av_fast_padded_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size,
469cabdff1aSopenharmony_ci                          bitstream_size);
470cabdff1aSopenharmony_ci    if (!f->bitstream_buffer)
471cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
472cabdff1aSopenharmony_ci    f->bbdsp.bswap_buf(f->bitstream_buffer, (const uint32_t *) (buf + extra),
473cabdff1aSopenharmony_ci                       bitstream_size / 4);
474cabdff1aSopenharmony_ci    init_get_bits(&f->gb, f->bitstream_buffer, 8 * bitstream_size);
475cabdff1aSopenharmony_ci
476cabdff1aSopenharmony_ci    wordstream_offset = extra + bitstream_size;
477cabdff1aSopenharmony_ci    bytestream_offset = extra + bitstream_size + wordstream_size;
478cabdff1aSopenharmony_ci    bytestream2_init(&f->g2, buf + wordstream_offset,
479cabdff1aSopenharmony_ci                     length - wordstream_offset);
480cabdff1aSopenharmony_ci    bytestream2_init(&f->g, buf + bytestream_offset,
481cabdff1aSopenharmony_ci                     length - bytestream_offset);
482cabdff1aSopenharmony_ci
483cabdff1aSopenharmony_ci    init_mv(f, width * 2);
484cabdff1aSopenharmony_ci
485cabdff1aSopenharmony_ci    for (y = 0; y < height; y += 8) {
486cabdff1aSopenharmony_ci        for (x = 0; x < width; x += 8)
487cabdff1aSopenharmony_ci            if ((ret = decode_p_block(f, dst + x, src + x, 3, 3, width)) < 0)
488cabdff1aSopenharmony_ci                return ret;
489cabdff1aSopenharmony_ci        src += 8 * width;
490cabdff1aSopenharmony_ci        dst += 8 * width;
491cabdff1aSopenharmony_ci    }
492cabdff1aSopenharmony_ci
493cabdff1aSopenharmony_ci    return 0;
494cabdff1aSopenharmony_ci}
495cabdff1aSopenharmony_ci
496cabdff1aSopenharmony_ci/**
497cabdff1aSopenharmony_ci * decode block and dequantize.
498cabdff1aSopenharmony_ci * Note this is almost identical to MJPEG.
499cabdff1aSopenharmony_ci */
500cabdff1aSopenharmony_cistatic int decode_i_block(FourXContext *f, int16_t *block)
501cabdff1aSopenharmony_ci{
502cabdff1aSopenharmony_ci    int code, i, j, level, val;
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_ci    if (get_bits_left(&f->pre_gb) < 2) {
505cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "%d bits left before decode_i_block()\n", get_bits_left(&f->pre_gb));
506cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
507cabdff1aSopenharmony_ci    }
508cabdff1aSopenharmony_ci
509cabdff1aSopenharmony_ci    /* DC coef */
510cabdff1aSopenharmony_ci    val = get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3);
511cabdff1aSopenharmony_ci    if (val >> 4) {
512cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "error dc run != 0\n");
513cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
514cabdff1aSopenharmony_ci    }
515cabdff1aSopenharmony_ci
516cabdff1aSopenharmony_ci    if (val)
517cabdff1aSopenharmony_ci        val = get_xbits(&f->gb, val);
518cabdff1aSopenharmony_ci
519cabdff1aSopenharmony_ci    val        = val * dequant_table[0] + f->last_dc;
520cabdff1aSopenharmony_ci    f->last_dc = block[0] = val;
521cabdff1aSopenharmony_ci    /* AC coefs */
522cabdff1aSopenharmony_ci    i = 1;
523cabdff1aSopenharmony_ci    for (;;) {
524cabdff1aSopenharmony_ci        code = get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3);
525cabdff1aSopenharmony_ci
526cabdff1aSopenharmony_ci        /* EOB */
527cabdff1aSopenharmony_ci        if (code == 0)
528cabdff1aSopenharmony_ci            break;
529cabdff1aSopenharmony_ci        if (code == 0xf0) {
530cabdff1aSopenharmony_ci            i += 16;
531cabdff1aSopenharmony_ci            if (i >= 64) {
532cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "run %d overflow\n", i);
533cabdff1aSopenharmony_ci                return 0;
534cabdff1aSopenharmony_ci            }
535cabdff1aSopenharmony_ci        } else {
536cabdff1aSopenharmony_ci            if (code & 0xf) {
537cabdff1aSopenharmony_ci                level = get_xbits(&f->gb, code & 0xf);
538cabdff1aSopenharmony_ci            } else {
539cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "0 coeff\n");
540cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
541cabdff1aSopenharmony_ci            }
542cabdff1aSopenharmony_ci            i    += code >> 4;
543cabdff1aSopenharmony_ci            if (i >= 64) {
544cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "run %d overflow\n", i);
545cabdff1aSopenharmony_ci                return 0;
546cabdff1aSopenharmony_ci            }
547cabdff1aSopenharmony_ci
548cabdff1aSopenharmony_ci            j = ff_zigzag_direct[i];
549cabdff1aSopenharmony_ci            block[j] = level * dequant_table[j];
550cabdff1aSopenharmony_ci            i++;
551cabdff1aSopenharmony_ci            if (i >= 64)
552cabdff1aSopenharmony_ci                break;
553cabdff1aSopenharmony_ci        }
554cabdff1aSopenharmony_ci    }
555cabdff1aSopenharmony_ci
556cabdff1aSopenharmony_ci    return 0;
557cabdff1aSopenharmony_ci}
558cabdff1aSopenharmony_ci
559cabdff1aSopenharmony_cistatic inline void idct_put(FourXContext *f, int x, int y)
560cabdff1aSopenharmony_ci{
561cabdff1aSopenharmony_ci    int16_t (*block)[64] = f->block;
562cabdff1aSopenharmony_ci    int stride           = f->avctx->width;
563cabdff1aSopenharmony_ci    int i;
564cabdff1aSopenharmony_ci    uint16_t *dst = f->frame_buffer + y * stride + x;
565cabdff1aSopenharmony_ci
566cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++) {
567cabdff1aSopenharmony_ci        block[i][0] += 0x80 * 8 * 8;
568cabdff1aSopenharmony_ci        idct(block[i]);
569cabdff1aSopenharmony_ci    }
570cabdff1aSopenharmony_ci
571cabdff1aSopenharmony_ci    if (!(f->avctx->flags & AV_CODEC_FLAG_GRAY)) {
572cabdff1aSopenharmony_ci        for (i = 4; i < 6; i++)
573cabdff1aSopenharmony_ci            idct(block[i]);
574cabdff1aSopenharmony_ci    }
575cabdff1aSopenharmony_ci
576cabdff1aSopenharmony_ci    /* Note transform is:
577cabdff1aSopenharmony_ci     * y  = ( 1b + 4g + 2r) / 14
578cabdff1aSopenharmony_ci     * cb = ( 3b - 2g - 1r) / 14
579cabdff1aSopenharmony_ci     * cr = (-1b - 4g + 5r) / 14 */
580cabdff1aSopenharmony_ci    for (y = 0; y < 8; y++) {
581cabdff1aSopenharmony_ci        for (x = 0; x < 8; x++) {
582cabdff1aSopenharmony_ci            int16_t *temp = block[(x >> 2) + 2 * (y >> 2)] +
583cabdff1aSopenharmony_ci                            2 * (x & 3) + 2 * 8 * (y & 3); // FIXME optimize
584cabdff1aSopenharmony_ci            int cb = block[4][x + 8 * y];
585cabdff1aSopenharmony_ci            int cr = block[5][x + 8 * y];
586cabdff1aSopenharmony_ci            int cg = (cb + cr) >> 1;
587cabdff1aSopenharmony_ci            int y;
588cabdff1aSopenharmony_ci
589cabdff1aSopenharmony_ci            cb += cb;
590cabdff1aSopenharmony_ci
591cabdff1aSopenharmony_ci            y               = temp[0];
592cabdff1aSopenharmony_ci            dst[0]          = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8);
593cabdff1aSopenharmony_ci            y               = temp[1];
594cabdff1aSopenharmony_ci            dst[1]          = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8);
595cabdff1aSopenharmony_ci            y               = temp[8];
596cabdff1aSopenharmony_ci            dst[stride]     = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8);
597cabdff1aSopenharmony_ci            y               = temp[9];
598cabdff1aSopenharmony_ci            dst[1 + stride] = ((y + cb) >> 3) + (((y - cg) & 0xFC) << 3) + (((y + cr) & 0xF8) << 8);
599cabdff1aSopenharmony_ci            dst            += 2;
600cabdff1aSopenharmony_ci        }
601cabdff1aSopenharmony_ci        dst += 2 * stride - 2 * 8;
602cabdff1aSopenharmony_ci    }
603cabdff1aSopenharmony_ci}
604cabdff1aSopenharmony_ci
605cabdff1aSopenharmony_cistatic int decode_i_mb(FourXContext *f)
606cabdff1aSopenharmony_ci{
607cabdff1aSopenharmony_ci    int ret;
608cabdff1aSopenharmony_ci    int i;
609cabdff1aSopenharmony_ci
610cabdff1aSopenharmony_ci    f->bdsp.clear_blocks(f->block[0]);
611cabdff1aSopenharmony_ci
612cabdff1aSopenharmony_ci    for (i = 0; i < 6; i++)
613cabdff1aSopenharmony_ci        if ((ret = decode_i_block(f, f->block[i])) < 0)
614cabdff1aSopenharmony_ci            return ret;
615cabdff1aSopenharmony_ci
616cabdff1aSopenharmony_ci    return 0;
617cabdff1aSopenharmony_ci}
618cabdff1aSopenharmony_ci
619cabdff1aSopenharmony_cistatic const uint8_t *read_huffman_tables(FourXContext *f,
620cabdff1aSopenharmony_ci                                          const uint8_t * const buf,
621cabdff1aSopenharmony_ci                                          int buf_size)
622cabdff1aSopenharmony_ci{
623cabdff1aSopenharmony_ci    int frequency[512] = { 0 };
624cabdff1aSopenharmony_ci    uint8_t flag[512];
625cabdff1aSopenharmony_ci    int up[512];
626cabdff1aSopenharmony_ci    uint8_t len_tab[257];
627cabdff1aSopenharmony_ci    int bits_tab[257];
628cabdff1aSopenharmony_ci    int start, end;
629cabdff1aSopenharmony_ci    const uint8_t *ptr = buf;
630cabdff1aSopenharmony_ci    const uint8_t *ptr_end = buf + buf_size;
631cabdff1aSopenharmony_ci    int j;
632cabdff1aSopenharmony_ci
633cabdff1aSopenharmony_ci    memset(up, -1, sizeof(up));
634cabdff1aSopenharmony_ci
635cabdff1aSopenharmony_ci    start = *ptr++;
636cabdff1aSopenharmony_ci    end   = *ptr++;
637cabdff1aSopenharmony_ci    for (;;) {
638cabdff1aSopenharmony_ci        int i;
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ci        if (ptr_end - ptr < FFMAX(end - start + 1, 0) + 1) {
641cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "invalid data in read_huffman_tables\n");
642cabdff1aSopenharmony_ci            return NULL;
643cabdff1aSopenharmony_ci        }
644cabdff1aSopenharmony_ci
645cabdff1aSopenharmony_ci        for (i = start; i <= end; i++)
646cabdff1aSopenharmony_ci            frequency[i] = *ptr++;
647cabdff1aSopenharmony_ci        start = *ptr++;
648cabdff1aSopenharmony_ci        if (start == 0)
649cabdff1aSopenharmony_ci            break;
650cabdff1aSopenharmony_ci
651cabdff1aSopenharmony_ci        end = *ptr++;
652cabdff1aSopenharmony_ci    }
653cabdff1aSopenharmony_ci    frequency[256] = 1;
654cabdff1aSopenharmony_ci
655cabdff1aSopenharmony_ci    while ((ptr - buf) & 3)
656cabdff1aSopenharmony_ci        ptr++; // 4byte align
657cabdff1aSopenharmony_ci
658cabdff1aSopenharmony_ci    if (ptr > ptr_end) {
659cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "ptr overflow in read_huffman_tables\n");
660cabdff1aSopenharmony_ci        return NULL;
661cabdff1aSopenharmony_ci    }
662cabdff1aSopenharmony_ci
663cabdff1aSopenharmony_ci    for (j = 257; j < 512; j++) {
664cabdff1aSopenharmony_ci        int min_freq[2] = { 256 * 256, 256 * 256 };
665cabdff1aSopenharmony_ci        int smallest[2] = { 0, 0 };
666cabdff1aSopenharmony_ci        int i;
667cabdff1aSopenharmony_ci        for (i = 0; i < j; i++) {
668cabdff1aSopenharmony_ci            if (frequency[i] == 0)
669cabdff1aSopenharmony_ci                continue;
670cabdff1aSopenharmony_ci            if (frequency[i] < min_freq[1]) {
671cabdff1aSopenharmony_ci                if (frequency[i] < min_freq[0]) {
672cabdff1aSopenharmony_ci                    min_freq[1] = min_freq[0];
673cabdff1aSopenharmony_ci                    smallest[1] = smallest[0];
674cabdff1aSopenharmony_ci                    min_freq[0] = frequency[i];
675cabdff1aSopenharmony_ci                    smallest[0] = i;
676cabdff1aSopenharmony_ci                } else {
677cabdff1aSopenharmony_ci                    min_freq[1] = frequency[i];
678cabdff1aSopenharmony_ci                    smallest[1] = i;
679cabdff1aSopenharmony_ci                }
680cabdff1aSopenharmony_ci            }
681cabdff1aSopenharmony_ci        }
682cabdff1aSopenharmony_ci        if (min_freq[1] == 256 * 256)
683cabdff1aSopenharmony_ci            break;
684cabdff1aSopenharmony_ci
685cabdff1aSopenharmony_ci        frequency[j]           = min_freq[0] + min_freq[1];
686cabdff1aSopenharmony_ci        flag[smallest[0]]      = 0;
687cabdff1aSopenharmony_ci        flag[smallest[1]]      = 1;
688cabdff1aSopenharmony_ci        up[smallest[0]]        =
689cabdff1aSopenharmony_ci        up[smallest[1]]        = j;
690cabdff1aSopenharmony_ci        frequency[smallest[0]] = frequency[smallest[1]] = 0;
691cabdff1aSopenharmony_ci    }
692cabdff1aSopenharmony_ci
693cabdff1aSopenharmony_ci    for (j = 0; j < 257; j++) {
694cabdff1aSopenharmony_ci        int node, len = 0, bits = 0;
695cabdff1aSopenharmony_ci
696cabdff1aSopenharmony_ci        for (node = j; up[node] != -1; node = up[node]) {
697cabdff1aSopenharmony_ci            bits += flag[node] << len;
698cabdff1aSopenharmony_ci            len++;
699cabdff1aSopenharmony_ci            if (len > 31)
700cabdff1aSopenharmony_ci                // can this happen at all ?
701cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR,
702cabdff1aSopenharmony_ci                       "vlc length overflow\n");
703cabdff1aSopenharmony_ci        }
704cabdff1aSopenharmony_ci
705cabdff1aSopenharmony_ci        bits_tab[j] = bits;
706cabdff1aSopenharmony_ci        len_tab[j]  = len;
707cabdff1aSopenharmony_ci    }
708cabdff1aSopenharmony_ci
709cabdff1aSopenharmony_ci    ff_free_vlc(&f->pre_vlc);
710cabdff1aSopenharmony_ci    if (init_vlc(&f->pre_vlc, ACDC_VLC_BITS, 257, len_tab, 1, 1,
711cabdff1aSopenharmony_ci                 bits_tab, 4, 4, 0))
712cabdff1aSopenharmony_ci        return NULL;
713cabdff1aSopenharmony_ci
714cabdff1aSopenharmony_ci    return ptr;
715cabdff1aSopenharmony_ci}
716cabdff1aSopenharmony_ci
717cabdff1aSopenharmony_cistatic int mix(int c0, int c1)
718cabdff1aSopenharmony_ci{
719cabdff1aSopenharmony_ci    int blue  =  2 * (c0 & 0x001F) + (c1 & 0x001F);
720cabdff1aSopenharmony_ci    int green = (2 * (c0 & 0x03E0) + (c1 & 0x03E0)) >> 5;
721cabdff1aSopenharmony_ci    int red   =  2 * (c0 >> 10)    + (c1 >> 10);
722cabdff1aSopenharmony_ci    return red / 3 * 1024 + green / 3 * 32 + blue / 3;
723cabdff1aSopenharmony_ci}
724cabdff1aSopenharmony_ci
725cabdff1aSopenharmony_cistatic int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length)
726cabdff1aSopenharmony_ci{
727cabdff1aSopenharmony_ci    int x, y, x2, y2;
728cabdff1aSopenharmony_ci    const int width  = f->avctx->width;
729cabdff1aSopenharmony_ci    const int height = f->avctx->height;
730cabdff1aSopenharmony_ci    const int mbs    = (FFALIGN(width, 16) >> 4) * (FFALIGN(height, 16) >> 4);
731cabdff1aSopenharmony_ci    uint16_t *dst    = f->frame_buffer;
732cabdff1aSopenharmony_ci    const uint8_t *buf_end = buf + length;
733cabdff1aSopenharmony_ci    GetByteContext g3;
734cabdff1aSopenharmony_ci
735cabdff1aSopenharmony_ci    if (length < mbs * 8) {
736cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "packet size too small\n");
737cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
738cabdff1aSopenharmony_ci    }
739cabdff1aSopenharmony_ci    bytestream2_init(&g3, buf, length);
740cabdff1aSopenharmony_ci
741cabdff1aSopenharmony_ci    for (y = 0; y < height; y += 16) {
742cabdff1aSopenharmony_ci        for (x = 0; x < width; x += 16) {
743cabdff1aSopenharmony_ci            unsigned int color[4] = { 0 }, bits;
744cabdff1aSopenharmony_ci            if (buf_end - buf < 8)
745cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
746cabdff1aSopenharmony_ci            // warning following is purely guessed ...
747cabdff1aSopenharmony_ci            color[0] = bytestream2_get_le16u(&g3);
748cabdff1aSopenharmony_ci            color[1] = bytestream2_get_le16u(&g3);
749cabdff1aSopenharmony_ci
750cabdff1aSopenharmony_ci            if (color[0] & 0x8000)
751cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "unk bit 1\n");
752cabdff1aSopenharmony_ci            if (color[1] & 0x8000)
753cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "unk bit 2\n");
754cabdff1aSopenharmony_ci
755cabdff1aSopenharmony_ci            color[2] = mix(color[0], color[1]);
756cabdff1aSopenharmony_ci            color[3] = mix(color[1], color[0]);
757cabdff1aSopenharmony_ci
758cabdff1aSopenharmony_ci            bits = bytestream2_get_le32u(&g3);
759cabdff1aSopenharmony_ci            for (y2 = 0; y2 < 16; y2++) {
760cabdff1aSopenharmony_ci                for (x2 = 0; x2 < 16; x2++) {
761cabdff1aSopenharmony_ci                    int index = 2 * (x2 >> 2) + 8 * (y2 >> 2);
762cabdff1aSopenharmony_ci                    dst[y2 * width + x2] = color[(bits >> index) & 3];
763cabdff1aSopenharmony_ci                }
764cabdff1aSopenharmony_ci            }
765cabdff1aSopenharmony_ci            dst += 16;
766cabdff1aSopenharmony_ci        }
767cabdff1aSopenharmony_ci        dst += 16 * width - x;
768cabdff1aSopenharmony_ci    }
769cabdff1aSopenharmony_ci
770cabdff1aSopenharmony_ci    return 0;
771cabdff1aSopenharmony_ci}
772cabdff1aSopenharmony_ci
773cabdff1aSopenharmony_cistatic int decode_i_frame(FourXContext *f, const uint8_t *buf, int length)
774cabdff1aSopenharmony_ci{
775cabdff1aSopenharmony_ci    int x, y, ret;
776cabdff1aSopenharmony_ci    const int width  = f->avctx->width;
777cabdff1aSopenharmony_ci    const int height = f->avctx->height;
778cabdff1aSopenharmony_ci    const unsigned int bitstream_size = AV_RL32(buf);
779cabdff1aSopenharmony_ci    unsigned int prestream_size;
780cabdff1aSopenharmony_ci    const uint8_t *prestream;
781cabdff1aSopenharmony_ci
782cabdff1aSopenharmony_ci    if (bitstream_size > (1 << 26))
783cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
784cabdff1aSopenharmony_ci
785cabdff1aSopenharmony_ci    if (length < bitstream_size + 12) {
786cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "packet size too small\n");
787cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
788cabdff1aSopenharmony_ci    }
789cabdff1aSopenharmony_ci
790cabdff1aSopenharmony_ci    prestream_size = 4 * AV_RL32(buf + bitstream_size + 4);
791cabdff1aSopenharmony_ci    prestream      =             buf + bitstream_size + 12;
792cabdff1aSopenharmony_ci
793cabdff1aSopenharmony_ci    if (prestream_size + bitstream_size + 12 != length
794cabdff1aSopenharmony_ci        || prestream_size > (1 << 26)) {
795cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n",
796cabdff1aSopenharmony_ci               prestream_size, bitstream_size, length);
797cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
798cabdff1aSopenharmony_ci    }
799cabdff1aSopenharmony_ci
800cabdff1aSopenharmony_ci    prestream = read_huffman_tables(f, prestream, prestream_size);
801cabdff1aSopenharmony_ci    if (!prestream) {
802cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "Error reading Huffman tables.\n");
803cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
804cabdff1aSopenharmony_ci    }
805cabdff1aSopenharmony_ci
806cabdff1aSopenharmony_ci    av_assert0(prestream <= buf + length);
807cabdff1aSopenharmony_ci
808cabdff1aSopenharmony_ci    init_get_bits(&f->gb, buf + 4, 8 * bitstream_size);
809cabdff1aSopenharmony_ci
810cabdff1aSopenharmony_ci    prestream_size = length + buf - prestream;
811cabdff1aSopenharmony_ci
812cabdff1aSopenharmony_ci    av_fast_padded_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size,
813cabdff1aSopenharmony_ci                          prestream_size);
814cabdff1aSopenharmony_ci    if (!f->bitstream_buffer)
815cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
816cabdff1aSopenharmony_ci    f->bbdsp.bswap_buf(f->bitstream_buffer, (const uint32_t *) prestream,
817cabdff1aSopenharmony_ci                       prestream_size / 4);
818cabdff1aSopenharmony_ci    init_get_bits(&f->pre_gb, f->bitstream_buffer, 8 * prestream_size);
819cabdff1aSopenharmony_ci
820cabdff1aSopenharmony_ci    f->last_dc = 0 * 128 * 8 * 8;
821cabdff1aSopenharmony_ci
822cabdff1aSopenharmony_ci    for (y = 0; y < height; y += 16) {
823cabdff1aSopenharmony_ci        for (x = 0; x < width; x += 16) {
824cabdff1aSopenharmony_ci            if ((ret = decode_i_mb(f)) < 0)
825cabdff1aSopenharmony_ci                return ret;
826cabdff1aSopenharmony_ci
827cabdff1aSopenharmony_ci            idct_put(f, x, y);
828cabdff1aSopenharmony_ci        }
829cabdff1aSopenharmony_ci    }
830cabdff1aSopenharmony_ci
831cabdff1aSopenharmony_ci    if (get_vlc2(&f->pre_gb, f->pre_vlc.table, ACDC_VLC_BITS, 3) != 256)
832cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "end mismatch\n");
833cabdff1aSopenharmony_ci
834cabdff1aSopenharmony_ci    return 0;
835cabdff1aSopenharmony_ci}
836cabdff1aSopenharmony_ci
837cabdff1aSopenharmony_cistatic int decode_frame(AVCodecContext *avctx, AVFrame *picture,
838cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
839cabdff1aSopenharmony_ci{
840cabdff1aSopenharmony_ci    const uint8_t *buf    = avpkt->data;
841cabdff1aSopenharmony_ci    int buf_size          = avpkt->size;
842cabdff1aSopenharmony_ci    FourXContext *const f = avctx->priv_data;
843cabdff1aSopenharmony_ci    int i, frame_4cc, frame_size, ret;
844cabdff1aSopenharmony_ci
845cabdff1aSopenharmony_ci    if (buf_size < 20)
846cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
847cabdff1aSopenharmony_ci
848cabdff1aSopenharmony_ci    av_assert0(avctx->width % 16 == 0 && avctx->height % 16 == 0);
849cabdff1aSopenharmony_ci
850cabdff1aSopenharmony_ci    if (buf_size < AV_RL32(buf + 4) + 8) {
851cabdff1aSopenharmony_ci        av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %"PRIu32"\n",
852cabdff1aSopenharmony_ci               buf_size, AV_RL32(buf + 4));
853cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
854cabdff1aSopenharmony_ci    }
855cabdff1aSopenharmony_ci
856cabdff1aSopenharmony_ci    frame_4cc = AV_RL32(buf);
857cabdff1aSopenharmony_ci
858cabdff1aSopenharmony_ci    if (frame_4cc == AV_RL32("cfrm")) {
859cabdff1aSopenharmony_ci        int free_index       = -1;
860cabdff1aSopenharmony_ci        int id, whole_size;
861cabdff1aSopenharmony_ci        const int data_size  = buf_size - 20;
862cabdff1aSopenharmony_ci        CFrameBuffer *cfrm;
863cabdff1aSopenharmony_ci
864cabdff1aSopenharmony_ci        if (f->version <= 1) {
865cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "cfrm in version %d\n", f->version);
866cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
867cabdff1aSopenharmony_ci        }
868cabdff1aSopenharmony_ci
869cabdff1aSopenharmony_ci        id         = AV_RL32(buf + 12);
870cabdff1aSopenharmony_ci        whole_size = AV_RL32(buf + 16);
871cabdff1aSopenharmony_ci
872cabdff1aSopenharmony_ci        if (data_size < 0 || whole_size < 0) {
873cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "sizes invalid\n");
874cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
875cabdff1aSopenharmony_ci        }
876cabdff1aSopenharmony_ci
877cabdff1aSopenharmony_ci        for (i = 0; i < CFRAME_BUFFER_COUNT; i++)
878cabdff1aSopenharmony_ci            if (f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number)
879cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n",
880cabdff1aSopenharmony_ci                       f->cfrm[i].id);
881cabdff1aSopenharmony_ci
882cabdff1aSopenharmony_ci        for (i = 0; i < CFRAME_BUFFER_COUNT; i++) {
883cabdff1aSopenharmony_ci            if (f->cfrm[i].id == id)
884cabdff1aSopenharmony_ci                break;
885cabdff1aSopenharmony_ci            if (f->cfrm[i].size == 0)
886cabdff1aSopenharmony_ci                free_index = i;
887cabdff1aSopenharmony_ci        }
888cabdff1aSopenharmony_ci
889cabdff1aSopenharmony_ci        if (i >= CFRAME_BUFFER_COUNT) {
890cabdff1aSopenharmony_ci            if (free_index < 0)
891cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
892cabdff1aSopenharmony_ci            i             = free_index;
893cabdff1aSopenharmony_ci            f->cfrm[i].id = id;
894cabdff1aSopenharmony_ci        }
895cabdff1aSopenharmony_ci        cfrm = &f->cfrm[i];
896cabdff1aSopenharmony_ci
897cabdff1aSopenharmony_ci        if (data_size > UINT_MAX -  cfrm->size - AV_INPUT_BUFFER_PADDING_SIZE)
898cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
899cabdff1aSopenharmony_ci
900cabdff1aSopenharmony_ci        cfrm->data = av_fast_realloc(cfrm->data, &cfrm->allocated_size,
901cabdff1aSopenharmony_ci                                     cfrm->size + data_size + AV_INPUT_BUFFER_PADDING_SIZE);
902cabdff1aSopenharmony_ci        // explicit check needed as memcpy below might not catch a NULL
903cabdff1aSopenharmony_ci        if (!cfrm->data) {
904cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "realloc failure\n");
905cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
906cabdff1aSopenharmony_ci        }
907cabdff1aSopenharmony_ci
908cabdff1aSopenharmony_ci        memcpy(cfrm->data + cfrm->size, buf + 20, data_size);
909cabdff1aSopenharmony_ci        cfrm->size += data_size;
910cabdff1aSopenharmony_ci
911cabdff1aSopenharmony_ci        if (cfrm->size >= whole_size) {
912cabdff1aSopenharmony_ci            buf        = cfrm->data;
913cabdff1aSopenharmony_ci            frame_size = cfrm->size;
914cabdff1aSopenharmony_ci
915cabdff1aSopenharmony_ci            if (id != avctx->frame_number)
916cabdff1aSopenharmony_ci                av_log(f->avctx, AV_LOG_ERROR, "cframe id mismatch %d %d\n",
917cabdff1aSopenharmony_ci                       id, avctx->frame_number);
918cabdff1aSopenharmony_ci
919cabdff1aSopenharmony_ci            if (f->version <= 1)
920cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
921cabdff1aSopenharmony_ci
922cabdff1aSopenharmony_ci            cfrm->size = cfrm->id = 0;
923cabdff1aSopenharmony_ci            frame_4cc  = AV_RL32("pfrm");
924cabdff1aSopenharmony_ci        } else
925cabdff1aSopenharmony_ci            return buf_size;
926cabdff1aSopenharmony_ci    } else {
927cabdff1aSopenharmony_ci        buf        = buf      + 12;
928cabdff1aSopenharmony_ci        frame_size = buf_size - 12;
929cabdff1aSopenharmony_ci    }
930cabdff1aSopenharmony_ci
931cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
932cabdff1aSopenharmony_ci        return ret;
933cabdff1aSopenharmony_ci
934cabdff1aSopenharmony_ci    if (frame_4cc == AV_RL32("ifr2")) {
935cabdff1aSopenharmony_ci        picture->pict_type = AV_PICTURE_TYPE_I;
936cabdff1aSopenharmony_ci        if ((ret = decode_i2_frame(f, buf - 4, frame_size + 4)) < 0) {
937cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "decode i2 frame failed\n");
938cabdff1aSopenharmony_ci            return ret;
939cabdff1aSopenharmony_ci        }
940cabdff1aSopenharmony_ci    } else if (frame_4cc == AV_RL32("ifrm")) {
941cabdff1aSopenharmony_ci        picture->pict_type = AV_PICTURE_TYPE_I;
942cabdff1aSopenharmony_ci        if ((ret = decode_i_frame(f, buf, frame_size)) < 0) {
943cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "decode i frame failed\n");
944cabdff1aSopenharmony_ci            return ret;
945cabdff1aSopenharmony_ci        }
946cabdff1aSopenharmony_ci    } else if (frame_4cc == AV_RL32("pfrm") || frame_4cc == AV_RL32("pfr2")) {
947cabdff1aSopenharmony_ci        picture->pict_type = AV_PICTURE_TYPE_P;
948cabdff1aSopenharmony_ci        if ((ret = decode_p_frame(f, buf, frame_size)) < 0) {
949cabdff1aSopenharmony_ci            av_log(f->avctx, AV_LOG_ERROR, "decode p frame failed\n");
950cabdff1aSopenharmony_ci            return ret;
951cabdff1aSopenharmony_ci        }
952cabdff1aSopenharmony_ci    } else if (frame_4cc == AV_RL32("snd_")) {
953cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "ignoring snd_ chunk length:%d\n",
954cabdff1aSopenharmony_ci               buf_size);
955cabdff1aSopenharmony_ci    } else {
956cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "ignoring unknown chunk length:%d\n",
957cabdff1aSopenharmony_ci               buf_size);
958cabdff1aSopenharmony_ci    }
959cabdff1aSopenharmony_ci
960cabdff1aSopenharmony_ci    picture->key_frame = picture->pict_type == AV_PICTURE_TYPE_I;
961cabdff1aSopenharmony_ci
962cabdff1aSopenharmony_ci    av_image_copy_plane(picture->data[0], picture->linesize[0],
963cabdff1aSopenharmony_ci                        (const uint8_t*)f->frame_buffer,  avctx->width * 2,
964cabdff1aSopenharmony_ci                        avctx->width * 2, avctx->height);
965cabdff1aSopenharmony_ci    FFSWAP(uint16_t *, f->frame_buffer, f->last_frame_buffer);
966cabdff1aSopenharmony_ci
967cabdff1aSopenharmony_ci    *got_frame = 1;
968cabdff1aSopenharmony_ci
969cabdff1aSopenharmony_ci    emms_c();
970cabdff1aSopenharmony_ci
971cabdff1aSopenharmony_ci    return buf_size;
972cabdff1aSopenharmony_ci}
973cabdff1aSopenharmony_ci
974cabdff1aSopenharmony_cistatic av_cold int decode_end(AVCodecContext *avctx)
975cabdff1aSopenharmony_ci{
976cabdff1aSopenharmony_ci    FourXContext * const f = avctx->priv_data;
977cabdff1aSopenharmony_ci    int i;
978cabdff1aSopenharmony_ci
979cabdff1aSopenharmony_ci    av_freep(&f->frame_buffer);
980cabdff1aSopenharmony_ci    av_freep(&f->last_frame_buffer);
981cabdff1aSopenharmony_ci    av_freep(&f->bitstream_buffer);
982cabdff1aSopenharmony_ci    f->bitstream_buffer_size = 0;
983cabdff1aSopenharmony_ci    for (i = 0; i < CFRAME_BUFFER_COUNT; i++) {
984cabdff1aSopenharmony_ci        av_freep(&f->cfrm[i].data);
985cabdff1aSopenharmony_ci        f->cfrm[i].allocated_size = 0;
986cabdff1aSopenharmony_ci    }
987cabdff1aSopenharmony_ci    ff_free_vlc(&f->pre_vlc);
988cabdff1aSopenharmony_ci
989cabdff1aSopenharmony_ci    return 0;
990cabdff1aSopenharmony_ci}
991cabdff1aSopenharmony_ci
992cabdff1aSopenharmony_cistatic av_cold int decode_init(AVCodecContext *avctx)
993cabdff1aSopenharmony_ci{
994cabdff1aSopenharmony_ci    static AVOnce init_static_once = AV_ONCE_INIT;
995cabdff1aSopenharmony_ci    FourXContext * const f = avctx->priv_data;
996cabdff1aSopenharmony_ci    int ret;
997cabdff1aSopenharmony_ci
998cabdff1aSopenharmony_ci    if (avctx->extradata_size != 4 || !avctx->extradata) {
999cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "extradata wrong or missing\n");
1000cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1001cabdff1aSopenharmony_ci    }
1002cabdff1aSopenharmony_ci    if((avctx->width % 16) || (avctx->height % 16)) {
1003cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "unsupported width/height\n");
1004cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
1005cabdff1aSopenharmony_ci    }
1006cabdff1aSopenharmony_ci
1007cabdff1aSopenharmony_ci    ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
1008cabdff1aSopenharmony_ci    if (ret < 0)
1009cabdff1aSopenharmony_ci        return ret;
1010cabdff1aSopenharmony_ci
1011cabdff1aSopenharmony_ci    f->frame_buffer      = av_mallocz(avctx->width * avctx->height * 2);
1012cabdff1aSopenharmony_ci    f->last_frame_buffer = av_mallocz(avctx->width * avctx->height * 2);
1013cabdff1aSopenharmony_ci    if (!f->frame_buffer || !f->last_frame_buffer)
1014cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
1015cabdff1aSopenharmony_ci
1016cabdff1aSopenharmony_ci    f->version = AV_RL32(avctx->extradata) >> 16;
1017cabdff1aSopenharmony_ci    ff_blockdsp_init(&f->bdsp, avctx);
1018cabdff1aSopenharmony_ci    ff_bswapdsp_init(&f->bbdsp);
1019cabdff1aSopenharmony_ci    f->avctx = avctx;
1020cabdff1aSopenharmony_ci
1021cabdff1aSopenharmony_ci    if (f->version > 2)
1022cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_RGB565;
1023cabdff1aSopenharmony_ci    else
1024cabdff1aSopenharmony_ci        avctx->pix_fmt = AV_PIX_FMT_BGR555;
1025cabdff1aSopenharmony_ci
1026cabdff1aSopenharmony_ci    ff_thread_once(&init_static_once, init_vlcs);
1027cabdff1aSopenharmony_ci
1028cabdff1aSopenharmony_ci    return 0;
1029cabdff1aSopenharmony_ci}
1030cabdff1aSopenharmony_ci
1031cabdff1aSopenharmony_ciconst FFCodec ff_fourxm_decoder = {
1032cabdff1aSopenharmony_ci    .p.name         = "4xm",
1033cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("4X Movie"),
1034cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
1035cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_4XM,
1036cabdff1aSopenharmony_ci    .priv_data_size = sizeof(FourXContext),
1037cabdff1aSopenharmony_ci    .init           = decode_init,
1038cabdff1aSopenharmony_ci    .close          = decode_end,
1039cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(decode_frame),
1040cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1,
1041cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
1042cabdff1aSopenharmony_ci};
1043