PPS结构解析

与之前解析SPS方式类似

一、定义PPS类:

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

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

#ifndef _PICPARAM_SET_H
#define _PICPARAM_SET_H class 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() 用于解析语法元素,代码如下。(均按照学习笔记12中官方文档顺序解析即可)

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;

【视频编解码·学习笔记】13. 提取PPS信息程序的更多相关文章

  1. 【视频编解码·学习笔记】11. 提取SPS信息程序

    一.准备工作: 回到之前SimpleH264Analyzer程序,找到SPS信息,并对其做解析 调整项目目录结构: 修改Global.h文件中代码,添加新数据类型UINT16,之前编写的工程中,UIN ...

  2. 【视频编解码·学习笔记】8. 熵编码算法:基本算法列举 & 指数哥伦布编码

    一.H.264中的熵编码基本方法: 熵编码具有消除数据之间统计冗余的功能,在编码端作为最后一道工序,将语法元素写入输出码流 熵解码作为解码过程的第一步,将码流解析出语法元素供后续步骤重建图像使用 在H ...

  3. 【视频编解码·学习笔记】5. NAL Unit 结构分析

    在上篇笔记中通过一个小程序,可以提取NAL Unit所包含的的字节数据.H.264码流中的每一个NAL Unit的作用并不是相同的,而是根据不同的类型起不同的作用.下面将对NAL Unit中的数据进行 ...

  4. 【视频编解码·学习笔记】6. H.264码流分析工程创建

    一.准备工作: 新建一个VS工程SimpleH264Analyzer, 修改工程属性参数-> 输出目录:$(SolutionDir)bin\$(Configuration)\,工作目录:$(So ...

  5. 【视频编解码·学习笔记】3. H.264视频编解码工程JM的下载与编解码

    一.下载JM工程: JM是H.264标准制定团队所认可的官方参考软件.网址如下 http://iphome.hhi.de/suehring/tml/ 从页面中可找到相应的工程源码,本次选择JM 8.6 ...

  6. 【视频编解码·学习笔记】12. 图像参数集(PPS)介绍

    一.PPS相关概念: 除了序列参数集SPS之外,H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS). 通常情况下,PPS类似于SPS,在H.264的裸码流中 ...

  7. 【视频编解码·学习笔记】4. H.264的码流封装格式 & 提取NAL有效数据

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

  8. 【视频编解码·学习笔记】10. 序列参数集(SPS)介绍

    一.SPS 相关概念: SPS即 "Sequence Paramater Set",又称作序列参数集. SPS中保存了一组编码视频序列(Coded video sequence)的 ...

  9. 【视频编解码·学习笔记】4. H.264的码流封装格式

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

随机推荐

  1. mac 安装secureCRT

    下载 http://www.xue51.com/mac/1632.html 会得到下面的文件: 打开dmg文件: 将SecureCRT移到Applications中,然后点击打开一次(重要): 然后打 ...

  2. c++问题整理

    1.C++ 多态,多态的实现,c++虚函数,虚函数和纯虚函数有什么区别,虚函数的实现原理,虚继承,析构函数能否为虚,为什么析构要虚函数,析构函数声明为虚函数的作用,构造函数为啥不能定义为虚函数,析构函 ...

  3. Selenium2+python-unittest之装饰器(@classmethod)

    原文地址:http://www.cnblogs.com/yoyoketang/p/6685416.html 前言 前面讲到unittest里面setUp可以在每次执行用例前执行,这样有效的减少了代码量 ...

  4. JS基础-组成

    类型 前缀 类型 实例 数组 a Array aItems 布尔值 b Boolean bIsComplete 浮点数 f Float fPrice 函数 fn Function fnHandler ...

  5. 为什么继续选择DELPHI?

    已经钻DELPHI很深了,当然现在DELPHI是过了最辉煌的时代.但为什么要继续下去,而不转向其它的?这是不是死脑筋? 我看了一下C#的LINQ的产生,然后又被实体框架所代替.思考了一下: 1)LIN ...

  6. Java基础—IO小结(一)概述与节点流

    一.File类的使用  由于file类是一个基础类,所以我们从file类开始了解.(SE有完善的中文文档,建议阅读) 构造器: 常用方法:——完整方法请参见API API API!!! File做的是 ...

  7. Facebook如何管理150亿张照片

    Facebook 的照片分享很受欢迎,迄今,Facebook 用户已经上传了150亿张照片,加上缩略图,总容量超过1.5PB,而每周新增的照片为2亿2000万张,约25TB,高峰期,Facebook ...

  8. 苏州Uber优步司机奖励政策(4月23日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  9. 9.22 开课第十九天(window对象)

    DOM:文档对象模型 --树模型 文档:标签文档,对象:文档中每个元素对象,模型:抽象化的东西 一:window: 属性(值或者子对象): opener:打开当前窗口的源窗口,如果当前窗口是首次启动浏 ...

  10. 【转载】COM 组件设计与应用(三)——数据类型

    原文:http://vckbase.com/index.php/wv/1206.html COM 组件设计与应用 系列文章:http://vckbase.com/index.php/piwz?& ...