📄 rv34.c
字号:
/* * RV30/40 decoder common data * Copyright (c) 2007 Mike Melanson, Konstantin Shishkov * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file rv34.c * RV30/40 decoder common data */#include "avcodec.h"#include "dsputil.h"#include "mpegvideo.h"#include "golomb.h"#include "rectangle.h"#include "rv34vlc.h"#include "rv34data.h"#include "rv34.h"//#define DEBUG/** translation of RV30/40 macroblock types to lavc ones */static const int rv34_mb_type_to_lavc[12] = { MB_TYPE_INTRA, MB_TYPE_INTRA16x16, MB_TYPE_16x16 | MB_TYPE_L0, MB_TYPE_8x8 | MB_TYPE_L0, MB_TYPE_16x16 | MB_TYPE_L0, MB_TYPE_16x16 | MB_TYPE_L1, MB_TYPE_SKIP, MB_TYPE_DIRECT2 | MB_TYPE_16x16, MB_TYPE_16x8 | MB_TYPE_L0, MB_TYPE_8x16 | MB_TYPE_L0, MB_TYPE_16x16 | MB_TYPE_L0L1, MB_TYPE_16x16 | MB_TYPE_L0};static RV34VLC intra_vlcs[NUM_INTRA_TABLES], inter_vlcs[NUM_INTER_TABLES];/** * @defgroup vlc RV30/40 VLC generating functions * @{ *//** * Generate VLC from codeword lengths. * @param bits codeword lengths (zeroes are accepted) * @param size length of input data * @param insyms symbols for input codes (NULL for default ones) */static void rv34_gen_vlc(const uint8_t *bits, int size, VLC *vlc, const uint8_t *insyms){ int i; int counts[17] = {0}, codes[17];#ifdef __CW32__ uint16_t *cw, *syms; uint8_t *bits2;#else uint16_t cw[size], syms[size]; uint8_t bits2[size];#endif int maxbits = 0, realsize = 0;#ifdef __CW32__ cw = av_malloc(sizeof(uint16_t)*size); syms = av_malloc(sizeof(uint16_t)*size); bits2 = av_malloc(sizeof(uint8_t)*size);#endif for(i = 0; i < size; i++){ if(bits[i]){ bits2[realsize] = bits[i]; syms[realsize] = insyms ? insyms[i] : i; realsize++; maxbits = FFMAX(maxbits, bits[i]); counts[bits[i]]++; } } codes[0] = 0; for(i = 0; i < 16; i++) codes[i+1] = (codes[i] + counts[i]) << 1; for(i = 0; i < realsize; i++) cw[i] = codes[bits2[i]]++; init_vlc_sparse(vlc, FFMIN(maxbits, 9), realsize, bits2, 1, 1, cw, 2, 2, syms, 2, 2, INIT_VLC_USE_STATIC);#ifdef __CW32__ av_free(cw); av_free(syms); av_free(bits2);#endif}/** * Initialize all tables. */static av_cold void rv34_init_tables(){ int i, j, k; for(i = 0; i < NUM_INTRA_TABLES; i++){ for(j = 0; j < 2; j++){ rv34_gen_vlc(rv34_table_intra_cbppat [i][j], CBPPAT_VLC_SIZE, &intra_vlcs[i].cbppattern[j], NULL); rv34_gen_vlc(rv34_table_intra_secondpat[i][j], OTHERBLK_VLC_SIZE, &intra_vlcs[i].second_pattern[j], NULL); rv34_gen_vlc(rv34_table_intra_thirdpat [i][j], OTHERBLK_VLC_SIZE, &intra_vlcs[i].third_pattern[j], NULL); for(k = 0; k < 4; k++) rv34_gen_vlc(rv34_table_intra_cbp[i][j+k*2], CBP_VLC_SIZE, &intra_vlcs[i].cbp[j][k], rv34_cbp_code); } for(j = 0; j < 4; j++) rv34_gen_vlc(rv34_table_intra_firstpat[i][j], FIRSTBLK_VLC_SIZE, &intra_vlcs[i].first_pattern[j], NULL); rv34_gen_vlc(rv34_intra_coeff[i], COEFF_VLC_SIZE, &intra_vlcs[i].coefficient, NULL); } for(i = 0; i < NUM_INTER_TABLES; i++){ rv34_gen_vlc(rv34_inter_cbppat[i], CBPPAT_VLC_SIZE, &inter_vlcs[i].cbppattern[0], NULL); for(j = 0; j < 4; j++) rv34_gen_vlc(rv34_inter_cbp[i][j], CBP_VLC_SIZE, &inter_vlcs[i].cbp[0][j], rv34_cbp_code); for(j = 0; j < 2; j++){ rv34_gen_vlc(rv34_table_inter_firstpat [i][j], FIRSTBLK_VLC_SIZE, &inter_vlcs[i].first_pattern[j], NULL); rv34_gen_vlc(rv34_table_inter_secondpat[i][j], OTHERBLK_VLC_SIZE, &inter_vlcs[i].second_pattern[j], NULL); rv34_gen_vlc(rv34_table_inter_thirdpat [i][j], OTHERBLK_VLC_SIZE, &inter_vlcs[i].third_pattern[j], NULL); } rv34_gen_vlc(rv34_inter_coeff[i], COEFF_VLC_SIZE, &inter_vlcs[i].coefficient, NULL); }}/** @} */ // vlc group/** * @defgroup transform RV30/40 inverse transform functions * @{ */static av_always_inline void rv34_row_transform(int temp[16], DCTELEM *block){ int i; for(i=0; i<4; i++){ const int z0= 13*(block[i+8*0] + block[i+8*2]); const int z1= 13*(block[i+8*0] - block[i+8*2]); const int z2= 7* block[i+8*1] - 17*block[i+8*3]; const int z3= 17* block[i+8*1] + 7*block[i+8*3]; temp[4*i+0]= z0+z3; temp[4*i+1]= z1+z2; temp[4*i+2]= z1-z2; temp[4*i+3]= z0-z3; }}/** * Real Video 3.0/4.0 inverse transform * Code is almost the same as in SVQ3, only scaling is different. */static void rv34_inv_transform(DCTELEM *block){ int temp[16]; int i; rv34_row_transform(temp, block); for(i=0; i<4; i++){ const int z0= 13*(temp[4*0+i] + temp[4*2+i]) + 0x200; const int z1= 13*(temp[4*0+i] - temp[4*2+i]) + 0x200; const int z2= 7* temp[4*1+i] - 17*temp[4*3+i]; const int z3= 17* temp[4*1+i] + 7*temp[4*3+i]; block[i*8+0]= (z0 + z3)>>10; block[i*8+1]= (z1 + z2)>>10; block[i*8+2]= (z1 - z2)>>10; block[i*8+3]= (z0 - z3)>>10; }}/** * RealVideo 3.0/4.0 inverse transform for DC block * * Code is almost the same as rv34_inv_transform() * but final coefficients are multiplied by 1.5 and have no rounding. */static void rv34_inv_transform_noround(DCTELEM *block){ int temp[16]; int i; rv34_row_transform(temp, block); for(i=0; i<4; i++){ const int z0= 13*(temp[4*0+i] + temp[4*2+i]); const int z1= 13*(temp[4*0+i] - temp[4*2+i]); const int z2= 7* temp[4*1+i] - 17*temp[4*3+i]; const int z3= 17* temp[4*1+i] + 7*temp[4*3+i]; block[i*8+0]= ((z0 + z3)*3)>>11; block[i*8+1]= ((z1 + z2)*3)>>11; block[i*8+2]= ((z1 - z2)*3)>>11; block[i*8+3]= ((z0 - z3)*3)>>11; }}/** @} */ // transform/** * @defgroup block RV30/40 4x4 block decoding functions * @{ *//** * Decode coded block pattern. */static int rv34_decode_cbp(GetBitContext *gb, RV34VLC *vlc, int table){ int pattern, code, cbp=0; int ones; static const int cbp_masks[3] = {0x100000, 0x010000, 0x110000}; static const int shifts[4] = { 0, 2, 8, 10 };#ifdef __CW32__ int *curshift = (int*)shifts;#else int *curshift = shifts;#endif int i, t, mask; code = get_vlc2(gb, vlc->cbppattern[table].table, 9, 2); pattern = code & 0xF; code >>= 4; ones = rv34_count_ones[pattern]; for(mask = 8; mask; mask >>= 1, curshift++){ if(pattern & mask) cbp |= get_vlc2(gb, vlc->cbp[table][ones].table, vlc->cbp[table][ones].bits, 1) << curshift[0]; } for(i = 0; i < 4; i++){ t = modulo_three_table[code][i]; if(t == 1) cbp |= cbp_masks[get_bits1(gb)] << i; if(t == 2) cbp |= cbp_masks[2] << i; } return cbp;}/** * Get one coefficient value from the bistream and store it. */static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext *gb, VLC* vlc){ if(coef){ if(coef == esc){ coef = get_vlc2(gb, vlc->table, 9, 2); if(coef > 23){ coef -= 23; coef = 22 + ((1 << coef) | get_bits(gb, coef)); } coef += esc; } if(get_bits1(gb)) coef = -coef; *dst = coef; }}/** * Decode 2x2 subblock of coefficients. */static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc){ int coeffs[4]; coeffs[0] = modulo_three_table[code][0]; coeffs[1] = modulo_three_table[code][1]; coeffs[2] = modulo_three_table[code][2]; coeffs[3] = modulo_three_table[code][3]; decode_coeff(dst , coeffs[0], 3, gb, vlc); if(is_block2){ decode_coeff(dst+8, coeffs[1], 2, gb, vlc); decode_coeff(dst+1, coeffs[2], 2, gb, vlc); }else{ decode_coeff(dst+1, coeffs[1], 2, gb, vlc); decode_coeff(dst+8, coeffs[2], 2, gb, vlc); } decode_coeff(dst+9, coeffs[3], 2, gb, vlc);}/** * Decode coefficients for 4x4 block. * * This is done by filling 2x2 subblocks with decoded coefficients * in this order (the same for subblocks and subblock coefficients): * o--o * / * / * o--o */static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc){ int code, pattern; code = get_vlc2(gb, rvlc->first_pattern[fc].table, 9, 2); pattern = code & 0x7; code >>= 3; decode_subblock(dst, code, 0, gb, &rvlc->coefficient); if(pattern & 4){ code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient); } if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient); } if(pattern & 1){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -