目录

  • 1. 申明
  • 2. 目的
  • 3. 背景知识
    • 3.1 哥伦比亚指数编码无符号数的解码
    • 3.2 哥伦比亚指数编码有符号数的解码
    • 3.3 解析参数序列集的过程
  • 4. 代码demo
  • 5. 专栏知识链接
  • 6. 写在最后

1. 申明

本文章属于原创,其中参考的代码及文章在结尾处标明,侵删。

2. 目的

本文是为了解析H265中携带的视频分辨率而写的一个demo。

3. 背景知识

本文及文中所涉及代码,均以TS流作为媒介。

3.1 哥伦比亚指数编码无符号数的解码

(1)首先读取当前位置的bit位,记录连续0的个数N

(2)对于连续0的个数为0值为0,对于连续0的个数不为0 跳过第一个非0的bit位

(3)再读取N个数据,此数据以无符号形式解析num

(4)num=num-1+2的N次方

3.2 哥伦比亚指数编码有符号数的解码

(1)按照3.1的讲述先获取此段数据的哥伦比亚指数编码的无符号形式

(2)如果数据为奇数num=(num+1)/2;如果是偶数num=-(num/2)

3.3 解析参数序列集的过程




   描述符一列表示此处数据的类型f和u表示的是无符号的数据类型,ue表示的是哥伦比亚指数编码的无符号数据,se表示的是哥伦比亚指数编码的有符号数据。

4. 代码demo


#define H265_SPS_HEAD_FLAG 0x42uint8_t getbyte(uint32_t *start_bit,unsigned char *m_data, uint32_t m_len, uint32_t *m_zeros)
{if (*start_bit >= m_len)return 0;BYTE b = m_data[(*start_bit)++];// to avoid start-code emulation, a byte 0x03 is inserted// after any 00 00 pair. Discard that here.if (b == 0){(*m_zeros)++;if ((*start_bit < m_len) && ((*m_zeros) == 2) && (m_data[*start_bit] == 0x03)){(*start_bit)++;(*m_zeros) = 0;}}else{(*m_zeros) = 0;}return b;
};uint32_t getbit(int *m_bits, uint8_t *m_byte, uint32_t *start_bit, unsigned char *m_data,uint32_t m_len, uint32_t *m_zeros)
{if (*m_bits == 0){*m_byte = getbyte(start_bit, m_data, m_len, m_zeros);*m_bits = 8;}*m_bits -= 1;return (*m_byte >> *m_bits) & 0x1;
};uint32_t getword(int bits, int *m_bits, uint8_t *m_byte, uint32_t *start_bit, unsigned char *m_data,uint32_t m_len, uint32_t *m_zeros)
{uint32_t u = 0;while (bits > 0){u <<= 1;u |= getbit(m_bits, m_byte, start_bit, m_data, m_len, m_zeros);bits--;}return u;
};uint32_t getue(int *m_bits, uint8_t *m_byte, uint32_t *start_bit, unsigned char *m_data,uint32_t m_len, uint32_t *m_zeros)
{int zeros = 0;while (*start_bit < m_len && getbit(m_bits, m_byte, start_bit, m_data, m_len, m_zeros) == 0)zeros++;return getword(zeros, m_bits, m_byte, start_bit, m_data, m_len, m_zeros) + ((1 << zeros) - 1);
};/*根据误差调整分辨率@param1 width:        原始宽数据的指针@param2 hight:        原始高数据的指针@param3 offset_width: 横向误差和@param4 offset_hight: 纵向误差和
*/
static inline BOOL adjust_resolution_by_offset(uint32_t *width, uint32_t *hight,uint8_t offset_width, uint8_t offset_hight)
{//左右存在对齐,分辨率宽度减去二倍的像素if (offset_width) {if ((offset_width * 2) <= *width)*width -= offset_width * 2;elsereturn FALSE;}//上下存在对齐,分辨率高度减去二倍的像素if (offset_hight) {if ((offset_hight * 2) <= *hight)*hight -= offset_hight * 2;elsereturn FALSE;}return TRUE;
}/*查找H265 SPS数据起始部分@param1 buf:  原始数据buf的二级指针@param2 len:  原始数据大小的指针@param3 type: 要查找的视频类型起始字节:H264: 0x67H265: 0x42
*/
static inline BOOL find_sps_first_byte(unsigned char **buf, uint32_t *len, uint8_t type)
{unsigned char *pos = (unsigned char *)memchr(*buf, type, *len);if (NULL == pos)return FALSE;*len -= pos - *buf;*buf = pos;return TRUE;
}/*解码H265@param1 pdata:    原始数据buf的指针@param2 len:      原始数据的大小
*/
static inline BOOL decode_h265(unsigned char *pdata, uint32_t len)
{uint32_t start_bit = 0;int m_bits = 0;uint8_t m_byte = 0;uint32_t m_zeros = 0;if (!find_sps_first_byte(&pdata, &len, H265_SPS_HEAD_FLAG))return FALSE;//解码 forbidden_zero_bitgetword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);//解码 nal_unit_typegetword(6, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);//解码 nuh_layer_idgetword(6, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);//解码 nuh_temporal_id_plus1getword(3, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);//解码 sps_video_parameter_set_idgetword(4, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);//解码 sps_max_sub_layers_minus1uint32_t sps_max_sub_layers_minus1 = getword(3, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);if (sps_max_sub_layers_minus1 > 6)return FALSE;//解码 temporal_id_nesting_flaggetword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);// profile_tier_level( sps_max_sub_layers_minus1 ){getword(2, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(5, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(32, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(44, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(8, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);unsigned char sub_layer_profile_present_flag[6] = { 0 };unsigned char sub_layer_level_present_flag[6] = { 0 };int i;for (i = 0; i < sps_max_sub_layers_minus1; i++){sub_layer_profile_present_flag[i] = getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);sub_layer_level_present_flag[i] = getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);}if (sps_max_sub_layers_minus1 > 0){for (i = sps_max_sub_layers_minus1; i < 8; i++)getword(2, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);}for (i = 0; i < sps_max_sub_layers_minus1; i++){if (sub_layer_profile_present_flag[i]){getword(2, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(5, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(32, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);getword(44, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);}if (sub_layer_level_present_flag[i])getword(8, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);}}// "The  value  of sps_seq_parameter_set_id shall be in the range of 0 to 15, inclusive."unsigned long sps_seq_parameter_set_id = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros);if (sps_seq_parameter_set_id > 15)return FALSE;// "The value of chroma_format_idc shall be in the range of 0 to 3, inclusive."unsigned long chroma_format_idc = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros);if (sps_seq_parameter_set_id > 3)return FALSE;if (chroma_format_idc == 3)getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros);uint32_t width = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros); // pic_width_in_luma_samplesuint32_t height = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros); // pic_height_in_luma_samplesif (getword(1, &m_bits, &m_byte, &start_bit, pdata, len, &m_zeros)){// conformance_window_flag// conf_win_left_offsetuint32_t conf_win_left_offset = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros);// conf_win_right_offsetuint32_t conf_win_right_offset = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros);// conf_win_top_offsetuint32_t conf_win_top_offset = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros);// conf_win_bottom_offsetuint32_t conf_win_bottom_offset = getue(&m_bits, &m_byte, &start_bit, pdata,len, &m_zeros);if (!adjust_resolution_by_offset(&width, &height,conf_win_left_offset + conf_win_right_offset,conf_win_top_offset + conf_win_bottom_offset)) {;//不够减}}return TRUE;
}

