1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * RV30/40 decoder common data 3cabdff1aSopenharmony_ci * Copyright (c) 2007 Mike Melanson, 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 * RV30/40 decoder common data 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 28cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 29cabdff1aSopenharmony_ci#include "libavutil/internal.h" 30cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h" 31cabdff1aSopenharmony_ci#include "libavutil/thread.h" 32cabdff1aSopenharmony_ci#include "libavutil/video_enc_params.h" 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci#include "avcodec.h" 35cabdff1aSopenharmony_ci#include "error_resilience.h" 36cabdff1aSopenharmony_ci#include "mpegutils.h" 37cabdff1aSopenharmony_ci#include "mpegvideo.h" 38cabdff1aSopenharmony_ci#include "mpegvideodec.h" 39cabdff1aSopenharmony_ci#include "golomb.h" 40cabdff1aSopenharmony_ci#include "internal.h" 41cabdff1aSopenharmony_ci#include "mathops.h" 42cabdff1aSopenharmony_ci#include "mpeg_er.h" 43cabdff1aSopenharmony_ci#include "qpeldsp.h" 44cabdff1aSopenharmony_ci#include "rectangle.h" 45cabdff1aSopenharmony_ci#include "thread.h" 46cabdff1aSopenharmony_ci#include "threadframe.h" 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci#include "rv34vlc.h" 49cabdff1aSopenharmony_ci#include "rv34data.h" 50cabdff1aSopenharmony_ci#include "rv34.h" 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_cistatic inline void ZERO8x2(void* dst, int stride) 53cabdff1aSopenharmony_ci{ 54cabdff1aSopenharmony_ci fill_rectangle(dst, 1, 2, stride, 0, 4); 55cabdff1aSopenharmony_ci fill_rectangle(((uint8_t*)(dst))+4, 1, 2, stride, 0, 4); 56cabdff1aSopenharmony_ci} 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci/** translation of RV30/40 macroblock types to lavc ones */ 59cabdff1aSopenharmony_cistatic const int rv34_mb_type_to_lavc[12] = { 60cabdff1aSopenharmony_ci MB_TYPE_INTRA, 61cabdff1aSopenharmony_ci MB_TYPE_INTRA16x16 | MB_TYPE_SEPARATE_DC, 62cabdff1aSopenharmony_ci MB_TYPE_16x16 | MB_TYPE_L0, 63cabdff1aSopenharmony_ci MB_TYPE_8x8 | MB_TYPE_L0, 64cabdff1aSopenharmony_ci MB_TYPE_16x16 | MB_TYPE_L0, 65cabdff1aSopenharmony_ci MB_TYPE_16x16 | MB_TYPE_L1, 66cabdff1aSopenharmony_ci MB_TYPE_SKIP, 67cabdff1aSopenharmony_ci MB_TYPE_DIRECT2 | MB_TYPE_16x16, 68cabdff1aSopenharmony_ci MB_TYPE_16x8 | MB_TYPE_L0, 69cabdff1aSopenharmony_ci MB_TYPE_8x16 | MB_TYPE_L0, 70cabdff1aSopenharmony_ci MB_TYPE_16x16 | MB_TYPE_L0L1, 71cabdff1aSopenharmony_ci MB_TYPE_16x16 | MB_TYPE_L0 | MB_TYPE_SEPARATE_DC 72cabdff1aSopenharmony_ci}; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_cistatic RV34VLC intra_vlcs[NUM_INTRA_TABLES], inter_vlcs[NUM_INTER_TABLES]; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_cistatic int rv34_decode_mv(RV34DecContext *r, int block_type); 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci/** 80cabdff1aSopenharmony_ci * @name RV30/40 VLC generating functions 81cabdff1aSopenharmony_ci * @{ 82cabdff1aSopenharmony_ci */ 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_cistatic VLCElem table_data[117592]; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci/** 87cabdff1aSopenharmony_ci * Generate VLC from codeword lengths. 88cabdff1aSopenharmony_ci * @param bits codeword lengths (zeroes are accepted) 89cabdff1aSopenharmony_ci * @param size length of input data 90cabdff1aSopenharmony_ci * @param vlc output VLC 91cabdff1aSopenharmony_ci * @param insyms symbols for input codes (NULL for default ones) 92cabdff1aSopenharmony_ci * @param num VLC table number (for static initialization) 93cabdff1aSopenharmony_ci */ 94cabdff1aSopenharmony_cistatic void rv34_gen_vlc(const uint8_t *bits, int size, VLC *vlc, const uint8_t *syms, 95cabdff1aSopenharmony_ci int *offset) 96cabdff1aSopenharmony_ci{ 97cabdff1aSopenharmony_ci int counts[17] = {0}, codes[17]; 98cabdff1aSopenharmony_ci uint16_t cw[MAX_VLC_SIZE]; 99cabdff1aSopenharmony_ci int maxbits; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci for (int i = 0; i < size; i++) 102cabdff1aSopenharmony_ci counts[bits[i]]++; 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci /* bits[0] is zero for some tables, i.e. syms actually starts at 1. 105cabdff1aSopenharmony_ci * So we reset it here. The code assigned to this element is 0x00. */ 106cabdff1aSopenharmony_ci codes[0] = counts[0] = 0; 107cabdff1aSopenharmony_ci for (int i = 0; i < 16; i++) { 108cabdff1aSopenharmony_ci codes[i+1] = (codes[i] + counts[i]) << 1; 109cabdff1aSopenharmony_ci if (counts[i]) 110cabdff1aSopenharmony_ci maxbits = i; 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci for (int i = 0; i < size; i++) 113cabdff1aSopenharmony_ci cw[i] = codes[bits[i]]++; 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci vlc->table = &table_data[*offset]; 116cabdff1aSopenharmony_ci vlc->table_allocated = FF_ARRAY_ELEMS(table_data) - *offset; 117cabdff1aSopenharmony_ci ff_init_vlc_sparse(vlc, FFMIN(maxbits, 9), size, 118cabdff1aSopenharmony_ci bits, 1, 1, 119cabdff1aSopenharmony_ci cw, 2, 2, 120cabdff1aSopenharmony_ci syms, !!syms, !!syms, INIT_VLC_STATIC_OVERLONG); 121cabdff1aSopenharmony_ci *offset += vlc->table_size; 122cabdff1aSopenharmony_ci} 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci/** 125cabdff1aSopenharmony_ci * Initialize all tables. 126cabdff1aSopenharmony_ci */ 127cabdff1aSopenharmony_cistatic av_cold void rv34_init_tables(void) 128cabdff1aSopenharmony_ci{ 129cabdff1aSopenharmony_ci int i, j, k, offset = 0; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci for(i = 0; i < NUM_INTRA_TABLES; i++){ 132cabdff1aSopenharmony_ci for(j = 0; j < 2; j++){ 133cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_intra_cbppat [i][j], CBPPAT_VLC_SIZE, 134cabdff1aSopenharmony_ci &intra_vlcs[i].cbppattern[j], NULL, &offset); 135cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_intra_secondpat[i][j], OTHERBLK_VLC_SIZE, 136cabdff1aSopenharmony_ci &intra_vlcs[i].second_pattern[j], NULL, &offset); 137cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_intra_thirdpat [i][j], OTHERBLK_VLC_SIZE, 138cabdff1aSopenharmony_ci &intra_vlcs[i].third_pattern[j], NULL, &offset); 139cabdff1aSopenharmony_ci for(k = 0; k < 4; k++){ 140cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_intra_cbp[i][j+k*2], CBP_VLC_SIZE, 141cabdff1aSopenharmony_ci &intra_vlcs[i].cbp[j][k], rv34_cbp_code, &offset); 142cabdff1aSopenharmony_ci } 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci for(j = 0; j < 4; j++){ 145cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_intra_firstpat[i][j], FIRSTBLK_VLC_SIZE, 146cabdff1aSopenharmony_ci &intra_vlcs[i].first_pattern[j], NULL, &offset); 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_intra_coeff[i], COEFF_VLC_SIZE, 149cabdff1aSopenharmony_ci &intra_vlcs[i].coefficient, NULL, &offset); 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci for(i = 0; i < NUM_INTER_TABLES; i++){ 153cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_inter_cbppat[i], CBPPAT_VLC_SIZE, 154cabdff1aSopenharmony_ci &inter_vlcs[i].cbppattern[0], NULL, &offset); 155cabdff1aSopenharmony_ci for(j = 0; j < 4; j++){ 156cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_inter_cbp[i][j], CBP_VLC_SIZE, 157cabdff1aSopenharmony_ci &inter_vlcs[i].cbp[0][j], rv34_cbp_code, &offset); 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci for(j = 0; j < 2; j++){ 160cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_inter_firstpat [i][j], FIRSTBLK_VLC_SIZE, 161cabdff1aSopenharmony_ci &inter_vlcs[i].first_pattern[j], NULL, &offset); 162cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_inter_secondpat[i][j], OTHERBLK_VLC_SIZE, 163cabdff1aSopenharmony_ci &inter_vlcs[i].second_pattern[j], NULL, &offset); 164cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_table_inter_thirdpat [i][j], OTHERBLK_VLC_SIZE, 165cabdff1aSopenharmony_ci &inter_vlcs[i].third_pattern[j], NULL, &offset); 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci rv34_gen_vlc(rv34_inter_coeff[i], COEFF_VLC_SIZE, 168cabdff1aSopenharmony_ci &inter_vlcs[i].coefficient, NULL, &offset); 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci} 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci/** @} */ // vlc group 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci/** 175cabdff1aSopenharmony_ci * @name RV30/40 4x4 block decoding functions 176cabdff1aSopenharmony_ci * @{ 177cabdff1aSopenharmony_ci */ 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_ci/** 180cabdff1aSopenharmony_ci * Decode coded block pattern. 181cabdff1aSopenharmony_ci */ 182cabdff1aSopenharmony_cistatic int rv34_decode_cbp(GetBitContext *gb, RV34VLC *vlc, int table) 183cabdff1aSopenharmony_ci{ 184cabdff1aSopenharmony_ci int pattern, code, cbp=0; 185cabdff1aSopenharmony_ci int ones; 186cabdff1aSopenharmony_ci static const int cbp_masks[3] = {0x100000, 0x010000, 0x110000}; 187cabdff1aSopenharmony_ci static const int shifts[4] = { 0, 2, 8, 10 }; 188cabdff1aSopenharmony_ci const int *curshift = shifts; 189cabdff1aSopenharmony_ci int i, t, mask; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci code = get_vlc2(gb, vlc->cbppattern[table].table, 9, 2); 192cabdff1aSopenharmony_ci pattern = code & 0xF; 193cabdff1aSopenharmony_ci code >>= 4; 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci ones = rv34_count_ones[pattern]; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci for(mask = 8; mask; mask >>= 1, curshift++){ 198cabdff1aSopenharmony_ci if(pattern & mask) 199cabdff1aSopenharmony_ci cbp |= get_vlc2(gb, vlc->cbp[table][ones].table, vlc->cbp[table][ones].bits, 1) << curshift[0]; 200cabdff1aSopenharmony_ci } 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci for(i = 0; i < 4; i++){ 203cabdff1aSopenharmony_ci t = (modulo_three_table[code] >> (6 - 2*i)) & 3; 204cabdff1aSopenharmony_ci if(t == 1) 205cabdff1aSopenharmony_ci cbp |= cbp_masks[get_bits1(gb)] << i; 206cabdff1aSopenharmony_ci if(t == 2) 207cabdff1aSopenharmony_ci cbp |= cbp_masks[2] << i; 208cabdff1aSopenharmony_ci } 209cabdff1aSopenharmony_ci return cbp; 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci/** 213cabdff1aSopenharmony_ci * Get one coefficient value from the bitstream and store it. 214cabdff1aSopenharmony_ci */ 215cabdff1aSopenharmony_cistatic inline void decode_coeff(int16_t *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q) 216cabdff1aSopenharmony_ci{ 217cabdff1aSopenharmony_ci if(coef){ 218cabdff1aSopenharmony_ci if(coef == esc){ 219cabdff1aSopenharmony_ci coef = get_vlc2(gb, vlc->table, 9, 2); 220cabdff1aSopenharmony_ci if(coef > 23){ 221cabdff1aSopenharmony_ci coef -= 23; 222cabdff1aSopenharmony_ci coef = 22 + ((1 << coef) | get_bits(gb, coef)); 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci coef += esc; 225cabdff1aSopenharmony_ci } 226cabdff1aSopenharmony_ci if(get_bits1(gb)) 227cabdff1aSopenharmony_ci coef = -coef; 228cabdff1aSopenharmony_ci *dst = (coef*q + 8) >> 4; 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci} 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci/** 233cabdff1aSopenharmony_ci * Decode 2x2 subblock of coefficients. 234cabdff1aSopenharmony_ci */ 235cabdff1aSopenharmony_cistatic inline void decode_subblock(int16_t *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc, int q) 236cabdff1aSopenharmony_ci{ 237cabdff1aSopenharmony_ci int flags = modulo_three_table[code]; 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_ci decode_coeff( dst+0*4+0, (flags >> 6) , 3, gb, vlc, q); 240cabdff1aSopenharmony_ci if(is_block2){ 241cabdff1aSopenharmony_ci decode_coeff(dst+1*4+0, (flags >> 4) & 3, 2, gb, vlc, q); 242cabdff1aSopenharmony_ci decode_coeff(dst+0*4+1, (flags >> 2) & 3, 2, gb, vlc, q); 243cabdff1aSopenharmony_ci }else{ 244cabdff1aSopenharmony_ci decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q); 245cabdff1aSopenharmony_ci decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q); 246cabdff1aSopenharmony_ci } 247cabdff1aSopenharmony_ci decode_coeff( dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q); 248cabdff1aSopenharmony_ci} 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_ci/** 251cabdff1aSopenharmony_ci * Decode a single coefficient. 252cabdff1aSopenharmony_ci */ 253cabdff1aSopenharmony_cistatic inline void decode_subblock1(int16_t *dst, int code, GetBitContext *gb, VLC *vlc, int q) 254cabdff1aSopenharmony_ci{ 255cabdff1aSopenharmony_ci int coeff = modulo_three_table[code] >> 6; 256cabdff1aSopenharmony_ci decode_coeff(dst, coeff, 3, gb, vlc, q); 257cabdff1aSopenharmony_ci} 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_cistatic inline void decode_subblock3(int16_t *dst, int code, GetBitContext *gb, VLC *vlc, 260cabdff1aSopenharmony_ci int q_dc, int q_ac1, int q_ac2) 261cabdff1aSopenharmony_ci{ 262cabdff1aSopenharmony_ci int flags = modulo_three_table[code]; 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci decode_coeff(dst+0*4+0, (flags >> 6) , 3, gb, vlc, q_dc); 265cabdff1aSopenharmony_ci decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q_ac1); 266cabdff1aSopenharmony_ci decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q_ac1); 267cabdff1aSopenharmony_ci decode_coeff(dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q_ac2); 268cabdff1aSopenharmony_ci} 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci/** 271cabdff1aSopenharmony_ci * Decode coefficients for 4x4 block. 272cabdff1aSopenharmony_ci * 273cabdff1aSopenharmony_ci * This is done by filling 2x2 subblocks with decoded coefficients 274cabdff1aSopenharmony_ci * in this order (the same for subblocks and subblock coefficients): 275cabdff1aSopenharmony_ci * o--o 276cabdff1aSopenharmony_ci * / 277cabdff1aSopenharmony_ci * / 278cabdff1aSopenharmony_ci * o--o 279cabdff1aSopenharmony_ci */ 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_cistatic int rv34_decode_block(int16_t *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc, int q_dc, int q_ac1, int q_ac2) 282cabdff1aSopenharmony_ci{ 283cabdff1aSopenharmony_ci int code, pattern, has_ac = 1; 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_ci code = get_vlc2(gb, rvlc->first_pattern[fc].table, 9, 2); 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci pattern = code & 0x7; 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci code >>= 3; 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci if (modulo_three_table[code] & 0x3F) { 292cabdff1aSopenharmony_ci decode_subblock3(dst, code, gb, &rvlc->coefficient, q_dc, q_ac1, q_ac2); 293cabdff1aSopenharmony_ci } else { 294cabdff1aSopenharmony_ci decode_subblock1(dst, code, gb, &rvlc->coefficient, q_dc); 295cabdff1aSopenharmony_ci if (!pattern) 296cabdff1aSopenharmony_ci return 0; 297cabdff1aSopenharmony_ci has_ac = 0; 298cabdff1aSopenharmony_ci } 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci if(pattern & 4){ 301cabdff1aSopenharmony_ci code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); 302cabdff1aSopenharmony_ci decode_subblock(dst + 4*0+2, code, 0, gb, &rvlc->coefficient, q_ac2); 303cabdff1aSopenharmony_ci } 304cabdff1aSopenharmony_ci if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block 305cabdff1aSopenharmony_ci code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); 306cabdff1aSopenharmony_ci decode_subblock(dst + 4*2+0, code, 1, gb, &rvlc->coefficient, q_ac2); 307cabdff1aSopenharmony_ci } 308cabdff1aSopenharmony_ci if(pattern & 1){ 309cabdff1aSopenharmony_ci code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2); 310cabdff1aSopenharmony_ci decode_subblock(dst + 4*2+2, code, 0, gb, &rvlc->coefficient, q_ac2); 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci return has_ac | pattern; 313cabdff1aSopenharmony_ci} 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci/** 316cabdff1aSopenharmony_ci * @name RV30/40 bitstream parsing 317cabdff1aSopenharmony_ci * @{ 318cabdff1aSopenharmony_ci */ 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci/** 321cabdff1aSopenharmony_ci * Decode starting slice position. 322cabdff1aSopenharmony_ci * @todo Maybe replace with ff_h263_decode_mba() ? 323cabdff1aSopenharmony_ci */ 324cabdff1aSopenharmony_ciint ff_rv34_get_start_offset(GetBitContext *gb, int mb_size) 325cabdff1aSopenharmony_ci{ 326cabdff1aSopenharmony_ci int i; 327cabdff1aSopenharmony_ci for(i = 0; i < 5; i++) 328cabdff1aSopenharmony_ci if(rv34_mb_max_sizes[i] >= mb_size - 1) 329cabdff1aSopenharmony_ci break; 330cabdff1aSopenharmony_ci return rv34_mb_bits_sizes[i]; 331cabdff1aSopenharmony_ci} 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci/** 334cabdff1aSopenharmony_ci * Select VLC set for decoding from current quantizer, modifier and frame type. 335cabdff1aSopenharmony_ci */ 336cabdff1aSopenharmony_cistatic inline RV34VLC* choose_vlc_set(int quant, int mod, int type) 337cabdff1aSopenharmony_ci{ 338cabdff1aSopenharmony_ci if(mod == 2 && quant < 19) quant += 10; 339cabdff1aSopenharmony_ci else if(mod && quant < 26) quant += 5; 340cabdff1aSopenharmony_ci av_assert2(quant >= 0 && quant < 32); 341cabdff1aSopenharmony_ci return type ? &inter_vlcs[rv34_quant_to_vlc_set[1][quant]] 342cabdff1aSopenharmony_ci : &intra_vlcs[rv34_quant_to_vlc_set[0][quant]]; 343cabdff1aSopenharmony_ci} 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_ci/** 346cabdff1aSopenharmony_ci * Decode intra macroblock header and return CBP in case of success, -1 otherwise. 347cabdff1aSopenharmony_ci */ 348cabdff1aSopenharmony_cistatic int rv34_decode_intra_mb_header(RV34DecContext *r, int8_t *intra_types) 349cabdff1aSopenharmony_ci{ 350cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 351cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 352cabdff1aSopenharmony_ci int mb_pos = s->mb_x + s->mb_y * s->mb_stride; 353cabdff1aSopenharmony_ci int t; 354cabdff1aSopenharmony_ci 355cabdff1aSopenharmony_ci r->is16 = get_bits1(gb); 356cabdff1aSopenharmony_ci if(r->is16){ 357cabdff1aSopenharmony_ci s->current_picture_ptr->mb_type[mb_pos] = MB_TYPE_INTRA16x16; 358cabdff1aSopenharmony_ci r->block_type = RV34_MB_TYPE_INTRA16x16; 359cabdff1aSopenharmony_ci t = get_bits(gb, 2); 360cabdff1aSopenharmony_ci fill_rectangle(intra_types, 4, 4, r->intra_types_stride, t, sizeof(intra_types[0])); 361cabdff1aSopenharmony_ci r->luma_vlc = 2; 362cabdff1aSopenharmony_ci }else{ 363cabdff1aSopenharmony_ci if(!r->rv30){ 364cabdff1aSopenharmony_ci if(!get_bits1(gb)) 365cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Need DQUANT\n"); 366cabdff1aSopenharmony_ci } 367cabdff1aSopenharmony_ci s->current_picture_ptr->mb_type[mb_pos] = MB_TYPE_INTRA; 368cabdff1aSopenharmony_ci r->block_type = RV34_MB_TYPE_INTRA; 369cabdff1aSopenharmony_ci if(r->decode_intra_types(r, gb, intra_types) < 0) 370cabdff1aSopenharmony_ci return -1; 371cabdff1aSopenharmony_ci r->luma_vlc = 1; 372cabdff1aSopenharmony_ci } 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci r->chroma_vlc = 0; 375cabdff1aSopenharmony_ci r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0); 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci return rv34_decode_cbp(gb, r->cur_vlcs, r->is16); 378cabdff1aSopenharmony_ci} 379cabdff1aSopenharmony_ci 380cabdff1aSopenharmony_ci/** 381cabdff1aSopenharmony_ci * Decode inter macroblock header and return CBP in case of success, -1 otherwise. 382cabdff1aSopenharmony_ci */ 383cabdff1aSopenharmony_cistatic int rv34_decode_inter_mb_header(RV34DecContext *r, int8_t *intra_types) 384cabdff1aSopenharmony_ci{ 385cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 386cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 387cabdff1aSopenharmony_ci int mb_pos = s->mb_x + s->mb_y * s->mb_stride; 388cabdff1aSopenharmony_ci int i, t; 389cabdff1aSopenharmony_ci 390cabdff1aSopenharmony_ci r->block_type = r->decode_mb_info(r); 391cabdff1aSopenharmony_ci if(r->block_type == -1) 392cabdff1aSopenharmony_ci return -1; 393cabdff1aSopenharmony_ci s->current_picture_ptr->mb_type[mb_pos] = rv34_mb_type_to_lavc[r->block_type]; 394cabdff1aSopenharmony_ci r->mb_type[mb_pos] = r->block_type; 395cabdff1aSopenharmony_ci if(r->block_type == RV34_MB_SKIP){ 396cabdff1aSopenharmony_ci if(s->pict_type == AV_PICTURE_TYPE_P) 397cabdff1aSopenharmony_ci r->mb_type[mb_pos] = RV34_MB_P_16x16; 398cabdff1aSopenharmony_ci if(s->pict_type == AV_PICTURE_TYPE_B) 399cabdff1aSopenharmony_ci r->mb_type[mb_pos] = RV34_MB_B_DIRECT; 400cabdff1aSopenharmony_ci } 401cabdff1aSopenharmony_ci r->is16 = !!IS_INTRA16x16(s->current_picture_ptr->mb_type[mb_pos]); 402cabdff1aSopenharmony_ci if (rv34_decode_mv(r, r->block_type) < 0) 403cabdff1aSopenharmony_ci return -1; 404cabdff1aSopenharmony_ci if(r->block_type == RV34_MB_SKIP){ 405cabdff1aSopenharmony_ci fill_rectangle(intra_types, 4, 4, r->intra_types_stride, 0, sizeof(intra_types[0])); 406cabdff1aSopenharmony_ci return 0; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci r->chroma_vlc = 1; 409cabdff1aSopenharmony_ci r->luma_vlc = 0; 410cabdff1aSopenharmony_ci 411cabdff1aSopenharmony_ci if(IS_INTRA(s->current_picture_ptr->mb_type[mb_pos])){ 412cabdff1aSopenharmony_ci if(r->is16){ 413cabdff1aSopenharmony_ci t = get_bits(gb, 2); 414cabdff1aSopenharmony_ci fill_rectangle(intra_types, 4, 4, r->intra_types_stride, t, sizeof(intra_types[0])); 415cabdff1aSopenharmony_ci r->luma_vlc = 2; 416cabdff1aSopenharmony_ci }else{ 417cabdff1aSopenharmony_ci if(r->decode_intra_types(r, gb, intra_types) < 0) 418cabdff1aSopenharmony_ci return -1; 419cabdff1aSopenharmony_ci r->luma_vlc = 1; 420cabdff1aSopenharmony_ci } 421cabdff1aSopenharmony_ci r->chroma_vlc = 0; 422cabdff1aSopenharmony_ci r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0); 423cabdff1aSopenharmony_ci }else{ 424cabdff1aSopenharmony_ci for(i = 0; i < 16; i++) 425cabdff1aSopenharmony_ci intra_types[(i & 3) + (i>>2) * r->intra_types_stride] = 0; 426cabdff1aSopenharmony_ci r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); 427cabdff1aSopenharmony_ci if(r->mb_type[mb_pos] == RV34_MB_P_MIX16x16){ 428cabdff1aSopenharmony_ci r->is16 = 1; 429cabdff1aSopenharmony_ci r->chroma_vlc = 1; 430cabdff1aSopenharmony_ci r->luma_vlc = 2; 431cabdff1aSopenharmony_ci r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 0); 432cabdff1aSopenharmony_ci } 433cabdff1aSopenharmony_ci } 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_ci return rv34_decode_cbp(gb, r->cur_vlcs, r->is16); 436cabdff1aSopenharmony_ci} 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_ci/** @} */ //bitstream functions 439cabdff1aSopenharmony_ci 440cabdff1aSopenharmony_ci/** 441cabdff1aSopenharmony_ci * @name motion vector related code (prediction, reconstruction, motion compensation) 442cabdff1aSopenharmony_ci * @{ 443cabdff1aSopenharmony_ci */ 444cabdff1aSopenharmony_ci 445cabdff1aSopenharmony_ci/** macroblock partition width in 8x8 blocks */ 446cabdff1aSopenharmony_cistatic const uint8_t part_sizes_w[RV34_MB_TYPES] = { 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2 }; 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci/** macroblock partition height in 8x8 blocks */ 449cabdff1aSopenharmony_cistatic const uint8_t part_sizes_h[RV34_MB_TYPES] = { 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2 }; 450cabdff1aSopenharmony_ci 451cabdff1aSopenharmony_ci/** availability index for subblocks */ 452cabdff1aSopenharmony_cistatic const uint8_t avail_indexes[4] = { 6, 7, 10, 11 }; 453cabdff1aSopenharmony_ci 454cabdff1aSopenharmony_ci/** 455cabdff1aSopenharmony_ci * motion vector prediction 456cabdff1aSopenharmony_ci * 457cabdff1aSopenharmony_ci * Motion prediction performed for the block by using median prediction of 458cabdff1aSopenharmony_ci * motion vectors from the left, top and right top blocks but in corner cases 459cabdff1aSopenharmony_ci * some other vectors may be used instead. 460cabdff1aSopenharmony_ci */ 461cabdff1aSopenharmony_cistatic void rv34_pred_mv(RV34DecContext *r, int block_type, int subblock_no, int dmv_no) 462cabdff1aSopenharmony_ci{ 463cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 464cabdff1aSopenharmony_ci int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; 465cabdff1aSopenharmony_ci int A[2] = {0}, B[2], C[2]; 466cabdff1aSopenharmony_ci int i, j; 467cabdff1aSopenharmony_ci int mx, my; 468cabdff1aSopenharmony_ci int* avail = r->avail_cache + avail_indexes[subblock_no]; 469cabdff1aSopenharmony_ci int c_off = part_sizes_w[block_type]; 470cabdff1aSopenharmony_ci 471cabdff1aSopenharmony_ci mv_pos += (subblock_no & 1) + (subblock_no >> 1)*s->b8_stride; 472cabdff1aSopenharmony_ci if(subblock_no == 3) 473cabdff1aSopenharmony_ci c_off = -1; 474cabdff1aSopenharmony_ci 475cabdff1aSopenharmony_ci if(avail[-1]){ 476cabdff1aSopenharmony_ci A[0] = s->current_picture_ptr->motion_val[0][mv_pos-1][0]; 477cabdff1aSopenharmony_ci A[1] = s->current_picture_ptr->motion_val[0][mv_pos-1][1]; 478cabdff1aSopenharmony_ci } 479cabdff1aSopenharmony_ci if(avail[-4]){ 480cabdff1aSopenharmony_ci B[0] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride][0]; 481cabdff1aSopenharmony_ci B[1] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride][1]; 482cabdff1aSopenharmony_ci }else{ 483cabdff1aSopenharmony_ci B[0] = A[0]; 484cabdff1aSopenharmony_ci B[1] = A[1]; 485cabdff1aSopenharmony_ci } 486cabdff1aSopenharmony_ci if(!avail[c_off-4]){ 487cabdff1aSopenharmony_ci if(avail[-4] && (avail[-1] || r->rv30)){ 488cabdff1aSopenharmony_ci C[0] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride-1][0]; 489cabdff1aSopenharmony_ci C[1] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride-1][1]; 490cabdff1aSopenharmony_ci }else{ 491cabdff1aSopenharmony_ci C[0] = A[0]; 492cabdff1aSopenharmony_ci C[1] = A[1]; 493cabdff1aSopenharmony_ci } 494cabdff1aSopenharmony_ci }else{ 495cabdff1aSopenharmony_ci C[0] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride+c_off][0]; 496cabdff1aSopenharmony_ci C[1] = s->current_picture_ptr->motion_val[0][mv_pos-s->b8_stride+c_off][1]; 497cabdff1aSopenharmony_ci } 498cabdff1aSopenharmony_ci mx = mid_pred(A[0], B[0], C[0]); 499cabdff1aSopenharmony_ci my = mid_pred(A[1], B[1], C[1]); 500cabdff1aSopenharmony_ci mx += r->dmv[dmv_no][0]; 501cabdff1aSopenharmony_ci my += r->dmv[dmv_no][1]; 502cabdff1aSopenharmony_ci for(j = 0; j < part_sizes_h[block_type]; j++){ 503cabdff1aSopenharmony_ci for(i = 0; i < part_sizes_w[block_type]; i++){ 504cabdff1aSopenharmony_ci s->current_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][0] = mx; 505cabdff1aSopenharmony_ci s->current_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][1] = my; 506cabdff1aSopenharmony_ci } 507cabdff1aSopenharmony_ci } 508cabdff1aSopenharmony_ci} 509cabdff1aSopenharmony_ci 510cabdff1aSopenharmony_ci#define GET_PTS_DIFF(a, b) (((a) - (b) + 8192) & 0x1FFF) 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci/** 513cabdff1aSopenharmony_ci * Calculate motion vector component that should be added for direct blocks. 514cabdff1aSopenharmony_ci */ 515cabdff1aSopenharmony_cistatic int calc_add_mv(RV34DecContext *r, int dir, int val) 516cabdff1aSopenharmony_ci{ 517cabdff1aSopenharmony_ci int mul = dir ? -r->mv_weight2 : r->mv_weight1; 518cabdff1aSopenharmony_ci 519cabdff1aSopenharmony_ci return (int)(val * (SUINT)mul + 0x2000) >> 14; 520cabdff1aSopenharmony_ci} 521cabdff1aSopenharmony_ci 522cabdff1aSopenharmony_ci/** 523cabdff1aSopenharmony_ci * Predict motion vector for B-frame macroblock. 524cabdff1aSopenharmony_ci */ 525cabdff1aSopenharmony_cistatic inline void rv34_pred_b_vector(int A[2], int B[2], int C[2], 526cabdff1aSopenharmony_ci int A_avail, int B_avail, int C_avail, 527cabdff1aSopenharmony_ci int *mx, int *my) 528cabdff1aSopenharmony_ci{ 529cabdff1aSopenharmony_ci if(A_avail + B_avail + C_avail != 3){ 530cabdff1aSopenharmony_ci *mx = A[0] + B[0] + C[0]; 531cabdff1aSopenharmony_ci *my = A[1] + B[1] + C[1]; 532cabdff1aSopenharmony_ci if(A_avail + B_avail + C_avail == 2){ 533cabdff1aSopenharmony_ci *mx /= 2; 534cabdff1aSopenharmony_ci *my /= 2; 535cabdff1aSopenharmony_ci } 536cabdff1aSopenharmony_ci }else{ 537cabdff1aSopenharmony_ci *mx = mid_pred(A[0], B[0], C[0]); 538cabdff1aSopenharmony_ci *my = mid_pred(A[1], B[1], C[1]); 539cabdff1aSopenharmony_ci } 540cabdff1aSopenharmony_ci} 541cabdff1aSopenharmony_ci 542cabdff1aSopenharmony_ci/** 543cabdff1aSopenharmony_ci * motion vector prediction for B-frames 544cabdff1aSopenharmony_ci */ 545cabdff1aSopenharmony_cistatic void rv34_pred_mv_b(RV34DecContext *r, int block_type, int dir) 546cabdff1aSopenharmony_ci{ 547cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 548cabdff1aSopenharmony_ci int mb_pos = s->mb_x + s->mb_y * s->mb_stride; 549cabdff1aSopenharmony_ci int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; 550cabdff1aSopenharmony_ci int A[2] = { 0 }, B[2] = { 0 }, C[2] = { 0 }; 551cabdff1aSopenharmony_ci int has_A = 0, has_B = 0, has_C = 0; 552cabdff1aSopenharmony_ci int mx, my; 553cabdff1aSopenharmony_ci int i, j; 554cabdff1aSopenharmony_ci Picture *cur_pic = s->current_picture_ptr; 555cabdff1aSopenharmony_ci const int mask = dir ? MB_TYPE_L1 : MB_TYPE_L0; 556cabdff1aSopenharmony_ci int type = cur_pic->mb_type[mb_pos]; 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci if((r->avail_cache[6-1] & type) & mask){ 559cabdff1aSopenharmony_ci A[0] = cur_pic->motion_val[dir][mv_pos - 1][0]; 560cabdff1aSopenharmony_ci A[1] = cur_pic->motion_val[dir][mv_pos - 1][1]; 561cabdff1aSopenharmony_ci has_A = 1; 562cabdff1aSopenharmony_ci } 563cabdff1aSopenharmony_ci if((r->avail_cache[6-4] & type) & mask){ 564cabdff1aSopenharmony_ci B[0] = cur_pic->motion_val[dir][mv_pos - s->b8_stride][0]; 565cabdff1aSopenharmony_ci B[1] = cur_pic->motion_val[dir][mv_pos - s->b8_stride][1]; 566cabdff1aSopenharmony_ci has_B = 1; 567cabdff1aSopenharmony_ci } 568cabdff1aSopenharmony_ci if(r->avail_cache[6-4] && (r->avail_cache[6-2] & type) & mask){ 569cabdff1aSopenharmony_ci C[0] = cur_pic->motion_val[dir][mv_pos - s->b8_stride + 2][0]; 570cabdff1aSopenharmony_ci C[1] = cur_pic->motion_val[dir][mv_pos - s->b8_stride + 2][1]; 571cabdff1aSopenharmony_ci has_C = 1; 572cabdff1aSopenharmony_ci }else if((s->mb_x+1) == s->mb_width && (r->avail_cache[6-5] & type) & mask){ 573cabdff1aSopenharmony_ci C[0] = cur_pic->motion_val[dir][mv_pos - s->b8_stride - 1][0]; 574cabdff1aSopenharmony_ci C[1] = cur_pic->motion_val[dir][mv_pos - s->b8_stride - 1][1]; 575cabdff1aSopenharmony_ci has_C = 1; 576cabdff1aSopenharmony_ci } 577cabdff1aSopenharmony_ci 578cabdff1aSopenharmony_ci rv34_pred_b_vector(A, B, C, has_A, has_B, has_C, &mx, &my); 579cabdff1aSopenharmony_ci 580cabdff1aSopenharmony_ci mx += r->dmv[dir][0]; 581cabdff1aSopenharmony_ci my += r->dmv[dir][1]; 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ci for(j = 0; j < 2; j++){ 584cabdff1aSopenharmony_ci for(i = 0; i < 2; i++){ 585cabdff1aSopenharmony_ci cur_pic->motion_val[dir][mv_pos + i + j*s->b8_stride][0] = mx; 586cabdff1aSopenharmony_ci cur_pic->motion_val[dir][mv_pos + i + j*s->b8_stride][1] = my; 587cabdff1aSopenharmony_ci } 588cabdff1aSopenharmony_ci } 589cabdff1aSopenharmony_ci if(block_type == RV34_MB_B_BACKWARD || block_type == RV34_MB_B_FORWARD){ 590cabdff1aSopenharmony_ci ZERO8x2(cur_pic->motion_val[!dir][mv_pos], s->b8_stride); 591cabdff1aSopenharmony_ci } 592cabdff1aSopenharmony_ci} 593cabdff1aSopenharmony_ci 594cabdff1aSopenharmony_ci/** 595cabdff1aSopenharmony_ci * motion vector prediction - RV3 version 596cabdff1aSopenharmony_ci */ 597cabdff1aSopenharmony_cistatic void rv34_pred_mv_rv3(RV34DecContext *r, int block_type, int dir) 598cabdff1aSopenharmony_ci{ 599cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 600cabdff1aSopenharmony_ci int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; 601cabdff1aSopenharmony_ci int A[2] = {0}, B[2], C[2]; 602cabdff1aSopenharmony_ci int i, j, k; 603cabdff1aSopenharmony_ci int mx, my; 604cabdff1aSopenharmony_ci int* avail = r->avail_cache + avail_indexes[0]; 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_ci if(avail[-1]){ 607cabdff1aSopenharmony_ci A[0] = s->current_picture_ptr->motion_val[0][mv_pos - 1][0]; 608cabdff1aSopenharmony_ci A[1] = s->current_picture_ptr->motion_val[0][mv_pos - 1][1]; 609cabdff1aSopenharmony_ci } 610cabdff1aSopenharmony_ci if(avail[-4]){ 611cabdff1aSopenharmony_ci B[0] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride][0]; 612cabdff1aSopenharmony_ci B[1] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride][1]; 613cabdff1aSopenharmony_ci }else{ 614cabdff1aSopenharmony_ci B[0] = A[0]; 615cabdff1aSopenharmony_ci B[1] = A[1]; 616cabdff1aSopenharmony_ci } 617cabdff1aSopenharmony_ci if(!avail[-4 + 2]){ 618cabdff1aSopenharmony_ci if(avail[-4] && (avail[-1])){ 619cabdff1aSopenharmony_ci C[0] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride - 1][0]; 620cabdff1aSopenharmony_ci C[1] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride - 1][1]; 621cabdff1aSopenharmony_ci }else{ 622cabdff1aSopenharmony_ci C[0] = A[0]; 623cabdff1aSopenharmony_ci C[1] = A[1]; 624cabdff1aSopenharmony_ci } 625cabdff1aSopenharmony_ci }else{ 626cabdff1aSopenharmony_ci C[0] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride + 2][0]; 627cabdff1aSopenharmony_ci C[1] = s->current_picture_ptr->motion_val[0][mv_pos - s->b8_stride + 2][1]; 628cabdff1aSopenharmony_ci } 629cabdff1aSopenharmony_ci mx = mid_pred(A[0], B[0], C[0]); 630cabdff1aSopenharmony_ci my = mid_pred(A[1], B[1], C[1]); 631cabdff1aSopenharmony_ci mx += r->dmv[0][0]; 632cabdff1aSopenharmony_ci my += r->dmv[0][1]; 633cabdff1aSopenharmony_ci for(j = 0; j < 2; j++){ 634cabdff1aSopenharmony_ci for(i = 0; i < 2; i++){ 635cabdff1aSopenharmony_ci for(k = 0; k < 2; k++){ 636cabdff1aSopenharmony_ci s->current_picture_ptr->motion_val[k][mv_pos + i + j*s->b8_stride][0] = mx; 637cabdff1aSopenharmony_ci s->current_picture_ptr->motion_val[k][mv_pos + i + j*s->b8_stride][1] = my; 638cabdff1aSopenharmony_ci } 639cabdff1aSopenharmony_ci } 640cabdff1aSopenharmony_ci } 641cabdff1aSopenharmony_ci} 642cabdff1aSopenharmony_ci 643cabdff1aSopenharmony_cistatic const int chroma_coeffs[3] = { 0, 3, 5 }; 644cabdff1aSopenharmony_ci 645cabdff1aSopenharmony_ci/** 646cabdff1aSopenharmony_ci * generic motion compensation function 647cabdff1aSopenharmony_ci * 648cabdff1aSopenharmony_ci * @param r decoder context 649cabdff1aSopenharmony_ci * @param block_type type of the current block 650cabdff1aSopenharmony_ci * @param xoff horizontal offset from the start of the current block 651cabdff1aSopenharmony_ci * @param yoff vertical offset from the start of the current block 652cabdff1aSopenharmony_ci * @param mv_off offset to the motion vector information 653cabdff1aSopenharmony_ci * @param width width of the current partition in 8x8 blocks 654cabdff1aSopenharmony_ci * @param height height of the current partition in 8x8 blocks 655cabdff1aSopenharmony_ci * @param dir motion compensation direction (i.e. from the last or the next reference frame) 656cabdff1aSopenharmony_ci * @param thirdpel motion vectors are specified in 1/3 of pixel 657cabdff1aSopenharmony_ci * @param qpel_mc a set of functions used to perform luma motion compensation 658cabdff1aSopenharmony_ci * @param chroma_mc a set of functions used to perform chroma motion compensation 659cabdff1aSopenharmony_ci */ 660cabdff1aSopenharmony_cistatic inline void rv34_mc(RV34DecContext *r, const int block_type, 661cabdff1aSopenharmony_ci const int xoff, const int yoff, int mv_off, 662cabdff1aSopenharmony_ci const int width, const int height, int dir, 663cabdff1aSopenharmony_ci const int thirdpel, int weighted, 664cabdff1aSopenharmony_ci qpel_mc_func (*qpel_mc)[16], 665cabdff1aSopenharmony_ci h264_chroma_mc_func (*chroma_mc)) 666cabdff1aSopenharmony_ci{ 667cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 668cabdff1aSopenharmony_ci uint8_t *Y, *U, *V, *srcY, *srcU, *srcV; 669cabdff1aSopenharmony_ci int dxy, mx, my, umx, umy, lx, ly, uvmx, uvmy, src_x, src_y, uvsrc_x, uvsrc_y; 670cabdff1aSopenharmony_ci int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride + mv_off; 671cabdff1aSopenharmony_ci int is16x16 = 1; 672cabdff1aSopenharmony_ci int emu = 0; 673cabdff1aSopenharmony_ci 674cabdff1aSopenharmony_ci if(thirdpel){ 675cabdff1aSopenharmony_ci int chroma_mx, chroma_my; 676cabdff1aSopenharmony_ci mx = (s->current_picture_ptr->motion_val[dir][mv_pos][0] + (3 << 24)) / 3 - (1 << 24); 677cabdff1aSopenharmony_ci my = (s->current_picture_ptr->motion_val[dir][mv_pos][1] + (3 << 24)) / 3 - (1 << 24); 678cabdff1aSopenharmony_ci lx = (s->current_picture_ptr->motion_val[dir][mv_pos][0] + (3 << 24)) % 3; 679cabdff1aSopenharmony_ci ly = (s->current_picture_ptr->motion_val[dir][mv_pos][1] + (3 << 24)) % 3; 680cabdff1aSopenharmony_ci chroma_mx = s->current_picture_ptr->motion_val[dir][mv_pos][0] / 2; 681cabdff1aSopenharmony_ci chroma_my = s->current_picture_ptr->motion_val[dir][mv_pos][1] / 2; 682cabdff1aSopenharmony_ci umx = (chroma_mx + (3 << 24)) / 3 - (1 << 24); 683cabdff1aSopenharmony_ci umy = (chroma_my + (3 << 24)) / 3 - (1 << 24); 684cabdff1aSopenharmony_ci uvmx = chroma_coeffs[(chroma_mx + (3 << 24)) % 3]; 685cabdff1aSopenharmony_ci uvmy = chroma_coeffs[(chroma_my + (3 << 24)) % 3]; 686cabdff1aSopenharmony_ci }else{ 687cabdff1aSopenharmony_ci int cx, cy; 688cabdff1aSopenharmony_ci mx = s->current_picture_ptr->motion_val[dir][mv_pos][0] >> 2; 689cabdff1aSopenharmony_ci my = s->current_picture_ptr->motion_val[dir][mv_pos][1] >> 2; 690cabdff1aSopenharmony_ci lx = s->current_picture_ptr->motion_val[dir][mv_pos][0] & 3; 691cabdff1aSopenharmony_ci ly = s->current_picture_ptr->motion_val[dir][mv_pos][1] & 3; 692cabdff1aSopenharmony_ci cx = s->current_picture_ptr->motion_val[dir][mv_pos][0] / 2; 693cabdff1aSopenharmony_ci cy = s->current_picture_ptr->motion_val[dir][mv_pos][1] / 2; 694cabdff1aSopenharmony_ci umx = cx >> 2; 695cabdff1aSopenharmony_ci umy = cy >> 2; 696cabdff1aSopenharmony_ci uvmx = (cx & 3) << 1; 697cabdff1aSopenharmony_ci uvmy = (cy & 3) << 1; 698cabdff1aSopenharmony_ci //due to some flaw RV40 uses the same MC compensation routine for H2V2 and H3V3 699cabdff1aSopenharmony_ci if(uvmx == 6 && uvmy == 6) 700cabdff1aSopenharmony_ci uvmx = uvmy = 4; 701cabdff1aSopenharmony_ci } 702cabdff1aSopenharmony_ci 703cabdff1aSopenharmony_ci if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) { 704cabdff1aSopenharmony_ci /* wait for the referenced mb row to be finished */ 705cabdff1aSopenharmony_ci int mb_row = s->mb_y + ((yoff + my + 5 + 8 * height) >> 4); 706cabdff1aSopenharmony_ci ThreadFrame *f = dir ? &s->next_picture_ptr->tf : &s->last_picture_ptr->tf; 707cabdff1aSopenharmony_ci ff_thread_await_progress(f, mb_row, 0); 708cabdff1aSopenharmony_ci } 709cabdff1aSopenharmony_ci 710cabdff1aSopenharmony_ci dxy = ly*4 + lx; 711cabdff1aSopenharmony_ci srcY = dir ? s->next_picture_ptr->f->data[0] : s->last_picture_ptr->f->data[0]; 712cabdff1aSopenharmony_ci srcU = dir ? s->next_picture_ptr->f->data[1] : s->last_picture_ptr->f->data[1]; 713cabdff1aSopenharmony_ci srcV = dir ? s->next_picture_ptr->f->data[2] : s->last_picture_ptr->f->data[2]; 714cabdff1aSopenharmony_ci src_x = s->mb_x * 16 + xoff + mx; 715cabdff1aSopenharmony_ci src_y = s->mb_y * 16 + yoff + my; 716cabdff1aSopenharmony_ci uvsrc_x = s->mb_x * 8 + (xoff >> 1) + umx; 717cabdff1aSopenharmony_ci uvsrc_y = s->mb_y * 8 + (yoff >> 1) + umy; 718cabdff1aSopenharmony_ci srcY += src_y * s->linesize + src_x; 719cabdff1aSopenharmony_ci srcU += uvsrc_y * s->uvlinesize + uvsrc_x; 720cabdff1aSopenharmony_ci srcV += uvsrc_y * s->uvlinesize + uvsrc_x; 721cabdff1aSopenharmony_ci if(s->h_edge_pos - (width << 3) < 6 || s->v_edge_pos - (height << 3) < 6 || 722cabdff1aSopenharmony_ci (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 || 723cabdff1aSopenharmony_ci (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4) { 724cabdff1aSopenharmony_ci srcY -= 2 + 2*s->linesize; 725cabdff1aSopenharmony_ci s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, srcY, 726cabdff1aSopenharmony_ci s->linesize, s->linesize, 727cabdff1aSopenharmony_ci (width << 3) + 6, (height << 3) + 6, 728cabdff1aSopenharmony_ci src_x - 2, src_y - 2, 729cabdff1aSopenharmony_ci s->h_edge_pos, s->v_edge_pos); 730cabdff1aSopenharmony_ci srcY = s->sc.edge_emu_buffer + 2 + 2*s->linesize; 731cabdff1aSopenharmony_ci emu = 1; 732cabdff1aSopenharmony_ci } 733cabdff1aSopenharmony_ci if(!weighted){ 734cabdff1aSopenharmony_ci Y = s->dest[0] + xoff + yoff *s->linesize; 735cabdff1aSopenharmony_ci U = s->dest[1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; 736cabdff1aSopenharmony_ci V = s->dest[2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; 737cabdff1aSopenharmony_ci }else{ 738cabdff1aSopenharmony_ci Y = r->tmp_b_block_y [dir] + xoff + yoff *s->linesize; 739cabdff1aSopenharmony_ci U = r->tmp_b_block_uv[dir*2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; 740cabdff1aSopenharmony_ci V = r->tmp_b_block_uv[dir*2+1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; 741cabdff1aSopenharmony_ci } 742cabdff1aSopenharmony_ci 743cabdff1aSopenharmony_ci if(block_type == RV34_MB_P_16x8){ 744cabdff1aSopenharmony_ci qpel_mc[1][dxy](Y, srcY, s->linesize); 745cabdff1aSopenharmony_ci Y += 8; 746cabdff1aSopenharmony_ci srcY += 8; 747cabdff1aSopenharmony_ci }else if(block_type == RV34_MB_P_8x16){ 748cabdff1aSopenharmony_ci qpel_mc[1][dxy](Y, srcY, s->linesize); 749cabdff1aSopenharmony_ci Y += 8 * s->linesize; 750cabdff1aSopenharmony_ci srcY += 8 * s->linesize; 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci is16x16 = (block_type != RV34_MB_P_8x8) && (block_type != RV34_MB_P_16x8) && (block_type != RV34_MB_P_8x16); 753cabdff1aSopenharmony_ci qpel_mc[!is16x16][dxy](Y, srcY, s->linesize); 754cabdff1aSopenharmony_ci if (emu) { 755cabdff1aSopenharmony_ci uint8_t *uvbuf = s->sc.edge_emu_buffer; 756cabdff1aSopenharmony_ci 757cabdff1aSopenharmony_ci s->vdsp.emulated_edge_mc(uvbuf, srcU, 758cabdff1aSopenharmony_ci s->uvlinesize, s->uvlinesize, 759cabdff1aSopenharmony_ci (width << 2) + 1, (height << 2) + 1, 760cabdff1aSopenharmony_ci uvsrc_x, uvsrc_y, 761cabdff1aSopenharmony_ci s->h_edge_pos >> 1, s->v_edge_pos >> 1); 762cabdff1aSopenharmony_ci srcU = uvbuf; 763cabdff1aSopenharmony_ci uvbuf += 9*s->uvlinesize; 764cabdff1aSopenharmony_ci 765cabdff1aSopenharmony_ci s->vdsp.emulated_edge_mc(uvbuf, srcV, 766cabdff1aSopenharmony_ci s->uvlinesize, s->uvlinesize, 767cabdff1aSopenharmony_ci (width << 2) + 1, (height << 2) + 1, 768cabdff1aSopenharmony_ci uvsrc_x, uvsrc_y, 769cabdff1aSopenharmony_ci s->h_edge_pos >> 1, s->v_edge_pos >> 1); 770cabdff1aSopenharmony_ci srcV = uvbuf; 771cabdff1aSopenharmony_ci } 772cabdff1aSopenharmony_ci chroma_mc[2-width] (U, srcU, s->uvlinesize, height*4, uvmx, uvmy); 773cabdff1aSopenharmony_ci chroma_mc[2-width] (V, srcV, s->uvlinesize, height*4, uvmx, uvmy); 774cabdff1aSopenharmony_ci} 775cabdff1aSopenharmony_ci 776cabdff1aSopenharmony_cistatic void rv34_mc_1mv(RV34DecContext *r, const int block_type, 777cabdff1aSopenharmony_ci const int xoff, const int yoff, int mv_off, 778cabdff1aSopenharmony_ci const int width, const int height, int dir) 779cabdff1aSopenharmony_ci{ 780cabdff1aSopenharmony_ci rv34_mc(r, block_type, xoff, yoff, mv_off, width, height, dir, r->rv30, 0, 781cabdff1aSopenharmony_ci r->rdsp.put_pixels_tab, 782cabdff1aSopenharmony_ci r->rdsp.put_chroma_pixels_tab); 783cabdff1aSopenharmony_ci} 784cabdff1aSopenharmony_ci 785cabdff1aSopenharmony_cistatic void rv4_weight(RV34DecContext *r) 786cabdff1aSopenharmony_ci{ 787cabdff1aSopenharmony_ci r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][0](r->s.dest[0], 788cabdff1aSopenharmony_ci r->tmp_b_block_y[0], 789cabdff1aSopenharmony_ci r->tmp_b_block_y[1], 790cabdff1aSopenharmony_ci r->weight1, 791cabdff1aSopenharmony_ci r->weight2, 792cabdff1aSopenharmony_ci r->s.linesize); 793cabdff1aSopenharmony_ci r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][1](r->s.dest[1], 794cabdff1aSopenharmony_ci r->tmp_b_block_uv[0], 795cabdff1aSopenharmony_ci r->tmp_b_block_uv[2], 796cabdff1aSopenharmony_ci r->weight1, 797cabdff1aSopenharmony_ci r->weight2, 798cabdff1aSopenharmony_ci r->s.uvlinesize); 799cabdff1aSopenharmony_ci r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][1](r->s.dest[2], 800cabdff1aSopenharmony_ci r->tmp_b_block_uv[1], 801cabdff1aSopenharmony_ci r->tmp_b_block_uv[3], 802cabdff1aSopenharmony_ci r->weight1, 803cabdff1aSopenharmony_ci r->weight2, 804cabdff1aSopenharmony_ci r->s.uvlinesize); 805cabdff1aSopenharmony_ci} 806cabdff1aSopenharmony_ci 807cabdff1aSopenharmony_cistatic void rv34_mc_2mv(RV34DecContext *r, const int block_type) 808cabdff1aSopenharmony_ci{ 809cabdff1aSopenharmony_ci int weighted = !r->rv30 && block_type != RV34_MB_B_BIDIR && r->weight1 != 8192; 810cabdff1aSopenharmony_ci 811cabdff1aSopenharmony_ci rv34_mc(r, block_type, 0, 0, 0, 2, 2, 0, r->rv30, weighted, 812cabdff1aSopenharmony_ci r->rdsp.put_pixels_tab, 813cabdff1aSopenharmony_ci r->rdsp.put_chroma_pixels_tab); 814cabdff1aSopenharmony_ci if(!weighted){ 815cabdff1aSopenharmony_ci rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, 0, 816cabdff1aSopenharmony_ci r->rdsp.avg_pixels_tab, 817cabdff1aSopenharmony_ci r->rdsp.avg_chroma_pixels_tab); 818cabdff1aSopenharmony_ci }else{ 819cabdff1aSopenharmony_ci rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, 1, 820cabdff1aSopenharmony_ci r->rdsp.put_pixels_tab, 821cabdff1aSopenharmony_ci r->rdsp.put_chroma_pixels_tab); 822cabdff1aSopenharmony_ci rv4_weight(r); 823cabdff1aSopenharmony_ci } 824cabdff1aSopenharmony_ci} 825cabdff1aSopenharmony_ci 826cabdff1aSopenharmony_cistatic void rv34_mc_2mv_skip(RV34DecContext *r) 827cabdff1aSopenharmony_ci{ 828cabdff1aSopenharmony_ci int i, j; 829cabdff1aSopenharmony_ci int weighted = !r->rv30 && r->weight1 != 8192; 830cabdff1aSopenharmony_ci 831cabdff1aSopenharmony_ci for(j = 0; j < 2; j++) 832cabdff1aSopenharmony_ci for(i = 0; i < 2; i++){ 833cabdff1aSopenharmony_ci rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 0, r->rv30, 834cabdff1aSopenharmony_ci weighted, 835cabdff1aSopenharmony_ci r->rdsp.put_pixels_tab, 836cabdff1aSopenharmony_ci r->rdsp.put_chroma_pixels_tab); 837cabdff1aSopenharmony_ci rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 1, r->rv30, 838cabdff1aSopenharmony_ci weighted, 839cabdff1aSopenharmony_ci weighted ? r->rdsp.put_pixels_tab : r->rdsp.avg_pixels_tab, 840cabdff1aSopenharmony_ci weighted ? r->rdsp.put_chroma_pixels_tab : r->rdsp.avg_chroma_pixels_tab); 841cabdff1aSopenharmony_ci } 842cabdff1aSopenharmony_ci if(weighted) 843cabdff1aSopenharmony_ci rv4_weight(r); 844cabdff1aSopenharmony_ci} 845cabdff1aSopenharmony_ci 846cabdff1aSopenharmony_ci/** number of motion vectors in each macroblock type */ 847cabdff1aSopenharmony_cistatic const int num_mvs[RV34_MB_TYPES] = { 0, 0, 1, 4, 1, 1, 0, 0, 2, 2, 2, 1 }; 848cabdff1aSopenharmony_ci 849cabdff1aSopenharmony_ci/** 850cabdff1aSopenharmony_ci * Decode motion vector differences 851cabdff1aSopenharmony_ci * and perform motion vector reconstruction and motion compensation. 852cabdff1aSopenharmony_ci */ 853cabdff1aSopenharmony_cistatic int rv34_decode_mv(RV34DecContext *r, int block_type) 854cabdff1aSopenharmony_ci{ 855cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 856cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 857cabdff1aSopenharmony_ci int i, j, k, l; 858cabdff1aSopenharmony_ci int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; 859cabdff1aSopenharmony_ci int next_bt; 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_ci memset(r->dmv, 0, sizeof(r->dmv)); 862cabdff1aSopenharmony_ci for(i = 0; i < num_mvs[block_type]; i++){ 863cabdff1aSopenharmony_ci r->dmv[i][0] = get_interleaved_se_golomb(gb); 864cabdff1aSopenharmony_ci r->dmv[i][1] = get_interleaved_se_golomb(gb); 865cabdff1aSopenharmony_ci if (r->dmv[i][0] == INVALID_VLC || 866cabdff1aSopenharmony_ci r->dmv[i][1] == INVALID_VLC) { 867cabdff1aSopenharmony_ci r->dmv[i][0] = r->dmv[i][1] = 0; 868cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 869cabdff1aSopenharmony_ci } 870cabdff1aSopenharmony_ci } 871cabdff1aSopenharmony_ci switch(block_type){ 872cabdff1aSopenharmony_ci case RV34_MB_TYPE_INTRA: 873cabdff1aSopenharmony_ci case RV34_MB_TYPE_INTRA16x16: 874cabdff1aSopenharmony_ci ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); 875cabdff1aSopenharmony_ci return 0; 876cabdff1aSopenharmony_ci case RV34_MB_SKIP: 877cabdff1aSopenharmony_ci if(s->pict_type == AV_PICTURE_TYPE_P){ 878cabdff1aSopenharmony_ci ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); 879cabdff1aSopenharmony_ci rv34_mc_1mv (r, block_type, 0, 0, 0, 2, 2, 0); 880cabdff1aSopenharmony_ci break; 881cabdff1aSopenharmony_ci } 882cabdff1aSopenharmony_ci case RV34_MB_B_DIRECT: 883cabdff1aSopenharmony_ci //surprisingly, it uses motion scheme from next reference frame 884cabdff1aSopenharmony_ci /* wait for the current mb row to be finished */ 885cabdff1aSopenharmony_ci if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) 886cabdff1aSopenharmony_ci ff_thread_await_progress(&s->next_picture_ptr->tf, FFMAX(0, s->mb_y-1), 0); 887cabdff1aSopenharmony_ci 888cabdff1aSopenharmony_ci next_bt = s->next_picture_ptr->mb_type[s->mb_x + s->mb_y * s->mb_stride]; 889cabdff1aSopenharmony_ci if(IS_INTRA(next_bt) || IS_SKIP(next_bt)){ 890cabdff1aSopenharmony_ci ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); 891cabdff1aSopenharmony_ci ZERO8x2(s->current_picture_ptr->motion_val[1][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); 892cabdff1aSopenharmony_ci }else 893cabdff1aSopenharmony_ci for(j = 0; j < 2; j++) 894cabdff1aSopenharmony_ci for(i = 0; i < 2; i++) 895cabdff1aSopenharmony_ci for(k = 0; k < 2; k++) 896cabdff1aSopenharmony_ci for(l = 0; l < 2; l++) 897cabdff1aSopenharmony_ci s->current_picture_ptr->motion_val[l][mv_pos + i + j*s->b8_stride][k] = calc_add_mv(r, l, s->next_picture_ptr->motion_val[0][mv_pos + i + j*s->b8_stride][k]); 898cabdff1aSopenharmony_ci if(!(IS_16X8(next_bt) || IS_8X16(next_bt) || IS_8X8(next_bt))) //we can use whole macroblock MC 899cabdff1aSopenharmony_ci rv34_mc_2mv(r, block_type); 900cabdff1aSopenharmony_ci else 901cabdff1aSopenharmony_ci rv34_mc_2mv_skip(r); 902cabdff1aSopenharmony_ci ZERO8x2(s->current_picture_ptr->motion_val[0][s->mb_x * 2 + s->mb_y * 2 * s->b8_stride], s->b8_stride); 903cabdff1aSopenharmony_ci break; 904cabdff1aSopenharmony_ci case RV34_MB_P_16x16: 905cabdff1aSopenharmony_ci case RV34_MB_P_MIX16x16: 906cabdff1aSopenharmony_ci rv34_pred_mv(r, block_type, 0, 0); 907cabdff1aSopenharmony_ci rv34_mc_1mv (r, block_type, 0, 0, 0, 2, 2, 0); 908cabdff1aSopenharmony_ci break; 909cabdff1aSopenharmony_ci case RV34_MB_B_FORWARD: 910cabdff1aSopenharmony_ci case RV34_MB_B_BACKWARD: 911cabdff1aSopenharmony_ci r->dmv[1][0] = r->dmv[0][0]; 912cabdff1aSopenharmony_ci r->dmv[1][1] = r->dmv[0][1]; 913cabdff1aSopenharmony_ci if(r->rv30) 914cabdff1aSopenharmony_ci rv34_pred_mv_rv3(r, block_type, block_type == RV34_MB_B_BACKWARD); 915cabdff1aSopenharmony_ci else 916cabdff1aSopenharmony_ci rv34_pred_mv_b (r, block_type, block_type == RV34_MB_B_BACKWARD); 917cabdff1aSopenharmony_ci rv34_mc_1mv (r, block_type, 0, 0, 0, 2, 2, block_type == RV34_MB_B_BACKWARD); 918cabdff1aSopenharmony_ci break; 919cabdff1aSopenharmony_ci case RV34_MB_P_16x8: 920cabdff1aSopenharmony_ci case RV34_MB_P_8x16: 921cabdff1aSopenharmony_ci rv34_pred_mv(r, block_type, 0, 0); 922cabdff1aSopenharmony_ci rv34_pred_mv(r, block_type, 1 + (block_type == RV34_MB_P_16x8), 1); 923cabdff1aSopenharmony_ci if(block_type == RV34_MB_P_16x8){ 924cabdff1aSopenharmony_ci rv34_mc_1mv(r, block_type, 0, 0, 0, 2, 1, 0); 925cabdff1aSopenharmony_ci rv34_mc_1mv(r, block_type, 0, 8, s->b8_stride, 2, 1, 0); 926cabdff1aSopenharmony_ci } 927cabdff1aSopenharmony_ci if(block_type == RV34_MB_P_8x16){ 928cabdff1aSopenharmony_ci rv34_mc_1mv(r, block_type, 0, 0, 0, 1, 2, 0); 929cabdff1aSopenharmony_ci rv34_mc_1mv(r, block_type, 8, 0, 1, 1, 2, 0); 930cabdff1aSopenharmony_ci } 931cabdff1aSopenharmony_ci break; 932cabdff1aSopenharmony_ci case RV34_MB_B_BIDIR: 933cabdff1aSopenharmony_ci rv34_pred_mv_b (r, block_type, 0); 934cabdff1aSopenharmony_ci rv34_pred_mv_b (r, block_type, 1); 935cabdff1aSopenharmony_ci rv34_mc_2mv (r, block_type); 936cabdff1aSopenharmony_ci break; 937cabdff1aSopenharmony_ci case RV34_MB_P_8x8: 938cabdff1aSopenharmony_ci for(i=0;i< 4;i++){ 939cabdff1aSopenharmony_ci rv34_pred_mv(r, block_type, i, i); 940cabdff1aSopenharmony_ci rv34_mc_1mv (r, block_type, (i&1)<<3, (i&2)<<2, (i&1)+(i>>1)*s->b8_stride, 1, 1, 0); 941cabdff1aSopenharmony_ci } 942cabdff1aSopenharmony_ci break; 943cabdff1aSopenharmony_ci } 944cabdff1aSopenharmony_ci 945cabdff1aSopenharmony_ci return 0; 946cabdff1aSopenharmony_ci} 947cabdff1aSopenharmony_ci/** @} */ // mv group 948cabdff1aSopenharmony_ci 949cabdff1aSopenharmony_ci/** 950cabdff1aSopenharmony_ci * @name Macroblock reconstruction functions 951cabdff1aSopenharmony_ci * @{ 952cabdff1aSopenharmony_ci */ 953cabdff1aSopenharmony_ci/** mapping of RV30/40 intra prediction types to standard H.264 types */ 954cabdff1aSopenharmony_cistatic const int ittrans[9] = { 955cabdff1aSopenharmony_ci DC_PRED, VERT_PRED, HOR_PRED, DIAG_DOWN_RIGHT_PRED, DIAG_DOWN_LEFT_PRED, 956cabdff1aSopenharmony_ci VERT_RIGHT_PRED, VERT_LEFT_PRED, HOR_UP_PRED, HOR_DOWN_PRED, 957cabdff1aSopenharmony_ci}; 958cabdff1aSopenharmony_ci 959cabdff1aSopenharmony_ci/** mapping of RV30/40 intra 16x16 prediction types to standard H.264 types */ 960cabdff1aSopenharmony_cistatic const int ittrans16[4] = { 961cabdff1aSopenharmony_ci DC_PRED8x8, VERT_PRED8x8, HOR_PRED8x8, PLANE_PRED8x8, 962cabdff1aSopenharmony_ci}; 963cabdff1aSopenharmony_ci 964cabdff1aSopenharmony_ci/** 965cabdff1aSopenharmony_ci * Perform 4x4 intra prediction. 966cabdff1aSopenharmony_ci */ 967cabdff1aSopenharmony_cistatic void rv34_pred_4x4_block(RV34DecContext *r, uint8_t *dst, int stride, int itype, int up, int left, int down, int right) 968cabdff1aSopenharmony_ci{ 969cabdff1aSopenharmony_ci uint8_t *prev = dst - stride + 4; 970cabdff1aSopenharmony_ci uint32_t topleft; 971cabdff1aSopenharmony_ci 972cabdff1aSopenharmony_ci if(!up && !left) 973cabdff1aSopenharmony_ci itype = DC_128_PRED; 974cabdff1aSopenharmony_ci else if(!up){ 975cabdff1aSopenharmony_ci if(itype == VERT_PRED) itype = HOR_PRED; 976cabdff1aSopenharmony_ci if(itype == DC_PRED) itype = LEFT_DC_PRED; 977cabdff1aSopenharmony_ci }else if(!left){ 978cabdff1aSopenharmony_ci if(itype == HOR_PRED) itype = VERT_PRED; 979cabdff1aSopenharmony_ci if(itype == DC_PRED) itype = TOP_DC_PRED; 980cabdff1aSopenharmony_ci if(itype == DIAG_DOWN_LEFT_PRED) itype = DIAG_DOWN_LEFT_PRED_RV40_NODOWN; 981cabdff1aSopenharmony_ci } 982cabdff1aSopenharmony_ci if(!down){ 983cabdff1aSopenharmony_ci if(itype == DIAG_DOWN_LEFT_PRED) itype = DIAG_DOWN_LEFT_PRED_RV40_NODOWN; 984cabdff1aSopenharmony_ci if(itype == HOR_UP_PRED) itype = HOR_UP_PRED_RV40_NODOWN; 985cabdff1aSopenharmony_ci if(itype == VERT_LEFT_PRED) itype = VERT_LEFT_PRED_RV40_NODOWN; 986cabdff1aSopenharmony_ci } 987cabdff1aSopenharmony_ci if(!right && up){ 988cabdff1aSopenharmony_ci topleft = dst[-stride + 3] * 0x01010101u; 989cabdff1aSopenharmony_ci prev = (uint8_t*)&topleft; 990cabdff1aSopenharmony_ci } 991cabdff1aSopenharmony_ci r->h.pred4x4[itype](dst, prev, stride); 992cabdff1aSopenharmony_ci} 993cabdff1aSopenharmony_ci 994cabdff1aSopenharmony_cistatic inline int adjust_pred16(int itype, int up, int left) 995cabdff1aSopenharmony_ci{ 996cabdff1aSopenharmony_ci if(!up && !left) 997cabdff1aSopenharmony_ci itype = DC_128_PRED8x8; 998cabdff1aSopenharmony_ci else if(!up){ 999cabdff1aSopenharmony_ci if(itype == PLANE_PRED8x8)itype = HOR_PRED8x8; 1000cabdff1aSopenharmony_ci if(itype == VERT_PRED8x8) itype = HOR_PRED8x8; 1001cabdff1aSopenharmony_ci if(itype == DC_PRED8x8) itype = LEFT_DC_PRED8x8; 1002cabdff1aSopenharmony_ci }else if(!left){ 1003cabdff1aSopenharmony_ci if(itype == PLANE_PRED8x8)itype = VERT_PRED8x8; 1004cabdff1aSopenharmony_ci if(itype == HOR_PRED8x8) itype = VERT_PRED8x8; 1005cabdff1aSopenharmony_ci if(itype == DC_PRED8x8) itype = TOP_DC_PRED8x8; 1006cabdff1aSopenharmony_ci } 1007cabdff1aSopenharmony_ci return itype; 1008cabdff1aSopenharmony_ci} 1009cabdff1aSopenharmony_ci 1010cabdff1aSopenharmony_cistatic inline void rv34_process_block(RV34DecContext *r, 1011cabdff1aSopenharmony_ci uint8_t *pdst, int stride, 1012cabdff1aSopenharmony_ci int fc, int sc, int q_dc, int q_ac) 1013cabdff1aSopenharmony_ci{ 1014cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1015cabdff1aSopenharmony_ci int16_t *ptr = s->block[0]; 1016cabdff1aSopenharmony_ci int has_ac = rv34_decode_block(ptr, &s->gb, r->cur_vlcs, 1017cabdff1aSopenharmony_ci fc, sc, q_dc, q_ac, q_ac); 1018cabdff1aSopenharmony_ci if(has_ac){ 1019cabdff1aSopenharmony_ci r->rdsp.rv34_idct_add(pdst, stride, ptr); 1020cabdff1aSopenharmony_ci }else{ 1021cabdff1aSopenharmony_ci r->rdsp.rv34_idct_dc_add(pdst, stride, ptr[0]); 1022cabdff1aSopenharmony_ci ptr[0] = 0; 1023cabdff1aSopenharmony_ci } 1024cabdff1aSopenharmony_ci} 1025cabdff1aSopenharmony_ci 1026cabdff1aSopenharmony_cistatic void rv34_output_i16x16(RV34DecContext *r, int8_t *intra_types, int cbp) 1027cabdff1aSopenharmony_ci{ 1028cabdff1aSopenharmony_ci LOCAL_ALIGNED_16(int16_t, block16, [16]); 1029cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1030cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 1031cabdff1aSopenharmony_ci int q_dc = rv34_qscale_tab[ r->luma_dc_quant_i[s->qscale] ], 1032cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[s->qscale]; 1033cabdff1aSopenharmony_ci uint8_t *dst = s->dest[0]; 1034cabdff1aSopenharmony_ci int16_t *ptr = s->block[0]; 1035cabdff1aSopenharmony_ci int i, j, itype, has_ac; 1036cabdff1aSopenharmony_ci 1037cabdff1aSopenharmony_ci memset(block16, 0, 16 * sizeof(*block16)); 1038cabdff1aSopenharmony_ci 1039cabdff1aSopenharmony_ci has_ac = rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac); 1040cabdff1aSopenharmony_ci if(has_ac) 1041cabdff1aSopenharmony_ci r->rdsp.rv34_inv_transform(block16); 1042cabdff1aSopenharmony_ci else 1043cabdff1aSopenharmony_ci r->rdsp.rv34_inv_transform_dc(block16); 1044cabdff1aSopenharmony_ci 1045cabdff1aSopenharmony_ci itype = ittrans16[intra_types[0]]; 1046cabdff1aSopenharmony_ci itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]); 1047cabdff1aSopenharmony_ci r->h.pred16x16[itype](dst, s->linesize); 1048cabdff1aSopenharmony_ci 1049cabdff1aSopenharmony_ci for(j = 0; j < 4; j++){ 1050cabdff1aSopenharmony_ci for(i = 0; i < 4; i++, cbp >>= 1){ 1051cabdff1aSopenharmony_ci int dc = block16[i + j*4]; 1052cabdff1aSopenharmony_ci 1053cabdff1aSopenharmony_ci if(cbp & 1){ 1054cabdff1aSopenharmony_ci has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac); 1055cabdff1aSopenharmony_ci }else 1056cabdff1aSopenharmony_ci has_ac = 0; 1057cabdff1aSopenharmony_ci 1058cabdff1aSopenharmony_ci if(has_ac){ 1059cabdff1aSopenharmony_ci ptr[0] = dc; 1060cabdff1aSopenharmony_ci r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr); 1061cabdff1aSopenharmony_ci }else 1062cabdff1aSopenharmony_ci r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc); 1063cabdff1aSopenharmony_ci } 1064cabdff1aSopenharmony_ci 1065cabdff1aSopenharmony_ci dst += 4*s->linesize; 1066cabdff1aSopenharmony_ci } 1067cabdff1aSopenharmony_ci 1068cabdff1aSopenharmony_ci itype = ittrans16[intra_types[0]]; 1069cabdff1aSopenharmony_ci if(itype == PLANE_PRED8x8) itype = DC_PRED8x8; 1070cabdff1aSopenharmony_ci itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]); 1071cabdff1aSopenharmony_ci 1072cabdff1aSopenharmony_ci q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; 1073cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; 1074cabdff1aSopenharmony_ci 1075cabdff1aSopenharmony_ci for(j = 1; j < 3; j++){ 1076cabdff1aSopenharmony_ci dst = s->dest[j]; 1077cabdff1aSopenharmony_ci r->h.pred8x8[itype](dst, s->uvlinesize); 1078cabdff1aSopenharmony_ci for(i = 0; i < 4; i++, cbp >>= 1){ 1079cabdff1aSopenharmony_ci uint8_t *pdst; 1080cabdff1aSopenharmony_ci if(!(cbp & 1)) continue; 1081cabdff1aSopenharmony_ci pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize; 1082cabdff1aSopenharmony_ci 1083cabdff1aSopenharmony_ci rv34_process_block(r, pdst, s->uvlinesize, 1084cabdff1aSopenharmony_ci r->chroma_vlc, 1, q_dc, q_ac); 1085cabdff1aSopenharmony_ci } 1086cabdff1aSopenharmony_ci } 1087cabdff1aSopenharmony_ci} 1088cabdff1aSopenharmony_ci 1089cabdff1aSopenharmony_cistatic void rv34_output_intra(RV34DecContext *r, int8_t *intra_types, int cbp) 1090cabdff1aSopenharmony_ci{ 1091cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1092cabdff1aSopenharmony_ci uint8_t *dst = s->dest[0]; 1093cabdff1aSopenharmony_ci int avail[6*8] = {0}; 1094cabdff1aSopenharmony_ci int i, j, k; 1095cabdff1aSopenharmony_ci int idx, q_ac, q_dc; 1096cabdff1aSopenharmony_ci 1097cabdff1aSopenharmony_ci // Set neighbour information. 1098cabdff1aSopenharmony_ci if(r->avail_cache[1]) 1099cabdff1aSopenharmony_ci avail[0] = 1; 1100cabdff1aSopenharmony_ci if(r->avail_cache[2]) 1101cabdff1aSopenharmony_ci avail[1] = avail[2] = 1; 1102cabdff1aSopenharmony_ci if(r->avail_cache[3]) 1103cabdff1aSopenharmony_ci avail[3] = avail[4] = 1; 1104cabdff1aSopenharmony_ci if(r->avail_cache[4]) 1105cabdff1aSopenharmony_ci avail[5] = 1; 1106cabdff1aSopenharmony_ci if(r->avail_cache[5]) 1107cabdff1aSopenharmony_ci avail[8] = avail[16] = 1; 1108cabdff1aSopenharmony_ci if(r->avail_cache[9]) 1109cabdff1aSopenharmony_ci avail[24] = avail[32] = 1; 1110cabdff1aSopenharmony_ci 1111cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[s->qscale]; 1112cabdff1aSopenharmony_ci for(j = 0; j < 4; j++){ 1113cabdff1aSopenharmony_ci idx = 9 + j*8; 1114cabdff1aSopenharmony_ci for(i = 0; i < 4; i++, cbp >>= 1, dst += 4, idx++){ 1115cabdff1aSopenharmony_ci rv34_pred_4x4_block(r, dst, s->linesize, ittrans[intra_types[i]], avail[idx-8], avail[idx-1], avail[idx+7], avail[idx-7]); 1116cabdff1aSopenharmony_ci avail[idx] = 1; 1117cabdff1aSopenharmony_ci if(!(cbp & 1)) continue; 1118cabdff1aSopenharmony_ci 1119cabdff1aSopenharmony_ci rv34_process_block(r, dst, s->linesize, 1120cabdff1aSopenharmony_ci r->luma_vlc, 0, q_ac, q_ac); 1121cabdff1aSopenharmony_ci } 1122cabdff1aSopenharmony_ci dst += s->linesize * 4 - 4*4; 1123cabdff1aSopenharmony_ci intra_types += r->intra_types_stride; 1124cabdff1aSopenharmony_ci } 1125cabdff1aSopenharmony_ci 1126cabdff1aSopenharmony_ci intra_types -= r->intra_types_stride * 4; 1127cabdff1aSopenharmony_ci 1128cabdff1aSopenharmony_ci q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; 1129cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; 1130cabdff1aSopenharmony_ci 1131cabdff1aSopenharmony_ci for(k = 0; k < 2; k++){ 1132cabdff1aSopenharmony_ci dst = s->dest[1+k]; 1133cabdff1aSopenharmony_ci fill_rectangle(r->avail_cache + 6, 2, 2, 4, 0, 4); 1134cabdff1aSopenharmony_ci 1135cabdff1aSopenharmony_ci for(j = 0; j < 2; j++){ 1136cabdff1aSopenharmony_ci int* acache = r->avail_cache + 6 + j*4; 1137cabdff1aSopenharmony_ci for(i = 0; i < 2; i++, cbp >>= 1, acache++){ 1138cabdff1aSopenharmony_ci int itype = ittrans[intra_types[i*2+j*2*r->intra_types_stride]]; 1139cabdff1aSopenharmony_ci rv34_pred_4x4_block(r, dst+4*i, s->uvlinesize, itype, acache[-4], acache[-1], !i && !j, acache[-3]); 1140cabdff1aSopenharmony_ci acache[0] = 1; 1141cabdff1aSopenharmony_ci 1142cabdff1aSopenharmony_ci if(!(cbp&1)) continue; 1143cabdff1aSopenharmony_ci 1144cabdff1aSopenharmony_ci rv34_process_block(r, dst + 4*i, s->uvlinesize, 1145cabdff1aSopenharmony_ci r->chroma_vlc, 1, q_dc, q_ac); 1146cabdff1aSopenharmony_ci } 1147cabdff1aSopenharmony_ci 1148cabdff1aSopenharmony_ci dst += 4*s->uvlinesize; 1149cabdff1aSopenharmony_ci } 1150cabdff1aSopenharmony_ci } 1151cabdff1aSopenharmony_ci} 1152cabdff1aSopenharmony_ci 1153cabdff1aSopenharmony_cistatic int is_mv_diff_gt_3(int16_t (*motion_val)[2], int step) 1154cabdff1aSopenharmony_ci{ 1155cabdff1aSopenharmony_ci int d; 1156cabdff1aSopenharmony_ci d = motion_val[0][0] - motion_val[-step][0]; 1157cabdff1aSopenharmony_ci if(d < -3 || d > 3) 1158cabdff1aSopenharmony_ci return 1; 1159cabdff1aSopenharmony_ci d = motion_val[0][1] - motion_val[-step][1]; 1160cabdff1aSopenharmony_ci if(d < -3 || d > 3) 1161cabdff1aSopenharmony_ci return 1; 1162cabdff1aSopenharmony_ci return 0; 1163cabdff1aSopenharmony_ci} 1164cabdff1aSopenharmony_ci 1165cabdff1aSopenharmony_cistatic int rv34_set_deblock_coef(RV34DecContext *r) 1166cabdff1aSopenharmony_ci{ 1167cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1168cabdff1aSopenharmony_ci int hmvmask = 0, vmvmask = 0, i, j; 1169cabdff1aSopenharmony_ci int midx = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride; 1170cabdff1aSopenharmony_ci int16_t (*motion_val)[2] = &s->current_picture_ptr->motion_val[0][midx]; 1171cabdff1aSopenharmony_ci for(j = 0; j < 16; j += 8){ 1172cabdff1aSopenharmony_ci for(i = 0; i < 2; i++){ 1173cabdff1aSopenharmony_ci if(is_mv_diff_gt_3(motion_val + i, 1)) 1174cabdff1aSopenharmony_ci vmvmask |= 0x11 << (j + i*2); 1175cabdff1aSopenharmony_ci if((j || s->mb_y) && is_mv_diff_gt_3(motion_val + i, s->b8_stride)) 1176cabdff1aSopenharmony_ci hmvmask |= 0x03 << (j + i*2); 1177cabdff1aSopenharmony_ci } 1178cabdff1aSopenharmony_ci motion_val += s->b8_stride; 1179cabdff1aSopenharmony_ci } 1180cabdff1aSopenharmony_ci if(s->first_slice_line) 1181cabdff1aSopenharmony_ci hmvmask &= ~0x000F; 1182cabdff1aSopenharmony_ci if(!s->mb_x) 1183cabdff1aSopenharmony_ci vmvmask &= ~0x1111; 1184cabdff1aSopenharmony_ci if(r->rv30){ //RV30 marks both subblocks on the edge for filtering 1185cabdff1aSopenharmony_ci vmvmask |= (vmvmask & 0x4444) >> 1; 1186cabdff1aSopenharmony_ci hmvmask |= (hmvmask & 0x0F00) >> 4; 1187cabdff1aSopenharmony_ci if(s->mb_x) 1188cabdff1aSopenharmony_ci r->deblock_coefs[s->mb_x - 1 + s->mb_y*s->mb_stride] |= (vmvmask & 0x1111) << 3; 1189cabdff1aSopenharmony_ci if(!s->first_slice_line) 1190cabdff1aSopenharmony_ci r->deblock_coefs[s->mb_x + (s->mb_y - 1)*s->mb_stride] |= (hmvmask & 0xF) << 12; 1191cabdff1aSopenharmony_ci } 1192cabdff1aSopenharmony_ci return hmvmask | vmvmask; 1193cabdff1aSopenharmony_ci} 1194cabdff1aSopenharmony_ci 1195cabdff1aSopenharmony_cistatic int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types) 1196cabdff1aSopenharmony_ci{ 1197cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1198cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 1199cabdff1aSopenharmony_ci uint8_t *dst = s->dest[0]; 1200cabdff1aSopenharmony_ci int16_t *ptr = s->block[0]; 1201cabdff1aSopenharmony_ci int mb_pos = s->mb_x + s->mb_y * s->mb_stride; 1202cabdff1aSopenharmony_ci int cbp, cbp2; 1203cabdff1aSopenharmony_ci int q_dc, q_ac, has_ac; 1204cabdff1aSopenharmony_ci int i, j; 1205cabdff1aSopenharmony_ci int dist; 1206cabdff1aSopenharmony_ci 1207cabdff1aSopenharmony_ci // Calculate which neighbours are available. Maybe it's worth optimizing too. 1208cabdff1aSopenharmony_ci memset(r->avail_cache, 0, sizeof(r->avail_cache)); 1209cabdff1aSopenharmony_ci fill_rectangle(r->avail_cache + 6, 2, 2, 4, 1, 4); 1210cabdff1aSopenharmony_ci dist = (s->mb_x - s->resync_mb_x) + (s->mb_y - s->resync_mb_y) * s->mb_width; 1211cabdff1aSopenharmony_ci if(s->mb_x && dist) 1212cabdff1aSopenharmony_ci r->avail_cache[5] = 1213cabdff1aSopenharmony_ci r->avail_cache[9] = s->current_picture_ptr->mb_type[mb_pos - 1]; 1214cabdff1aSopenharmony_ci if(dist >= s->mb_width) 1215cabdff1aSopenharmony_ci r->avail_cache[2] = 1216cabdff1aSopenharmony_ci r->avail_cache[3] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride]; 1217cabdff1aSopenharmony_ci if(((s->mb_x+1) < s->mb_width) && dist >= s->mb_width - 1) 1218cabdff1aSopenharmony_ci r->avail_cache[4] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride + 1]; 1219cabdff1aSopenharmony_ci if(s->mb_x && dist > s->mb_width) 1220cabdff1aSopenharmony_ci r->avail_cache[1] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride - 1]; 1221cabdff1aSopenharmony_ci 1222cabdff1aSopenharmony_ci s->qscale = r->si.quant; 1223cabdff1aSopenharmony_ci cbp = cbp2 = rv34_decode_inter_mb_header(r, intra_types); 1224cabdff1aSopenharmony_ci r->cbp_luma [mb_pos] = cbp; 1225cabdff1aSopenharmony_ci r->cbp_chroma[mb_pos] = cbp >> 16; 1226cabdff1aSopenharmony_ci r->deblock_coefs[mb_pos] = rv34_set_deblock_coef(r) | r->cbp_luma[mb_pos]; 1227cabdff1aSopenharmony_ci s->current_picture_ptr->qscale_table[mb_pos] = s->qscale; 1228cabdff1aSopenharmony_ci 1229cabdff1aSopenharmony_ci if(cbp == -1) 1230cabdff1aSopenharmony_ci return -1; 1231cabdff1aSopenharmony_ci 1232cabdff1aSopenharmony_ci if (IS_INTRA(s->current_picture_ptr->mb_type[mb_pos])){ 1233cabdff1aSopenharmony_ci if(r->is16) rv34_output_i16x16(r, intra_types, cbp); 1234cabdff1aSopenharmony_ci else rv34_output_intra(r, intra_types, cbp); 1235cabdff1aSopenharmony_ci return 0; 1236cabdff1aSopenharmony_ci } 1237cabdff1aSopenharmony_ci 1238cabdff1aSopenharmony_ci if(r->is16){ 1239cabdff1aSopenharmony_ci // Only for RV34_MB_P_MIX16x16 1240cabdff1aSopenharmony_ci LOCAL_ALIGNED_16(int16_t, block16, [16]); 1241cabdff1aSopenharmony_ci memset(block16, 0, 16 * sizeof(*block16)); 1242cabdff1aSopenharmony_ci q_dc = rv34_qscale_tab[ r->luma_dc_quant_p[s->qscale] ]; 1243cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[s->qscale]; 1244cabdff1aSopenharmony_ci if (rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac)) 1245cabdff1aSopenharmony_ci r->rdsp.rv34_inv_transform(block16); 1246cabdff1aSopenharmony_ci else 1247cabdff1aSopenharmony_ci r->rdsp.rv34_inv_transform_dc(block16); 1248cabdff1aSopenharmony_ci 1249cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[s->qscale]; 1250cabdff1aSopenharmony_ci 1251cabdff1aSopenharmony_ci for(j = 0; j < 4; j++){ 1252cabdff1aSopenharmony_ci for(i = 0; i < 4; i++, cbp >>= 1){ 1253cabdff1aSopenharmony_ci int dc = block16[i + j*4]; 1254cabdff1aSopenharmony_ci 1255cabdff1aSopenharmony_ci if(cbp & 1){ 1256cabdff1aSopenharmony_ci has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac); 1257cabdff1aSopenharmony_ci }else 1258cabdff1aSopenharmony_ci has_ac = 0; 1259cabdff1aSopenharmony_ci 1260cabdff1aSopenharmony_ci if(has_ac){ 1261cabdff1aSopenharmony_ci ptr[0] = dc; 1262cabdff1aSopenharmony_ci r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr); 1263cabdff1aSopenharmony_ci }else 1264cabdff1aSopenharmony_ci r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc); 1265cabdff1aSopenharmony_ci } 1266cabdff1aSopenharmony_ci 1267cabdff1aSopenharmony_ci dst += 4*s->linesize; 1268cabdff1aSopenharmony_ci } 1269cabdff1aSopenharmony_ci 1270cabdff1aSopenharmony_ci r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); 1271cabdff1aSopenharmony_ci }else{ 1272cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[s->qscale]; 1273cabdff1aSopenharmony_ci 1274cabdff1aSopenharmony_ci for(j = 0; j < 4; j++){ 1275cabdff1aSopenharmony_ci for(i = 0; i < 4; i++, cbp >>= 1){ 1276cabdff1aSopenharmony_ci if(!(cbp & 1)) continue; 1277cabdff1aSopenharmony_ci 1278cabdff1aSopenharmony_ci rv34_process_block(r, dst + 4*i, s->linesize, 1279cabdff1aSopenharmony_ci r->luma_vlc, 0, q_ac, q_ac); 1280cabdff1aSopenharmony_ci } 1281cabdff1aSopenharmony_ci dst += 4*s->linesize; 1282cabdff1aSopenharmony_ci } 1283cabdff1aSopenharmony_ci } 1284cabdff1aSopenharmony_ci 1285cabdff1aSopenharmony_ci q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; 1286cabdff1aSopenharmony_ci q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; 1287cabdff1aSopenharmony_ci 1288cabdff1aSopenharmony_ci for(j = 1; j < 3; j++){ 1289cabdff1aSopenharmony_ci dst = s->dest[j]; 1290cabdff1aSopenharmony_ci for(i = 0; i < 4; i++, cbp >>= 1){ 1291cabdff1aSopenharmony_ci uint8_t *pdst; 1292cabdff1aSopenharmony_ci if(!(cbp & 1)) continue; 1293cabdff1aSopenharmony_ci pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize; 1294cabdff1aSopenharmony_ci 1295cabdff1aSopenharmony_ci rv34_process_block(r, pdst, s->uvlinesize, 1296cabdff1aSopenharmony_ci r->chroma_vlc, 1, q_dc, q_ac); 1297cabdff1aSopenharmony_ci } 1298cabdff1aSopenharmony_ci } 1299cabdff1aSopenharmony_ci 1300cabdff1aSopenharmony_ci return 0; 1301cabdff1aSopenharmony_ci} 1302cabdff1aSopenharmony_ci 1303cabdff1aSopenharmony_cistatic int rv34_decode_intra_macroblock(RV34DecContext *r, int8_t *intra_types) 1304cabdff1aSopenharmony_ci{ 1305cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1306cabdff1aSopenharmony_ci int cbp, dist; 1307cabdff1aSopenharmony_ci int mb_pos = s->mb_x + s->mb_y * s->mb_stride; 1308cabdff1aSopenharmony_ci 1309cabdff1aSopenharmony_ci // Calculate which neighbours are available. Maybe it's worth optimizing too. 1310cabdff1aSopenharmony_ci memset(r->avail_cache, 0, sizeof(r->avail_cache)); 1311cabdff1aSopenharmony_ci fill_rectangle(r->avail_cache + 6, 2, 2, 4, 1, 4); 1312cabdff1aSopenharmony_ci dist = (s->mb_x - s->resync_mb_x) + (s->mb_y - s->resync_mb_y) * s->mb_width; 1313cabdff1aSopenharmony_ci if(s->mb_x && dist) 1314cabdff1aSopenharmony_ci r->avail_cache[5] = 1315cabdff1aSopenharmony_ci r->avail_cache[9] = s->current_picture_ptr->mb_type[mb_pos - 1]; 1316cabdff1aSopenharmony_ci if(dist >= s->mb_width) 1317cabdff1aSopenharmony_ci r->avail_cache[2] = 1318cabdff1aSopenharmony_ci r->avail_cache[3] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride]; 1319cabdff1aSopenharmony_ci if(((s->mb_x+1) < s->mb_width) && dist >= s->mb_width - 1) 1320cabdff1aSopenharmony_ci r->avail_cache[4] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride + 1]; 1321cabdff1aSopenharmony_ci if(s->mb_x && dist > s->mb_width) 1322cabdff1aSopenharmony_ci r->avail_cache[1] = s->current_picture_ptr->mb_type[mb_pos - s->mb_stride - 1]; 1323cabdff1aSopenharmony_ci 1324cabdff1aSopenharmony_ci s->qscale = r->si.quant; 1325cabdff1aSopenharmony_ci cbp = rv34_decode_intra_mb_header(r, intra_types); 1326cabdff1aSopenharmony_ci r->cbp_luma [mb_pos] = cbp; 1327cabdff1aSopenharmony_ci r->cbp_chroma[mb_pos] = cbp >> 16; 1328cabdff1aSopenharmony_ci r->deblock_coefs[mb_pos] = 0xFFFF; 1329cabdff1aSopenharmony_ci s->current_picture_ptr->qscale_table[mb_pos] = s->qscale; 1330cabdff1aSopenharmony_ci 1331cabdff1aSopenharmony_ci if(cbp == -1) 1332cabdff1aSopenharmony_ci return -1; 1333cabdff1aSopenharmony_ci 1334cabdff1aSopenharmony_ci if(r->is16){ 1335cabdff1aSopenharmony_ci rv34_output_i16x16(r, intra_types, cbp); 1336cabdff1aSopenharmony_ci return 0; 1337cabdff1aSopenharmony_ci } 1338cabdff1aSopenharmony_ci 1339cabdff1aSopenharmony_ci rv34_output_intra(r, intra_types, cbp); 1340cabdff1aSopenharmony_ci return 0; 1341cabdff1aSopenharmony_ci} 1342cabdff1aSopenharmony_ci 1343cabdff1aSopenharmony_cistatic int check_slice_end(RV34DecContext *r, MpegEncContext *s) 1344cabdff1aSopenharmony_ci{ 1345cabdff1aSopenharmony_ci int bits; 1346cabdff1aSopenharmony_ci if(s->mb_y >= s->mb_height) 1347cabdff1aSopenharmony_ci return 1; 1348cabdff1aSopenharmony_ci if(!s->mb_num_left) 1349cabdff1aSopenharmony_ci return 1; 1350cabdff1aSopenharmony_ci if(r->s.mb_skip_run > 1) 1351cabdff1aSopenharmony_ci return 0; 1352cabdff1aSopenharmony_ci bits = get_bits_left(&s->gb); 1353cabdff1aSopenharmony_ci if(bits <= 0 || (bits < 8 && !show_bits(&s->gb, bits))) 1354cabdff1aSopenharmony_ci return 1; 1355cabdff1aSopenharmony_ci return 0; 1356cabdff1aSopenharmony_ci} 1357cabdff1aSopenharmony_ci 1358cabdff1aSopenharmony_ci 1359cabdff1aSopenharmony_cistatic void rv34_decoder_free(RV34DecContext *r) 1360cabdff1aSopenharmony_ci{ 1361cabdff1aSopenharmony_ci av_freep(&r->intra_types_hist); 1362cabdff1aSopenharmony_ci r->intra_types = NULL; 1363cabdff1aSopenharmony_ci av_freep(&r->tmp_b_block_base); 1364cabdff1aSopenharmony_ci av_freep(&r->mb_type); 1365cabdff1aSopenharmony_ci av_freep(&r->cbp_luma); 1366cabdff1aSopenharmony_ci av_freep(&r->cbp_chroma); 1367cabdff1aSopenharmony_ci av_freep(&r->deblock_coefs); 1368cabdff1aSopenharmony_ci} 1369cabdff1aSopenharmony_ci 1370cabdff1aSopenharmony_ci 1371cabdff1aSopenharmony_cistatic int rv34_decoder_alloc(RV34DecContext *r) 1372cabdff1aSopenharmony_ci{ 1373cabdff1aSopenharmony_ci r->intra_types_stride = r->s.mb_width * 4 + 4; 1374cabdff1aSopenharmony_ci 1375cabdff1aSopenharmony_ci r->cbp_chroma = av_mallocz(r->s.mb_stride * r->s.mb_height * 1376cabdff1aSopenharmony_ci sizeof(*r->cbp_chroma)); 1377cabdff1aSopenharmony_ci r->cbp_luma = av_mallocz(r->s.mb_stride * r->s.mb_height * 1378cabdff1aSopenharmony_ci sizeof(*r->cbp_luma)); 1379cabdff1aSopenharmony_ci r->deblock_coefs = av_mallocz(r->s.mb_stride * r->s.mb_height * 1380cabdff1aSopenharmony_ci sizeof(*r->deblock_coefs)); 1381cabdff1aSopenharmony_ci r->intra_types_hist = av_malloc(r->intra_types_stride * 4 * 2 * 1382cabdff1aSopenharmony_ci sizeof(*r->intra_types_hist)); 1383cabdff1aSopenharmony_ci r->mb_type = av_mallocz(r->s.mb_stride * r->s.mb_height * 1384cabdff1aSopenharmony_ci sizeof(*r->mb_type)); 1385cabdff1aSopenharmony_ci 1386cabdff1aSopenharmony_ci if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs && 1387cabdff1aSopenharmony_ci r->intra_types_hist && r->mb_type)) { 1388cabdff1aSopenharmony_ci r->s.context_reinit = 1; 1389cabdff1aSopenharmony_ci rv34_decoder_free(r); 1390cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1391cabdff1aSopenharmony_ci } 1392cabdff1aSopenharmony_ci 1393cabdff1aSopenharmony_ci r->intra_types = r->intra_types_hist + r->intra_types_stride * 4; 1394cabdff1aSopenharmony_ci 1395cabdff1aSopenharmony_ci return 0; 1396cabdff1aSopenharmony_ci} 1397cabdff1aSopenharmony_ci 1398cabdff1aSopenharmony_ci 1399cabdff1aSopenharmony_cistatic int rv34_decoder_realloc(RV34DecContext *r) 1400cabdff1aSopenharmony_ci{ 1401cabdff1aSopenharmony_ci rv34_decoder_free(r); 1402cabdff1aSopenharmony_ci return rv34_decoder_alloc(r); 1403cabdff1aSopenharmony_ci} 1404cabdff1aSopenharmony_ci 1405cabdff1aSopenharmony_ci 1406cabdff1aSopenharmony_cistatic int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int buf_size) 1407cabdff1aSopenharmony_ci{ 1408cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1409cabdff1aSopenharmony_ci GetBitContext *gb = &s->gb; 1410cabdff1aSopenharmony_ci int mb_pos, slice_type; 1411cabdff1aSopenharmony_ci int res; 1412cabdff1aSopenharmony_ci 1413cabdff1aSopenharmony_ci init_get_bits(&r->s.gb, buf, buf_size*8); 1414cabdff1aSopenharmony_ci res = r->parse_slice_header(r, gb, &r->si); 1415cabdff1aSopenharmony_ci if(res < 0){ 1416cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Incorrect or unknown slice header\n"); 1417cabdff1aSopenharmony_ci return -1; 1418cabdff1aSopenharmony_ci } 1419cabdff1aSopenharmony_ci 1420cabdff1aSopenharmony_ci slice_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I; 1421cabdff1aSopenharmony_ci if (slice_type != s->pict_type) { 1422cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n"); 1423cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1424cabdff1aSopenharmony_ci } 1425cabdff1aSopenharmony_ci if (s->width != r->si.width || s->height != r->si.height) { 1426cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Size mismatch\n"); 1427cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1428cabdff1aSopenharmony_ci } 1429cabdff1aSopenharmony_ci 1430cabdff1aSopenharmony_ci r->si.end = end; 1431cabdff1aSopenharmony_ci s->qscale = r->si.quant; 1432cabdff1aSopenharmony_ci s->mb_num_left = r->si.end - r->si.start; 1433cabdff1aSopenharmony_ci r->s.mb_skip_run = 0; 1434cabdff1aSopenharmony_ci 1435cabdff1aSopenharmony_ci mb_pos = s->mb_x + s->mb_y * s->mb_width; 1436cabdff1aSopenharmony_ci if(r->si.start != mb_pos){ 1437cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Slice indicates MB offset %d, got %d\n", r->si.start, mb_pos); 1438cabdff1aSopenharmony_ci s->mb_x = r->si.start % s->mb_width; 1439cabdff1aSopenharmony_ci s->mb_y = r->si.start / s->mb_width; 1440cabdff1aSopenharmony_ci } 1441cabdff1aSopenharmony_ci memset(r->intra_types_hist, -1, r->intra_types_stride * 4 * 2 * sizeof(*r->intra_types_hist)); 1442cabdff1aSopenharmony_ci s->first_slice_line = 1; 1443cabdff1aSopenharmony_ci s->resync_mb_x = s->mb_x; 1444cabdff1aSopenharmony_ci s->resync_mb_y = s->mb_y; 1445cabdff1aSopenharmony_ci 1446cabdff1aSopenharmony_ci ff_init_block_index(s); 1447cabdff1aSopenharmony_ci while(!check_slice_end(r, s)) { 1448cabdff1aSopenharmony_ci ff_update_block_index(s); 1449cabdff1aSopenharmony_ci 1450cabdff1aSopenharmony_ci if(r->si.type) 1451cabdff1aSopenharmony_ci res = rv34_decode_inter_macroblock(r, r->intra_types + s->mb_x * 4 + 4); 1452cabdff1aSopenharmony_ci else 1453cabdff1aSopenharmony_ci res = rv34_decode_intra_macroblock(r, r->intra_types + s->mb_x * 4 + 4); 1454cabdff1aSopenharmony_ci if(res < 0){ 1455cabdff1aSopenharmony_ci ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_ERROR); 1456cabdff1aSopenharmony_ci return -1; 1457cabdff1aSopenharmony_ci } 1458cabdff1aSopenharmony_ci if (++s->mb_x == s->mb_width) { 1459cabdff1aSopenharmony_ci s->mb_x = 0; 1460cabdff1aSopenharmony_ci s->mb_y++; 1461cabdff1aSopenharmony_ci ff_init_block_index(s); 1462cabdff1aSopenharmony_ci 1463cabdff1aSopenharmony_ci memmove(r->intra_types_hist, r->intra_types, r->intra_types_stride * 4 * sizeof(*r->intra_types_hist)); 1464cabdff1aSopenharmony_ci memset(r->intra_types, -1, r->intra_types_stride * 4 * sizeof(*r->intra_types_hist)); 1465cabdff1aSopenharmony_ci 1466cabdff1aSopenharmony_ci if(r->loop_filter && s->mb_y >= 2) 1467cabdff1aSopenharmony_ci r->loop_filter(r, s->mb_y - 2); 1468cabdff1aSopenharmony_ci 1469cabdff1aSopenharmony_ci if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) 1470cabdff1aSopenharmony_ci ff_thread_report_progress(&s->current_picture_ptr->tf, 1471cabdff1aSopenharmony_ci s->mb_y - 2, 0); 1472cabdff1aSopenharmony_ci 1473cabdff1aSopenharmony_ci } 1474cabdff1aSopenharmony_ci if(s->mb_x == s->resync_mb_x) 1475cabdff1aSopenharmony_ci s->first_slice_line=0; 1476cabdff1aSopenharmony_ci s->mb_num_left--; 1477cabdff1aSopenharmony_ci } 1478cabdff1aSopenharmony_ci ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END); 1479cabdff1aSopenharmony_ci 1480cabdff1aSopenharmony_ci return s->mb_y == s->mb_height; 1481cabdff1aSopenharmony_ci} 1482cabdff1aSopenharmony_ci 1483cabdff1aSopenharmony_ci/** @} */ // reconstruction group end 1484cabdff1aSopenharmony_ci 1485cabdff1aSopenharmony_ci/** 1486cabdff1aSopenharmony_ci * Initialize decoder. 1487cabdff1aSopenharmony_ci */ 1488cabdff1aSopenharmony_ciav_cold int ff_rv34_decode_init(AVCodecContext *avctx) 1489cabdff1aSopenharmony_ci{ 1490cabdff1aSopenharmony_ci static AVOnce init_static_once = AV_ONCE_INIT; 1491cabdff1aSopenharmony_ci RV34DecContext *r = avctx->priv_data; 1492cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1493cabdff1aSopenharmony_ci int ret; 1494cabdff1aSopenharmony_ci 1495cabdff1aSopenharmony_ci ff_mpv_decode_init(s, avctx); 1496cabdff1aSopenharmony_ci s->out_format = FMT_H263; 1497cabdff1aSopenharmony_ci 1498cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV420P; 1499cabdff1aSopenharmony_ci avctx->has_b_frames = 1; 1500cabdff1aSopenharmony_ci s->low_delay = 0; 1501cabdff1aSopenharmony_ci 1502cabdff1aSopenharmony_ci ff_mpv_idct_init(s); 1503cabdff1aSopenharmony_ci if ((ret = ff_mpv_common_init(s)) < 0) 1504cabdff1aSopenharmony_ci return ret; 1505cabdff1aSopenharmony_ci 1506cabdff1aSopenharmony_ci ff_h264_pred_init(&r->h, AV_CODEC_ID_RV40, 8, 1); 1507cabdff1aSopenharmony_ci 1508cabdff1aSopenharmony_ci if ((ret = rv34_decoder_alloc(r)) < 0) { 1509cabdff1aSopenharmony_ci ff_mpv_common_end(&r->s); 1510cabdff1aSopenharmony_ci return ret; 1511cabdff1aSopenharmony_ci } 1512cabdff1aSopenharmony_ci 1513cabdff1aSopenharmony_ci ff_thread_once(&init_static_once, rv34_init_tables); 1514cabdff1aSopenharmony_ci 1515cabdff1aSopenharmony_ci return 0; 1516cabdff1aSopenharmony_ci} 1517cabdff1aSopenharmony_ci 1518cabdff1aSopenharmony_ciint ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src) 1519cabdff1aSopenharmony_ci{ 1520cabdff1aSopenharmony_ci RV34DecContext *r = dst->priv_data, *r1 = src->priv_data; 1521cabdff1aSopenharmony_ci MpegEncContext * const s = &r->s, * const s1 = &r1->s; 1522cabdff1aSopenharmony_ci int err; 1523cabdff1aSopenharmony_ci 1524cabdff1aSopenharmony_ci if (dst == src || !s1->context_initialized) 1525cabdff1aSopenharmony_ci return 0; 1526cabdff1aSopenharmony_ci 1527cabdff1aSopenharmony_ci if (s->height != s1->height || s->width != s1->width || s->context_reinit) { 1528cabdff1aSopenharmony_ci s->height = s1->height; 1529cabdff1aSopenharmony_ci s->width = s1->width; 1530cabdff1aSopenharmony_ci if ((err = ff_mpv_common_frame_size_change(s)) < 0) 1531cabdff1aSopenharmony_ci return err; 1532cabdff1aSopenharmony_ci if ((err = rv34_decoder_realloc(r)) < 0) 1533cabdff1aSopenharmony_ci return err; 1534cabdff1aSopenharmony_ci } 1535cabdff1aSopenharmony_ci 1536cabdff1aSopenharmony_ci r->cur_pts = r1->cur_pts; 1537cabdff1aSopenharmony_ci r->last_pts = r1->last_pts; 1538cabdff1aSopenharmony_ci r->next_pts = r1->next_pts; 1539cabdff1aSopenharmony_ci 1540cabdff1aSopenharmony_ci memset(&r->si, 0, sizeof(r->si)); 1541cabdff1aSopenharmony_ci 1542cabdff1aSopenharmony_ci // Do no call ff_mpeg_update_thread_context on a partially initialized 1543cabdff1aSopenharmony_ci // decoder context. 1544cabdff1aSopenharmony_ci if (!s1->context_initialized) 1545cabdff1aSopenharmony_ci return 0; 1546cabdff1aSopenharmony_ci 1547cabdff1aSopenharmony_ci return ff_mpeg_update_thread_context(dst, src); 1548cabdff1aSopenharmony_ci} 1549cabdff1aSopenharmony_ci 1550cabdff1aSopenharmony_cistatic int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n, int slice_count, int buf_size) 1551cabdff1aSopenharmony_ci{ 1552cabdff1aSopenharmony_ci if (n < slice_count) { 1553cabdff1aSopenharmony_ci if(avctx->slice_count) return avctx->slice_offset[n]; 1554cabdff1aSopenharmony_ci else return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8); 1555cabdff1aSopenharmony_ci } else 1556cabdff1aSopenharmony_ci return buf_size; 1557cabdff1aSopenharmony_ci} 1558cabdff1aSopenharmony_ci 1559cabdff1aSopenharmony_cistatic int finish_frame(AVCodecContext *avctx, AVFrame *pict) 1560cabdff1aSopenharmony_ci{ 1561cabdff1aSopenharmony_ci RV34DecContext *r = avctx->priv_data; 1562cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1563cabdff1aSopenharmony_ci int got_picture = 0, ret; 1564cabdff1aSopenharmony_ci 1565cabdff1aSopenharmony_ci ff_er_frame_end(&s->er); 1566cabdff1aSopenharmony_ci ff_mpv_frame_end(s); 1567cabdff1aSopenharmony_ci s->mb_num_left = 0; 1568cabdff1aSopenharmony_ci 1569cabdff1aSopenharmony_ci if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) 1570cabdff1aSopenharmony_ci ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); 1571cabdff1aSopenharmony_ci 1572cabdff1aSopenharmony_ci if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) { 1573cabdff1aSopenharmony_ci if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) 1574cabdff1aSopenharmony_ci return ret; 1575cabdff1aSopenharmony_ci ff_print_debug_info(s, s->current_picture_ptr, pict); 1576cabdff1aSopenharmony_ci ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); 1577cabdff1aSopenharmony_ci got_picture = 1; 1578cabdff1aSopenharmony_ci } else if (s->last_picture_ptr) { 1579cabdff1aSopenharmony_ci if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) 1580cabdff1aSopenharmony_ci return ret; 1581cabdff1aSopenharmony_ci ff_print_debug_info(s, s->last_picture_ptr, pict); 1582cabdff1aSopenharmony_ci ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); 1583cabdff1aSopenharmony_ci got_picture = 1; 1584cabdff1aSopenharmony_ci } 1585cabdff1aSopenharmony_ci 1586cabdff1aSopenharmony_ci return got_picture; 1587cabdff1aSopenharmony_ci} 1588cabdff1aSopenharmony_ci 1589cabdff1aSopenharmony_cistatic AVRational update_sar(int old_w, int old_h, AVRational sar, int new_w, int new_h) 1590cabdff1aSopenharmony_ci{ 1591cabdff1aSopenharmony_ci // attempt to keep aspect during typical resolution switches 1592cabdff1aSopenharmony_ci if (!sar.num) 1593cabdff1aSopenharmony_ci sar = (AVRational){1, 1}; 1594cabdff1aSopenharmony_ci 1595cabdff1aSopenharmony_ci sar = av_mul_q(sar, av_mul_q((AVRational){new_h, new_w}, (AVRational){old_w, old_h})); 1596cabdff1aSopenharmony_ci return sar; 1597cabdff1aSopenharmony_ci} 1598cabdff1aSopenharmony_ci 1599cabdff1aSopenharmony_ciint ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict, 1600cabdff1aSopenharmony_ci int *got_picture_ptr, AVPacket *avpkt) 1601cabdff1aSopenharmony_ci{ 1602cabdff1aSopenharmony_ci const uint8_t *buf = avpkt->data; 1603cabdff1aSopenharmony_ci int buf_size = avpkt->size; 1604cabdff1aSopenharmony_ci RV34DecContext *r = avctx->priv_data; 1605cabdff1aSopenharmony_ci MpegEncContext *s = &r->s; 1606cabdff1aSopenharmony_ci SliceInfo si; 1607cabdff1aSopenharmony_ci int i, ret; 1608cabdff1aSopenharmony_ci int slice_count; 1609cabdff1aSopenharmony_ci const uint8_t *slices_hdr = NULL; 1610cabdff1aSopenharmony_ci int last = 0; 1611cabdff1aSopenharmony_ci int faulty_b = 0; 1612cabdff1aSopenharmony_ci int offset; 1613cabdff1aSopenharmony_ci 1614cabdff1aSopenharmony_ci /* no supplementary picture */ 1615cabdff1aSopenharmony_ci if (buf_size == 0) { 1616cabdff1aSopenharmony_ci /* special case for last picture */ 1617cabdff1aSopenharmony_ci if (s->low_delay==0 && s->next_picture_ptr) { 1618cabdff1aSopenharmony_ci if ((ret = av_frame_ref(pict, s->next_picture_ptr->f)) < 0) 1619cabdff1aSopenharmony_ci return ret; 1620cabdff1aSopenharmony_ci s->next_picture_ptr = NULL; 1621cabdff1aSopenharmony_ci 1622cabdff1aSopenharmony_ci *got_picture_ptr = 1; 1623cabdff1aSopenharmony_ci } 1624cabdff1aSopenharmony_ci return 0; 1625cabdff1aSopenharmony_ci } 1626cabdff1aSopenharmony_ci 1627cabdff1aSopenharmony_ci if(!avctx->slice_count){ 1628cabdff1aSopenharmony_ci slice_count = (*buf++) + 1; 1629cabdff1aSopenharmony_ci slices_hdr = buf + 4; 1630cabdff1aSopenharmony_ci buf += 8 * slice_count; 1631cabdff1aSopenharmony_ci buf_size -= 1 + 8 * slice_count; 1632cabdff1aSopenharmony_ci }else 1633cabdff1aSopenharmony_ci slice_count = avctx->slice_count; 1634cabdff1aSopenharmony_ci 1635cabdff1aSopenharmony_ci offset = get_slice_offset(avctx, slices_hdr, 0, slice_count, buf_size); 1636cabdff1aSopenharmony_ci //parse first slice header to check whether this frame can be decoded 1637cabdff1aSopenharmony_ci if(offset < 0 || offset > buf_size){ 1638cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); 1639cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1640cabdff1aSopenharmony_ci } 1641cabdff1aSopenharmony_ci init_get_bits(&s->gb, buf+offset, (buf_size-offset)*8); 1642cabdff1aSopenharmony_ci if(r->parse_slice_header(r, &r->s.gb, &si) < 0 || si.start){ 1643cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n"); 1644cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1645cabdff1aSopenharmony_ci } 1646cabdff1aSopenharmony_ci if ((!s->last_picture_ptr || !s->last_picture_ptr->f->data[0]) && 1647cabdff1aSopenharmony_ci si.type == AV_PICTURE_TYPE_B) { 1648cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid decoder state: B-frame without " 1649cabdff1aSopenharmony_ci "reference data.\n"); 1650cabdff1aSopenharmony_ci faulty_b = 1; 1651cabdff1aSopenharmony_ci } 1652cabdff1aSopenharmony_ci if( (avctx->skip_frame >= AVDISCARD_NONREF && si.type==AV_PICTURE_TYPE_B) 1653cabdff1aSopenharmony_ci || (avctx->skip_frame >= AVDISCARD_NONKEY && si.type!=AV_PICTURE_TYPE_I) 1654cabdff1aSopenharmony_ci || avctx->skip_frame >= AVDISCARD_ALL) 1655cabdff1aSopenharmony_ci return avpkt->size; 1656cabdff1aSopenharmony_ci 1657cabdff1aSopenharmony_ci /* first slice */ 1658cabdff1aSopenharmony_ci if (si.start == 0) { 1659cabdff1aSopenharmony_ci if (s->mb_num_left > 0 && s->current_picture_ptr) { 1660cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n", 1661cabdff1aSopenharmony_ci s->mb_num_left); 1662cabdff1aSopenharmony_ci if (!s->context_reinit) 1663cabdff1aSopenharmony_ci ff_er_frame_end(&s->er); 1664cabdff1aSopenharmony_ci ff_mpv_frame_end(s); 1665cabdff1aSopenharmony_ci } 1666cabdff1aSopenharmony_ci 1667cabdff1aSopenharmony_ci if (s->width != si.width || s->height != si.height || s->context_reinit) { 1668cabdff1aSopenharmony_ci int err; 1669cabdff1aSopenharmony_ci 1670cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n", 1671cabdff1aSopenharmony_ci si.width, si.height); 1672cabdff1aSopenharmony_ci 1673cabdff1aSopenharmony_ci if (av_image_check_size(si.width, si.height, 0, s->avctx)) 1674cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1675cabdff1aSopenharmony_ci 1676cabdff1aSopenharmony_ci s->avctx->sample_aspect_ratio = update_sar( 1677cabdff1aSopenharmony_ci s->width, s->height, s->avctx->sample_aspect_ratio, 1678cabdff1aSopenharmony_ci si.width, si.height); 1679cabdff1aSopenharmony_ci s->width = si.width; 1680cabdff1aSopenharmony_ci s->height = si.height; 1681cabdff1aSopenharmony_ci 1682cabdff1aSopenharmony_ci err = ff_set_dimensions(s->avctx, s->width, s->height); 1683cabdff1aSopenharmony_ci if (err < 0) 1684cabdff1aSopenharmony_ci return err; 1685cabdff1aSopenharmony_ci if ((err = ff_mpv_common_frame_size_change(s)) < 0) 1686cabdff1aSopenharmony_ci return err; 1687cabdff1aSopenharmony_ci if ((err = rv34_decoder_realloc(r)) < 0) 1688cabdff1aSopenharmony_ci return err; 1689cabdff1aSopenharmony_ci } 1690cabdff1aSopenharmony_ci if (faulty_b) 1691cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1692cabdff1aSopenharmony_ci s->pict_type = si.type ? si.type : AV_PICTURE_TYPE_I; 1693cabdff1aSopenharmony_ci if (ff_mpv_frame_start(s, s->avctx) < 0) 1694cabdff1aSopenharmony_ci return -1; 1695cabdff1aSopenharmony_ci ff_mpeg_er_frame_start(s); 1696cabdff1aSopenharmony_ci if (!r->tmp_b_block_base) { 1697cabdff1aSopenharmony_ci int i; 1698cabdff1aSopenharmony_ci 1699cabdff1aSopenharmony_ci r->tmp_b_block_base = av_malloc(s->linesize * 48); 1700cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) 1701cabdff1aSopenharmony_ci r->tmp_b_block_y[i] = r->tmp_b_block_base 1702cabdff1aSopenharmony_ci + i * 16 * s->linesize; 1703cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 1704cabdff1aSopenharmony_ci r->tmp_b_block_uv[i] = r->tmp_b_block_base + 32 * s->linesize 1705cabdff1aSopenharmony_ci + (i >> 1) * 8 * s->uvlinesize 1706cabdff1aSopenharmony_ci + (i & 1) * 16; 1707cabdff1aSopenharmony_ci } 1708cabdff1aSopenharmony_ci r->cur_pts = si.pts; 1709cabdff1aSopenharmony_ci if (s->pict_type != AV_PICTURE_TYPE_B) { 1710cabdff1aSopenharmony_ci r->last_pts = r->next_pts; 1711cabdff1aSopenharmony_ci r->next_pts = r->cur_pts; 1712cabdff1aSopenharmony_ci } else { 1713cabdff1aSopenharmony_ci int refdist = GET_PTS_DIFF(r->next_pts, r->last_pts); 1714cabdff1aSopenharmony_ci int dist0 = GET_PTS_DIFF(r->cur_pts, r->last_pts); 1715cabdff1aSopenharmony_ci int dist1 = GET_PTS_DIFF(r->next_pts, r->cur_pts); 1716cabdff1aSopenharmony_ci 1717cabdff1aSopenharmony_ci if(!refdist){ 1718cabdff1aSopenharmony_ci r->mv_weight1 = r->mv_weight2 = r->weight1 = r->weight2 = 8192; 1719cabdff1aSopenharmony_ci r->scaled_weight = 0; 1720cabdff1aSopenharmony_ci }else{ 1721cabdff1aSopenharmony_ci if (FFMAX(dist0, dist1) > refdist) 1722cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_TRACE, "distance overflow\n"); 1723cabdff1aSopenharmony_ci 1724cabdff1aSopenharmony_ci r->mv_weight1 = (dist0 << 14) / refdist; 1725cabdff1aSopenharmony_ci r->mv_weight2 = (dist1 << 14) / refdist; 1726cabdff1aSopenharmony_ci if((r->mv_weight1|r->mv_weight2) & 511){ 1727cabdff1aSopenharmony_ci r->weight1 = r->mv_weight1; 1728cabdff1aSopenharmony_ci r->weight2 = r->mv_weight2; 1729cabdff1aSopenharmony_ci r->scaled_weight = 0; 1730cabdff1aSopenharmony_ci }else{ 1731cabdff1aSopenharmony_ci r->weight1 = r->mv_weight1 >> 9; 1732cabdff1aSopenharmony_ci r->weight2 = r->mv_weight2 >> 9; 1733cabdff1aSopenharmony_ci r->scaled_weight = 1; 1734cabdff1aSopenharmony_ci } 1735cabdff1aSopenharmony_ci } 1736cabdff1aSopenharmony_ci } 1737cabdff1aSopenharmony_ci s->mb_x = s->mb_y = 0; 1738cabdff1aSopenharmony_ci ff_thread_finish_setup(s->avctx); 1739cabdff1aSopenharmony_ci } else if (s->context_reinit) { 1740cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames to " 1741cabdff1aSopenharmony_ci "reinitialize (start MB is %d).\n", si.start); 1742cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1743cabdff1aSopenharmony_ci } else if (HAVE_THREADS && 1744cabdff1aSopenharmony_ci (s->avctx->active_thread_type & FF_THREAD_FRAME)) { 1745cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames in frame " 1746cabdff1aSopenharmony_ci "multithreading mode (start MB is %d).\n", si.start); 1747cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1748cabdff1aSopenharmony_ci } 1749cabdff1aSopenharmony_ci 1750cabdff1aSopenharmony_ci for(i = 0; i < slice_count; i++){ 1751cabdff1aSopenharmony_ci int offset = get_slice_offset(avctx, slices_hdr, i , slice_count, buf_size); 1752cabdff1aSopenharmony_ci int offset1 = get_slice_offset(avctx, slices_hdr, i+1, slice_count, buf_size); 1753cabdff1aSopenharmony_ci int size; 1754cabdff1aSopenharmony_ci 1755cabdff1aSopenharmony_ci if(offset < 0 || offset > offset1 || offset1 > buf_size){ 1756cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); 1757cabdff1aSopenharmony_ci break; 1758cabdff1aSopenharmony_ci } 1759cabdff1aSopenharmony_ci size = offset1 - offset; 1760cabdff1aSopenharmony_ci 1761cabdff1aSopenharmony_ci r->si.end = s->mb_width * s->mb_height; 1762cabdff1aSopenharmony_ci s->mb_num_left = r->s.mb_x + r->s.mb_y*r->s.mb_width - r->si.start; 1763cabdff1aSopenharmony_ci 1764cabdff1aSopenharmony_ci if(i+1 < slice_count){ 1765cabdff1aSopenharmony_ci int offset2 = get_slice_offset(avctx, slices_hdr, i+2, slice_count, buf_size); 1766cabdff1aSopenharmony_ci if (offset2 < offset1 || offset2 > buf_size) { 1767cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); 1768cabdff1aSopenharmony_ci break; 1769cabdff1aSopenharmony_ci } 1770cabdff1aSopenharmony_ci init_get_bits(&s->gb, buf+offset1, (buf_size-offset1)*8); 1771cabdff1aSopenharmony_ci if(r->parse_slice_header(r, &r->s.gb, &si) < 0){ 1772cabdff1aSopenharmony_ci size = offset2 - offset; 1773cabdff1aSopenharmony_ci }else 1774cabdff1aSopenharmony_ci r->si.end = si.start; 1775cabdff1aSopenharmony_ci } 1776cabdff1aSopenharmony_ci av_assert0 (size >= 0 && size <= buf_size - offset); 1777cabdff1aSopenharmony_ci last = rv34_decode_slice(r, r->si.end, buf + offset, size); 1778cabdff1aSopenharmony_ci if(last) 1779cabdff1aSopenharmony_ci break; 1780cabdff1aSopenharmony_ci } 1781cabdff1aSopenharmony_ci 1782cabdff1aSopenharmony_ci if (s->current_picture_ptr) { 1783cabdff1aSopenharmony_ci if (last) { 1784cabdff1aSopenharmony_ci if(r->loop_filter) 1785cabdff1aSopenharmony_ci r->loop_filter(r, s->mb_height - 1); 1786cabdff1aSopenharmony_ci 1787cabdff1aSopenharmony_ci ret = finish_frame(avctx, pict); 1788cabdff1aSopenharmony_ci if (ret < 0) 1789cabdff1aSopenharmony_ci return ret; 1790cabdff1aSopenharmony_ci *got_picture_ptr = ret; 1791cabdff1aSopenharmony_ci } else if (HAVE_THREADS && 1792cabdff1aSopenharmony_ci (s->avctx->active_thread_type & FF_THREAD_FRAME)) { 1793cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "marking unfished frame as finished\n"); 1794cabdff1aSopenharmony_ci /* always mark the current frame as finished, frame-mt supports 1795cabdff1aSopenharmony_ci * only complete frames */ 1796cabdff1aSopenharmony_ci ff_er_frame_end(&s->er); 1797cabdff1aSopenharmony_ci ff_mpv_frame_end(s); 1798cabdff1aSopenharmony_ci s->mb_num_left = 0; 1799cabdff1aSopenharmony_ci ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); 1800cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1801cabdff1aSopenharmony_ci } 1802cabdff1aSopenharmony_ci } 1803cabdff1aSopenharmony_ci 1804cabdff1aSopenharmony_ci return avpkt->size; 1805cabdff1aSopenharmony_ci} 1806cabdff1aSopenharmony_ci 1807cabdff1aSopenharmony_ciav_cold int ff_rv34_decode_end(AVCodecContext *avctx) 1808cabdff1aSopenharmony_ci{ 1809cabdff1aSopenharmony_ci RV34DecContext *r = avctx->priv_data; 1810cabdff1aSopenharmony_ci 1811cabdff1aSopenharmony_ci ff_mpv_common_end(&r->s); 1812cabdff1aSopenharmony_ci rv34_decoder_free(r); 1813cabdff1aSopenharmony_ci 1814cabdff1aSopenharmony_ci return 0; 1815cabdff1aSopenharmony_ci} 1816