1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * MobiClip Video decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2015-2016 Florian Nouwt 4cabdff1aSopenharmony_ci * Copyright (c) 2017 Adib Surani 5cabdff1aSopenharmony_ci * Copyright (c) 2020 Paul B Mahol 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include <inttypes.h> 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 27cabdff1aSopenharmony_ci#include "libavutil/thread.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "avcodec.h" 30cabdff1aSopenharmony_ci#include "bytestream.h" 31cabdff1aSopenharmony_ci#include "bswapdsp.h" 32cabdff1aSopenharmony_ci#include "codec_internal.h" 33cabdff1aSopenharmony_ci#include "get_bits.h" 34cabdff1aSopenharmony_ci#include "golomb.h" 35cabdff1aSopenharmony_ci#include "internal.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#define MOBI_RL_VLC_BITS 12 38cabdff1aSopenharmony_ci#define MOBI_MV_VLC_BITS 6 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic const uint8_t zigzag4x4_tab[] = 41cabdff1aSopenharmony_ci{ 42cabdff1aSopenharmony_ci 0x00, 0x04, 0x01, 0x02, 0x05, 0x08, 0x0C, 0x09, 0x06, 0x03, 0x07, 0x0A, 43cabdff1aSopenharmony_ci 0x0D, 0x0E, 0x0B, 0x0F 44cabdff1aSopenharmony_ci}; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic const uint8_t quant4x4_tab[][16] = 47cabdff1aSopenharmony_ci{ 48cabdff1aSopenharmony_ci { 10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16 }, 49cabdff1aSopenharmony_ci { 11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18 }, 50cabdff1aSopenharmony_ci { 13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20 }, 51cabdff1aSopenharmony_ci { 14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23 }, 52cabdff1aSopenharmony_ci { 16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25 }, 53cabdff1aSopenharmony_ci { 18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29 }, 54cabdff1aSopenharmony_ci}; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_cistatic const uint8_t quant8x8_tab[][64] = 57cabdff1aSopenharmony_ci{ 58cabdff1aSopenharmony_ci { 20, 19, 19, 25, 18, 25, 19, 24, 24, 19, 20, 18, 32, 18, 20, 19, 19, 24, 24, 19, 19, 25, 18, 25, 18, 25, 18, 25, 19, 24, 24, 19, 59cabdff1aSopenharmony_ci 19, 24, 24, 19, 18, 32, 18, 20, 18, 32, 18, 24, 24, 19, 19, 24, 24, 18, 25, 18, 25, 18, 19, 24, 24, 19, 18, 32, 18, 24, 24, 18,}, 60cabdff1aSopenharmony_ci { 22, 21, 21, 28, 19, 28, 21, 26, 26, 21, 22, 19, 35, 19, 22, 21, 21, 26, 26, 21, 21, 28, 19, 28, 19, 28, 19, 28, 21, 26, 26, 21, 61cabdff1aSopenharmony_ci 21, 26, 26, 21, 19, 35, 19, 22, 19, 35, 19, 26, 26, 21, 21, 26, 26, 19, 28, 19, 28, 19, 21, 26, 26, 21, 19, 35, 19, 26, 26, 19,}, 62cabdff1aSopenharmony_ci { 26, 24, 24, 33, 23, 33, 24, 31, 31, 24, 26, 23, 42, 23, 26, 24, 24, 31, 31, 24, 24, 33, 23, 33, 23, 33, 23, 33, 24, 31, 31, 24, 63cabdff1aSopenharmony_ci 24, 31, 31, 24, 23, 42, 23, 26, 23, 42, 23, 31, 31, 24, 24, 31, 31, 23, 33, 23, 33, 23, 24, 31, 31, 24, 23, 42, 23, 31, 31, 23,}, 64cabdff1aSopenharmony_ci { 28, 26, 26, 35, 25, 35, 26, 33, 33, 26, 28, 25, 45, 25, 28, 26, 26, 33, 33, 26, 26, 35, 25, 35, 25, 35, 25, 35, 26, 33, 33, 26, 65cabdff1aSopenharmony_ci 26, 33, 33, 26, 25, 45, 25, 28, 25, 45, 25, 33, 33, 26, 26, 33, 33, 25, 35, 25, 35, 25, 26, 33, 33, 26, 25, 45, 25, 33, 33, 25,}, 66cabdff1aSopenharmony_ci { 32, 30, 30, 40, 28, 40, 30, 38, 38, 30, 32, 28, 51, 28, 32, 30, 30, 38, 38, 30, 30, 40, 28, 40, 28, 40, 28, 40, 30, 38, 38, 30, 67cabdff1aSopenharmony_ci 30, 38, 38, 30, 28, 51, 28, 32, 28, 51, 28, 38, 38, 30, 30, 38, 38, 28, 40, 28, 40, 28, 30, 38, 38, 30, 28, 51, 28, 38, 38, 28,}, 68cabdff1aSopenharmony_ci { 36, 34, 34, 46, 32, 46, 34, 43, 43, 34, 36, 32, 58, 32, 36, 34, 34, 43, 43, 34, 34, 46, 32, 46, 32, 46, 32, 46, 34, 43, 43, 34, 69cabdff1aSopenharmony_ci 34, 43, 43, 34, 32, 58, 32, 36, 32, 58, 32, 43, 43, 34, 34, 43, 43, 32, 46, 32, 46, 32, 34, 43, 43, 34, 32, 58, 32, 43, 43, 32,}, 70cabdff1aSopenharmony_ci}; 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_cistatic const uint8_t block4x4_coefficients_tab[] = 73cabdff1aSopenharmony_ci{ 74cabdff1aSopenharmony_ci 15, 0, 2, 1, 4, 8, 12, 3, 11, 13, 14, 7, 10, 5, 9, 6, 75cabdff1aSopenharmony_ci}; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_cistatic const uint8_t pframe_block4x4_coefficients_tab[] = 78cabdff1aSopenharmony_ci{ 79cabdff1aSopenharmony_ci 0, 4, 1, 8, 2, 12, 3, 5, 10, 15, 7, 13, 14, 11, 9, 6, 80cabdff1aSopenharmony_ci}; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cistatic const uint8_t block8x8_coefficients_tab[] = 83cabdff1aSopenharmony_ci{ 84cabdff1aSopenharmony_ci 0x00, 0x1F, 0x3F, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x0B, 0x0E, 0x1B, 0x0D, 85cabdff1aSopenharmony_ci 0x03, 0x07, 0x0C, 0x17, 0x1D, 0x0A, 0x1E, 0x05, 0x10, 0x2F, 0x37, 0x3B, 86cabdff1aSopenharmony_ci 0x13, 0x3D, 0x3E, 0x09, 0x1C, 0x06, 0x15, 0x1A, 0x33, 0x11, 0x12, 0x14, 87cabdff1aSopenharmony_ci 0x18, 0x20, 0x3C, 0x35, 0x19, 0x16, 0x3A, 0x30, 0x31, 0x32, 0x27, 0x34, 88cabdff1aSopenharmony_ci 0x2B, 0x2D, 0x39, 0x38, 0x23, 0x36, 0x2E, 0x21, 0x25, 0x22, 0x24, 0x2C, 89cabdff1aSopenharmony_ci 0x2A, 0x28, 0x29, 0x26, 90cabdff1aSopenharmony_ci}; 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_cistatic const uint8_t pframe_block8x8_coefficients_tab[] = 93cabdff1aSopenharmony_ci{ 94cabdff1aSopenharmony_ci 0x00, 0x0F, 0x04, 0x01, 0x08, 0x02, 0x0C, 0x03, 0x05, 0x0A, 0x0D, 0x07, 0x0E, 0x0B, 0x1F, 0x09, 95cabdff1aSopenharmony_ci 0x06, 0x10, 0x3F, 0x1E, 0x17, 0x1D, 0x1B, 0x1C, 0x13, 0x18, 0x1A, 0x12, 0x11, 0x14, 0x15, 0x20, 96cabdff1aSopenharmony_ci 0x2F, 0x16, 0x19, 0x37, 0x3D, 0x3E, 0x3B, 0x3C, 0x33, 0x35, 0x21, 0x24, 0x22, 0x28, 0x23, 0x2C, 97cabdff1aSopenharmony_ci 0x30, 0x27, 0x2D, 0x25, 0x3A, 0x2B, 0x2E, 0x2A, 0x31, 0x34, 0x38, 0x32, 0x29, 0x26, 0x39, 0x36 98cabdff1aSopenharmony_ci}; 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_cistatic const uint8_t run_residue[2][256] = 101cabdff1aSopenharmony_ci{ 102cabdff1aSopenharmony_ci { 103cabdff1aSopenharmony_ci 12, 6, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 104cabdff1aSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105cabdff1aSopenharmony_ci 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 106cabdff1aSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107cabdff1aSopenharmony_ci 1, 27, 11, 7, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 108cabdff1aSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 109cabdff1aSopenharmony_ci 1, 41, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 110cabdff1aSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 111cabdff1aSopenharmony_ci }, 112cabdff1aSopenharmony_ci { 113cabdff1aSopenharmony_ci 27, 10, 5, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114cabdff1aSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115cabdff1aSopenharmony_ci 8, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116cabdff1aSopenharmony_ci 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117cabdff1aSopenharmony_ci 1, 15, 10, 8, 4, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 118cabdff1aSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 119cabdff1aSopenharmony_ci 1, 21, 7, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 120cabdff1aSopenharmony_ci 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 121cabdff1aSopenharmony_ci }, 122cabdff1aSopenharmony_ci}; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_cistatic const uint8_t bits0[] = { 125cabdff1aSopenharmony_ci 9, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 126cabdff1aSopenharmony_ci 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 127cabdff1aSopenharmony_ci 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 10, 10, 9, 128cabdff1aSopenharmony_ci 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 129cabdff1aSopenharmony_ci 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 130cabdff1aSopenharmony_ci 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 131cabdff1aSopenharmony_ci 6, 6, 6, 6, 6, 6, 5, 5, 5, 4, 2, 3, 4, 4, 132cabdff1aSopenharmony_ci}; 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_cistatic const uint16_t syms0[] = { 135cabdff1aSopenharmony_ci 0x0, 0x822, 0x803, 0xB, 0xA, 0xB81, 0xB61, 0xB41, 0xB21, 0x122, 136cabdff1aSopenharmony_ci 0x102, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x24, 0xC, 0x25, 0x2E1, 0x301, 137cabdff1aSopenharmony_ci 0xBA1, 0xBC1, 0xBE1, 0xC01, 0x26, 0x44, 0x83, 0xA3, 0xC3, 0x142, 138cabdff1aSopenharmony_ci 0x321, 0x341, 0xC21, 0xC41, 0xC61, 0xC81, 0xCA1, 0xCC1, 0xCE1, 0xD01, 139cabdff1aSopenharmony_ci 0x0, 0x9, 0x8, 0xB01, 0xAE1, 0xAC1, 0xAA1, 0xA81, 0xA61, 0xA41, 0xA21, 140cabdff1aSopenharmony_ci 0x802, 0x2C1, 0x2A1, 0x281, 0x261, 0x241, 0x221, 0x201, 0x1E1, 0x82, 141cabdff1aSopenharmony_ci 0x62, 0x7, 0x6, 0xA01, 0x9E1, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x921, 142cabdff1aSopenharmony_ci 0x1C1, 0x1A1, 0x42, 0x23, 0x5, 0x901, 0x8E1, 0x8C1, 0x8A1, 0x181, 0x161, 143cabdff1aSopenharmony_ci 0x141, 0x4, 0x881, 0x861, 0x841, 0x821, 0x121, 0x101, 0xE1, 0xC1, 0x22, 144cabdff1aSopenharmony_ci 0x3, 0xA1, 0x81, 0x61, 0x801, 0x1, 0x21, 0x41, 0x2, 145cabdff1aSopenharmony_ci}; 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_cistatic const uint16_t syms1[] = { 148cabdff1aSopenharmony_ci 0x0, 0x807, 0x806, 0x16, 0x15, 0x842, 0x823, 0x805, 0x1A1, 0xA3, 0x102, 0x83, 149cabdff1aSopenharmony_ci 0x64, 0x44, 0x27, 0x14, 0x13, 0x17, 0x18, 0x28, 0x122, 0x862, 0x882, 0x9E1, 0xA01, 150cabdff1aSopenharmony_ci 0x19, 0x1A, 0x1B, 0x29, 0xC3, 0x2A, 0x45, 0xE3, 0x1C1, 0x808, 0x8A2, 0x8C2, 0xA21, 151cabdff1aSopenharmony_ci 0xA41, 0xA61, 0xA81, 0x0, 0x12, 0x11, 0x9C1, 0x9A1, 0x981, 0x961, 0x941, 0x822, 0x804, 152cabdff1aSopenharmony_ci 0x181, 0x161, 0xE2, 0xC2, 0xA2, 0x63, 0x43, 0x26, 0x25, 0x10, 0x82, 0xF, 0xE, 0xD, 0x901, 153cabdff1aSopenharmony_ci 0x8E1, 0x8C1, 0x803, 0x141, 0x121, 0x101, 0x921, 0x62, 0x24, 0xC, 0xB, 0xA, 0x881, 0x861, 154cabdff1aSopenharmony_ci 0xC1, 0x8A1, 0xE1, 0x42, 0x23, 0x9, 0x802, 0xA1, 0x841, 0x821, 0x81, 0x61, 0x8, 0x7, 0x22, 155cabdff1aSopenharmony_ci 0x6, 0x41, 0x5, 0x4, 0x801, 0x1, 0x2, 0x21, 0x3, 156cabdff1aSopenharmony_ci}; 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_cistatic const uint8_t mv_len[16] = 159cabdff1aSopenharmony_ci{ 160cabdff1aSopenharmony_ci 10, 8, 8, 7, 8, 8, 8, 7, 8, 8, 8, 7, 7, 7, 7, 6, 161cabdff1aSopenharmony_ci}; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_cistatic const uint8_t mv_bits[2][16][10] = 164cabdff1aSopenharmony_ci{ 165cabdff1aSopenharmony_ci { 166cabdff1aSopenharmony_ci { 2, 3, 3, 5, 5, 4, 4, 5, 5, 2 }, 167cabdff1aSopenharmony_ci { 2, 3, 4, 4, 3, 4, 4, 2 }, 168cabdff1aSopenharmony_ci { 3, 4, 4, 2, 4, 4, 3, 2 }, 169cabdff1aSopenharmony_ci { 1, 3, 4, 5, 5, 3, 3 }, 170cabdff1aSopenharmony_ci { 2, 4, 4, 3, 3, 4, 4, 2 }, 171cabdff1aSopenharmony_ci { 2, 3, 4, 4, 4, 4, 3, 2 }, 172cabdff1aSopenharmony_ci { 2, 3, 4, 4, 4, 4, 3, 2 }, 173cabdff1aSopenharmony_ci { 2, 2, 3, 4, 5, 5, 2 }, 174cabdff1aSopenharmony_ci { 2, 3, 4, 4, 3, 4, 4, 2 }, 175cabdff1aSopenharmony_ci { 2, 4, 4, 3, 4, 4, 3, 2 }, 176cabdff1aSopenharmony_ci { 2, 3, 3, 5, 5, 4, 3, 2 }, 177cabdff1aSopenharmony_ci { 2, 3, 4, 4, 3, 3, 2 }, 178cabdff1aSopenharmony_ci { 1, 4, 4, 3, 3, 4, 4 }, 179cabdff1aSopenharmony_ci { 2, 3, 4, 4, 3, 3, 2 }, 180cabdff1aSopenharmony_ci { 2, 3, 4, 4, 3, 3, 2 }, 181cabdff1aSopenharmony_ci { 3, 3, 2, 2, 3, 3 }, 182cabdff1aSopenharmony_ci }, 183cabdff1aSopenharmony_ci { 184cabdff1aSopenharmony_ci { 3, 4, 5, 5, 3, 5, 6, 6, 4, 1 }, 185cabdff1aSopenharmony_ci { 2, 3, 4, 5, 5, 2, 3, 3 }, 186cabdff1aSopenharmony_ci { 2, 4, 4, 3, 3, 4, 4, 2 }, 187cabdff1aSopenharmony_ci { 1, 4, 4, 3, 4, 4, 3 }, 188cabdff1aSopenharmony_ci { 3, 3, 2, 4, 5, 5, 3, 2 }, 189cabdff1aSopenharmony_ci { 3, 4, 4, 3, 3, 3, 3, 2 }, 190cabdff1aSopenharmony_ci { 1, 3, 3, 4, 4, 4, 5, 5 }, 191cabdff1aSopenharmony_ci { 1, 4, 4, 3, 3, 4, 4 }, 192cabdff1aSopenharmony_ci { 2, 4, 4, 3, 3, 4, 4, 2 }, 193cabdff1aSopenharmony_ci { 1, 3, 3, 4, 4, 4, 5, 5 }, 194cabdff1aSopenharmony_ci { 2, 3, 4, 4, 4, 4, 3, 2 }, 195cabdff1aSopenharmony_ci { 2, 3, 3, 4, 4, 3, 2 }, 196cabdff1aSopenharmony_ci { 1, 4, 4, 3, 3, 4, 4 }, 197cabdff1aSopenharmony_ci { 1, 4, 4, 3, 3, 4, 4 }, 198cabdff1aSopenharmony_ci { 2, 3, 3, 4, 4, 3, 2 }, 199cabdff1aSopenharmony_ci { 2, 3, 3, 3, 3, 2 }, 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci}; 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_cistatic const uint8_t mv_syms[2][16][10] = 204cabdff1aSopenharmony_ci{ 205cabdff1aSopenharmony_ci { 206cabdff1aSopenharmony_ci { 1, 8, 9, 4, 3, 2, 7, 5, 6, 0 }, 207cabdff1aSopenharmony_ci { 0, 9, 5, 4, 2, 3, 8, 1 }, 208cabdff1aSopenharmony_ci { 3, 9, 5, 0, 4, 8, 2, 1 }, 209cabdff1aSopenharmony_ci { 1, 3, 4, 8, 5, 2, 0 }, 210cabdff1aSopenharmony_ci { 0, 5, 4, 8, 2, 3, 9, 1 }, 211cabdff1aSopenharmony_ci { 0, 3, 5, 9, 4, 8, 2, 1 }, 212cabdff1aSopenharmony_ci { 0, 3, 9, 5, 8, 4, 2, 1 }, 213cabdff1aSopenharmony_ci { 0, 2, 3, 4, 8, 5, 1 }, 214cabdff1aSopenharmony_ci { 0, 3, 8, 4, 2, 5, 9, 1 }, 215cabdff1aSopenharmony_ci { 2, 8, 9, 3, 5, 4, 0, 1 }, 216cabdff1aSopenharmony_ci { 0, 4, 3, 8, 9, 5, 2, 1 }, 217cabdff1aSopenharmony_ci { 0, 4, 8, 5, 3, 2, 1 }, 218cabdff1aSopenharmony_ci { 1, 9, 4, 2, 0, 5, 3 }, 219cabdff1aSopenharmony_ci { 2, 4, 9, 5, 3, 0, 1 }, 220cabdff1aSopenharmony_ci { 0, 4, 9, 5, 3, 2, 1 }, 221cabdff1aSopenharmony_ci { 5, 4, 1, 0, 3, 2 }, 222cabdff1aSopenharmony_ci }, 223cabdff1aSopenharmony_ci { 224cabdff1aSopenharmony_ci { 8, 2, 3, 6, 1, 7, 5, 4, 9, 0 }, 225cabdff1aSopenharmony_ci { 9, 2, 3, 5, 4, 1, 8, 0 }, 226cabdff1aSopenharmony_ci { 0, 5, 4, 2, 9, 3, 8, 1 }, 227cabdff1aSopenharmony_ci { 1, 5, 4, 2, 8, 3, 0 }, 228cabdff1aSopenharmony_ci { 2, 9, 8, 3, 5, 4, 0, 1 }, 229cabdff1aSopenharmony_ci { 3, 5, 4, 2, 9, 8, 0, 1 }, 230cabdff1aSopenharmony_ci { 1, 2, 0, 9, 8, 3, 5, 4 }, 231cabdff1aSopenharmony_ci { 1, 8, 5, 2, 0, 4, 3 }, 232cabdff1aSopenharmony_ci { 0, 5, 4, 2, 8, 3, 9, 1 }, 233cabdff1aSopenharmony_ci { 1, 2, 0, 9, 8, 3, 5, 4 }, 234cabdff1aSopenharmony_ci { 0, 3, 9, 8, 5, 4, 2, 1 }, 235cabdff1aSopenharmony_ci { 0, 4, 3, 8, 5, 2, 1 }, 236cabdff1aSopenharmony_ci { 1, 5, 4, 2, 0, 9, 3 }, 237cabdff1aSopenharmony_ci { 1, 9, 5, 2, 0, 4, 3 }, 238cabdff1aSopenharmony_ci { 0, 5, 3, 9, 4, 2, 1 }, 239cabdff1aSopenharmony_ci { 0, 4, 5, 3, 2, 1 }, 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci}; 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_citypedef struct BlockXY { 244cabdff1aSopenharmony_ci int w, h; 245cabdff1aSopenharmony_ci int ax, ay; 246cabdff1aSopenharmony_ci int x, y; 247cabdff1aSopenharmony_ci int size; 248cabdff1aSopenharmony_ci uint8_t *block; 249cabdff1aSopenharmony_ci int linesize; 250cabdff1aSopenharmony_ci} BlockXY; 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_citypedef struct MotionXY { 253cabdff1aSopenharmony_ci int x, y; 254cabdff1aSopenharmony_ci} MotionXY; 255cabdff1aSopenharmony_ci 256cabdff1aSopenharmony_citypedef struct MobiClipContext { 257cabdff1aSopenharmony_ci AVFrame *pic[6]; 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci int current_pic; 260cabdff1aSopenharmony_ci int moflex; 261cabdff1aSopenharmony_ci int dct_tab_idx; 262cabdff1aSopenharmony_ci int quantizer; 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci GetBitContext gb; 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci uint8_t *bitstream; 267cabdff1aSopenharmony_ci int bitstream_size; 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci int qtab[2][64]; 270cabdff1aSopenharmony_ci uint8_t pre[32]; 271cabdff1aSopenharmony_ci MotionXY *motion; 272cabdff1aSopenharmony_ci int motion_size; 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_ci BswapDSPContext bdsp; 275cabdff1aSopenharmony_ci} MobiClipContext; 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_cistatic VLC rl_vlc[2]; 278cabdff1aSopenharmony_cistatic VLC mv_vlc[2][16]; 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_cistatic av_cold void mobiclip_init_static(void) 281cabdff1aSopenharmony_ci{ 282cabdff1aSopenharmony_ci INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[0], MOBI_RL_VLC_BITS, 104, 283cabdff1aSopenharmony_ci bits0, sizeof(*bits0), 284cabdff1aSopenharmony_ci syms0, sizeof(*syms0), sizeof(*syms0), 285cabdff1aSopenharmony_ci 0, 0, 1 << MOBI_RL_VLC_BITS); 286cabdff1aSopenharmony_ci INIT_VLC_STATIC_FROM_LENGTHS(&rl_vlc[1], MOBI_RL_VLC_BITS, 104, 287cabdff1aSopenharmony_ci bits0, sizeof(*bits0), 288cabdff1aSopenharmony_ci syms1, sizeof(*syms1), sizeof(*syms1), 289cabdff1aSopenharmony_ci 0, 0, 1 << MOBI_RL_VLC_BITS); 290cabdff1aSopenharmony_ci for (int i = 0; i < 2; i++) { 291cabdff1aSopenharmony_ci static VLCElem vlc_buf[2 * 16 << MOBI_MV_VLC_BITS]; 292cabdff1aSopenharmony_ci for (int j = 0; j < 16; j++) { 293cabdff1aSopenharmony_ci mv_vlc[i][j].table = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS]; 294cabdff1aSopenharmony_ci mv_vlc[i][j].table_allocated = 1 << MOBI_MV_VLC_BITS; 295cabdff1aSopenharmony_ci ff_init_vlc_from_lengths(&mv_vlc[i][j], MOBI_MV_VLC_BITS, mv_len[j], 296cabdff1aSopenharmony_ci mv_bits[i][j], sizeof(*mv_bits[i][j]), 297cabdff1aSopenharmony_ci mv_syms[i][j], sizeof(*mv_syms[i][j]), sizeof(*mv_syms[i][j]), 298cabdff1aSopenharmony_ci 0, INIT_VLC_USE_NEW_STATIC, NULL); 299cabdff1aSopenharmony_ci } 300cabdff1aSopenharmony_ci } 301cabdff1aSopenharmony_ci} 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_cistatic av_cold int mobiclip_init(AVCodecContext *avctx) 304cabdff1aSopenharmony_ci{ 305cabdff1aSopenharmony_ci static AVOnce init_static_once = AV_ONCE_INIT; 306cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci if (avctx->width & 15 || avctx->height & 15) { 309cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "width/height not multiple of 16\n"); 310cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci ff_bswapdsp_init(&s->bdsp); 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV420P; 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_ci s->motion = av_calloc(avctx->width / 16 + 3, sizeof(MotionXY)); 318cabdff1aSopenharmony_ci if (!s->motion) 319cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 320cabdff1aSopenharmony_ci s->motion_size = (avctx->width / 16 + 3) * sizeof(MotionXY); 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_ci for (int i = 0; i < 6; i++) { 323cabdff1aSopenharmony_ci s->pic[i] = av_frame_alloc(); 324cabdff1aSopenharmony_ci if (!s->pic[i]) 325cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 326cabdff1aSopenharmony_ci } 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci ff_thread_once(&init_static_once, mobiclip_init_static); 329cabdff1aSopenharmony_ci 330cabdff1aSopenharmony_ci return 0; 331cabdff1aSopenharmony_ci} 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_cistatic int setup_qtables(AVCodecContext *avctx, int64_t quantizer) 334cabdff1aSopenharmony_ci{ 335cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 336cabdff1aSopenharmony_ci int qx, qy; 337cabdff1aSopenharmony_ci 338cabdff1aSopenharmony_ci if (quantizer < 12 || quantizer > 161) 339cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci s->quantizer = quantizer; 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci qx = quantizer % 6; 344cabdff1aSopenharmony_ci qy = quantizer / 6; 345cabdff1aSopenharmony_ci 346cabdff1aSopenharmony_ci for (int i = 0; i < 16; i++) 347cabdff1aSopenharmony_ci s->qtab[0][i] = quant4x4_tab[qx][i] << qy; 348cabdff1aSopenharmony_ci 349cabdff1aSopenharmony_ci for (int i = 0; i < 64; i++) 350cabdff1aSopenharmony_ci s->qtab[1][i] = quant8x8_tab[qx][i] << (qy - 2); 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci for (int i = 0; i < 20; i++) 353cabdff1aSopenharmony_ci s->pre[i] = 9; 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci return 0; 356cabdff1aSopenharmony_ci} 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_cistatic void inverse4(unsigned *rs) 359cabdff1aSopenharmony_ci{ 360cabdff1aSopenharmony_ci unsigned a = rs[0] + rs[2]; 361cabdff1aSopenharmony_ci unsigned b = rs[0] - rs[2]; 362cabdff1aSopenharmony_ci unsigned c = rs[1] + ((int)rs[3] >> 1); 363cabdff1aSopenharmony_ci unsigned d = ((int)rs[1] >> 1) - rs[3]; 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_ci rs[0] = a + c; 366cabdff1aSopenharmony_ci rs[1] = b + d; 367cabdff1aSopenharmony_ci rs[2] = b - d; 368cabdff1aSopenharmony_ci rs[3] = a - c; 369cabdff1aSopenharmony_ci} 370cabdff1aSopenharmony_ci 371cabdff1aSopenharmony_cistatic void idct(int *arr, int size) 372cabdff1aSopenharmony_ci{ 373cabdff1aSopenharmony_ci int e, f, g, h; 374cabdff1aSopenharmony_ci unsigned x3, x2, x1, x0; 375cabdff1aSopenharmony_ci int tmp[4]; 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci if (size == 4) { 378cabdff1aSopenharmony_ci inverse4(arr); 379cabdff1aSopenharmony_ci return; 380cabdff1aSopenharmony_ci } 381cabdff1aSopenharmony_ci 382cabdff1aSopenharmony_ci tmp[0] = arr[0]; 383cabdff1aSopenharmony_ci tmp[1] = arr[2]; 384cabdff1aSopenharmony_ci tmp[2] = arr[4]; 385cabdff1aSopenharmony_ci tmp[3] = arr[6]; 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci inverse4(tmp); 388cabdff1aSopenharmony_ci 389cabdff1aSopenharmony_ci e = (unsigned)arr[7] + arr[1] - arr[3] - (arr[3] >> 1); 390cabdff1aSopenharmony_ci f = (unsigned)arr[7] - arr[1] + arr[5] + (arr[5] >> 1); 391cabdff1aSopenharmony_ci g = (unsigned)arr[5] - arr[3] - arr[7] - (arr[7] >> 1); 392cabdff1aSopenharmony_ci h = (unsigned)arr[5] + arr[3] + arr[1] + (arr[1] >> 1); 393cabdff1aSopenharmony_ci x3 = (unsigned)g + (h >> 2); 394cabdff1aSopenharmony_ci x2 = (unsigned)e + (f >> 2); 395cabdff1aSopenharmony_ci x1 = (e >> 2) - (unsigned)f; 396cabdff1aSopenharmony_ci x0 = (unsigned)h - (g >> 2); 397cabdff1aSopenharmony_ci 398cabdff1aSopenharmony_ci arr[0] = tmp[0] + x0; 399cabdff1aSopenharmony_ci arr[1] = tmp[1] + x1; 400cabdff1aSopenharmony_ci arr[2] = tmp[2] + x2; 401cabdff1aSopenharmony_ci arr[3] = tmp[3] + x3; 402cabdff1aSopenharmony_ci arr[4] = tmp[3] - x3; 403cabdff1aSopenharmony_ci arr[5] = tmp[2] - x2; 404cabdff1aSopenharmony_ci arr[6] = tmp[1] - x1; 405cabdff1aSopenharmony_ci arr[7] = tmp[0] - x0; 406cabdff1aSopenharmony_ci} 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_cistatic void read_run_encoding(AVCodecContext *avctx, 409cabdff1aSopenharmony_ci int *last, int *run, int *level) 410cabdff1aSopenharmony_ci{ 411cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 412cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 413cabdff1aSopenharmony_ci int n = get_vlc2(gb, rl_vlc[s->dct_tab_idx].table, 414cabdff1aSopenharmony_ci MOBI_RL_VLC_BITS, 1); 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci *last = (n >> 11) == 1; 417cabdff1aSopenharmony_ci *run = (n >> 5) & 0x3F; 418cabdff1aSopenharmony_ci *level = n & 0x1F; 419cabdff1aSopenharmony_ci} 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_cistatic int add_coefficients(AVCodecContext *avctx, AVFrame *frame, 422cabdff1aSopenharmony_ci int bx, int by, int size, int plane) 423cabdff1aSopenharmony_ci{ 424cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 425cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 426cabdff1aSopenharmony_ci int mat[64] = { 0 }; 427cabdff1aSopenharmony_ci const uint8_t *ztab = size == 8 ? ff_zigzag_direct : zigzag4x4_tab; 428cabdff1aSopenharmony_ci const int *qtab = s->qtab[size == 8]; 429cabdff1aSopenharmony_ci uint8_t *dst = frame->data[plane] + by * frame->linesize[plane] + bx; 430cabdff1aSopenharmony_ci 431cabdff1aSopenharmony_ci for (int pos = 0; get_bits_left(gb) > 0; pos++) { 432cabdff1aSopenharmony_ci int qval, last, run, level; 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci read_run_encoding(avctx, &last, &run, &level); 435cabdff1aSopenharmony_ci 436cabdff1aSopenharmony_ci if (level) { 437cabdff1aSopenharmony_ci if (get_bits1(gb)) 438cabdff1aSopenharmony_ci level = -level; 439cabdff1aSopenharmony_ci } else if (!get_bits1(gb)) { 440cabdff1aSopenharmony_ci read_run_encoding(avctx, &last, &run, &level); 441cabdff1aSopenharmony_ci level += run_residue[s->dct_tab_idx][(last ? 64 : 0) + run]; 442cabdff1aSopenharmony_ci if (get_bits1(gb)) 443cabdff1aSopenharmony_ci level = -level; 444cabdff1aSopenharmony_ci } else if (!get_bits1(gb)) { 445cabdff1aSopenharmony_ci read_run_encoding(avctx, &last, &run, &level); 446cabdff1aSopenharmony_ci run += run_residue[s->dct_tab_idx][128 + (last ? 64 : 0) + level]; 447cabdff1aSopenharmony_ci if (get_bits1(gb)) 448cabdff1aSopenharmony_ci level = -level; 449cabdff1aSopenharmony_ci } else { 450cabdff1aSopenharmony_ci last = get_bits1(gb); 451cabdff1aSopenharmony_ci run = get_bits(gb, 6); 452cabdff1aSopenharmony_ci level = get_sbits(gb, 12); 453cabdff1aSopenharmony_ci } 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_ci pos += run; 456cabdff1aSopenharmony_ci if (pos >= size * size) 457cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 458cabdff1aSopenharmony_ci qval = qtab[pos]; 459cabdff1aSopenharmony_ci mat[ztab[pos]] = qval *(unsigned)level; 460cabdff1aSopenharmony_ci 461cabdff1aSopenharmony_ci if (last) 462cabdff1aSopenharmony_ci break; 463cabdff1aSopenharmony_ci } 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_ci mat[0] += 32; 466cabdff1aSopenharmony_ci for (int y = 0; y < size; y++) 467cabdff1aSopenharmony_ci idct(&mat[y * size], size); 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci for (int y = 0; y < size; y++) { 470cabdff1aSopenharmony_ci for (int x = y + 1; x < size; x++) { 471cabdff1aSopenharmony_ci int a = mat[x * size + y]; 472cabdff1aSopenharmony_ci int b = mat[y * size + x]; 473cabdff1aSopenharmony_ci 474cabdff1aSopenharmony_ci mat[y * size + x] = a; 475cabdff1aSopenharmony_ci mat[x * size + y] = b; 476cabdff1aSopenharmony_ci } 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_ci idct(&mat[y * size], size); 479cabdff1aSopenharmony_ci for (int x = 0; x < size; x++) 480cabdff1aSopenharmony_ci dst[x] = av_clip_uint8(dst[x] + (mat[y * size + x] >> 6)); 481cabdff1aSopenharmony_ci dst += frame->linesize[plane]; 482cabdff1aSopenharmony_ci } 483cabdff1aSopenharmony_ci 484cabdff1aSopenharmony_ci return 0; 485cabdff1aSopenharmony_ci} 486cabdff1aSopenharmony_ci 487cabdff1aSopenharmony_cistatic int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, 488cabdff1aSopenharmony_ci int bx, int by, int size, int plane) 489cabdff1aSopenharmony_ci{ 490cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 491cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 492cabdff1aSopenharmony_ci int ret, idx = get_ue_golomb_31(gb); 493cabdff1aSopenharmony_ci 494cabdff1aSopenharmony_ci if (idx == 0) { 495cabdff1aSopenharmony_ci return add_coefficients(avctx, frame, bx, by, size, plane); 496cabdff1aSopenharmony_ci } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) { 497cabdff1aSopenharmony_ci int flags = pframe_block4x4_coefficients_tab[idx]; 498cabdff1aSopenharmony_ci 499cabdff1aSopenharmony_ci for (int y = by; y < by + 8; y += 4) { 500cabdff1aSopenharmony_ci for (int x = bx; x < bx + 8; x += 4) { 501cabdff1aSopenharmony_ci if (flags & 1) { 502cabdff1aSopenharmony_ci ret = add_coefficients(avctx, frame, x, y, 4, plane); 503cabdff1aSopenharmony_ci if (ret < 0) 504cabdff1aSopenharmony_ci return ret; 505cabdff1aSopenharmony_ci } 506cabdff1aSopenharmony_ci flags >>= 1; 507cabdff1aSopenharmony_ci } 508cabdff1aSopenharmony_ci } 509cabdff1aSopenharmony_ci return 0; 510cabdff1aSopenharmony_ci } else { 511cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 512cabdff1aSopenharmony_ci } 513cabdff1aSopenharmony_ci} 514cabdff1aSopenharmony_ci 515cabdff1aSopenharmony_cistatic int adjust(int x, int size) 516cabdff1aSopenharmony_ci{ 517cabdff1aSopenharmony_ci return size == 16 ? (x + 1) >> 1 : x; 518cabdff1aSopenharmony_ci} 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_cistatic uint8_t pget(BlockXY b) 521cabdff1aSopenharmony_ci{ 522cabdff1aSopenharmony_ci BlockXY ret = b; 523cabdff1aSopenharmony_ci int x, y; 524cabdff1aSopenharmony_ci 525cabdff1aSopenharmony_ci if (b.x == -1 && b.y >= b.size) { 526cabdff1aSopenharmony_ci ret.x = -1, ret.y = b.size - 1; 527cabdff1aSopenharmony_ci } else if (b.x >= -1 && b.y >= -1) { 528cabdff1aSopenharmony_ci ret.x = b.x, ret.y = b.y; 529cabdff1aSopenharmony_ci } else if (b.x == -1 && b.y == -2) { 530cabdff1aSopenharmony_ci ret.x = 0, ret.y = -1; 531cabdff1aSopenharmony_ci } else if (b.x == -2 && b.y == -1) { 532cabdff1aSopenharmony_ci ret.x = -1, ret.y = 0; 533cabdff1aSopenharmony_ci } 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci y = av_clip(ret.ay + ret.y, 0, ret.h - 1); 536cabdff1aSopenharmony_ci x = av_clip(ret.ax + ret.x, 0, ret.w - 1); 537cabdff1aSopenharmony_ci 538cabdff1aSopenharmony_ci return ret.block[y * ret.linesize + x]; 539cabdff1aSopenharmony_ci} 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_cistatic uint8_t half(int a, int b) 542cabdff1aSopenharmony_ci{ 543cabdff1aSopenharmony_ci return ((a + b) + 1) / 2; 544cabdff1aSopenharmony_ci} 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_cistatic uint8_t half3(int a, int b, int c) 547cabdff1aSopenharmony_ci{ 548cabdff1aSopenharmony_ci return ((a + b + b + c) * 2 / 4 + 1) / 2; 549cabdff1aSopenharmony_ci} 550cabdff1aSopenharmony_ci 551cabdff1aSopenharmony_cistatic uint8_t pick_above(BlockXY bxy) 552cabdff1aSopenharmony_ci{ 553cabdff1aSopenharmony_ci bxy.y = bxy.y - 1; 554cabdff1aSopenharmony_ci 555cabdff1aSopenharmony_ci return pget(bxy); 556cabdff1aSopenharmony_ci} 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_cistatic uint8_t pick_left(BlockXY bxy) 559cabdff1aSopenharmony_ci{ 560cabdff1aSopenharmony_ci bxy.x = bxy.x - 1; 561cabdff1aSopenharmony_ci 562cabdff1aSopenharmony_ci return pget(bxy); 563cabdff1aSopenharmony_ci} 564cabdff1aSopenharmony_ci 565cabdff1aSopenharmony_cistatic uint8_t half_horz(BlockXY bxy) 566cabdff1aSopenharmony_ci{ 567cabdff1aSopenharmony_ci BlockXY a = bxy, b = bxy, c = bxy; 568cabdff1aSopenharmony_ci 569cabdff1aSopenharmony_ci a.x -= 1; 570cabdff1aSopenharmony_ci c.x += 1; 571cabdff1aSopenharmony_ci 572cabdff1aSopenharmony_ci return half3(pget(a), pget(b), pget(c)); 573cabdff1aSopenharmony_ci} 574cabdff1aSopenharmony_ci 575cabdff1aSopenharmony_cistatic uint8_t half_vert(BlockXY bxy) 576cabdff1aSopenharmony_ci{ 577cabdff1aSopenharmony_ci BlockXY a = bxy, b = bxy, c = bxy; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci a.y -= 1; 580cabdff1aSopenharmony_ci c.y += 1; 581cabdff1aSopenharmony_ci 582cabdff1aSopenharmony_ci return half3(pget(a), pget(b), pget(c)); 583cabdff1aSopenharmony_ci} 584cabdff1aSopenharmony_ci 585cabdff1aSopenharmony_cistatic uint8_t pick_4(BlockXY bxy) 586cabdff1aSopenharmony_ci{ 587cabdff1aSopenharmony_ci int val; 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_ci if ((bxy.x % 2) == 0) { 590cabdff1aSopenharmony_ci BlockXY ba, bb; 591cabdff1aSopenharmony_ci int a, b; 592cabdff1aSopenharmony_ci 593cabdff1aSopenharmony_ci ba = bxy; 594cabdff1aSopenharmony_ci ba.x = -1; 595cabdff1aSopenharmony_ci ba.y = bxy.y + bxy.x / 2; 596cabdff1aSopenharmony_ci a = pget(ba); 597cabdff1aSopenharmony_ci 598cabdff1aSopenharmony_ci bb = bxy; 599cabdff1aSopenharmony_ci bb.x = -1; 600cabdff1aSopenharmony_ci bb.y = bxy.y + bxy.x / 2 + 1; 601cabdff1aSopenharmony_ci b = pget(bb); 602cabdff1aSopenharmony_ci 603cabdff1aSopenharmony_ci val = half(a, b); 604cabdff1aSopenharmony_ci } else { 605cabdff1aSopenharmony_ci BlockXY ba; 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci ba = bxy; 608cabdff1aSopenharmony_ci ba.x = -1; 609cabdff1aSopenharmony_ci ba.y = bxy.y + bxy.x / 2 + 1; 610cabdff1aSopenharmony_ci val = half_vert(ba); 611cabdff1aSopenharmony_ci } 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_ci return val; 614cabdff1aSopenharmony_ci} 615cabdff1aSopenharmony_ci 616cabdff1aSopenharmony_cistatic uint8_t pick_5(BlockXY bxy) 617cabdff1aSopenharmony_ci{ 618cabdff1aSopenharmony_ci int val; 619cabdff1aSopenharmony_ci 620cabdff1aSopenharmony_ci if (bxy.x == 0) { 621cabdff1aSopenharmony_ci BlockXY a = bxy; 622cabdff1aSopenharmony_ci BlockXY b = bxy; 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci a.x = -1; 625cabdff1aSopenharmony_ci a.y -= 1; 626cabdff1aSopenharmony_ci 627cabdff1aSopenharmony_ci b.x = -1; 628cabdff1aSopenharmony_ci 629cabdff1aSopenharmony_ci val = half(pget(a), pget(b)); 630cabdff1aSopenharmony_ci } else if (bxy.y == 0) { 631cabdff1aSopenharmony_ci BlockXY a = bxy; 632cabdff1aSopenharmony_ci 633cabdff1aSopenharmony_ci a.x -= 2; 634cabdff1aSopenharmony_ci a.y -= 1; 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_ci val = half_horz(a); 637cabdff1aSopenharmony_ci } else if (bxy.x == 1) { 638cabdff1aSopenharmony_ci BlockXY a = bxy; 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci a.x -= 2; 641cabdff1aSopenharmony_ci a.y -= 1; 642cabdff1aSopenharmony_ci 643cabdff1aSopenharmony_ci val = half_vert(a); 644cabdff1aSopenharmony_ci } else { 645cabdff1aSopenharmony_ci BlockXY a = bxy; 646cabdff1aSopenharmony_ci 647cabdff1aSopenharmony_ci a.x -= 2; 648cabdff1aSopenharmony_ci a.y -= 1; 649cabdff1aSopenharmony_ci 650cabdff1aSopenharmony_ci val = pget(a); 651cabdff1aSopenharmony_ci } 652cabdff1aSopenharmony_ci 653cabdff1aSopenharmony_ci return val; 654cabdff1aSopenharmony_ci} 655cabdff1aSopenharmony_ci 656cabdff1aSopenharmony_cistatic uint8_t pick_6(BlockXY bxy) 657cabdff1aSopenharmony_ci{ 658cabdff1aSopenharmony_ci int val; 659cabdff1aSopenharmony_ci 660cabdff1aSopenharmony_ci if (bxy.y == 0) { 661cabdff1aSopenharmony_ci BlockXY a = bxy; 662cabdff1aSopenharmony_ci BlockXY b = bxy; 663cabdff1aSopenharmony_ci 664cabdff1aSopenharmony_ci a.x -= 1; 665cabdff1aSopenharmony_ci a.y = -1; 666cabdff1aSopenharmony_ci 667cabdff1aSopenharmony_ci b.y = -1; 668cabdff1aSopenharmony_ci 669cabdff1aSopenharmony_ci val = half(pget(a), pget(b)); 670cabdff1aSopenharmony_ci } else if (bxy.x == 0) { 671cabdff1aSopenharmony_ci BlockXY a = bxy; 672cabdff1aSopenharmony_ci 673cabdff1aSopenharmony_ci a.x -= 1; 674cabdff1aSopenharmony_ci a.y -= 2; 675cabdff1aSopenharmony_ci 676cabdff1aSopenharmony_ci val = half_vert(a); 677cabdff1aSopenharmony_ci } else if (bxy.y == 1) { 678cabdff1aSopenharmony_ci BlockXY a = bxy; 679cabdff1aSopenharmony_ci 680cabdff1aSopenharmony_ci a.x -= 1; 681cabdff1aSopenharmony_ci a.y -= 2; 682cabdff1aSopenharmony_ci 683cabdff1aSopenharmony_ci val = half_horz(a); 684cabdff1aSopenharmony_ci } else { 685cabdff1aSopenharmony_ci BlockXY a = bxy; 686cabdff1aSopenharmony_ci 687cabdff1aSopenharmony_ci a.x -= 1; 688cabdff1aSopenharmony_ci a.y -= 2; 689cabdff1aSopenharmony_ci 690cabdff1aSopenharmony_ci val = pget(a); 691cabdff1aSopenharmony_ci } 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci return val; 694cabdff1aSopenharmony_ci} 695cabdff1aSopenharmony_ci 696cabdff1aSopenharmony_cistatic uint8_t pick_7(BlockXY bxy) 697cabdff1aSopenharmony_ci{ 698cabdff1aSopenharmony_ci int clr, acc1, acc2; 699cabdff1aSopenharmony_ci BlockXY a = bxy; 700cabdff1aSopenharmony_ci 701cabdff1aSopenharmony_ci a.x -= 1; 702cabdff1aSopenharmony_ci a.y -= 1; 703cabdff1aSopenharmony_ci clr = pget(a); 704cabdff1aSopenharmony_ci if (bxy.x && bxy.y) 705cabdff1aSopenharmony_ci return clr; 706cabdff1aSopenharmony_ci 707cabdff1aSopenharmony_ci if (bxy.x == 0) { 708cabdff1aSopenharmony_ci a.x = -1; 709cabdff1aSopenharmony_ci a.y = bxy.y; 710cabdff1aSopenharmony_ci } else { 711cabdff1aSopenharmony_ci a.x = bxy.x - 2; 712cabdff1aSopenharmony_ci a.y = -1; 713cabdff1aSopenharmony_ci } 714cabdff1aSopenharmony_ci acc1 = pget(a); 715cabdff1aSopenharmony_ci 716cabdff1aSopenharmony_ci if (bxy.y == 0) { 717cabdff1aSopenharmony_ci a.x = bxy.x; 718cabdff1aSopenharmony_ci a.y = -1; 719cabdff1aSopenharmony_ci } else { 720cabdff1aSopenharmony_ci a.x = -1; 721cabdff1aSopenharmony_ci a.y = bxy.y - 2; 722cabdff1aSopenharmony_ci } 723cabdff1aSopenharmony_ci acc2 = pget(a); 724cabdff1aSopenharmony_ci 725cabdff1aSopenharmony_ci return half3(acc1, clr, acc2); 726cabdff1aSopenharmony_ci} 727cabdff1aSopenharmony_ci 728cabdff1aSopenharmony_cistatic uint8_t pick_8(BlockXY bxy) 729cabdff1aSopenharmony_ci{ 730cabdff1aSopenharmony_ci BlockXY ba = bxy; 731cabdff1aSopenharmony_ci BlockXY bb = bxy; 732cabdff1aSopenharmony_ci int val; 733cabdff1aSopenharmony_ci 734cabdff1aSopenharmony_ci if (bxy.y == 0) { 735cabdff1aSopenharmony_ci int a, b; 736cabdff1aSopenharmony_ci 737cabdff1aSopenharmony_ci ba.y = -1; 738cabdff1aSopenharmony_ci a = pget(ba); 739cabdff1aSopenharmony_ci 740cabdff1aSopenharmony_ci bb.x += 1; 741cabdff1aSopenharmony_ci bb.y = -1; 742cabdff1aSopenharmony_ci 743cabdff1aSopenharmony_ci b = pget(bb); 744cabdff1aSopenharmony_ci 745cabdff1aSopenharmony_ci val = half(a, b); 746cabdff1aSopenharmony_ci } else if (bxy.y == 1) { 747cabdff1aSopenharmony_ci ba.x += 1; 748cabdff1aSopenharmony_ci ba.y -= 2; 749cabdff1aSopenharmony_ci 750cabdff1aSopenharmony_ci val = half_horz(ba); 751cabdff1aSopenharmony_ci } else if (bxy.x < bxy.size - 1) { 752cabdff1aSopenharmony_ci ba.x += 1; 753cabdff1aSopenharmony_ci ba.y -= 2; 754cabdff1aSopenharmony_ci 755cabdff1aSopenharmony_ci val = pget(ba); 756cabdff1aSopenharmony_ci } else if (bxy.y % 2 == 0) { 757cabdff1aSopenharmony_ci int a, b; 758cabdff1aSopenharmony_ci 759cabdff1aSopenharmony_ci ba.x = bxy.y / 2 + bxy.size - 1; 760cabdff1aSopenharmony_ci ba.y = -1; 761cabdff1aSopenharmony_ci a = pget(ba); 762cabdff1aSopenharmony_ci 763cabdff1aSopenharmony_ci bb.x = bxy.y / 2 + bxy.size; 764cabdff1aSopenharmony_ci bb.y = -1; 765cabdff1aSopenharmony_ci 766cabdff1aSopenharmony_ci b = pget(bb); 767cabdff1aSopenharmony_ci 768cabdff1aSopenharmony_ci val = half(a, b); 769cabdff1aSopenharmony_ci } else { 770cabdff1aSopenharmony_ci ba.x = bxy.y / 2 + bxy.size; 771cabdff1aSopenharmony_ci ba.y = -1; 772cabdff1aSopenharmony_ci 773cabdff1aSopenharmony_ci val = half_horz(ba); 774cabdff1aSopenharmony_ci } 775cabdff1aSopenharmony_ci 776cabdff1aSopenharmony_ci return val; 777cabdff1aSopenharmony_ci} 778cabdff1aSopenharmony_ci 779cabdff1aSopenharmony_cistatic void block_fill_simple(uint8_t *block, int size, int linesize, int fill) 780cabdff1aSopenharmony_ci{ 781cabdff1aSopenharmony_ci for (int y = 0; y < size; y++) { 782cabdff1aSopenharmony_ci memset(block, fill, size); 783cabdff1aSopenharmony_ci block += linesize; 784cabdff1aSopenharmony_ci } 785cabdff1aSopenharmony_ci} 786cabdff1aSopenharmony_ci 787cabdff1aSopenharmony_cistatic void block_fill(uint8_t *block, int size, int linesize, 788cabdff1aSopenharmony_ci int w, int h, int ax, int ay, 789cabdff1aSopenharmony_ci uint8_t (*pick)(BlockXY bxy)) 790cabdff1aSopenharmony_ci{ 791cabdff1aSopenharmony_ci BlockXY bxy; 792cabdff1aSopenharmony_ci 793cabdff1aSopenharmony_ci bxy.size = size; 794cabdff1aSopenharmony_ci bxy.block = block; 795cabdff1aSopenharmony_ci bxy.linesize = linesize; 796cabdff1aSopenharmony_ci bxy.w = w; 797cabdff1aSopenharmony_ci bxy.h = h; 798cabdff1aSopenharmony_ci bxy.ay = ay; 799cabdff1aSopenharmony_ci bxy.ax = ax; 800cabdff1aSopenharmony_ci 801cabdff1aSopenharmony_ci for (int y = 0; y < size; y++) { 802cabdff1aSopenharmony_ci bxy.y = y; 803cabdff1aSopenharmony_ci for (int x = 0; x < size; x++) { 804cabdff1aSopenharmony_ci uint8_t val; 805cabdff1aSopenharmony_ci 806cabdff1aSopenharmony_ci bxy.x = x; 807cabdff1aSopenharmony_ci 808cabdff1aSopenharmony_ci val = pick(bxy); 809cabdff1aSopenharmony_ci 810cabdff1aSopenharmony_ci block[ax + x + (ay + y) * linesize] = val; 811cabdff1aSopenharmony_ci } 812cabdff1aSopenharmony_ci } 813cabdff1aSopenharmony_ci} 814cabdff1aSopenharmony_ci 815cabdff1aSopenharmony_cistatic int block_sum(const uint8_t *block, int w, int h, int linesize) 816cabdff1aSopenharmony_ci{ 817cabdff1aSopenharmony_ci int sum = 0; 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci for (int y = 0; y < h; y++) { 820cabdff1aSopenharmony_ci for (int x = 0; x < w; x++) { 821cabdff1aSopenharmony_ci sum += block[x]; 822cabdff1aSopenharmony_ci } 823cabdff1aSopenharmony_ci block += linesize; 824cabdff1aSopenharmony_ci } 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_ci return sum; 827cabdff1aSopenharmony_ci} 828cabdff1aSopenharmony_ci 829cabdff1aSopenharmony_cistatic int predict_intra(AVCodecContext *avctx, AVFrame *frame, int ax, int ay, 830cabdff1aSopenharmony_ci int pmode, int add_coeffs, int size, int plane) 831cabdff1aSopenharmony_ci{ 832cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 833cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 834cabdff1aSopenharmony_ci int w = avctx->width >> !!plane, h = avctx->height >> !!plane; 835cabdff1aSopenharmony_ci int ret = 0; 836cabdff1aSopenharmony_ci 837cabdff1aSopenharmony_ci switch (pmode) { 838cabdff1aSopenharmony_ci case 0: 839cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_above); 840cabdff1aSopenharmony_ci break; 841cabdff1aSopenharmony_ci case 1: 842cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_left); 843cabdff1aSopenharmony_ci break; 844cabdff1aSopenharmony_ci case 2: 845cabdff1aSopenharmony_ci { 846cabdff1aSopenharmony_ci int arr1[16]; 847cabdff1aSopenharmony_ci int arr2[16]; 848cabdff1aSopenharmony_ci uint8_t *top = frame->data[plane] + FFMAX(ay - 1, 0) * frame->linesize[plane] + ax; 849cabdff1aSopenharmony_ci uint8_t *left = frame->data[plane] + ay * frame->linesize[plane] + FFMAX(ax - 1, 0); 850cabdff1aSopenharmony_ci int bottommost = frame->data[plane][(ay + size - 1) * frame->linesize[plane] + FFMAX(ax - 1, 0)]; 851cabdff1aSopenharmony_ci int rightmost = frame->data[plane][FFMAX(ay - 1, 0) * frame->linesize[plane] + ax + size - 1]; 852cabdff1aSopenharmony_ci int avg = (bottommost + rightmost + 1) / 2 + 2 * av_clip(get_se_golomb(gb), -(1<<16), 1<<16); 853cabdff1aSopenharmony_ci int r6 = adjust(avg - bottommost, size); 854cabdff1aSopenharmony_ci int r9 = adjust(avg - rightmost, size); 855cabdff1aSopenharmony_ci int shift = adjust(size, size) == 8 ? 3 : 2; 856cabdff1aSopenharmony_ci uint8_t *block; 857cabdff1aSopenharmony_ci 858cabdff1aSopenharmony_ci for (int x = 0; x < size; x++) { 859cabdff1aSopenharmony_ci int val = top[x]; 860cabdff1aSopenharmony_ci arr1[x] = adjust(((bottommost - val) * (1 << shift)) + r6 * (x + 1), size); 861cabdff1aSopenharmony_ci } 862cabdff1aSopenharmony_ci 863cabdff1aSopenharmony_ci for (int y = 0; y < size; y++) { 864cabdff1aSopenharmony_ci int val = left[y * frame->linesize[plane]]; 865cabdff1aSopenharmony_ci arr2[y] = adjust(((rightmost - val) * (1 << shift)) + r9 * (y + 1), size); 866cabdff1aSopenharmony_ci } 867cabdff1aSopenharmony_ci 868cabdff1aSopenharmony_ci block = frame->data[plane] + ay * frame->linesize[plane] + ax; 869cabdff1aSopenharmony_ci for (int y = 0; y < size; y++) { 870cabdff1aSopenharmony_ci for (int x = 0; x < size; x++) { 871cabdff1aSopenharmony_ci block[x] = (((top[x] + left[0] + ((arr1[x] * (y + 1) + 872cabdff1aSopenharmony_ci arr2[y] * (x + 1)) >> 2 * shift)) + 1) / 2) & 0xFF; 873cabdff1aSopenharmony_ci } 874cabdff1aSopenharmony_ci block += frame->linesize[plane]; 875cabdff1aSopenharmony_ci left += frame->linesize[plane]; 876cabdff1aSopenharmony_ci } 877cabdff1aSopenharmony_ci } 878cabdff1aSopenharmony_ci break; 879cabdff1aSopenharmony_ci case 3: 880cabdff1aSopenharmony_ci { 881cabdff1aSopenharmony_ci uint8_t fill; 882cabdff1aSopenharmony_ci 883cabdff1aSopenharmony_ci if (ax == 0 && ay == 0) { 884cabdff1aSopenharmony_ci fill = 0x80; 885cabdff1aSopenharmony_ci } else if (ax >= 1 && ay >= 1) { 886cabdff1aSopenharmony_ci int left = block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1, 887cabdff1aSopenharmony_ci 1, size, frame->linesize[plane]); 888cabdff1aSopenharmony_ci int top = block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax, 889cabdff1aSopenharmony_ci size, 1, frame->linesize[plane]); 890cabdff1aSopenharmony_ci 891cabdff1aSopenharmony_ci fill = ((left + top) * 2 / (2 * size) + 1) / 2; 892cabdff1aSopenharmony_ci } else if (ax >= 1) { 893cabdff1aSopenharmony_ci fill = (block_sum(frame->data[plane] + ay * frame->linesize[plane] + ax - 1, 894cabdff1aSopenharmony_ci 1, size, frame->linesize[plane]) * 2 / size + 1) / 2; 895cabdff1aSopenharmony_ci } else if (ay >= 1) { 896cabdff1aSopenharmony_ci fill = (block_sum(frame->data[plane] + (ay - 1) * frame->linesize[plane] + ax, 897cabdff1aSopenharmony_ci size, 1, frame->linesize[plane]) * 2 / size + 1) / 2; 898cabdff1aSopenharmony_ci } else { 899cabdff1aSopenharmony_ci return -1; 900cabdff1aSopenharmony_ci } 901cabdff1aSopenharmony_ci 902cabdff1aSopenharmony_ci block_fill_simple(frame->data[plane] + ay * frame->linesize[plane] + ax, 903cabdff1aSopenharmony_ci size, frame->linesize[plane], fill); 904cabdff1aSopenharmony_ci } 905cabdff1aSopenharmony_ci break; 906cabdff1aSopenharmony_ci case 4: 907cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_4); 908cabdff1aSopenharmony_ci break; 909cabdff1aSopenharmony_ci case 5: 910cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_5); 911cabdff1aSopenharmony_ci break; 912cabdff1aSopenharmony_ci case 6: 913cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_6); 914cabdff1aSopenharmony_ci break; 915cabdff1aSopenharmony_ci case 7: 916cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_7); 917cabdff1aSopenharmony_ci break; 918cabdff1aSopenharmony_ci case 8: 919cabdff1aSopenharmony_ci block_fill(frame->data[plane], size, frame->linesize[plane], w, h, ax, ay, pick_8); 920cabdff1aSopenharmony_ci break; 921cabdff1aSopenharmony_ci } 922cabdff1aSopenharmony_ci 923cabdff1aSopenharmony_ci if (add_coeffs) 924cabdff1aSopenharmony_ci ret = add_coefficients(avctx, frame, ax, ay, size, plane); 925cabdff1aSopenharmony_ci 926cabdff1aSopenharmony_ci return ret; 927cabdff1aSopenharmony_ci} 928cabdff1aSopenharmony_ci 929cabdff1aSopenharmony_cistatic int get_prediction(AVCodecContext *avctx, int x, int y, int size) 930cabdff1aSopenharmony_ci{ 931cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 932cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 933cabdff1aSopenharmony_ci int index = (y & 0xC) | (x / 4 % 4); 934cabdff1aSopenharmony_ci 935cabdff1aSopenharmony_ci uint8_t val = FFMIN(s->pre[index], index % 4 == 0 ? 9 : s->pre[index + 3]); 936cabdff1aSopenharmony_ci if (val == 9) 937cabdff1aSopenharmony_ci val = 3; 938cabdff1aSopenharmony_ci 939cabdff1aSopenharmony_ci if (!get_bits1(gb)) { 940cabdff1aSopenharmony_ci int x = get_bits(gb, 3); 941cabdff1aSopenharmony_ci val = x + (x >= val ? 1 : 0); 942cabdff1aSopenharmony_ci } 943cabdff1aSopenharmony_ci 944cabdff1aSopenharmony_ci s->pre[index + 4] = val; 945cabdff1aSopenharmony_ci if (size == 8) 946cabdff1aSopenharmony_ci s->pre[index + 5] = s->pre[index + 8] = s->pre[index + 9] = val; 947cabdff1aSopenharmony_ci 948cabdff1aSopenharmony_ci return val; 949cabdff1aSopenharmony_ci} 950cabdff1aSopenharmony_ci 951cabdff1aSopenharmony_cistatic int process_block(AVCodecContext *avctx, AVFrame *frame, 952cabdff1aSopenharmony_ci int x, int y, int pmode, int has_coeffs, int plane) 953cabdff1aSopenharmony_ci{ 954cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 955cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 956cabdff1aSopenharmony_ci int tmp, ret; 957cabdff1aSopenharmony_ci 958cabdff1aSopenharmony_ci if (!has_coeffs) { 959cabdff1aSopenharmony_ci if (pmode < 0) 960cabdff1aSopenharmony_ci pmode = get_prediction(avctx, x, y, 8); 961cabdff1aSopenharmony_ci return predict_intra(avctx, frame, x, y, pmode, 0, 8, plane); 962cabdff1aSopenharmony_ci } 963cabdff1aSopenharmony_ci 964cabdff1aSopenharmony_ci tmp = get_ue_golomb_31(gb); 965cabdff1aSopenharmony_ci if ((unsigned)tmp > FF_ARRAY_ELEMS(block4x4_coefficients_tab)) 966cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 967cabdff1aSopenharmony_ci 968cabdff1aSopenharmony_ci if (tmp == 0) { 969cabdff1aSopenharmony_ci if (pmode < 0) 970cabdff1aSopenharmony_ci pmode = get_prediction(avctx, x, y, 8); 971cabdff1aSopenharmony_ci ret = predict_intra(avctx, frame, x, y, pmode, 1, 8, plane); 972cabdff1aSopenharmony_ci } else { 973cabdff1aSopenharmony_ci int flags = block4x4_coefficients_tab[tmp - 1]; 974cabdff1aSopenharmony_ci 975cabdff1aSopenharmony_ci for (int by = y; by < y + 8; by += 4) { 976cabdff1aSopenharmony_ci for (int bx = x; bx < x + 8; bx += 4) { 977cabdff1aSopenharmony_ci int new_pmode = pmode; 978cabdff1aSopenharmony_ci 979cabdff1aSopenharmony_ci if (new_pmode < 0) 980cabdff1aSopenharmony_ci new_pmode = get_prediction(avctx, bx, by, 4); 981cabdff1aSopenharmony_ci ret = predict_intra(avctx, frame, bx, by, new_pmode, flags & 1, 4, plane); 982cabdff1aSopenharmony_ci if (ret < 0) 983cabdff1aSopenharmony_ci return ret; 984cabdff1aSopenharmony_ci flags >>= 1; 985cabdff1aSopenharmony_ci } 986cabdff1aSopenharmony_ci } 987cabdff1aSopenharmony_ci } 988cabdff1aSopenharmony_ci 989cabdff1aSopenharmony_ci return ret; 990cabdff1aSopenharmony_ci} 991cabdff1aSopenharmony_ci 992cabdff1aSopenharmony_cistatic int decode_macroblock(AVCodecContext *avctx, AVFrame *frame, 993cabdff1aSopenharmony_ci int x, int y, int predict) 994cabdff1aSopenharmony_ci{ 995cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 996cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 997cabdff1aSopenharmony_ci int flags, pmode_uv, idx = get_ue_golomb(gb); 998cabdff1aSopenharmony_ci int ret = 0; 999cabdff1aSopenharmony_ci 1000cabdff1aSopenharmony_ci if (idx < 0 || idx >= FF_ARRAY_ELEMS(block8x8_coefficients_tab)) 1001cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1002cabdff1aSopenharmony_ci 1003cabdff1aSopenharmony_ci flags = block8x8_coefficients_tab[idx]; 1004cabdff1aSopenharmony_ci 1005cabdff1aSopenharmony_ci if (predict) { 1006cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x, y, -1, flags & 1, 0); 1007cabdff1aSopenharmony_ci if (ret < 0) 1008cabdff1aSopenharmony_ci return ret; 1009cabdff1aSopenharmony_ci flags >>= 1; 1010cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x + 8, y, -1, flags & 1, 0); 1011cabdff1aSopenharmony_ci if (ret < 0) 1012cabdff1aSopenharmony_ci return ret; 1013cabdff1aSopenharmony_ci flags >>= 1; 1014cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x, y + 8, -1, flags & 1, 0); 1015cabdff1aSopenharmony_ci if (ret < 0) 1016cabdff1aSopenharmony_ci return ret; 1017cabdff1aSopenharmony_ci flags >>= 1; 1018cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x + 8, y + 8, -1, flags & 1, 0); 1019cabdff1aSopenharmony_ci if (ret < 0) 1020cabdff1aSopenharmony_ci return ret; 1021cabdff1aSopenharmony_ci flags >>= 1; 1022cabdff1aSopenharmony_ci } else { 1023cabdff1aSopenharmony_ci int pmode = get_bits(gb, 3); 1024cabdff1aSopenharmony_ci 1025cabdff1aSopenharmony_ci if (pmode == 2) { 1026cabdff1aSopenharmony_ci ret = predict_intra(avctx, frame, x, y, pmode, 0, 16, 0); 1027cabdff1aSopenharmony_ci if (ret < 0) 1028cabdff1aSopenharmony_ci return ret; 1029cabdff1aSopenharmony_ci pmode = 9; 1030cabdff1aSopenharmony_ci } 1031cabdff1aSopenharmony_ci 1032cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x, y, pmode, flags & 1, 0); 1033cabdff1aSopenharmony_ci if (ret < 0) 1034cabdff1aSopenharmony_ci return ret; 1035cabdff1aSopenharmony_ci flags >>= 1; 1036cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x + 8, y, pmode, flags & 1, 0); 1037cabdff1aSopenharmony_ci if (ret < 0) 1038cabdff1aSopenharmony_ci return ret; 1039cabdff1aSopenharmony_ci flags >>= 1; 1040cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x, y + 8, pmode, flags & 1, 0); 1041cabdff1aSopenharmony_ci if (ret < 0) 1042cabdff1aSopenharmony_ci return ret; 1043cabdff1aSopenharmony_ci flags >>= 1; 1044cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x + 8, y + 8, pmode, flags & 1, 0); 1045cabdff1aSopenharmony_ci if (ret < 0) 1046cabdff1aSopenharmony_ci return ret; 1047cabdff1aSopenharmony_ci flags >>= 1; 1048cabdff1aSopenharmony_ci } 1049cabdff1aSopenharmony_ci 1050cabdff1aSopenharmony_ci pmode_uv = get_bits(gb, 3); 1051cabdff1aSopenharmony_ci if (pmode_uv == 2) { 1052cabdff1aSopenharmony_ci ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 1 + !s->moflex); 1053cabdff1aSopenharmony_ci if (ret < 0) 1054cabdff1aSopenharmony_ci return ret; 1055cabdff1aSopenharmony_ci ret = predict_intra(avctx, frame, x >> 1, y >> 1, pmode_uv, 0, 8, 2 - !s->moflex); 1056cabdff1aSopenharmony_ci if (ret < 0) 1057cabdff1aSopenharmony_ci return ret; 1058cabdff1aSopenharmony_ci pmode_uv = 9; 1059cabdff1aSopenharmony_ci } 1060cabdff1aSopenharmony_ci 1061cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 1 + !s->moflex); 1062cabdff1aSopenharmony_ci if (ret < 0) 1063cabdff1aSopenharmony_ci return ret; 1064cabdff1aSopenharmony_ci flags >>= 1; 1065cabdff1aSopenharmony_ci ret = process_block(avctx, frame, x >> 1, y >> 1, pmode_uv, flags & 1, 2 - !s->moflex); 1066cabdff1aSopenharmony_ci if (ret < 0) 1067cabdff1aSopenharmony_ci return ret; 1068cabdff1aSopenharmony_ci 1069cabdff1aSopenharmony_ci return 0; 1070cabdff1aSopenharmony_ci} 1071cabdff1aSopenharmony_ci 1072cabdff1aSopenharmony_cistatic int get_index(int x) 1073cabdff1aSopenharmony_ci{ 1074cabdff1aSopenharmony_ci return x == 16 ? 0 : x == 8 ? 1 : x == 4 ? 2 : x == 2 ? 3 : 0; 1075cabdff1aSopenharmony_ci} 1076cabdff1aSopenharmony_ci 1077cabdff1aSopenharmony_cistatic int predict_motion(AVCodecContext *avctx, 1078cabdff1aSopenharmony_ci int width, int height, int index, 1079cabdff1aSopenharmony_ci int offsetm, int offsetx, int offsety) 1080cabdff1aSopenharmony_ci{ 1081cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 1082cabdff1aSopenharmony_ci MotionXY *motion = s->motion; 1083cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 1084cabdff1aSopenharmony_ci int fheight = avctx->height; 1085cabdff1aSopenharmony_ci int fwidth = avctx->width; 1086cabdff1aSopenharmony_ci 1087cabdff1aSopenharmony_ci if (index <= 5) { 1088cabdff1aSopenharmony_ci int sidx = -FFMAX(1, index) + s->current_pic; 1089cabdff1aSopenharmony_ci MotionXY mv = s->motion[0]; 1090cabdff1aSopenharmony_ci 1091cabdff1aSopenharmony_ci if (sidx < 0) 1092cabdff1aSopenharmony_ci sidx += 6; 1093cabdff1aSopenharmony_ci 1094cabdff1aSopenharmony_ci if (index > 0) { 1095cabdff1aSopenharmony_ci mv.x = mv.x + (unsigned)get_se_golomb(gb); 1096cabdff1aSopenharmony_ci mv.y = mv.y + (unsigned)get_se_golomb(gb); 1097cabdff1aSopenharmony_ci } 1098cabdff1aSopenharmony_ci if (mv.x >= INT_MAX || mv.y >= INT_MAX) 1099cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1100cabdff1aSopenharmony_ci 1101cabdff1aSopenharmony_ci motion[offsetm].x = mv.x; 1102cabdff1aSopenharmony_ci motion[offsetm].y = mv.y; 1103cabdff1aSopenharmony_ci 1104cabdff1aSopenharmony_ci for (int i = 0; i < 3; i++) { 1105cabdff1aSopenharmony_ci int method, src_linesize, dst_linesize; 1106cabdff1aSopenharmony_ci uint8_t *src, *dst; 1107cabdff1aSopenharmony_ci 1108cabdff1aSopenharmony_ci if (i == 1) { 1109cabdff1aSopenharmony_ci offsetx = offsetx >> 1; 1110cabdff1aSopenharmony_ci offsety = offsety >> 1; 1111cabdff1aSopenharmony_ci mv.x = mv.x >> 1; 1112cabdff1aSopenharmony_ci mv.y = mv.y >> 1; 1113cabdff1aSopenharmony_ci width = width >> 1; 1114cabdff1aSopenharmony_ci height = height >> 1; 1115cabdff1aSopenharmony_ci fwidth = fwidth >> 1; 1116cabdff1aSopenharmony_ci fheight = fheight >> 1; 1117cabdff1aSopenharmony_ci } 1118cabdff1aSopenharmony_ci 1119cabdff1aSopenharmony_ci av_assert0(s->pic[sidx]); 1120cabdff1aSopenharmony_ci av_assert0(s->pic[s->current_pic]); 1121cabdff1aSopenharmony_ci av_assert0(s->pic[s->current_pic]->data[i]); 1122cabdff1aSopenharmony_ci if (!s->pic[sidx]->data[i]) 1123cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1124cabdff1aSopenharmony_ci 1125cabdff1aSopenharmony_ci method = (mv.x & 1) | ((mv.y & 1) << 1); 1126cabdff1aSopenharmony_ci src_linesize = s->pic[sidx]->linesize[i]; 1127cabdff1aSopenharmony_ci dst_linesize = s->pic[s->current_pic]->linesize[i]; 1128cabdff1aSopenharmony_ci dst = s->pic[s->current_pic]->data[i] + offsetx + offsety * dst_linesize; 1129cabdff1aSopenharmony_ci 1130cabdff1aSopenharmony_ci if (offsetx + (mv.x >> 1) < 0 || 1131cabdff1aSopenharmony_ci offsety + (mv.y >> 1) < 0 || 1132cabdff1aSopenharmony_ci offsetx + width + (mv.x + 1 >> 1) > fwidth || 1133cabdff1aSopenharmony_ci offsety + height + (mv.y + 1 >> 1) > fheight) 1134cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1135cabdff1aSopenharmony_ci 1136cabdff1aSopenharmony_ci switch (method) { 1137cabdff1aSopenharmony_ci case 0: 1138cabdff1aSopenharmony_ci src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + 1139cabdff1aSopenharmony_ci (offsety + (mv.y >> 1)) * src_linesize; 1140cabdff1aSopenharmony_ci for (int y = 0; y < height; y++) { 1141cabdff1aSopenharmony_ci for (int x = 0; x < width; x++) 1142cabdff1aSopenharmony_ci dst[x] = src[x]; 1143cabdff1aSopenharmony_ci dst += dst_linesize; 1144cabdff1aSopenharmony_ci src += src_linesize; 1145cabdff1aSopenharmony_ci } 1146cabdff1aSopenharmony_ci break; 1147cabdff1aSopenharmony_ci case 1: 1148cabdff1aSopenharmony_ci src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + 1149cabdff1aSopenharmony_ci (offsety + (mv.y >> 1)) * src_linesize; 1150cabdff1aSopenharmony_ci for (int y = 0; y < height; y++) { 1151cabdff1aSopenharmony_ci for (int x = 0; x < width; x++) { 1152cabdff1aSopenharmony_ci dst[x] = (uint8_t)((src[x] >> 1) + (src[x + 1] >> 1)); 1153cabdff1aSopenharmony_ci } 1154cabdff1aSopenharmony_ci 1155cabdff1aSopenharmony_ci dst += dst_linesize; 1156cabdff1aSopenharmony_ci src += src_linesize; 1157cabdff1aSopenharmony_ci } 1158cabdff1aSopenharmony_ci break; 1159cabdff1aSopenharmony_ci case 2: 1160cabdff1aSopenharmony_ci src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + 1161cabdff1aSopenharmony_ci (offsety + (mv.y >> 1)) * src_linesize; 1162cabdff1aSopenharmony_ci for (int y = 0; y < height; y++) { 1163cabdff1aSopenharmony_ci for (int x = 0; x < width; x++) { 1164cabdff1aSopenharmony_ci dst[x] = (uint8_t)((src[x] >> 1) + (src[x + src_linesize] >> 1)); 1165cabdff1aSopenharmony_ci } 1166cabdff1aSopenharmony_ci 1167cabdff1aSopenharmony_ci dst += dst_linesize; 1168cabdff1aSopenharmony_ci src += src_linesize; 1169cabdff1aSopenharmony_ci } 1170cabdff1aSopenharmony_ci break; 1171cabdff1aSopenharmony_ci case 3: 1172cabdff1aSopenharmony_ci src = s->pic[sidx]->data[i] + offsetx + (mv.x >> 1) + 1173cabdff1aSopenharmony_ci (offsety + (mv.y >> 1)) * src_linesize; 1174cabdff1aSopenharmony_ci for (int y = 0; y < height; y++) { 1175cabdff1aSopenharmony_ci for (int x = 0; x < width; x++) { 1176cabdff1aSopenharmony_ci dst[x] = (uint8_t)((((src[x] >> 1) + (src[x + 1] >> 1)) >> 1) + 1177cabdff1aSopenharmony_ci (((src[x + src_linesize] >> 1) + (src[x + 1 + src_linesize] >> 1)) >> 1)); 1178cabdff1aSopenharmony_ci } 1179cabdff1aSopenharmony_ci 1180cabdff1aSopenharmony_ci dst += dst_linesize; 1181cabdff1aSopenharmony_ci src += src_linesize; 1182cabdff1aSopenharmony_ci } 1183cabdff1aSopenharmony_ci break; 1184cabdff1aSopenharmony_ci } 1185cabdff1aSopenharmony_ci } 1186cabdff1aSopenharmony_ci } else { 1187cabdff1aSopenharmony_ci int tidx; 1188cabdff1aSopenharmony_ci int adjx = index == 8 ? 0 : width / 2; 1189cabdff1aSopenharmony_ci int adjy = index == 8 ? height / 2 : 0; 1190cabdff1aSopenharmony_ci 1191cabdff1aSopenharmony_ci width = width - adjx; 1192cabdff1aSopenharmony_ci height = height - adjy; 1193cabdff1aSopenharmony_ci tidx = get_index(height) * 4 + get_index(width); 1194cabdff1aSopenharmony_ci 1195cabdff1aSopenharmony_ci for (int i = 0; i < 2; i++) { 1196cabdff1aSopenharmony_ci int ret, idx2; 1197cabdff1aSopenharmony_ci 1198cabdff1aSopenharmony_ci idx2 = get_vlc2(gb, mv_vlc[s->moflex][tidx].table, 1199cabdff1aSopenharmony_ci MOBI_MV_VLC_BITS, 1); 1200cabdff1aSopenharmony_ci 1201cabdff1aSopenharmony_ci ret = predict_motion(avctx, width, height, idx2, 1202cabdff1aSopenharmony_ci offsetm, offsetx + i * adjx, offsety + i * adjy); 1203cabdff1aSopenharmony_ci if (ret < 0) 1204cabdff1aSopenharmony_ci return ret; 1205cabdff1aSopenharmony_ci } 1206cabdff1aSopenharmony_ci } 1207cabdff1aSopenharmony_ci 1208cabdff1aSopenharmony_ci return 0; 1209cabdff1aSopenharmony_ci} 1210cabdff1aSopenharmony_ci 1211cabdff1aSopenharmony_cistatic int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe, 1212cabdff1aSopenharmony_ci int *got_frame, AVPacket *pkt) 1213cabdff1aSopenharmony_ci{ 1214cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 1215cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 1216cabdff1aSopenharmony_ci AVFrame *frame = s->pic[s->current_pic]; 1217cabdff1aSopenharmony_ci int ret; 1218cabdff1aSopenharmony_ci 1219cabdff1aSopenharmony_ci av_fast_padded_malloc(&s->bitstream, &s->bitstream_size, 1220cabdff1aSopenharmony_ci pkt->size); 1221cabdff1aSopenharmony_ci 1222cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, frame, 0)) < 0) 1223cabdff1aSopenharmony_ci return ret; 1224cabdff1aSopenharmony_ci 1225cabdff1aSopenharmony_ci s->bdsp.bswap16_buf((uint16_t *)s->bitstream, 1226cabdff1aSopenharmony_ci (uint16_t *)pkt->data, 1227cabdff1aSopenharmony_ci (pkt->size + 1) >> 1); 1228cabdff1aSopenharmony_ci 1229cabdff1aSopenharmony_ci ret = init_get_bits8(gb, s->bitstream, FFALIGN(pkt->size, 2)); 1230cabdff1aSopenharmony_ci if (ret < 0) 1231cabdff1aSopenharmony_ci return ret; 1232cabdff1aSopenharmony_ci 1233cabdff1aSopenharmony_ci if (get_bits1(gb)) { 1234cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_I; 1235cabdff1aSopenharmony_ci frame->key_frame = 1; 1236cabdff1aSopenharmony_ci s->moflex = get_bits1(gb); 1237cabdff1aSopenharmony_ci s->dct_tab_idx = get_bits1(gb); 1238cabdff1aSopenharmony_ci 1239cabdff1aSopenharmony_ci ret = setup_qtables(avctx, get_bits(gb, 6)); 1240cabdff1aSopenharmony_ci if (ret < 0) 1241cabdff1aSopenharmony_ci return ret; 1242cabdff1aSopenharmony_ci 1243cabdff1aSopenharmony_ci for (int y = 0; y < avctx->height; y += 16) { 1244cabdff1aSopenharmony_ci for (int x = 0; x < avctx->width; x += 16) { 1245cabdff1aSopenharmony_ci ret = decode_macroblock(avctx, frame, x, y, get_bits1(gb)); 1246cabdff1aSopenharmony_ci if (ret < 0) 1247cabdff1aSopenharmony_ci return ret; 1248cabdff1aSopenharmony_ci } 1249cabdff1aSopenharmony_ci } 1250cabdff1aSopenharmony_ci } else { 1251cabdff1aSopenharmony_ci MotionXY *motion = s->motion; 1252cabdff1aSopenharmony_ci 1253cabdff1aSopenharmony_ci memset(motion, 0, s->motion_size); 1254cabdff1aSopenharmony_ci 1255cabdff1aSopenharmony_ci frame->pict_type = AV_PICTURE_TYPE_P; 1256cabdff1aSopenharmony_ci frame->key_frame = 0; 1257cabdff1aSopenharmony_ci s->dct_tab_idx = 0; 1258cabdff1aSopenharmony_ci 1259cabdff1aSopenharmony_ci ret = setup_qtables(avctx, s->quantizer + (int64_t)get_se_golomb(gb)); 1260cabdff1aSopenharmony_ci if (ret < 0) 1261cabdff1aSopenharmony_ci return ret; 1262cabdff1aSopenharmony_ci 1263cabdff1aSopenharmony_ci for (int y = 0; y < avctx->height; y += 16) { 1264cabdff1aSopenharmony_ci for (int x = 0; x < avctx->width; x += 16) { 1265cabdff1aSopenharmony_ci int idx; 1266cabdff1aSopenharmony_ci 1267cabdff1aSopenharmony_ci motion[0].x = mid_pred(motion[x / 16 + 1].x, motion[x / 16 + 2].x, motion[x / 16 + 3].x); 1268cabdff1aSopenharmony_ci motion[0].y = mid_pred(motion[x / 16 + 1].y, motion[x / 16 + 2].y, motion[x / 16 + 3].y); 1269cabdff1aSopenharmony_ci motion[x / 16 + 2].x = 0; 1270cabdff1aSopenharmony_ci motion[x / 16 + 2].y = 0; 1271cabdff1aSopenharmony_ci 1272cabdff1aSopenharmony_ci idx = get_vlc2(gb, mv_vlc[s->moflex][0].table, 1273cabdff1aSopenharmony_ci MOBI_MV_VLC_BITS, 1); 1274cabdff1aSopenharmony_ci 1275cabdff1aSopenharmony_ci if (idx == 6 || idx == 7) { 1276cabdff1aSopenharmony_ci ret = decode_macroblock(avctx, frame, x, y, idx == 7); 1277cabdff1aSopenharmony_ci if (ret < 0) 1278cabdff1aSopenharmony_ci return ret; 1279cabdff1aSopenharmony_ci } else { 1280cabdff1aSopenharmony_ci int flags, idx2; 1281cabdff1aSopenharmony_ci ret = predict_motion(avctx, 16, 16, idx, x / 16 + 2, x, y); 1282cabdff1aSopenharmony_ci if (ret < 0) 1283cabdff1aSopenharmony_ci return ret; 1284cabdff1aSopenharmony_ci idx2 = get_ue_golomb(gb); 1285cabdff1aSopenharmony_ci if (idx2 >= FF_ARRAY_ELEMS(pframe_block8x8_coefficients_tab)) 1286cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1287cabdff1aSopenharmony_ci flags = pframe_block8x8_coefficients_tab[idx2]; 1288cabdff1aSopenharmony_ci 1289cabdff1aSopenharmony_ci for (int sy = y; sy < y + 16; sy += 8) { 1290cabdff1aSopenharmony_ci for (int sx = x; sx < x + 16; sx += 8) { 1291cabdff1aSopenharmony_ci if (flags & 1) 1292cabdff1aSopenharmony_ci add_pframe_coefficients(avctx, frame, sx, sy, 8, 0); 1293cabdff1aSopenharmony_ci flags >>= 1; 1294cabdff1aSopenharmony_ci } 1295cabdff1aSopenharmony_ci } 1296cabdff1aSopenharmony_ci 1297cabdff1aSopenharmony_ci if (flags & 1) 1298cabdff1aSopenharmony_ci add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 1 + !s->moflex); 1299cabdff1aSopenharmony_ci flags >>= 1; 1300cabdff1aSopenharmony_ci if (flags & 1) 1301cabdff1aSopenharmony_ci add_pframe_coefficients(avctx, frame, x >> 1, y >> 1, 8, 2 - !s->moflex); 1302cabdff1aSopenharmony_ci } 1303cabdff1aSopenharmony_ci } 1304cabdff1aSopenharmony_ci } 1305cabdff1aSopenharmony_ci } 1306cabdff1aSopenharmony_ci 1307cabdff1aSopenharmony_ci if (!s->moflex) 1308cabdff1aSopenharmony_ci avctx->colorspace = AVCOL_SPC_YCGCO; 1309cabdff1aSopenharmony_ci 1310cabdff1aSopenharmony_ci s->current_pic = (s->current_pic + 1) % 6; 1311cabdff1aSopenharmony_ci ret = av_frame_ref(rframe, frame); 1312cabdff1aSopenharmony_ci if (ret < 0) 1313cabdff1aSopenharmony_ci return ret; 1314cabdff1aSopenharmony_ci *got_frame = 1; 1315cabdff1aSopenharmony_ci 1316cabdff1aSopenharmony_ci return 0; 1317cabdff1aSopenharmony_ci} 1318cabdff1aSopenharmony_ci 1319cabdff1aSopenharmony_cistatic void mobiclip_flush(AVCodecContext *avctx) 1320cabdff1aSopenharmony_ci{ 1321cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 1322cabdff1aSopenharmony_ci 1323cabdff1aSopenharmony_ci for (int i = 0; i < 6; i++) 1324cabdff1aSopenharmony_ci av_frame_unref(s->pic[i]); 1325cabdff1aSopenharmony_ci} 1326cabdff1aSopenharmony_ci 1327cabdff1aSopenharmony_cistatic av_cold int mobiclip_close(AVCodecContext *avctx) 1328cabdff1aSopenharmony_ci{ 1329cabdff1aSopenharmony_ci MobiClipContext *s = avctx->priv_data; 1330cabdff1aSopenharmony_ci 1331cabdff1aSopenharmony_ci av_freep(&s->bitstream); 1332cabdff1aSopenharmony_ci s->bitstream_size = 0; 1333cabdff1aSopenharmony_ci av_freep(&s->motion); 1334cabdff1aSopenharmony_ci s->motion_size = 0; 1335cabdff1aSopenharmony_ci 1336cabdff1aSopenharmony_ci for (int i = 0; i < 6; i++) { 1337cabdff1aSopenharmony_ci av_frame_free(&s->pic[i]); 1338cabdff1aSopenharmony_ci } 1339cabdff1aSopenharmony_ci 1340cabdff1aSopenharmony_ci return 0; 1341cabdff1aSopenharmony_ci} 1342cabdff1aSopenharmony_ci 1343cabdff1aSopenharmony_ciconst FFCodec ff_mobiclip_decoder = { 1344cabdff1aSopenharmony_ci .p.name = "mobiclip", 1345cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"), 1346cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 1347cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_MOBICLIP, 1348cabdff1aSopenharmony_ci .priv_data_size = sizeof(MobiClipContext), 1349cabdff1aSopenharmony_ci .init = mobiclip_init, 1350cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(mobiclip_decode), 1351cabdff1aSopenharmony_ci .flush = mobiclip_flush, 1352cabdff1aSopenharmony_ci .close = mobiclip_close, 1353cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 1354cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 1355cabdff1aSopenharmony_ci}; 1356