H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解

H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解h265 HEVC nal 单元头介绍 及 h265 视频数据传输 通过 rtp 传输时 fu 分组包头结构介绍

        首先来介绍下h265(HEVC)nal单元头,与h264的nal层相比,h265的nal unit header有两个字节构成,如下图所示:

H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解

从图中可以看出hHEVC的nal包结构与h264有明显的不同,hevc加入了nal所在的时间层的ID,取去除了nal_ref_idc,此信息合并到了naltype中,通常情况下F为0,layerid为0,TID为1。

        nal单元的类型有如下几种:

     

 enum NalUnitType { NAL_UNIT_CODED_SLICE_TRAIL_N = 0, // 0 NAL_UNIT_CODED_SLICE_TRAIL_R, // 1 NAL_UNIT_CODED_SLICE_TSA_N, // 2 NAL_UNIT_CODED_SLICE_TLA, // 3 // Current name in the spec: TSA_R NAL_UNIT_CODED_SLICE_STSA_N, // 4 NAL_UNIT_CODED_SLICE_STSA_R, // 5 NAL_UNIT_CODED_SLICE_RADL_N, // 6 NAL_UNIT_CODED_SLICE_DLP, // 7 // Current name in the spec: RADL_R NAL_UNIT_CODED_SLICE_RASL_N, // 8 NAL_UNIT_CODED_SLICE_TFD, // 9 // Current name in the spec: RASL_R NAL_UNIT_RESERVED_10, NAL_UNIT_RESERVED_11, NAL_UNIT_RESERVED_12, NAL_UNIT_RESERVED_13, NAL_UNIT_RESERVED_14, NAL_UNIT_RESERVED_15, NAL_UNIT_CODED_SLICE_BLA, // 16 // Current name in the spec: BLA_W_LP NAL_UNIT_CODED_SLICE_BLA, // 16 // Current name in the spec: BLA_W_LP NAL_UNIT_CODED_SLICE_BLANT, // 17 // Current name in the spec: BLA_W_DLP NAL_UNIT_CODED_SLICE_BLA_N_LP, // 18 NAL_UNIT_CODED_SLICE_IDR, // 19 // Current name in the spec: IDR_W_DLP NAL_UNIT_CODED_SLICE_IDR_N_LP, // 20 NAL_UNIT_CODED_SLICE_CRA, // 21 NAL_UNIT_RESERVED_22, NAL_UNIT_RESERVED_23, NAL_UNIT_RESERVED_24, NAL_UNIT_RESERVED_25, NAL_UNIT_RESERVED_26, NAL_UNIT_RESERVED_27, NAL_UNIT_RESERVED_28, NAL_UNIT_RESERVED_29, NAL_UNIT_RESERVED_30, NAL_UNIT_RESERVED_31, NAL_UNIT_VPS, // 32 NAL_UNIT_SPS, // 33 NAL_UNIT_PPS, // 34 NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35 NAL_UNIT_EOS, // 36 NAL_UNIT_EOB, // 37 NAL_UNIT_FILLER_DATA, // 38 NAL_UNIT_SEI, // 39 Prefix SEI NAL_UNIT_SEI_SUFFIX, // 40 Suffix SEI NAL_UNIT_RESERVED_41, NAL_UNIT_RESERVED_42, NAL_UNIT_RESERVED_43, NAL_UNIT_RESERVED_44, NAL_UNIT_RESERVED_45, NAL_UNIT_RESERVED_46, NAL_UNIT_RESERVED_47, NAL_UNIT_UNSPECIFIED_48, NAL_UNIT_UNSPECIFIED_49, NAL_UNIT_UNSPECIFIED_50, NAL_UNIT_UNSPECIFIED_51, NAL_UNIT_UNSPECIFIED_52, NAL_UNIT_UNSPECIFIED_53, NAL_UNIT_UNSPECIFIED_54, NAL_UNIT_UNSPECIFIED_55, NAL_UNIT_UNSPECIFIED_56, NAL_UNIT_UNSPECIFIED_57, NAL_UNIT_UNSPECIFIED_58, NAL_UNIT_UNSPECIFIED_59, NAL_UNIT_UNSPECIFIED_60, NAL_UNIT_UNSPECIFIED_61, NAL_UNIT_UNSPECIFIED_62, NAL_UNIT_UNSPECIFIED_63, NAL_UNIT_INVALID, };

下面接收下fu分组打包方式,fu分组包头格式如下:

H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解

fus包头包含了两个字节的payloadhdr,一个字节的fu header,fu header与h264一样,结构如下图,包含开始位(1b)、停止位(1b)、futype(6b)

H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解

paylodhdr两个自己的赋值,其实就是把hevc帧数据的nal unit header的naltype替换为49即可,下面是从ffmpeg源码中截取出来的fu打包方式代码片段:

static void nal_send(AVFormatContext *ctx, const uint8_t *buf, int len, int last_packet_of_frame) { RTPMuxContext *rtp_ctx = ctx->priv_data; int rtp_payload_size = rtp_ctx->max_payload_size - RTP_HEVC_HEADERS_SIZE; int nal_type = (buf[0] >> 1) & 0x3F; /* send it as one single NAL unit? */ if (len <= rtp_ctx->max_payload_size) //小于对定的最大值时,直接发送(最大值一般小于mtu) { /* use the original NAL unit buffer and transmit it as RTP payload */ ff_rtp_send_data(ctx, buf, len, last_packet_of_frame); } else //大于最大值时进行fu分组发送 { /* create the HEVC payload header and transmit the buffer as fragmentation units (FU) 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |F| Type | LayerId | TID | +-------------+-----------------+ F = 0 Type = 49 (fragmentation unit (FU)) LayerId = 0 TID = 1 */ rtp_ctx->buf[0] = 49 << 1; rtp_ctx->buf[1] = 1; //此处为paylaodhdr,规范赋值应该是替换hevc数据nal 的payloadhdr的type //rtp_ctx->buf[0] = (buf[0] &0x81) | (49<<1); //rtp_ctx->buf[1] = buf[1] /* create the FU header 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |S|E| FuType | +---------------+ S = variable E = variable FuType = NAL unit type */ rtp_ctx->buf[2] = nal_type; /* set the S bit: mark as start fragment */ rtp_ctx->buf[2] |= 1 << 7; /* pass the original NAL header */ //此处要注意,当是分组的第一报数据时,应该覆盖掉前两个字节的数据,h264要覆盖前一个字节的数据,即是第一包要去除hevc帧数据的paylaodhdr buf += 2; len -= 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 += rtp_payload_size; len -= rtp_payload_size; /* reset the S bit */ rtp_ctx->buf[2] &= ~(1 << 7); } /* set the E bit: mark as last fragment */ rtp_ctx->buf[2] |= 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 + 2, last_packet_of_frame); } }

通过rtp发送hevc视频数据,当hevc帧数据大于mtu时,应该进行fu分组发送,从上面代码流程就是对超过max_payload_size数据进行fu分组的流程,这个h264 fu-A很类似,很容易理解。

参考规范:

https://tools.ietf.org/html/draft-ietf-payload-rtp-h265-14

ffmpeg相关代码

https://www.ffmpeg.org/doxygen/2.5/rtpenc__hevc_8c_source.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205624.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午5:35
下一篇 2026年3月19日 下午5:35


相关推荐

  • Linux 安装JDK详细步骤

    Linux 安装JDK详细步骤Linux 系统上一般会安装好 OpenJDK 所以安装 JDK 之前 需要卸载系统自带的 OpenJDK 以及相关的 Java 文件 一 卸载系统自带的 OpenJDK 以及相关的 Java 文件 1 查看 Java 信息以及相关的 Java 文件查看 JDK 信息 输入 java version 检测 jdk 的安装包 输入 rpm qa grepjava2 接着删除相关 Java 文件 并检查是否删除完即可删除输入 rpm enodeps 包名检查是否删除完 输入 rpm qa

    2026年3月16日
    2
  • C之 十九 使用WinForm控件

    C之 十九 使用WinForm控件十九使用 WinForm 控件比如说电脑有显示器 鼠标 主机以及键盘的基本元素组成 在 windows 窗体中也有其基本控件 这些控件在每一个窗体中都要用到 也就是说无所不在 有些控件可能外观不同但是他们的使用方式都基本上一样 重点 掌握这些控件常用属性方法以及事件 能用编码的形式实

    2026年3月26日
    2
  • Qt实现简单的单例模式

    Qt实现简单的单例模式

    2021年9月11日
    65
  • 网站前端性能优化

    继前面几篇文章后再来说说老生常谈的话题,怎么样提升前端性能。文中很多取材自网络及《HighPerformanceWebSites》,并根据自己工作中所接触到的知识整理而成。http://hov

    2021年12月24日
    42
  • 浅复制,深复制详解下载_复制时如何跳过一部分内容

    浅复制,深复制详解下载_复制时如何跳过一部分内容文章目录浅复制和深复制String类实现浅复制和深复制有关浅复制与深复制的定义为:对类进行复制的时候按位复制,即把一个对象各数据成员的值原样复制到目标对象中。当类中涉及到指针类型数据成员的时候,往往就会产生指针悬挂问题。看以下结构:class A{ public: int* a;};A a1;A b1=a1;b1=a1执行的是浅复制,此时a1.a和b1….

    2022年8月18日
    8
  • Python用subprocess的Popen来调用系统命令

    Python用subprocess的Popen来调用系统命令

    2021年12月14日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号