划重点: 为了解析分辨率,需要一层层进行解码,所以上面代码中,只调用getword(),getue()而未获取返回值的,可以暂时不用关注,有兴趣可以自己了解。需要强调的是,最后对于补齐的计算,如果不进行补齐的核对,会出现640*368这种分辨率,而实际应用中我们的宽高比为16:9, 所以分辨率应该为640:360, 那么这多出来的8,其实就是在传输过程中,必须以宏块(16的倍数)来传输,为了满足这个要求,高度向上进行了补齐,所以在计算真实值的时候,要根据conf_win_left_offset,conf_win_right_offset,conf_win_top_offset,conf_win_bottom_offset进行相应的调整。

5. 专栏知识链接

1. 协议知识概述
2. H264分辨率解码概述
3. 以太网Ethernet解码概述

6. 写在最后

本文引用了以下文章作者的代码或思路,
并结合了实际项目中的代码整理出的demo,如有问题欢迎指正。

https://blog.csdn.net/chinabinlang/article/details/89209609
https://blog.csdn.net/chinabinlang/article/details/93640746?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160742052619724848117078%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=160742052619724848117078&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-6-93640746.nonecase&utm_term=H265%20%E8%A7%A3%E7%A0%81&spm=1018.2118.3001.4449

官方文档
https://www.doc88.com/p-8708471960665.html

