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