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