H265分辨率解码概述相关推荐

  1. H264分辨率解码概述

    目录 1. 申明 2. 目的 3. 背景知识 3.1 哥伦比亚指数编码无符号数的解码 3.2 哥伦比亚指数编码有符号数的解码 3.3 解析参数序列集的过程 4. 代码demo 5. 专栏知识链接 6. ...

  2. 以太网Ethernet解码概述

    目录 1. 申明 2. 目的 3. 背景知识 3.1 Ethernet协议的作用和历史 3.2 Ethernet承载IP的例子 4. 代码demo 5. 专栏知识链接 6. 写在最后 1. 申明 本文 ...

  3. web无插件解码播放H264/H265(js解码HTML5播放)

    项目意义: 长久以来,安防领域的网络摄像机(IPC)的WEB视频直播都依赖于浏览器插件,IE浏览器使用ActiveX插件,Chrome和Firefox浏览器使用NPAPI插件. 之所以开发浏览器插件来 ...

  4. web无插件解码播放H264/H265(WebAssembly解码HTML5播放)

    我之前写过一篇<web无插件解码播放H264/H265(js解码HTML5播放)>,与本文的项目意义基本一致,不同的是实现方案有一定差异.之前介绍的是纯JS解码,本文介绍WebAssemb ...

  5. MPEG音视频编解码之MP3编解码概述

    2 MP3编解码原理 2.1 MP3音频压缩标准概述 MP3全称是动态影像专家压缩标准音频层面3(Moving Picture Experts Group Audio Layer III).是当今较流 ...

  6. 手淘H265编解码算法与工程优化

    本文来自淘宝(中国)软件有限公司 高级算法专家 李晓波在LiveVideoStackCon 2018讲师热身分享,并由LiveVideoStack整理而成.在分享中李晓波详细解析了手淘在H.265高效 ...

  7. 龙讯LT8911EXB高性能MIPI转EDP分辨率1080P概述

    LT8911EXB 功能:MIPI CSI/DSI转EDP信号转换芯片 1.特点 单端口MIPI®DSI接收器 符合D-PHY1.2.DSI1.3和CSI1.3 1条时钟通道和1~4条可配置数据通道 ...

  8. 手机淘宝H265编解码算法与工程优化

    本文来自淘宝 高级算法专家 李晓波(篱悠)在LiveVideoStackCon 2018讲师热身分享,由LiveVideoStack整理而成.在分享中李晓波详细解析了手淘在H.265高效编解码器的实现 ...

  9. 语音编解码技术演进和应用选型

    本文来自现网易云音乐音视频实验室负责人刘华平在LiveVideoStackCon 2017大会上的分享,并由LiveVideoStack整理而成.分享中刘华平以时间为主线,讲述了语音编解码技术的演进路 ...

  10. SOPHON BM1684芯片解码性能以及支持的文件格式

    SOPHON BM1684芯片解码性能相关问题 1. BM1684芯片的编解码性能数据 2. BM1684解码性能对于H264/H265有差别吗?如果调整码率的话,最多可以解多少路呢?有没有对应的数据 ...

最新文章

  1. 黑客组织称7月将售新入侵工具 价格超2.2万美元
  2. SPFA算法O(kE)
  3. java上课作业(第三次)
  4. tomcat 绑定 ip 及域名,限制非法域名访问
  5. 【CS论坛】维护网络安全的四块基石
  6. JDK有三种字体绘制系统
  7. Java高级程序员面试大纲——备战金三银四跳槽季
  8. delphi 2010 mysql_delphi2010读取MySQL数据库TEXT类型乱码的解决方案
  9. 如何用spss客户端和SPSS AU在线进行单样本T检验操作?
  10. html怎么播放f4v,优秀的flv网页播放器,支持高清f4v,mp4,rtmp,支持广告
  11. 【编程语言】Java夯实基础(一):Java的起源与发展
  12. window.onload=function()是什么意思
  13. 6iypl8php,无线超方便 YPL TL-1/TL-3蓝牙音箱新品上市
  14. windows 10专业版 1709 使用curl命令
  15. 苹果16g不够用怎么办_孩子不够自信怎么办?父母学会用这4个方法,孩子长大更优秀自信...
  16. Admin.NET管理系统(vue3等前后端分离)学习笔记--持续更新
  17. pip安装三方库不成功的解决方法
  18. 聚划算成清仓专用 问题产品充斥
  19. 前端Vue H5生成带二维码的分享海报,实现长按保存到手机相册
  20. 10分钟在服务器上搭建WordPress

热门文章

  1. java——编程案例
  2. 物联网系统怎么部署服务器,如何搭建物联网云服务器
  3. 自适应滤波器的FPGA实现
  4. pyqt QListView详细用法
  5. w7 internet信息服务器,Win7安装IIS Internet信息服务步骤
  6. ubuntu系统下如何查看opencv版本
  7. 国产CI520 13.56MHz非接触式读写器NFC读卡芯片替代CV520
  8. 高精度三维扫描仪用于运动鞋逆向建模
  9. SpringMVC中get请求中文乱码问题
  10. Linux安装与配置SSH服务