HEVC解码器HM源码阅读(四)解析参数集
2017-05-02 21:14
316 查看
解析视频参数集VPS
如果NALU的装的是VPS,那么需要从NALU中把VPS解析出来。VPS包含了全局使用的一些信息,包含Profile、Level、Tier、时域层信息、TimingInfo、HRD等。解析VPS的入口函数
1、创建VPS对象2、解析VPS
3、把VPS放入参数集管理器中
Void TDecTop::xDecodeVPS() { TComVPS* vps = new TComVPS(); // 解析vps m_cEntropyDecoder.decodeVPS( vps ); // 把vps放入参数集管理器中 m_parameterSetManagerDecoder.storePrefetchedVPS(vps); }
解析VPS
按照顺序依次解码VPS中的语法元素,不同的语法元素使用的编解码方法可能不同。另外请注意,VPS、SPS、PPS等参数集使用cavlc进行熵编码/解码,视频数据使用CABAC进行熵编码/解码Void TDecCavlc::parseVPS(TComVPS* pcVPS) { UInt uiCode; READ_CODE( 4, uiCode, "vps_video_parameter_set_id" ); pcVPS->setVPSId( uiCode ); READ_CODE( 2, uiCode, "vps_reserved_three_2bits" ); assert(uiCode == 3); READ_CODE( 6, uiCode, "vps_reserved_zero_6bits" ); assert(uiCode == 0); READ_CODE( 3, uiCode, "vps_max_sub_layers_minus1" ); pcVPS->setMaxTLayers( uiCode + 1 ); READ_FLAG( uiCode, "vps_temporal_id_nesting_flag" ); pcVPS->setTemporalNestingFlag( uiCode ? true:false ); assert (pcVPS->getMaxTLayers()>1||pcVPS->getTemporalNestingFlag()); READ_CODE( 16, uiCode, "vps_reserved_ffff_16bits" ); assert(uiCode == 0xffff); parsePTL ( pcVPS->getPTL(), true, pcVPS->getMaxTLayers()-1); UInt subLayerOrderingInfoPresentFlag; READ_FLAG(subLayerOrderingInfoPresentFlag, "vps_sub_layer_ordering_info_present_flag"); for(UInt i = 0; i <= pcVPS->getMaxTLayers()-1; i++) { READ_UVLC( uiCode, "vps_max_dec_pic_buffering_minus1[i]" ); pcVPS->setMaxDecPicBuffering( uiCode + 1, i ); READ_UVLC( uiCode, "vps_num_reorder_pics[i]" ); pcVPS->setNumReorderPics( uiCode, i ); READ_UVLC( uiCode, "vps_max_latency_increase_plus1[i]" ); pcVPS->setMaxLatencyIncrease( uiCode, i ); if (!subLayerOrderingInfoPresentFlag) { for (i++; i <= pcVPS->getMaxTLayers()-1; i++) { pcVPS->setMaxDecPicBuffering(pcVPS->getMaxDecPicBuffering(0), i); pcVPS->setNumReorderPics(pcVPS->getNumReorderPics(0), i); pcVPS->setMaxLatencyIncrease(pcVPS->getMaxLatencyIncrease(0), i); } break; } } assert( pcVPS->getNumHrdParameters() < MAX_VPS_OP_SETS_PLUS1 ); assert( pcVPS->getMaxNuhReservedZeroLayerId() < MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 ); READ_CODE( 6, uiCode, "vps_max_nuh_reserved_zero_layer_id" ); pcVPS->setMaxNuhReservedZeroLayerId( uiCode ); READ_UVLC( uiCode, "vps_max_op_sets_minus1" ); pcVPS->setMaxOpSets( uiCode + 1 ); for( UInt opsIdx = 1; opsIdx <= ( pcVPS->getMaxOpSets() - 1 ); opsIdx ++ ) { // Operation point set for( UInt i = 0; i <= pcVPS->getMaxNuhReservedZeroLayerId(); i ++ ) { READ_FLAG( uiCode, "layer_id_included_flag[opsIdx][i]" ); pcVPS->setLayerIdIncludedFlag( uiCode == 1 ? true : false, opsIdx, i ); } } TimingInfo *timingInfo = pcVPS->getTimingInfo(); READ_FLAG( uiCode, "vps_timing_info_present_flag"); timingInfo->setTimingInfoPresentFlag (uiCode ? true : false); if(timingInfo->getTimingInfoPresentFlag()) { READ_CODE( 32, uiCode, "vps_num_units_in_tick"); timingInfo->setNumUnitsInTick (uiCode); READ_CODE( 32, uiCode, "vps_time_scale"); timingInfo->setTimeScale (uiCode); READ_FLAG( uiCode, "vps_poc_proportional_to_timing_flag"); timingInfo->setPocProportionalToTimingFlag(uiCode ? true : false); if(timingInfo->getPocProportionalToTimingFlag()) { READ_UVLC( uiCode, "vps_num_ticks_poc_diff_one_minus1"); timingInfo->setNumTicksPocDiffOneMinus1 (uiCode); } READ_UVLC( uiCode, "vps_num_hrd_parameters" ); pcVPS->setNumHrdParameters( uiCode ); if( pcVPS->getNumHrdParameters() > 0 ) { pcVPS->createHrdParamBuffer(); } for( UInt i = 0; i < pcVPS->getNumHrdParameters(); i ++ ) { READ_UVLC( uiCode, "hrd_op_set_idx" ); pcVPS->setHrdOpSetIdx( uiCode, i ); if( i > 0 ) { READ_FLAG( uiCode, "cprms_present_flag[i]" ); pcVPS->setCprmsPresentFlag( uiCode == 1 ? true : false, i ); } parseHrdParameters(pcVPS->getHrdParameters(i), pcVPS->getCprmsPresentFlag( i ), pcVPS->getMaxTLayers() - 1); } } READ_FLAG( uiCode, "vps_extension_flag" ); if (uiCode) { while ( xMoreRbspData() ) { READ_FLAG( uiCode, "vps_extension_data_flag"); } } return; }
常见的几种CAVLC解码方法
#define READ_CODE(length, code, name) xReadCode ( length, code ) // 直接读取指定长度的比特 #define READ_UVLC( code, name) xReadUvlc ( code ) // 无符号指数哥伦布解码 #define READ_SVLC( code, name) xReadSvlc ( code ) // 有符号指数哥伦布解码 #define READ_FLAG( code, name) xReadFlag ( code ) // 读取一个比特
解析SPS、PPS的方法和VPS类似,这里不再赘述。
相关文章推荐
- HEVC解码器HM源码阅读(一)介绍
- HEVC解码器HM源码阅读(三)读取一个NALU
- HEVC解码器HM源码阅读(二)解码器中类的介绍
- HEVC学习与研究】11.HEVC参考解码器的设置及参数解析过程
- 【HEVC学习与研究】11.HEVC参考解码器的设置及参数解析过程
- Memcached源码阅读之初始化参数解析
- Memcached源码阅读之初始化参数解析
- HEVC——PPS参数解析
- Spring源码解析——如何阅读源码(转)
- Spring源码阅读之IoC容器初始化2 -- BeanDefinition载入与解析
- 四.jQuery源码解析之jQuery.fn.init()的参数解析
- HEVC码率控制浅析——HM代码阅读之三
- 淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树
- 源代码阅读方法 jQuery源码解析 核心模块core.js
- HEVC码率控制浅析——HM代码阅读之一
- HEVC码率控制浅析——HM代码阅读之四
- HEVC码率控制浅析——HM代码阅读之二
- HEVC码率控制浅析——HM代码阅读之一
- oschina-app源码解析-系统参数保存
- [hadoop源码阅读][4]-org.apache.hadoop.io.compress系列1-认识解码器/编码器