博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【视频编解码·学习笔记】13. 提取PPS信息程序
阅读量:6313 次
发布时间:2019-06-22

本文共 6268 字,大约阅读时间需要 20 分钟。

PPS结构解析

与之前解析SPS方式类似

一、定义PPS类:

3.NAL Unit目录下,新建PicParamSet.cppPicParamSet.h,在这两个文件中写入类的定义和函数实现。

类定义写在PicParamSet.h文件中,定义待解析语法元素变量,并定义相应的setter函数,代码如下:

#ifndef _PICPARAM_SET_H#define _PICPARAM_SET_Hclass CPicParamSet{public:    CPicParamSet();    ~CPicParamSet();    void Set_pps_id(UINT8 ppsID);    void Set_sps_id(UINT8 spsID);    void Set_num_slice_groups(UINT8 num_slice_grops);    void Set_num_ref_idx(UINT8 l0, UINT8 l1);    void Set_weighted_bipred_idc(UINT8 weighted_bipred_idc);    void Set_pic_init_qp(int pic_init_qp);    void Set_pic_init_qs(int pic_init_qs);    void Set_chroma_qp_index_offset(int chroma_qp_index_offset);    void Set_multiple_flags(UINT16 flags);private:    UINT8  m_pps_id;    UINT8  m_sps_id;    bool   m_entropy_coding_flag;    bool   m_bottom_field_pic_order_in_frame_present_flag;    UINT8  m_num_slice_groups;    UINT8  m_num_ref_idx_l0_default_active;    UINT8  m_num_ref_idx_l1_default_active;    bool   m_weighted_pred_flag;    UINT8  m_weighted_bipred_idc;    int    m_pic_init_qp;    int    m_pic_init_qs;    int    m_chroma_qp_index_offset;    bool   m_deblocking_filter_control_present_flag;    bool   m_constrained_intra_pred_flag;    bool   m_redundant_pic_cnt_present_flag;    bool   m_transform_8x8_mode_flag;};#endif // !_PICPARAM_SET_H

setter函数具体实现写在PicParamSet.cpp中,均为简单的set赋值方法,所有的标志位仍按位存在一个flag中,并从中解析,代码如下:

#include "stdafx.h"#include "PicParamSet.h"CPicParamSet::CPicParamSet(){}CPicParamSet::~CPicParamSet(){}void CPicParamSet::Set_pps_id(UINT8 ppsID){    m_pps_id = ppsID;}void CPicParamSet::Set_sps_id(UINT8 spsID){    m_sps_id = spsID;}void CPicParamSet::Set_num_slice_groups(UINT8 num_slice_grops){    m_num_slice_groups = num_slice_grops;}void CPicParamSet::Set_num_ref_idx(UINT8 l0, UINT8 l1){    m_num_ref_idx_l0_default_active = l0;    m_num_ref_idx_l1_default_active = l1;}void CPicParamSet::Set_weighted_bipred_idc(UINT8 weighted_bipred_idc){    m_weighted_bipred_idc = weighted_bipred_idc;}void CPicParamSet::Set_pic_init_qp(int pic_init_qp){    m_pic_init_qp = pic_init_qp;}void CPicParamSet::Set_pic_init_qs(int  pic_init_qs){    m_pic_init_qs = pic_init_qs;}void CPicParamSet::Set_chroma_qp_index_offset(int chroma_qp_index_offset){    m_chroma_qp_index_offset = chroma_qp_index_offset;}void CPicParamSet::Set_multiple_flags(UINT16 flags){    m_entropy_coding_flag = flags & 1;    m_bottom_field_pic_order_in_frame_present_flag = flags & (1 << 1);    m_weighted_pred_flag = flags & (1 << 2);    m_deblocking_filter_control_present_flag = flags & (1 << 3);    m_constrained_intra_pred_flag = flags & (1 << 4);    m_redundant_pic_cnt_present_flag = flags & (1 << 5);}

二、解析NALUnit中PPS数据:

1. 添加解析有符号指数哥伦布编码函数:

由于PPS语法元素中包含有符号指数哥伦布编码的数据,这里新建一个函数Get_sev_code_num

无符号指数哥伦布编码(k)转为有符号的(n)公式:\(n = (-1)^{(k+1)} \times Ceil(k / 2)\)

int Get_sev_code_num(UINT8 * buf, UINT8 & bytePosition, UINT8 & bitPosition){    int uev = Get_uev_code_num(buf, bytePosition, bitPosition);    int sign = (uev % 2) ? 1 : -1;    int sev = sign * ((uev + 1) >> 1);    return sev;}

2. 获取PPS中各个成员变量的值:

在NALUnit.h和NALUnit.cpp中添加函数,Parse_as_seq_param_set() 用于解析语法元素,代码如下。(均按照中官方文档顺序解析即可)

int CNalUnit::Parse_as_pic_param_set(CPicParamSet * pps){    UINT8  pps_id = 0;    UINT8  sps_id = 0;    bool   entropy_coding_flag = 0;    bool   bottom_field_pic_order_in_frame_present_flag = 0;    UINT8  num_slice_groups = 0;    UINT8  num_ref_idx_l0_default_active = 0;    UINT8  num_ref_idx_l1_default_active = 0;    bool   weighted_pred_flag = 0;    UINT8  weighted_bipred_idc = 0;    int    pic_init_qp = 0;    int    pic_init_qs = 0;    int    chroma_qp_index_offset = 0;    bool   deblocking_filter_control_present_flag = 0;    bool   constrained_intra_pred_flag = 0;    bool   redundant_pic_cnt_present_flag = 0;    UINT8 bitPosition = 0;    UINT8 bytePosition = 0;    UINT16 flags = 0;    pps_id = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);    sps_id = Get_uev_code_num(m_pSODB, bytePosition, bitPosition);    entropy_coding_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    flags |= entropy_coding_flag;    bottom_field_pic_order_in_frame_present_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    flags |= bottom_field_pic_order_in_frame_present_flag << 1;    num_slice_groups = Get_uev_code_num(m_pSODB, bytePosition, bitPosition) + 1;    if (1 != num_slice_groups)    {        return -1;    }    num_ref_idx_l0_default_active = Get_uev_code_num(m_pSODB, bytePosition, bitPosition) + 1;    num_ref_idx_l1_default_active = Get_uev_code_num(m_pSODB, bytePosition, bitPosition) + 1;    weighted_pred_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    flags |= weighted_pred_flag << 2;    // 这里是获取连续两个比特位数据——把第一次获取到的左移1位,再加上第二次获取到的    weighted_bipred_idc = Get_bit_at_position(m_pSODB, bytePosition, bitPosition) << 1 + Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    pic_init_qp = Get_sev_code_num(m_pSODB, bytePosition, bitPosition) + 26;    pic_init_qs = Get_sev_code_num(m_pSODB, bytePosition, bitPosition) + 26;    chroma_qp_index_offset = Get_sev_code_num(m_pSODB, bytePosition, bitPosition);    deblocking_filter_control_present_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    flags |= deblocking_filter_control_present_flag << 3;    constrained_intra_pred_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    flags |= constrained_intra_pred_flag << 4;    redundant_pic_cnt_present_flag = Get_bit_at_position(m_pSODB, bytePosition, bitPosition);    flags |= redundant_pic_cnt_present_flag << 5;    pps->Set_pps_id(pps_id);    pps->Set_sps_id(sps_id);    pps->Set_num_slice_groups(num_slice_groups);    pps->Set_num_ref_idx(num_ref_idx_l0_default_active, num_ref_idx_l1_default_active);    pps->Set_weighted_bipred_idc(weighted_bipred_idc);    pps->Set_pic_init_qp(pic_init_qp);    pps->Set_pic_init_qs(pic_init_qs);    pps->Set_chroma_qp_index_offset(chroma_qp_index_offset);    pps->Set_multiple_flags(flags);    return 0;}

三、添加调用部分:

回到Stream.cpp中,找到Parse_h264_bitstream() 函数中switch (nalType)条件分支,在后面添加解析序列参数集pps的部分:

case 8:    // 解析PPS NAL 数据    if (m_pps)    {        delete m_pps;    }    m_pps = new CPicParamSet;    nalUint.Parse_as_pic_param_set(m_pps);    break;

转载于:https://www.cnblogs.com/shuofxz/p/8551519.html

你可能感兴趣的文章
如何应对BYOD时代的安全风险
查看>>
倒计时
查看>>
在windows下部署包含C3P0的war包没问题,部署到linux下面的tomcat下C3P0报错
查看>>
nginx负载均衡配置
查看>>
Centos 7 添加epel源
查看>>
mac使用pip3报错
查看>>
XML和DataTable相互转换
查看>>
nodeJS介绍(一)
查看>>
asp.net Web.config 在不同版本的IIS配置的IHttpHandler的访问路径,以及经典模式和集成模式不同的配置...
查看>>
线段树
查看>>
EOS开发环境搭建
查看>>
SSL证书部署
查看>>
Asp.net中实现多语言的Page的扩展的基类
查看>>
[LintCode] 在O(1)时间复杂度删除链表节点
查看>>
ehcache2拾遗之write和load
查看>>
高性能 TCP & UDP 通信框架 HP-Socket v3.5.2
查看>>
从二进制数据流中构造GDAL可以读取的图像数据
查看>>
Android自定义组件系列【11】——实现3D立体旋转效果
查看>>
数组方法
查看>>
C# 视频监控系列 序 [完]
查看>>