热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

H265打包成RTP包详解

在我们的高清视频传输中,一般都需要对视频信息进行指定协议的打包,RTP是比较常用的一种视频打包负载传输方式,那么具体是怎么打包的呢

        在我们的高清视频传输中,一般都需要对视频信息进行指定协议的打包,RTP是比较常用的一种视频打包负载传输方式,那么具体是怎么打包的呢?今天就简单介绍一下。

1.H265的结构

       在H265中,每一个前缀码00000001后面跟随的前两个字节为NALU的语法元素,总体结构如下:   

 

 

 

这两个字节字段分布如下,F(forbidden_zero_bit)通常为0,LayId(nuh_layer_id)通常为0,Tid(nuh_temporal_id_plus1)通常为1,所以对一段码流来说第二字节通常都是1。 

      1. 当收到NALU单元长度小于MTU时,直接把00000001/000001前缀去掉,加上RTPHead即可 

      2.当收到NALU单元长度大于MTU时,需要做FU分包处理,先把00000001前缀+2B类型去掉,然后对剩下的数据分包处理。分包的每一段数据前加上FUHead,FUHead长度是3字节。FUHead[0],FUHead[1]的结构和H265NULU类型2B结构相同,只是Type取值49即可。FUHead[2]结构如下,S置1表示分包开始,E置1分包结束,中间包都不置1,后面6bit就是H265的类型字段。本篇介绍一下H265怎么打包RTP,在H265中,每一个前缀码00000001后面跟随的前两个字节为NALU的语法元素,总体结构如下:

 

        H265类型定义如下:

 

/*** Table 7-1: NAL unit type codes*/
enum HEVCNALUnitType {HEVC_NAL_TRAIL_N = 0,HEVC_NAL_TRAIL_R = 1,HEVC_NAL_TSA_N = 2,HEVC_NAL_TSA_R = 3,HEVC_NAL_STSA_N = 4,HEVC_NAL_STSA_R = 5,HEVC_NAL_RADL_N = 6,HEVC_NAL_RADL_R = 7,HEVC_NAL_RASL_N = 8,HEVC_NAL_RASL_R = 9,HEVC_NAL_VCL_N10 = 10,HEVC_NAL_VCL_R11 = 11,HEVC_NAL_VCL_N12 = 12,HEVC_NAL_VCL_R13 = 13,HEVC_NAL_VCL_N14 = 14,HEVC_NAL_VCL_R15 = 15,HEVC_NAL_BLA_W_LP = 16,HEVC_NAL_BLA_W_RADL = 17,HEVC_NAL_BLA_N_LP = 18,HEVC_NAL_IDR_W_RADL = 19,HEVC_NAL_IDR_N_LP = 20,HEVC_NAL_CRA_NUT = 21,HEVC_NAL_IRAP_VCL22 = 22,HEVC_NAL_IRAP_VCL23 = 23,HEVC_NAL_RSV_VCL24 = 24,HEVC_NAL_RSV_VCL25 = 25,HEVC_NAL_RSV_VCL26 = 26,HEVC_NAL_RSV_VCL27 = 27,HEVC_NAL_RSV_VCL28 = 28,HEVC_NAL_RSV_VCL29 = 29,HEVC_NAL_RSV_VCL30 = 30,HEVC_NAL_RSV_VCL31 = 31,HEVC_NAL_VPS = 32,HEVC_NAL_SPS = 33,HEVC_NAL_PPS = 34,HEVC_NAL_AUD = 35,HEVC_NAL_EOS_NUT = 36,HEVC_NAL_EOB_NUT = 37,HEVC_NAL_FD_NUT = 38,HEVC_NAL_SEI_PREFIX = 39,HEVC_NAL_SEI_SUFFIX = 40,};

来看一段FFmpeg的源码:

static void nal_send(AVFormatContext *ctx, const uint8_t *buf, int len, int last_packet_of_frame){RTPMuxContext *rtp_ctx &#61; ctx->priv_data;int rtp_payload_size &#61; rtp_ctx->max_payload_size - RTP_HEVC_HEADERS_SIZE;int nal_type &#61; (buf[0] >> 1) & 0x3F;//长度max_payload_size) {/* use the original NAL unit buffer and transmit it as RTP payload */ff_rtp_send_data(ctx, buf, len, last_packet_of_frame);} else {/*create the HEVC payload header and transmit the buffer as fragmentation units (FU)0 10 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;|F| Type | LayerId | TID |&#43;-------------&#43;-----------------&#43;F &#61; 0Type &#61; 49 (fragmentation unit (FU))LayerId &#61; 0TID &#61; 1*///分包先赋值RTP头三个字节//类型49表示该包是FU分包rtp_ctx->buf[0] &#61; 49 <<1;//保持原来H265类型字段第二个字段 一般都是1rtp_ctx->buf[1] &#61; 1;/*create the FU header0 1 2 3 4 5 6 7&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;-&#43;|S|E| FuType |&#43;---------------&#43;S &#61; variableE &#61; variableFuType &#61; NAL unit type*///保持原来H265类型字段类型字段 rtp_ctx->buf[2] &#61; nal_type;/* set the S bit: mark as start fragment *///设置开始标志rtp_ctx->buf[2] |&#61; 1 <<7;/* pass the original NAL header *///去掉H264头类型长度buf &#43;&#61; 2;len -&#61; 2;while (len > rtp_payload_size) {/* complete and send current RTP packet */memcpy(&rtp_ctx->buf[RTP_HEVC_HEADERS_SIZE], buf, rtp_payload_size);ff_rtp_send_data(ctx, rtp_ctx->buf, rtp_ctx->max_payload_size, 0);buf &#43;&#61; rtp_payload_size;len -&#61; rtp_payload_size;/* reset the S bit *///去掉开始结束标志rtp_ctx->buf[2] &&#61; ~(1 <<7);}/* set the E bit: mark as last fragment *///设置结束标志rtp_ctx->buf[2] |&#61; 1 <<6;/* complete and send last RTP packet */memcpy(&rtp_ctx->buf[RTP_HEVC_HEADERS_SIZE], buf, len);ff_rtp_send_data(ctx, rtp_ctx->buf, len &#43; 2, last_packet_of_frame);}}

 

 


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 配置IPv4静态路由实现企业网内不同网段用户互访
    本文介绍了通过配置IPv4静态路由实现企业网内不同网段用户互访的方法。首先需要配置接口的链路层协议参数和IP地址,使相邻节点网络层可达。然后按照静态路由组网图的操作步骤,配置静态路由。这样任意两台主机之间都能够互通。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 本文介绍了一种在PHP中对二维数组根据某个字段进行排序的方法,以年龄字段为例,按照倒序的方式进行排序,并给出了具体的代码实现。 ... [详细]
  • 本文介绍了使用Python编写购物程序的实现步骤和代码示例。程序启动后,用户需要输入工资,并打印商品列表。用户可以根据商品编号选择购买商品,程序会检测余额是否充足,如果充足则直接扣款,否则提醒用户。用户可以随时退出程序,在退出时打印已购买商品的数量和余额。附带了完整的代码示例。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
author-avatar
手机用户2502905147
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有