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

2023-10-12 03:10

本文主要是介绍H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

从图中可以看出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,   // 0NAL_UNIT_CODED_SLICE_TRAIL_R,   // 1NAL_UNIT_CODED_SLICE_TSA_N,     // 2NAL_UNIT_CODED_SLICE_TLA,       // 3   // Current name in the spec: TSA_RNAL_UNIT_CODED_SLICE_STSA_N,    // 4NAL_UNIT_CODED_SLICE_STSA_R,    // 5NAL_UNIT_CODED_SLICE_RADL_N,    // 6NAL_UNIT_CODED_SLICE_DLP,       // 7 // Current name in the spec: RADL_RNAL_UNIT_CODED_SLICE_RASL_N,    // 8NAL_UNIT_CODED_SLICE_TFD,       // 9 // Current name in the spec: RASL_RNAL_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_LPNAL_UNIT_CODED_SLICE_BLANT,     // 17   // Current name in the spec: BLA_W_DLPNAL_UNIT_CODED_SLICE_BLA_N_LP,  // 18NAL_UNIT_CODED_SLICE_IDR,       // 19  // Current name in the spec: IDR_W_DLPNAL_UNIT_CODED_SLICE_IDR_N_LP,  // 20NAL_UNIT_CODED_SLICE_CRA,       // 21NAL_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,                   // 32NAL_UNIT_SPS,                   // 33NAL_UNIT_PPS,                   // 34NAL_UNIT_ACCESS_UNIT_DELIMITER, // 35NAL_UNIT_EOS,                   // 36NAL_UNIT_EOB,                   // 37NAL_UNIT_FILLER_DATA,           // 38NAL_UNIT_SEI,                   // 39 Prefix SEINAL_UNIT_SEI_SUFFIX,            // 40 Suffix SEINAL_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分组包头格式如下:

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

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                   10 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|F|   Type    |  LayerId  | TID |+-------------+-----------------+F       = 0Type    = 49 (fragmentation unit (FU))LayerId = 0TID     = 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 header0 1 2 3 4 5 6 7+-+-+-+-+-+-+-+-+|S|E|  FuType   |+---------------+S       = variableE       = variableFuType  = 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帧数据的paylaodhdrbuf += 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

这篇关于H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/192808

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现