📄 vc9.c
字号:
if (v->profile < PROFILE_ADVANCED)#endif { v->finterpflag = get_bits(gb, 1); //common v->res_rtm_flag = get_bits(gb, 1); //reserved if (!v->res_rtm_flag) { av_log(avctx, AV_LOG_ERROR, "0 for reserved RES_RTM_FLAG is forbidden\n"); //return -1; }#if TRACE av_log(avctx, AV_LOG_INFO, "Profile %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n" "LoopFilter=%i, MultiRes=%i, FastUVMV=%i, Extended MV=%i\n" "Rangered=%i, VSTransform=%i, Overlap=%i, SyncMarker=%i\n" "DQuant=%i, Quantizer mode=%i, Max B frames=%i\n", v->profile, v->frmrtq_postproc, v->bitrtq_postproc, v->s.loop_filter, v->multires, v->fastuvmc, v->extended_mv, v->rangered, v->vstransform, v->overlap, v->s.resync_marker, v->dquant, v->quantizer_mode, avctx->max_b_frames ); return 0;#endif }#if HAS_ADVANCED_PROFILE else return decode_advanced_sequence_header(avctx, gb);#endif}#if HAS_ADVANCED_PROFILE/** Entry point decoding (Advanced Profile) * @param avctx Codec context * @param gb GetBit context initialized from avctx->extra_data * @return Status */static int advanced_entry_point_process(AVCodecContext *avctx, GetBitContext *gb){ VC9Context *v = avctx->priv_data; int i; if (v->profile != PROFILE_ADVANCED) { av_log(avctx, AV_LOG_ERROR, "Entry point are only defined in Advanced Profile!\n"); return -1; //Only for advanced profile! } if (v->hrd_param_flag) { //Update buffer fullness av_log(avctx, AV_LOG_DEBUG, "Buffer fullness update\n"); assert(v->hrd_num_leaky_buckets > 0); for (i=0; i<v->hrd_num_leaky_buckets; i++) v->hrd_fullness[i] = get_bits(gb, 8); } if ((v->range_mapy_flag = get_bits(gb, 1))) { //RANGE_MAPY av_log(avctx, AV_LOG_DEBUG, "RANGE_MAPY\n"); v->range_mapy = get_bits(gb, 3); } if ((v->range_mapuv_flag = get_bits(gb, 1))) { //RANGE_MAPUV av_log(avctx, AV_LOG_DEBUG, "RANGE_MAPUV\n"); v->range_mapuv = get_bits(gb, 3); } if (v->panscanflag) { //NUMPANSCANWIN v->numpanscanwin = get_bits(gb, 3); av_log(avctx, AV_LOG_DEBUG, "NUMPANSCANWIN: %u\n", v->numpanscanwin); } return 0;}#endif/***********************************************************************//** * @defgroup bitplane VC9 Bitplane decoding * @see 8.7, p56 * @{ *//** @addtogroup bitplane * Imode types * @{ */#define IMODE_RAW 0#define IMODE_NORM2 1#define IMODE_DIFF2 2#define IMODE_NORM6 3#define IMODE_DIFF6 4#define IMODE_ROWSKIP 5#define IMODE_COLSKIP 6/** @} */ //imode defines/** Allocate the buffer from a bitplane, given its dimensions * @param bp Bitplane which buffer is to allocate * @param[in] width Width of the buffer * @param[in] height Height of the buffer * @return Status * @todo TODO: Take into account stride * @todo TODO: Allow use of external buffers ? */static int alloc_bitplane(BitPlane *bp, int width, int height){ if (!bp || bp->width<0 || bp->height<0) return -1; bp->data = (uint8_t*)av_malloc(width*height); if (!bp->data) return -1; bp->width = bp->stride = width; bp->height = height; return 0;}/** Free the bitplane's buffer * @param bp Bitplane which buffer is to free */static void free_bitplane(BitPlane *bp){ bp->width = bp->stride = bp->height = 0; if (bp->data) av_freep(&bp->data);}/** Decode rows by checking if they are skipped * @param plane Buffer to store decoded bits * @param[in] width Width of this buffer * @param[in] height Height of this buffer * @param[in] stride of this buffer */static void decode_rowskip(uint8_t* plane, int width, int height, int stride, GetBitContext *gb){ int x, y; for (y=0; y<height; y++){ if (!get_bits(gb, 1)) //rowskip memset(plane, 0, width); else for (x=0; x<width; x++) plane[x] = get_bits(gb, 1); plane += stride; }}/** Decode columns by checking if they are skipped * @param plane Buffer to store decoded bits * @param[in] width Width of this buffer * @param[in] height Height of this buffer * @param[in] stride of this buffer * @fixme FIXME: Optimize */static void decode_colskip(uint8_t* plane, int width, int height, int stride, GetBitContext *gb){ int x, y; for (x=0; x<width; x++){ if (!get_bits(gb, 1)) //colskip for (y=0; y<height; y++) plane[y*stride] = 0; else for (y=0; y<height; y++) plane[y*stride] = get_bits(gb, 1); plane ++; }}/** Decode a bitplane's bits * @param bp Bitplane where to store the decode bits * @param v VC9 context for bit reading and logging * @return Status * @fixme FIXME: Optimize * @todo TODO: Decide if a struct is needed */static int bitplane_decoding(BitPlane *bp, VC9Context *v){ GetBitContext *gb = &v->s.gb; int imode, x, y, code, use_vertical_tile, tile_w, tile_h, offset; uint8_t invert, *planep = bp->data; invert = get_bits(gb, 1); imode = get_vlc2(gb, vc9_imode_vlc.table, VC9_IMODE_VLC_BITS, 2); bp->is_raw = 0; switch (imode) { case IMODE_RAW: //Data is actually read in the MB layer (same for all tests == "raw") bp->is_raw = 1; //invert ignored return invert; case IMODE_DIFF2: case IMODE_NORM2: if ((bp->height*bp->width) & 1) { *(++planep) = get_bits(gb, 1); offset = x = 1; } else offset = x = 0; for (y=0; y<bp->height; y++) { for(; x<bp->width; x+=2) { code = get_vlc2(gb, vc9_norm2_vlc.table, VC9_NORM2_VLC_BITS, 2); *(++planep) = code&1; //lsb => left *(++planep) = (code>>1)&1; //msb => right } planep += bp->stride-bp->width; if ((bp->width-offset)&1) //Odd number previously processed { code = get_vlc2(gb, vc9_norm2_vlc.table, VC9_NORM2_VLC_BITS, 2); *planep = code&1; planep += bp->stride-bp->width; *planep = (code>>1)&1; //msb => right offset = x = 1; } else { offset = x = 0; planep += bp->stride-bp->width; } } break; case IMODE_DIFF6: case IMODE_NORM6: use_vertical_tile= bp->height%3==0 && bp->width%3!=0; tile_w= use_vertical_tile ? 2 : 3; tile_h= use_vertical_tile ? 3 : 2; for(y= bp->height%tile_h; y< bp->height; y+=tile_h){ for(x= bp->width%tile_w; x< bp->width; x+=tile_w){ code = get_vlc2(gb, vc9_norm6_vlc.table, VC9_NORM6_VLC_BITS, 2); if(code<0){ av_log(v->s.avctx, AV_LOG_DEBUG, "invalid NORM-6 VLC\n"); return -1; } //FIXME following is a pure guess and probably wrong //FIXME A bitplane (0 | !0), so could the shifts be avoided ? planep[x + 0*bp->stride]= (code>>0)&1; planep[x + 1 + 0*bp->stride]= (code>>1)&1; //FIXME Does branch prediction help here? if(use_vertical_tile){ planep[x + 0 + 1*bp->stride]= (code>>2)&1; planep[x + 1 + 1*bp->stride]= (code>>3)&1; planep[x + 0 + 2*bp->stride]= (code>>4)&1; planep[x + 1 + 2*bp->stride]= (code>>5)&1; }else{ planep[x + 2 + 0*bp->stride]= (code>>2)&1; planep[x + 0 + 1*bp->stride]= (code>>3)&1; planep[x + 1 + 1*bp->stride]= (code>>4)&1; planep[x + 2 + 1*bp->stride]= (code>>5)&1; } } } x= bp->width % tile_w; decode_colskip(bp->data , x, bp->height , bp->stride, &v->s.gb); decode_rowskip(bp->data+x, bp->width - x, bp->height % tile_h, bp->stride, &v->s.gb); break; case IMODE_ROWSKIP: decode_rowskip(bp->data, bp->width, bp->height, bp->stride, &v->s.gb); break; case IMODE_COLSKIP: decode_colskip(bp->data, bp->width, bp->height, bp->stride, &v->s.gb); break; default: break; } /* Applying diff operator */ if (imode == IMODE_DIFF2 || imode == IMODE_DIFF6) { planep = bp->data; planep[0] ^= invert; for (x=1; x<bp->width; x++) planep[x] ^= planep[x-1]; for (y=1; y<bp->height; y++) { planep += bp->stride; planep[0] ^= planep[-bp->stride]; for (x=1; x<bp->width; x++) { if (planep[x-1] != planep[x-bp->stride]) planep[x] ^= invert; else planep[x] ^= planep[x-1]; } } } else if (invert) { planep = bp->data; for (x=0; x<bp->width*bp->height; x++) planep[x] = !planep[x]; //FIXME stride } return (imode<<1) + invert;}/** @} */ //Bitplane group/***********************************************************************//** VOP Dquant decoding * @param v VC9 Context */static int vop_dquant_decoding(VC9Context *v){ GetBitContext *gb = &v->s.gb; int pqdiff; //variable size if (v->dquant == 2) { pqdiff = get_bits(gb, 3); if (pqdiff == 7) v->altpq = get_bits(gb, 5); else v->altpq = v->pq + pqdiff + 1; } else { v->dquantfrm = get_bits(gb, 1); if ( v->dquantfrm ) { v->dqprofile = get_bits(gb, 2); switch (v->dqprofile) { case DQPROFILE_SINGLE_EDGE: case DQPROFILE_DOUBLE_EDGES: v->dqsbedge = get_bits(gb, 2); break; case DQPROFILE_ALL_MBS: v->dqbilevel = get_bits(gb, 1); default: break; //Forbidden ? } if (!v->dqbilevel || v->dqprofile != DQPROFILE_ALL_MBS) { pqdiff = get_bits(gb, 3); if (pqdiff == 7) v->altpq = get_bits(gb, 5); else v->altpq = v->pq + pqdiff + 1; } } } return 0;}/***********************************************************************//** * @defgroup all_frame_hdr All VC9 profiles frame header * @brief Part of the frame header decoding from all profiles * @warning Only pro/epilog differs between Simple/Main and Advanced => check caller * @{ *//** B and BI frame header decoding, primary part * @see Tables 11+12, p62-65 * @param v VC9 context * @return Status * @warning Also handles BI frames */static int decode_b_picture_primary_header(VC9Context *v){ GetBitContext *gb = &v->s.gb; int pqindex; /* Prolog common to all frametypes should be done in caller */ if (v->profile == PROFILE_SIMPLE) { av_log(v->s.avctx, AV_LOG_ERROR, "Found a B frame while in Simple Profile!\n"); return FRAME_SKIPPED; } v->bfraction = vc9_bfraction_lut[get_vlc2(gb, vc9_bfraction_vlc.table, VC9_BFRACTION_VLC_BITS, 2)]; if (v->bfraction < -1) { av_log(v->s.avctx, AV_LOG_ERROR, "Invalid BFRaction\n"); return FRAME_SKIPPED; } else if (!v->bfraction) { /* We actually have a BI frame */ v->s.pict_type = BI_TYPE; v->buffer_fullness = get_bits(gb, 7); } /* Read the quantization stuff */ pqindex = get_bits(gb, 5); if (v->quantizer_mode == QUANT_FRAME_IMPLICIT) v->pq = pquant_table[0][pqindex]; else { v->pq = pquant_table[v->quantizer_mode-1][pqindex]; } if (pqindex < 9) v->halfpq = get_bits(gb, 1); if (v->quantizer_mode == QUANT_FRAME_EXPLICIT) v->pquantizer = get_bits(gb, 1);#if HAS_ADVANCED_PROFILE if (v->profile == PROFILE_ADVANCED) { if (v->postprocflag) v->postproc = get_bits(gb, 2); if (v->extended_mv == 1 && v->s.pict_type != BI_TYPE) v->mvrange = get_prefix(gb, 0, 3); }#endif else { if (v->extended_mv == 1) v->mvrange = get_prefix(gb, 0, 3); } /* Read the MV mode */ if (v->s.pict_type != BI_TYPE) { v->mv_mode = get_bits(gb, 1); if (v->pq < 13) { if (!v->mv_mode) { v->mv_mode = get_bits(gb, 2); if (v->mv_mode) av_log(v->s.avctx, AV_LOG_ERROR, "mv_mode for lowquant B frame was %i\n", v->mv_mode); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -