1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Microsoft Screen 4 (aka Microsoft Expression Encoder Screen) decoder 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Konstantin Shishkov 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Microsoft Screen 4 (aka Microsoft Titanium Screen 2, 25cabdff1aSopenharmony_ci * aka Microsoft Expression Encoder Screen) decoder 26cabdff1aSopenharmony_ci */ 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include "libavutil/thread.h" 29cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "avcodec.h" 32cabdff1aSopenharmony_ci#include "bytestream.h" 33cabdff1aSopenharmony_ci#include "codec_internal.h" 34cabdff1aSopenharmony_ci#include "get_bits.h" 35cabdff1aSopenharmony_ci#include "internal.h" 36cabdff1aSopenharmony_ci#include "jpegtables.h" 37cabdff1aSopenharmony_ci#include "mss34dsp.h" 38cabdff1aSopenharmony_ci#include "unary.h" 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci#define HEADER_SIZE 8 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_cienum FrameType { 43cabdff1aSopenharmony_ci INTRA_FRAME = 0, 44cabdff1aSopenharmony_ci INTER_FRAME, 45cabdff1aSopenharmony_ci SKIP_FRAME 46cabdff1aSopenharmony_ci}; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_cienum BlockType { 49cabdff1aSopenharmony_ci SKIP_BLOCK = 0, 50cabdff1aSopenharmony_ci DCT_BLOCK, 51cabdff1aSopenharmony_ci IMAGE_BLOCK, 52cabdff1aSopenharmony_ci}; 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_cienum CachePos { 55cabdff1aSopenharmony_ci LEFT = 0, 56cabdff1aSopenharmony_ci TOP_LEFT, 57cabdff1aSopenharmony_ci TOP, 58cabdff1aSopenharmony_ci}; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_cistatic const uint8_t mss4_dc_vlc_lens[2][16] = { 61cabdff1aSopenharmony_ci { 0, 1, 5, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, 62cabdff1aSopenharmony_ci { 0, 3, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0 } 63cabdff1aSopenharmony_ci}; 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_cistatic const uint8_t vec_len_syms[2][4] = { 66cabdff1aSopenharmony_ci { 4, 2, 3, 1 }, 67cabdff1aSopenharmony_ci { 4, 1, 2, 3 } 68cabdff1aSopenharmony_ci}; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_cistatic const uint8_t mss4_vec_entry_vlc_lens[2][16] = { 71cabdff1aSopenharmony_ci { 0, 2, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 72cabdff1aSopenharmony_ci { 0, 1, 5, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 73cabdff1aSopenharmony_ci}; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_cistatic const uint8_t mss4_vec_entry_vlc_syms[2][9] = { 76cabdff1aSopenharmony_ci { 0, 7, 6, 5, 8, 4, 3, 1, 2 }, 77cabdff1aSopenharmony_ci { 0, 2, 3, 4, 5, 6, 7, 1, 8 } 78cabdff1aSopenharmony_ci}; 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci#define MAX_ENTRIES 162 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_citypedef struct MSS4Context { 83cabdff1aSopenharmony_ci AVFrame *pic; 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci int block[64]; 86cabdff1aSopenharmony_ci uint8_t imgbuf[3][16 * 16]; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci int quality; 89cabdff1aSopenharmony_ci uint16_t quant_mat[2][64]; 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci int *prev_dc[3]; 92cabdff1aSopenharmony_ci ptrdiff_t dc_stride[3]; 93cabdff1aSopenharmony_ci int dc_cache[4][4]; 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci int prev_vec[3][4]; 96cabdff1aSopenharmony_ci} MSS4Context; 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_cistatic VLC dc_vlc[2], ac_vlc[2]; 99cabdff1aSopenharmony_cistatic VLC vec_entry_vlc[2]; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_cistatic av_cold void mss4_init_vlc(VLC *vlc, unsigned *offset, 102cabdff1aSopenharmony_ci const uint8_t *lens, const uint8_t *syms) 103cabdff1aSopenharmony_ci{ 104cabdff1aSopenharmony_ci static VLCElem vlc_buf[2146]; 105cabdff1aSopenharmony_ci uint8_t bits[MAX_ENTRIES]; 106cabdff1aSopenharmony_ci int i, j; 107cabdff1aSopenharmony_ci int idx = 0; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) { 110cabdff1aSopenharmony_ci for (j = 0; j < lens[i]; j++) { 111cabdff1aSopenharmony_ci bits[idx] = i + 1; 112cabdff1aSopenharmony_ci idx++; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci vlc->table = &vlc_buf[*offset]; 117cabdff1aSopenharmony_ci vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *offset; 118cabdff1aSopenharmony_ci ff_init_vlc_from_lengths(vlc, FFMIN(bits[idx - 1], 9), idx, 119cabdff1aSopenharmony_ci bits, 1, syms, 1, 1, 120cabdff1aSopenharmony_ci 0, INIT_VLC_STATIC_OVERLONG, NULL); 121cabdff1aSopenharmony_ci *offset += vlc->table_size; 122cabdff1aSopenharmony_ci} 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_cistatic av_cold void mss4_init_vlcs(void) 125cabdff1aSopenharmony_ci{ 126cabdff1aSopenharmony_ci for (unsigned i = 0, offset = 0; i < 2; i++) { 127cabdff1aSopenharmony_ci mss4_init_vlc(&dc_vlc[i], &offset, mss4_dc_vlc_lens[i], NULL); 128cabdff1aSopenharmony_ci mss4_init_vlc(&ac_vlc[i], &offset, 129cabdff1aSopenharmony_ci i ? ff_mjpeg_bits_ac_chrominance + 1 130cabdff1aSopenharmony_ci : ff_mjpeg_bits_ac_luminance + 1, 131cabdff1aSopenharmony_ci i ? ff_mjpeg_val_ac_chrominance 132cabdff1aSopenharmony_ci : ff_mjpeg_val_ac_luminance); 133cabdff1aSopenharmony_ci mss4_init_vlc(&vec_entry_vlc[i], &offset, mss4_vec_entry_vlc_lens[i], 134cabdff1aSopenharmony_ci mss4_vec_entry_vlc_syms[i]); 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci} 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci/* This function returns values in the range 139cabdff1aSopenharmony_ci * (-range + 1; -range/2] U [range/2; range - 1) 140cabdff1aSopenharmony_ci * i.e. 141cabdff1aSopenharmony_ci * nbits = 0 -> 0 142cabdff1aSopenharmony_ci * nbits = 1 -> -1, 1 143cabdff1aSopenharmony_ci * nbits = 2 -> -3, -2, 2, 3 144cabdff1aSopenharmony_ci */ 145cabdff1aSopenharmony_cistatic av_always_inline int get_coeff_bits(GetBitContext *gb, int nbits) 146cabdff1aSopenharmony_ci{ 147cabdff1aSopenharmony_ci int val; 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci if (!nbits) 150cabdff1aSopenharmony_ci return 0; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci val = get_bits(gb, nbits); 153cabdff1aSopenharmony_ci if (val < (1 << (nbits - 1))) 154cabdff1aSopenharmony_ci val -= (1 << nbits) - 1; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci return val; 157cabdff1aSopenharmony_ci} 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_cistatic inline int get_coeff(GetBitContext *gb, VLC *vlc) 160cabdff1aSopenharmony_ci{ 161cabdff1aSopenharmony_ci int val = get_vlc2(gb, vlc->table, vlc->bits, 2); 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci return get_coeff_bits(gb, val); 164cabdff1aSopenharmony_ci} 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_cistatic int mss4_decode_dct(GetBitContext *gb, VLC *dc_vlc, VLC *ac_vlc, 167cabdff1aSopenharmony_ci int *block, int *dc_cache, 168cabdff1aSopenharmony_ci int bx, int by, uint16_t *quant_mat) 169cabdff1aSopenharmony_ci{ 170cabdff1aSopenharmony_ci int skip, val, pos = 1, zz_pos, dc; 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci memset(block, 0, sizeof(*block) * 64); 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci dc = get_coeff(gb, dc_vlc); 175cabdff1aSopenharmony_ci // DC prediction is the same as in MSS3 176cabdff1aSopenharmony_ci if (by) { 177cabdff1aSopenharmony_ci if (bx) { 178cabdff1aSopenharmony_ci int l, tl, t; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci l = dc_cache[LEFT]; 181cabdff1aSopenharmony_ci tl = dc_cache[TOP_LEFT]; 182cabdff1aSopenharmony_ci t = dc_cache[TOP]; 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci if (FFABS(t - tl) <= FFABS(l - tl)) 185cabdff1aSopenharmony_ci dc += l; 186cabdff1aSopenharmony_ci else 187cabdff1aSopenharmony_ci dc += t; 188cabdff1aSopenharmony_ci } else { 189cabdff1aSopenharmony_ci dc += dc_cache[TOP]; 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci } else if (bx) { 192cabdff1aSopenharmony_ci dc += dc_cache[LEFT]; 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci dc_cache[LEFT] = dc; 195cabdff1aSopenharmony_ci block[0] = dc * quant_mat[0]; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci while (pos < 64) { 198cabdff1aSopenharmony_ci val = get_vlc2(gb, ac_vlc->table, 9, 2); 199cabdff1aSopenharmony_ci if (!val) 200cabdff1aSopenharmony_ci return 0; 201cabdff1aSopenharmony_ci if (val == -1) 202cabdff1aSopenharmony_ci return -1; 203cabdff1aSopenharmony_ci if (val == 0xF0) { 204cabdff1aSopenharmony_ci pos += 16; 205cabdff1aSopenharmony_ci continue; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci skip = val >> 4; 208cabdff1aSopenharmony_ci val = get_coeff_bits(gb, val & 0xF); 209cabdff1aSopenharmony_ci pos += skip; 210cabdff1aSopenharmony_ci if (pos >= 64) 211cabdff1aSopenharmony_ci return -1; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci zz_pos = ff_zigzag_direct[pos]; 214cabdff1aSopenharmony_ci block[zz_pos] = val * quant_mat[zz_pos]; 215cabdff1aSopenharmony_ci pos++; 216cabdff1aSopenharmony_ci } 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci return pos == 64 ? 0 : -1; 219cabdff1aSopenharmony_ci} 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_cistatic int mss4_decode_dct_block(MSS4Context *c, GetBitContext *gb, 222cabdff1aSopenharmony_ci uint8_t *dst[3], int mb_x, int mb_y) 223cabdff1aSopenharmony_ci{ 224cabdff1aSopenharmony_ci int i, j, k, ret; 225cabdff1aSopenharmony_ci uint8_t *out = dst[0]; 226cabdff1aSopenharmony_ci 227cabdff1aSopenharmony_ci for (j = 0; j < 2; j++) { 228cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) { 229cabdff1aSopenharmony_ci int xpos = mb_x * 2 + i; 230cabdff1aSopenharmony_ci c->dc_cache[j][TOP_LEFT] = c->dc_cache[j][TOP]; 231cabdff1aSopenharmony_ci c->dc_cache[j][TOP] = c->prev_dc[0][mb_x * 2 + i]; 232cabdff1aSopenharmony_ci ret = mss4_decode_dct(gb, &dc_vlc[0], &ac_vlc[0], c->block, 233cabdff1aSopenharmony_ci c->dc_cache[j], 234cabdff1aSopenharmony_ci xpos, mb_y * 2 + j, c->quant_mat[0]); 235cabdff1aSopenharmony_ci if (ret) 236cabdff1aSopenharmony_ci return ret; 237cabdff1aSopenharmony_ci c->prev_dc[0][mb_x * 2 + i] = c->dc_cache[j][LEFT]; 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_ci ff_mss34_dct_put(out + xpos * 8, c->pic->linesize[0], 240cabdff1aSopenharmony_ci c->block); 241cabdff1aSopenharmony_ci } 242cabdff1aSopenharmony_ci out += 8 * c->pic->linesize[0]; 243cabdff1aSopenharmony_ci } 244cabdff1aSopenharmony_ci 245cabdff1aSopenharmony_ci for (i = 1; i < 3; i++) { 246cabdff1aSopenharmony_ci c->dc_cache[i + 1][TOP_LEFT] = c->dc_cache[i + 1][TOP]; 247cabdff1aSopenharmony_ci c->dc_cache[i + 1][TOP] = c->prev_dc[i][mb_x]; 248cabdff1aSopenharmony_ci ret = mss4_decode_dct(gb, &dc_vlc[1], &ac_vlc[1], 249cabdff1aSopenharmony_ci c->block, c->dc_cache[i + 1], mb_x, mb_y, 250cabdff1aSopenharmony_ci c->quant_mat[1]); 251cabdff1aSopenharmony_ci if (ret) 252cabdff1aSopenharmony_ci return ret; 253cabdff1aSopenharmony_ci c->prev_dc[i][mb_x] = c->dc_cache[i + 1][LEFT]; 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ci ff_mss34_dct_put(c->imgbuf[i], 8, c->block); 256cabdff1aSopenharmony_ci out = dst[i] + mb_x * 16; 257cabdff1aSopenharmony_ci // Since the DCT block is coded as YUV420 and the whole frame as YUV444, 258cabdff1aSopenharmony_ci // we need to scale chroma. 259cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) { 260cabdff1aSopenharmony_ci for (k = 0; k < 8; k++) 261cabdff1aSopenharmony_ci AV_WN16A(out + k * 2, c->imgbuf[i][k + (j & ~1) * 4] * 0x101); 262cabdff1aSopenharmony_ci out += c->pic->linesize[i]; 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci } 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci return 0; 267cabdff1aSopenharmony_ci} 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_cistatic void read_vec_pos(GetBitContext *gb, int *vec_pos, int *sel_flag, 270cabdff1aSopenharmony_ci int *sel_len, int *prev) 271cabdff1aSopenharmony_ci{ 272cabdff1aSopenharmony_ci int i, y_flag = 0; 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_ci for (i = 2; i >= 0; i--) { 275cabdff1aSopenharmony_ci if (!sel_flag[i]) { 276cabdff1aSopenharmony_ci vec_pos[i] = 0; 277cabdff1aSopenharmony_ci continue; 278cabdff1aSopenharmony_ci } 279cabdff1aSopenharmony_ci if ((!i && !y_flag) || get_bits1(gb)) { 280cabdff1aSopenharmony_ci if (sel_len[i] > 0) { 281cabdff1aSopenharmony_ci int pval = prev[i]; 282cabdff1aSopenharmony_ci vec_pos[i] = get_bits(gb, sel_len[i]); 283cabdff1aSopenharmony_ci if (vec_pos[i] >= pval) 284cabdff1aSopenharmony_ci vec_pos[i]++; 285cabdff1aSopenharmony_ci } else { 286cabdff1aSopenharmony_ci vec_pos[i] = !prev[i]; 287cabdff1aSopenharmony_ci } 288cabdff1aSopenharmony_ci y_flag = 1; 289cabdff1aSopenharmony_ci } else { 290cabdff1aSopenharmony_ci vec_pos[i] = prev[i]; 291cabdff1aSopenharmony_ci } 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci} 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_cistatic int get_value_cached(GetBitContext *gb, int vec_pos, uint8_t *vec, 296cabdff1aSopenharmony_ci int vec_size, int component, int shift, int *prev) 297cabdff1aSopenharmony_ci{ 298cabdff1aSopenharmony_ci if (vec_pos < vec_size) 299cabdff1aSopenharmony_ci return vec[vec_pos]; 300cabdff1aSopenharmony_ci if (!get_bits1(gb)) 301cabdff1aSopenharmony_ci return prev[component]; 302cabdff1aSopenharmony_ci prev[component] = get_bits(gb, 8 - shift) << shift; 303cabdff1aSopenharmony_ci return prev[component]; 304cabdff1aSopenharmony_ci} 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci#define MKVAL(vals) ((vals)[0] | ((vals)[1] << 3) | ((vals)[2] << 6)) 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci/* Image mode - the hardest to comprehend MSS4 coding mode. 309cabdff1aSopenharmony_ci * 310cabdff1aSopenharmony_ci * In this mode all three 16x16 blocks are coded together with a method 311cabdff1aSopenharmony_ci * remotely similar to the methods employed in MSS1-MSS3. 312cabdff1aSopenharmony_ci * The idea is that every component has a vector of 1-4 most common symbols 313cabdff1aSopenharmony_ci * and an escape mode for reading new value from the bitstream. Decoding 314cabdff1aSopenharmony_ci * consists of retrieving pixel values from the vector or reading new ones 315cabdff1aSopenharmony_ci * from the bitstream; depending on flags read from the bitstream, these vector 316cabdff1aSopenharmony_ci * positions can be updated or reused from the state of the previous line 317cabdff1aSopenharmony_ci * or previous pixel. 318cabdff1aSopenharmony_ci */ 319cabdff1aSopenharmony_cistatic int mss4_decode_image_block(MSS4Context *ctx, GetBitContext *gb, 320cabdff1aSopenharmony_ci uint8_t *picdst[3], int mb_x, int mb_y) 321cabdff1aSopenharmony_ci{ 322cabdff1aSopenharmony_ci uint8_t vec[3][4]; 323cabdff1aSopenharmony_ci int vec_len[3]; 324cabdff1aSopenharmony_ci int sel_len[3], sel_flag[3]; 325cabdff1aSopenharmony_ci int i, j, k, mode, split; 326cabdff1aSopenharmony_ci int prev_vec1 = 0, prev_split = 0; 327cabdff1aSopenharmony_ci int vals[3] = { 0 }; 328cabdff1aSopenharmony_ci int prev_pix[3] = { 0 }; 329cabdff1aSopenharmony_ci int prev_mode[16] = { 0 }; 330cabdff1aSopenharmony_ci uint8_t *dst[3]; 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci const int val_shift = ctx->quality == 100 ? 0 : 2; 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) 335cabdff1aSopenharmony_ci dst[i] = ctx->imgbuf[i]; 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 338cabdff1aSopenharmony_ci vec_len[i] = vec_len_syms[!!i][get_unary(gb, 0, 3)]; 339cabdff1aSopenharmony_ci for (j = 0; j < vec_len[i]; j++) { 340cabdff1aSopenharmony_ci vec[i][j] = get_coeff(gb, &vec_entry_vlc[!!i]); 341cabdff1aSopenharmony_ci vec[i][j] += ctx->prev_vec[i][j]; 342cabdff1aSopenharmony_ci ctx->prev_vec[i][j] = vec[i][j]; 343cabdff1aSopenharmony_ci } 344cabdff1aSopenharmony_ci sel_flag[i] = vec_len[i] > 1; 345cabdff1aSopenharmony_ci sel_len[i] = vec_len[i] > 2 ? vec_len[i] - 2 : 0; 346cabdff1aSopenharmony_ci } 347cabdff1aSopenharmony_ci 348cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) { 349cabdff1aSopenharmony_ci if (get_bits1(gb)) { 350cabdff1aSopenharmony_ci split = 0; 351cabdff1aSopenharmony_ci if (get_bits1(gb)) { 352cabdff1aSopenharmony_ci prev_mode[0] = 0; 353cabdff1aSopenharmony_ci vals[0] = vals[1] = vals[2] = 0; 354cabdff1aSopenharmony_ci mode = 2; 355cabdff1aSopenharmony_ci } else { 356cabdff1aSopenharmony_ci mode = get_bits1(gb); 357cabdff1aSopenharmony_ci if (mode) 358cabdff1aSopenharmony_ci split = get_bits(gb, 4); 359cabdff1aSopenharmony_ci } 360cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) { 361cabdff1aSopenharmony_ci if (mode <= 1) { 362cabdff1aSopenharmony_ci vals[0] = prev_mode[i] & 7; 363cabdff1aSopenharmony_ci vals[1] = (prev_mode[i] >> 3) & 7; 364cabdff1aSopenharmony_ci vals[2] = prev_mode[i] >> 6; 365cabdff1aSopenharmony_ci if (mode == 1 && i == split) { 366cabdff1aSopenharmony_ci read_vec_pos(gb, vals, sel_flag, sel_len, vals); 367cabdff1aSopenharmony_ci } 368cabdff1aSopenharmony_ci } else if (mode == 2) { 369cabdff1aSopenharmony_ci if (get_bits1(gb)) 370cabdff1aSopenharmony_ci read_vec_pos(gb, vals, sel_flag, sel_len, vals); 371cabdff1aSopenharmony_ci } 372cabdff1aSopenharmony_ci for (k = 0; k < 3; k++) 373cabdff1aSopenharmony_ci *dst[k]++ = get_value_cached(gb, vals[k], vec[k], 374cabdff1aSopenharmony_ci vec_len[k], k, 375cabdff1aSopenharmony_ci val_shift, prev_pix); 376cabdff1aSopenharmony_ci prev_mode[i] = MKVAL(vals); 377cabdff1aSopenharmony_ci } 378cabdff1aSopenharmony_ci } else { 379cabdff1aSopenharmony_ci if (get_bits1(gb)) { 380cabdff1aSopenharmony_ci split = get_bits(gb, 4); 381cabdff1aSopenharmony_ci if (split >= prev_split) 382cabdff1aSopenharmony_ci split++; 383cabdff1aSopenharmony_ci prev_split = split; 384cabdff1aSopenharmony_ci } else { 385cabdff1aSopenharmony_ci split = prev_split; 386cabdff1aSopenharmony_ci } 387cabdff1aSopenharmony_ci if (split) { 388cabdff1aSopenharmony_ci vals[0] = prev_mode[0] & 7; 389cabdff1aSopenharmony_ci vals[1] = (prev_mode[0] >> 3) & 7; 390cabdff1aSopenharmony_ci vals[2] = prev_mode[0] >> 6; 391cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 392cabdff1aSopenharmony_ci for (k = 0; k < split; k++) { 393cabdff1aSopenharmony_ci *dst[i]++ = get_value_cached(gb, vals[i], vec[i], 394cabdff1aSopenharmony_ci vec_len[i], i, val_shift, 395cabdff1aSopenharmony_ci prev_pix); 396cabdff1aSopenharmony_ci prev_mode[k] = MKVAL(vals); 397cabdff1aSopenharmony_ci } 398cabdff1aSopenharmony_ci } 399cabdff1aSopenharmony_ci } 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci if (split != 16) { 402cabdff1aSopenharmony_ci vals[0] = prev_vec1 & 7; 403cabdff1aSopenharmony_ci vals[1] = (prev_vec1 >> 3) & 7; 404cabdff1aSopenharmony_ci vals[2] = prev_vec1 >> 6; 405cabdff1aSopenharmony_ci if (get_bits1(gb)) { 406cabdff1aSopenharmony_ci read_vec_pos(gb, vals, sel_flag, sel_len, vals); 407cabdff1aSopenharmony_ci prev_vec1 = MKVAL(vals); 408cabdff1aSopenharmony_ci } 409cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 410cabdff1aSopenharmony_ci for (k = 0; k < 16 - split; k++) { 411cabdff1aSopenharmony_ci *dst[i]++ = get_value_cached(gb, vals[i], vec[i], 412cabdff1aSopenharmony_ci vec_len[i], i, val_shift, 413cabdff1aSopenharmony_ci prev_pix); 414cabdff1aSopenharmony_ci prev_mode[split + k] = MKVAL(vals); 415cabdff1aSopenharmony_ci } 416cabdff1aSopenharmony_ci } 417cabdff1aSopenharmony_ci } 418cabdff1aSopenharmony_ci } 419cabdff1aSopenharmony_ci } 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) 422cabdff1aSopenharmony_ci for (j = 0; j < 16; j++) 423cabdff1aSopenharmony_ci memcpy(picdst[i] + mb_x * 16 + j * ctx->pic->linesize[i], 424cabdff1aSopenharmony_ci ctx->imgbuf[i] + j * 16, 16); 425cabdff1aSopenharmony_ci 426cabdff1aSopenharmony_ci return 0; 427cabdff1aSopenharmony_ci} 428cabdff1aSopenharmony_ci 429cabdff1aSopenharmony_cistatic inline void mss4_update_dc_cache(MSS4Context *c, int mb_x) 430cabdff1aSopenharmony_ci{ 431cabdff1aSopenharmony_ci int i; 432cabdff1aSopenharmony_ci 433cabdff1aSopenharmony_ci c->dc_cache[0][TOP] = c->prev_dc[0][mb_x * 2 + 1]; 434cabdff1aSopenharmony_ci c->dc_cache[0][LEFT] = 0; 435cabdff1aSopenharmony_ci c->dc_cache[1][TOP] = 0; 436cabdff1aSopenharmony_ci c->dc_cache[1][LEFT] = 0; 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) 439cabdff1aSopenharmony_ci c->prev_dc[0][mb_x * 2 + i] = 0; 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ci for (i = 1; i < 3; i++) { 442cabdff1aSopenharmony_ci c->dc_cache[i + 1][TOP] = c->prev_dc[i][mb_x]; 443cabdff1aSopenharmony_ci c->dc_cache[i + 1][LEFT] = 0; 444cabdff1aSopenharmony_ci c->prev_dc[i][mb_x] = 0; 445cabdff1aSopenharmony_ci } 446cabdff1aSopenharmony_ci} 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_cistatic int mss4_decode_frame(AVCodecContext *avctx, AVFrame *rframe, 449cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 450cabdff1aSopenharmony_ci{ 451cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 452cabdff1aSopenharmony_ci int buf_size = avpkt->size; 453cabdff1aSopenharmony_ci MSS4Context *c = avctx->priv_data; 454cabdff1aSopenharmony_ci GetBitContext gb; 455cabdff1aSopenharmony_ci GetByteContext bc; 456cabdff1aSopenharmony_ci uint8_t *dst[3]; 457cabdff1aSopenharmony_ci int width, height, quality, frame_type; 458cabdff1aSopenharmony_ci int x, y, i, mb_width, mb_height, blk_type; 459cabdff1aSopenharmony_ci int ret; 460cabdff1aSopenharmony_ci 461cabdff1aSopenharmony_ci if (buf_size < HEADER_SIZE) { 462cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 463cabdff1aSopenharmony_ci "Frame should have at least %d bytes, got %d instead\n", 464cabdff1aSopenharmony_ci HEADER_SIZE, buf_size); 465cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 466cabdff1aSopenharmony_ci } 467cabdff1aSopenharmony_ci 468cabdff1aSopenharmony_ci bytestream2_init(&bc, buf, buf_size); 469cabdff1aSopenharmony_ci width = bytestream2_get_be16(&bc); 470cabdff1aSopenharmony_ci height = bytestream2_get_be16(&bc); 471cabdff1aSopenharmony_ci bytestream2_skip(&bc, 2); 472cabdff1aSopenharmony_ci quality = bytestream2_get_byte(&bc); 473cabdff1aSopenharmony_ci frame_type = bytestream2_get_byte(&bc); 474cabdff1aSopenharmony_ci 475cabdff1aSopenharmony_ci if (width > avctx->width || 476cabdff1aSopenharmony_ci height != avctx->height) { 477cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid frame dimensions %dx%d\n", 478cabdff1aSopenharmony_ci width, height); 479cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 480cabdff1aSopenharmony_ci } 481cabdff1aSopenharmony_ci if (av_image_check_size2(width, height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0) 482cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 483cabdff1aSopenharmony_ci 484cabdff1aSopenharmony_ci if (quality < 1 || quality > 100) { 485cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid quality setting %d\n", quality); 486cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 487cabdff1aSopenharmony_ci } 488cabdff1aSopenharmony_ci if ((frame_type & ~3) || frame_type == 3) { 489cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid frame type %d\n", frame_type); 490cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 491cabdff1aSopenharmony_ci } 492cabdff1aSopenharmony_ci 493cabdff1aSopenharmony_ci if (frame_type != SKIP_FRAME && !bytestream2_get_bytes_left(&bc)) { 494cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 495cabdff1aSopenharmony_ci "Empty frame found but it is not a skip frame.\n"); 496cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 497cabdff1aSopenharmony_ci } 498cabdff1aSopenharmony_ci mb_width = FFALIGN(width, 16) >> 4; 499cabdff1aSopenharmony_ci mb_height = FFALIGN(height, 16) >> 4; 500cabdff1aSopenharmony_ci 501cabdff1aSopenharmony_ci if (frame_type != SKIP_FRAME && 8*buf_size < 8*HEADER_SIZE + mb_width*mb_height) 502cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 503cabdff1aSopenharmony_ci 504cabdff1aSopenharmony_ci if ((ret = ff_reget_buffer(avctx, c->pic, 0)) < 0) 505cabdff1aSopenharmony_ci return ret; 506cabdff1aSopenharmony_ci c->pic->key_frame = (frame_type == INTRA_FRAME); 507cabdff1aSopenharmony_ci c->pic->pict_type = (frame_type == INTRA_FRAME) ? AV_PICTURE_TYPE_I 508cabdff1aSopenharmony_ci : AV_PICTURE_TYPE_P; 509cabdff1aSopenharmony_ci if (frame_type == SKIP_FRAME) { 510cabdff1aSopenharmony_ci *got_frame = 1; 511cabdff1aSopenharmony_ci if ((ret = av_frame_ref(rframe, c->pic)) < 0) 512cabdff1aSopenharmony_ci return ret; 513cabdff1aSopenharmony_ci 514cabdff1aSopenharmony_ci return buf_size; 515cabdff1aSopenharmony_ci } 516cabdff1aSopenharmony_ci 517cabdff1aSopenharmony_ci if (c->quality != quality) { 518cabdff1aSopenharmony_ci c->quality = quality; 519cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) 520cabdff1aSopenharmony_ci ff_mss34_gen_quant_mat(c->quant_mat[i], quality, !i); 521cabdff1aSopenharmony_ci } 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci if ((ret = init_get_bits8(&gb, buf + HEADER_SIZE, buf_size - HEADER_SIZE)) < 0) 524cabdff1aSopenharmony_ci return ret; 525cabdff1aSopenharmony_ci dst[0] = c->pic->data[0]; 526cabdff1aSopenharmony_ci dst[1] = c->pic->data[1]; 527cabdff1aSopenharmony_ci dst[2] = c->pic->data[2]; 528cabdff1aSopenharmony_ci 529cabdff1aSopenharmony_ci memset(c->prev_vec, 0, sizeof(c->prev_vec)); 530cabdff1aSopenharmony_ci for (y = 0; y < mb_height; y++) { 531cabdff1aSopenharmony_ci memset(c->dc_cache, 0, sizeof(c->dc_cache)); 532cabdff1aSopenharmony_ci for (x = 0; x < mb_width; x++) { 533cabdff1aSopenharmony_ci blk_type = decode012(&gb); 534cabdff1aSopenharmony_ci switch (blk_type) { 535cabdff1aSopenharmony_ci case DCT_BLOCK: 536cabdff1aSopenharmony_ci if (mss4_decode_dct_block(c, &gb, dst, x, y) < 0) { 537cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 538cabdff1aSopenharmony_ci "Error decoding DCT block %d,%d\n", 539cabdff1aSopenharmony_ci x, y); 540cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 541cabdff1aSopenharmony_ci } 542cabdff1aSopenharmony_ci break; 543cabdff1aSopenharmony_ci case IMAGE_BLOCK: 544cabdff1aSopenharmony_ci if (mss4_decode_image_block(c, &gb, dst, x, y) < 0) { 545cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 546cabdff1aSopenharmony_ci "Error decoding VQ block %d,%d\n", 547cabdff1aSopenharmony_ci x, y); 548cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 549cabdff1aSopenharmony_ci } 550cabdff1aSopenharmony_ci break; 551cabdff1aSopenharmony_ci case SKIP_BLOCK: 552cabdff1aSopenharmony_ci if (frame_type == INTRA_FRAME) { 553cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Skip block in intra frame\n"); 554cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 555cabdff1aSopenharmony_ci } 556cabdff1aSopenharmony_ci break; 557cabdff1aSopenharmony_ci } 558cabdff1aSopenharmony_ci if (blk_type != DCT_BLOCK) 559cabdff1aSopenharmony_ci mss4_update_dc_cache(c, x); 560cabdff1aSopenharmony_ci } 561cabdff1aSopenharmony_ci dst[0] += c->pic->linesize[0] * 16; 562cabdff1aSopenharmony_ci dst[1] += c->pic->linesize[1] * 16; 563cabdff1aSopenharmony_ci dst[2] += c->pic->linesize[2] * 16; 564cabdff1aSopenharmony_ci } 565cabdff1aSopenharmony_ci 566cabdff1aSopenharmony_ci if ((ret = av_frame_ref(rframe, c->pic)) < 0) 567cabdff1aSopenharmony_ci return ret; 568cabdff1aSopenharmony_ci 569cabdff1aSopenharmony_ci *got_frame = 1; 570cabdff1aSopenharmony_ci 571cabdff1aSopenharmony_ci return buf_size; 572cabdff1aSopenharmony_ci} 573cabdff1aSopenharmony_ci 574cabdff1aSopenharmony_cistatic av_cold int mss4_decode_end(AVCodecContext *avctx) 575cabdff1aSopenharmony_ci{ 576cabdff1aSopenharmony_ci MSS4Context * const c = avctx->priv_data; 577cabdff1aSopenharmony_ci int i; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci av_frame_free(&c->pic); 580cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) 581cabdff1aSopenharmony_ci av_freep(&c->prev_dc[i]); 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ci return 0; 584cabdff1aSopenharmony_ci} 585cabdff1aSopenharmony_ci 586cabdff1aSopenharmony_cistatic av_cold int mss4_decode_init(AVCodecContext *avctx) 587cabdff1aSopenharmony_ci{ 588cabdff1aSopenharmony_ci static AVOnce init_static_once = AV_ONCE_INIT; 589cabdff1aSopenharmony_ci MSS4Context * const c = avctx->priv_data; 590cabdff1aSopenharmony_ci int i; 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 593cabdff1aSopenharmony_ci c->dc_stride[i] = FFALIGN(avctx->width, 16) >> (2 + !!i); 594cabdff1aSopenharmony_ci c->prev_dc[i] = av_malloc_array(c->dc_stride[i], sizeof(**c->prev_dc)); 595cabdff1aSopenharmony_ci if (!c->prev_dc[i]) { 596cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Cannot allocate buffer\n"); 597cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 598cabdff1aSopenharmony_ci } 599cabdff1aSopenharmony_ci } 600cabdff1aSopenharmony_ci 601cabdff1aSopenharmony_ci c->pic = av_frame_alloc(); 602cabdff1aSopenharmony_ci if (!c->pic) 603cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 604cabdff1aSopenharmony_ci 605cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV444P; 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci ff_thread_once(&init_static_once, mss4_init_vlcs); 608cabdff1aSopenharmony_ci 609cabdff1aSopenharmony_ci return 0; 610cabdff1aSopenharmony_ci} 611cabdff1aSopenharmony_ci 612cabdff1aSopenharmony_ciconst FFCodec ff_mts2_decoder = { 613cabdff1aSopenharmony_ci .p.name = "mts2", 614cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("MS Expression Encoder Screen"), 615cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 616cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_MTS2, 617cabdff1aSopenharmony_ci .priv_data_size = sizeof(MSS4Context), 618cabdff1aSopenharmony_ci .init = mss4_decode_init, 619cabdff1aSopenharmony_ci .close = mss4_decode_end, 620cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(mss4_decode_frame), 621cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1, 622cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, 623cabdff1aSopenharmony_ci}; 624