📄 vc9.c
字号:
{ case P_TYPE: status = decode_p_picture_secondary_header(v); break; case B_TYPE: status = decode_b_picture_secondary_header(v); break; case BI_TYPE: case I_TYPE: status = decode_i_picture_secondary_header(v); break; } if (status<0) return FRAME_SKIPPED; /* AC Syntax */ v->c_ac_table_index = decode012(gb); if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE) { v->y_ac_table_index = decode012(gb); } /* DC Syntax */ v->s.dc_table_index = decode012(gb); return 0;}#endif/** @} */ //End for adv_frame_hdr/***********************************************************************//** * @defgroup block VC9 Block-level functions * @see 7.1.4, p91 and 8.1.1.7, p(1)04 * @todo TODO: Integrate to MpegEncContext facilities * @{ *//** * @def GET_MQUANT * @brief Get macroblock-level quantizer scale * @warning XXX: qdiff to the frame quant, not previous quant ? * @fixme XXX: Don't know how to initialize mquant otherwise in last case */#define GET_MQUANT() \ if (v->dquantfrm) \ { \ if (v->dqprofile == DQPROFILE_ALL_MBS) \ { \ if (v->dqbilevel) \ { \ mquant = (get_bits(gb, 1)) ? v->pq : v->altpq; \ } \ else \ { \ mqdiff = get_bits(gb, 3); \ if (mqdiff != 7) mquant = v->pq + mqdiff; \ else mquant = get_bits(gb, 5); \ } \ } \ else mquant = v->pq; \ }/** * @def GET_MVDATA(_dmv_x, _dmv_y) * @brief Get MV differentials * @see MVDATA decoding from 8.3.5.2, p(1)20 * @param _dmv_x Horizontal differential for decoded MV * @param _dmv_y Vertical differential for decoded MV * @todo TODO: Use MpegEncContext arrays to store them */#define GET_MVDATA(_dmv_x, _dmv_y) \ index = 1 + get_vlc2(gb, vc9_mv_diff_vlc[s->mv_table_index].table,\ VC9_MV_DIFF_VLC_BITS, 2); \ if (index > 36) \ { \ mb_has_coeffs = 1; \ index -= 37; \ } \ else mb_has_coeffs = 0; \ s->mb_intra = 0; \ if (!index) { _dmv_x = _dmv_y = 0; } \ else if (index == 35) \ { \ _dmv_x = get_bits(gb, v->k_x); \ _dmv_y = get_bits(gb, v->k_y); \ s->mb_intra = 1; \ } \ else \ { \ index1 = index%6; \ if (s->mspel && index1 == 5) val = 1; \ else val = 0; \ val = get_bits(gb, size_table[index1] - val); \ sign = 0 - (val&1); \ _dmv_x = (sign ^ ((val>>1) + offset_table[index1])) - sign; \ \ index1 = index/6; \ if (s->mspel && index1 == 5) val = 1; \ else val = 0; \ val = get_bits(gb, size_table[index1] - val); \ sign = 0 - (val&1); \ _dmv_y = (sign ^ ((val>>1) + offset_table[index1])) - sign; \ }/** Get predicted DC value * prediction dir: left=0, top=1 * @param s MpegEncContext * @param[in] n block index in the current MB * @param dc_val_ptr Pointer to DC predictor * @param dir_ptr Prediction direction for use in AC prediction * @todo TODO: Actually do it the VC9 way * @todo TODO: Handle properly edges */static inline int vc9_pred_dc(MpegEncContext *s, int n, uint16_t **dc_val_ptr, int *dir_ptr){ int a, b, c, wrap, pred, scale; int16_t *dc_val; static const uint16_t dcpred[31] = { 1024, 512, 341, 256, 205, 171, 146, 128, 114, 102, 93, 85, 79, 73, 68, 64, 60, 57, 54, 51, 49, 47, 45, 43, 41, 39, 38, 37, 35, 34, 33 }; /* find prediction - wmv3_dc_scale always used here in fact */ if (n < 4) scale = s->y_dc_scale; else scale = s->c_dc_scale; wrap = s->block_wrap[n]; dc_val= s->dc_val[0] + s->block_index[n]; /* B C * A X */ a = dc_val[ - 1]; b = dc_val[ - 1 - wrap]; c = dc_val[ - wrap]; /* XXX: Rule B is used only for I and BI frames in S/M/C profile * with overlap filtering off */ if ((s->pict_type == I_TYPE || s->pict_type == BI_TYPE) && 1 /* XXX: overlap filtering off */) { /* Set outer values */ if (s->first_slice_line && n!=2) b=c=dcpred[scale]; if (s->mb_x == 0) b=a=dcpred[scale]; } else { /* Set outer values */ if (s->first_slice_line && n!=2) b=c=0; if (s->mb_x == 0) b=a=0; /* XXX: Rule A needs to know if blocks are inter or intra :/ */ if (0) { /* update predictor */ *dc_val_ptr = &dc_val[0]; dir_ptr = 0; return a; } } if (abs(a - b) <= abs(b - c)) { pred = c; *dir_ptr = 1; } else { pred = a; *dir_ptr = 0; } /* update predictor */ *dc_val_ptr = &dc_val[0]; return pred;}/** Decode one block, inter or intra * @param v The VC9 context * @param block 8x8 DCT block * @param n Block index in the current MB (<4=>luma) * @param coded If the block is coded * @param mquant Quantizer step for the current block * @see Inter TT: Table 21, p73 + p91-85 * @see Intra TT: Table 20, p72 + p(1)05-(1)07 * @todo TODO: Process the blocks * @todo TODO: Use M$ MPEG-4 cbp prediction */static int vc9_decode_block(VC9Context *v, DCTELEM block[64], int n, int coded, int mquant){ GetBitContext *gb = &v->s.gb; MpegEncContext *s = &v->s; int ttblk; /* Transform Type per Block */ int subblkpat; /* Sub-block Transform Type Pattern */ int dc_pred_dir; /* Direction of the DC prediction used */ int run_diff, i; /* XXX: Guard against dumb values of mquant */ mquant = (mquant < 1) ? 0 : ( (mquant>31) ? 31 : mquant ); /* Set DC scale - y and c use the same */ s->y_dc_scale = s->y_dc_scale_table[mquant]; s->c_dc_scale = s->c_dc_scale_table[mquant]; if (s->mb_intra) { int dcdiff; uint16_t *dc_val; /* Get DC differential */ if (n < 4) { dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_luma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); } else { dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); } if (dcdiff < 0){ av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n"); return -1; } if (dcdiff) { if (dcdiff == 119 /* ESC index value */) { /* TODO: Optimize */ if (mquant == 1) dcdiff = get_bits(gb, 10); else if (mquant == 2) dcdiff = get_bits(gb, 9); else dcdiff = get_bits(gb, 8); } else { if (mquant == 1) dcdiff = (dcdiff<<2) + get_bits(gb, 2) - 3; else if (mquant == 2) dcdiff = (dcdiff<<1) + get_bits(gb, 1) - 1; } if (get_bits(gb, 1)) dcdiff = -dcdiff; } /* Prediction */ dcdiff += vc9_pred_dc(s, n, &dc_val, &dc_pred_dir); *dc_val = dcdiff; /* Store the quantized DC coeff, used for prediction */ if (n < 4) { block[0] = dcdiff * s->y_dc_scale; } else { block[0] = dcdiff * s->c_dc_scale; } if (block[0] < 0) {#if TRACE //av_log(s->avctx, AV_LOG_ERROR, "DC=%i<0\n", dcdiff);#endif //return -1; } /* Skip ? */ run_diff = 0; i = 0; if (!coded) { goto not_coded; } } else { mquant = v->pq; /* Get TTBLK */ if (v->ttmb < 8) /* per block */ ttblk = get_vlc2(gb, vc9_ttblk_vlc[v->tt_index].table, VC9_TTBLK_VLC_BITS, 2); else /* Per frame */ ttblk = 0; //FIXME, depends on ttfrm /* Get SUBBLKPAT */ if (ttblk == v->ttblk4x4) /* 4x4 transform for that qp value */ subblkpat = 1+get_vlc2(gb, vc9_subblkpat_vlc[v->tt_index].table, VC9_SUBBLKPAT_VLC_BITS, 2); else /* All others: 8x8, 4x8, 8x4 */ subblkpat = decode012(gb); } //TODO AC Decoding i = 63; //XXX: nothing done yet not_coded: if (s->mb_intra) { mpeg4_pred_ac(s, block, n, dc_pred_dir); if (s->ac_pred) { i = 63; /* XXX: not optimal */ } } if(i>0) i=63; //FIXME/XXX optimize s->block_last_index[n] = i; return 0;}/** @} */ //End for group block/***********************************************************************//** * @defgroup std_mb VC9 Macroblock-level functions in Simple/Main Profiles * @see 7.1.4, p91 and 8.1.1.7, p(1)04 * @todo TODO: Integrate to MpegEncContext facilities * @{ */static inline int vc9_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr){ int xy, wrap, pred, a, b, c; xy = s->block_index[n]; wrap = s->b8_stride; /* B C * A X */ a = s->coded_block[xy - 1 ]; b = s->coded_block[xy - 1 - wrap]; c = s->coded_block[xy - wrap]; if (b == c) { pred = a; } else { pred = c; } /* store value */ *coded_block_ptr = &s->coded_block[xy]; return pred;}/** Decode one I-frame MB (in Simple/Main profile) * @todo TODO: Extend to AP */static int vc9_decode_i_mb(VC9Context *v, DCTELEM block[6][64]){ int i, cbp, val; uint8_t *coded_val;// uint32_t * const mb_type_ptr= &v->s.current_picture.mb_type[ v->s.mb_x + v->s.mb_y*v->s.mb_stride ]; v->s.mb_intra = 1; cbp = get_vlc2(&v->s.gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); if (cbp < 0) return -1; v->s.ac_pred = get_bits(&v->s.gb, 1); for (i=0; i<6; i++) { val = ((cbp >> (5 - i)) & 1); if (i < 4) { int pred = vc9_coded_block_pred(&v->s, i, &coded_val); val = val ^ pred; *coded_val = val; } cbp |= val << (5 - i); if (vc9_decode_block(v, block[i], i, val, v->pq) < 0) //FIXME Should be mquant { av_log(v->s.avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", v->s.mb_x, v->s.mb_y, i); return -1; } } return 0;}/** Decode one P-frame MB (in Simple/Main profile) * @todo TODO: Extend to AP * @fixme FIXME: DC value for inter blocks not set */static int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64]){ MpegEncContext *s = &v->s; GetBitContext *gb = &s->gb; int i, mb_offset = s->mb_x + s->mb_y*s->mb_width; /* XXX: mb_stride */ int cbp; /* cbp decoding stuff */ int hybrid_pred; /* Prediction types */ int mv_mode_bit = 0; int mqdiff, mquant; /* MB quantization */ int ttmb; /* MB Transform type */ int status; uint8_t *coded_val; static const int size_table[6] = { 0, 2, 3, 4, 5, 8 }, offset_table[6] = { 0, 1, 3, 7, 15, 31 }; int mb_has_coeffs = 1; /* last_flag */ int dmv_x, dmv_y; /* Differential MV components */ int index, index1; /* LUT indices */ int val, sign; /* temp values */ mquant = v->pq; /* Loosy initialization */ if (v->mv_type_mb_plane.is_raw) v->mv_type_mb_plane.data[mb_offset] = get_bits(gb, 1); if (v->skip_mb_plane.is_raw) v->skip_mb_plane.data[mb_offset] = get_bits(gb, 1); if (!mv_mode_bit) /* 1MV mode */ { if (!v->skip_mb_plane.data[mb_offset]) { GET_MVDATA(dmv_x, dmv_y); /* hybrid mv pred, 8.3.5.3.4 */ if (v->mv_mode == MV_PMODE_1MV || v->mv_mode == MV_PMODE_MIXED_MV) hybrid_pred = get_bits(gb, 1); /* FIXME Set DC val for inter block ? */ if (s->mb_intra && !mb_has_coeffs) { GET_MQUANT(); s->ac_pred = get_bits(gb, 1); /* XXX: how to handle cbp ? */ cbp = 0; for (i=0; i<6; i++) { s->coded_block[s->block_index[i]] = 0; vc9_decode_block(v, block[i], i, 0, mquant); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -