java rtp打包_多媒体开发之rtp打包---打包中的FU-A分包方式说明_木-Star的博客-程序员ITS203

技术标签: java rtp打包  

继上篇rtp中的时间戳和负载类型之后,升入到了nalu的分片打包问题,这里做下笔记

(1)fu-a的打包格式

1.基于RTP协议的打包及解包

(1)单个NAL打包

H.264NALU单元常由[start code][NALU header][NALU payload]三部分组成,其中start code 用于标志一个NALU单元的开始,必须是“00000001”或者是“000001”,打包时去掉开始码,把其他数据打包到RTP包就可以了。

(2)分片打包

由于1500个字节是IP数据报的长度的上限,去除20个字节的数据报首部,1480字节是用来存放UDP数据报的。所以当一帧中的字节数超过这个数值时,我们必须将其分片打包。而且UDP在传输的过程中也要由包头开销,所以将RTP包的最大字节数定位1400字节。

需要分片的包格式有所区别,首先说明下分片的格式:

FU指示字节有以下格式:

+---------------+

|0|1|2|3|4|5|6|7|

+-+-+-+-+-+-+-+-+

|F|NRI| Type |

+---------------+

FU指示字节的类型28,29表示FU-A和FU-B。NRI域的值必须根据要分片的NAL单元NRI的值设置。

FU头的格式如下:

+---------------+

|0|1|2|3|4|5|6|7|

+-+-+-+-+-+-+-+-+

|S|E|R| Type |

+---------------+

S:开始位(1bit),当设置为1,开始位指示分片NAL单元的开始。第一个分片包设为1,其他的分片设置为0。

E:结束位(1bit),当设置为1,结束位指示分片NAL单元的结束,即,FU荷载是最后分片时设置为1,其他时候设置为0。

R:保留位(1bit),必须设置为0。

Type:5bit

(3)打包和解包的流程分析:

打包:

20120712114433758.jpg

分片时详细说明:

①第一个FU-A包的FU indicator 是这么设置的:F=NALU头中的F,NRI=NALU头中的NRI,Type=28 FU header: S=1,E=0,R=0,Type=NALU头中的Type;

②中间的FU-A包的FU indicator是这么设置的:F=NALU头中的F,NRI=NALU头中的NRI,Type=28 FU header: S=0,E=0,R=0,Type=NALU头中的Type;

③尾FU-A包的FU indicator是这么设置的:F=NALU头中的F,NRI=NALU头中的NRI,Type=28 FU header: S=0,E=1,R=0,Type=NALU头中的Type。

解包:

下面我们针对RTP解包时对待分片进行分类的代码实现做分析:

byte startBit=(byte)(recbuf[13]&0x80); byte endBit=(byte)(recbuf[13]&0x40);

①如果,startBit==-128,这包是分片的首包。

NalBuf[4]=(byte) ((recbuf[12]&0xE0)+(recbuf[13]&0x1F)); 这句用于重建组合NAL单元类型

②如果(startBit==0)&&(endBit==0),这包是分片的中间部分。

③如果 endBit==64 ,这包是分片尾部。

当分类清楚,就可以对各部分做相应的处理,如图中分析的那样。

2.码流管理机制

(1) 码流的接收。在发送端码流发送很快的情况下,由于接收端不仅要接收码流,还要进行分析,解码,这个处理需要一个较长的过程,如果接收端顺序执行这个过程的话,会导致无法完整接收发送端的包、出现丢包,由此而带来的是解码错误、无法正常播放视频、甚至程序奔溃等严重错误。针对这个问题我们采取并发的处理机制予以解决。线程并发存在的一个意义就是为了提高运行在单处理器上的速度。在java中我们采用java.util.concurrent包中的执行器(Executor)来管理线程Thread对象。我们创建20个线程,也就是向SingleThreadExecutor提交了20个任务,这些任务将排好队,每个任务会在下一个任务开始之前运行结束,每个任务都是按照他们被提交的顺序,在下一个任务开始之前完成。这样不仅实现了快速的接收而且还保证了接收到的包顺序是正确的。通过这样的处理后,接收和分析解码可以被分成两个部分,我们可以把接收到的数据暂时存放在缓冲区,然后就可以接着去接收下一包数据,不用等着分析、解码完成后才去接收下一包数据。这样做大大提高了接收效率,同时避免了丢包问题。

(2) 视频数据解析和解码。由于采用了并发的机制,接收到的数据不止一包,所以对接收到的数据应该做怎样合理的处理,成为我们接下来的难点。我们需要保证的仍然是数据包的顺序,还且每次只能处理一包,这里涉及到一个线程之间的协作问题。我们采用消费者生产者这种线程协作模式来做处理。我们将从存放数据的缓冲区中按顺序取到的包经过分析后放入另外一个缓冲区,通知解码程序可以进行从此缓冲区中获得数据解码,然后分析视频数据的程序进入等待。解码完成后,通知分析视频数据的程序继续进行视频数据分析,同时解码程序又进入等待。两个程序在执行和等待中交替进行。

20120712114443758.jpg

(3) 多级缓冲机制。上面我们也提到了几个缓冲,总结如下。

①接收后存放数据的缓冲,由于服务器端源源不断的实时码流,和采用了并发机制后带来更大量的数据,我们不可能马上处理完,所以必须设置一个缓冲区。

②接收端和处理端之间的缓冲,由于网络不稳定,接收到的数据可能会有时快有时慢,这直接会造成解码的不稳定和视频播放的不连续,所以在此设置一个缓冲,起到一个平滑,过渡的作用,这个缓冲区既要存放接收到大量的码流还要为视频数据分析提供数据,有个写读入和读出的过程,所以我们使用先入先出的队列Queue容器来做缓冲区。

③解析和解码过程之间的缓冲,由于在此过程中的数据量相较而言不是很大,而这个获取数据的速度直接影响了解码的速度,所以我们要用一个高效的缓冲区来担当此时的缓冲作用,由于stack是由系统自动分配,所以速度比较快,所以我们就在栈上分配一个数组用于存储即可。

④解码后到播放之间的缓冲,这个缓冲区同样除了起到使播放视频连续稳定的作用外,主要就是用来显示图像,还可以对视频图像进行一些处理工作,平滑,滤波等。

3.解码和播放的实现

H.264解码是移植了ffmpeg 中的H.264解码部分到Android,并且了深度删减优化。界面部分,文件接收处理以及视频显示都是用java做的,底层的视频解码部分则使用C来做从而满足速度的要求。H.264码流分割NAl(接受到视频数据的复原工作)是在java层做而没有分装到c中,是因为每次送的数据会受到限制,如果送的数据量大,底层可能会一次解码好几帧视频,但是到界面层只能显示一帧,造成丢帧。如果每次送的数据量较少,就会使得多次底层调用但并没有进行实质解码的现象发生,所以尽管这样做耦合度差些,速度慢些,但是综合考虑还是将数据分析工作放在java层完成。

20120712114458586.jpg

我们将解码后的视频数据用bitmap显示,draw到surfaceView的方法显示到手机屏上,由于有些手机不支持rgb24但几乎所有手机都支持rgb565,所以解码后返回的是rgb565数据。

4.程序流程功能架构

三、结束语

本文完整的设计并实现了从pc端到android手机端的H.264视频传输与解码播放功能。详细的分析了实现中的技术要点和难点,详细分析了rtp打包,解包的流程,针对发送数据快而处理速度慢的问题,采用多线程并发机制予以解决,面对大量,而且不稳定的数据包,针对各个环节的特点,设置了多级缓冲。使得视频播放更加流畅、平稳。对于分析和解码的先后次序问题,采用线程协作的思想,利用消费者,生产者模式,保证了视频数据的时序性。另外对于解码部分,则利用现有解码方法进行平台移植,合理处理c层和java层的分工,并以实现了这个完整的功能。在网络状况好的情况下,android手机端视频播放延时短,播放流畅,平稳。本文技术研究可以运用到视频播放的各个应用中,有着很强的实用价值。

http://blog.csdn.net/jwybobo2007/article/details/7235942

http://blog.sina.com.cn/s/blog_4ad7c2540101lep1.html

http://www.360doc.com/content/11/1018/13/1016783_157130105.shtml

http://blog.csdn.net/zjf82031913/article/details/7210106 讲的很深入!!!

(2)

(3)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_32822843/article/details/114189146

智能推荐

Java POI 导出EXCEL经典实现 Java导出Excel弹出下载框_Java面试:的博客-程序员ITS203

在web开发中,有一个经典的功能,就是数据的导入导出。特别是数据的导出,在生产管理或者财务系统中用的非常普遍,因为这些系统经常要做一些报表打印的工作。而数据导出的格式一般是EXCEL或者PDF,我这里就分别给大家介绍下。(注意,我们这里说的数据导出可不是数据库中的数据导出!么误会啦^_^)首先我们来导出EXCEL格式的文件吧。现在主流的操作Excel文件的开源工具有很多,用得比较多的就是Apach...

sphinx-apidoc_longgb123的博客-程序员ITS203

一、使用二、选项三、automodapi一、使用sphinx-apidoc [OPTIONS] -o <OUTPUT_PATH> <MODULE_PATH> [EXCLUDE_PATTERN, …]sphinx-apidoc是一个自动生成Sphinx源的工具,使用该autodoc扩展。 MODULE_PATH:是 python 的源...

git命令合并分支代码_bingguang1993的博客-程序员ITS203_gitee合并分支代码

对于复杂的系统,我们可能要开好几个分支来开发,那么怎样使用git合并分支呢?合并步骤:1、进入要合并的分支(如开发分支合并到master,则进入master目录)git checkout mastergit pull2、查看所有分支是否都pull下来了git branch -a3、使用merge合并开发分支git merge 分支名4、查看合并之后的状态git s...

JSP: 九个内置对象、四种属性范围_梦世的博客-程序员ITS203

九个内置对象比较熟悉的request.getParameter("参数名称"),显然request是一个类,而getParameter()是类中的方法,这个对象的实例化是由WEB容器帮助用户提供此对象的实例,这样的对象就被称为内置对象。在整个JSP之中一共提供有九个内置对象(背下来):No 内置对象 类型 描述 01 request javax.servlet.http.HttpServletResquest 服务器端接收客户端发送的用户请求信息 02.

Linux 专栏目录_Stark-Gs的博客-程序员ITS203_linux专栏

Linux 专栏目录LinuxLinux 文件系统结构Linux(Ubuntu) 查看文件类型&权限Linux 下文件操作命令Linux 下文件的压缩与解压缩Linux 下文件的查询与搜索Linux 用户权限管理Linux 磁盘管理UbuntuUbuntu 下 复制、粘贴、剪切、重命名Ubuntu 安装 pipUbuntu 安装 gitUbuntu 更改系统语言Linux 常用 shell 命令Ubuntu-APT 下载工具&APT 工具常用的命令Ubun

DevOps CI/CD 分析(一)之Dockerfile基础命令_m0_67505608的博客-程序员ITS203_ci dockerfile

本节我们总结Dockerfile命令是建立在SpringBoot/SpringCloud这样的Java项目基础之上,后续的分析和总结也均围绕SpringBoot/SpringCloud进行。Dockerfile文件作为构建Docker镜像的构建文件,它的地位毋庸置疑,无论我们是否引入了DevOps CI/CD,Dockerfile这个基础文件始终都是不可或缺的一环,所以我们在正式开始介绍CI/CD之前,我们先讲解DevOps CI/CD整个流程中的Dockerfile基础命令,因为整个CI/CD过程中会依.

随便推点

【腾讯TMQ】基于模型的自动化测试工具——GraphWalker_腾讯移动品质中心TMQ的博客-程序员ITS203

一、概述GraphWalker就是一个基于测试模型的用例生成工具。它主要应用于FSM, EFSM模型。可以用来它可以直接读取FSM, EFSM图形模型、json模型、生成测试用例。二、背景知识要了解GraphWalker首先要了解MBT是什么。MBT中文名称为基于模型的测试, 基于模型的测试属于软件测试领域的一种测试方法。MBT步骤如下:首先由被测系统(SUT, system under test

用vs编译后报错:NuGet Package restore failed for project PROJECT: Unable to find version 2.7.82 of package_回首愁的博客-程序员ITS203

从github上克隆的命令行代码,用vs编译后报错:NuGet Package restore failed for project PROJECT: Unable to find version 2.7.82 of package ‘CommandLineParser’解决方案依次打开tools -> NuGet Package Manager -> Package Manager Console解决方案1:参考官方网站https://www.nuget.org/packages/Com

AutoCAD二次开发&实现简单的自动编号_yGIS的博客-程序员ITS203

今天一早上看了群里有小伙伴有这样的需求,是实现用户用鼠标点击拾取AutoCAD平面,拾取点然后作为插入编号文字位置,按住esc键后,退出自动编号。按照他的需求,我这里大致想了一下,如果按照该小伙伴提出的用多线程和委托,想必有点复杂了。首先AutoCAD是不支持多线程的,至于使用委托,我想大概意思是使用鼠标的点击事件回调而已。还有他另外提到的使用钩子,这估计就更复杂了。我做了一个简单的实现,使用的w...

一文理解全文搜索引擎(Lucene、Elasticsearch、Solr)、目录搜索引擎、元搜索引擎的异同_tonglingtou1875的博客-程序员ITS203_全文式搜索引擎

一、全文搜索引擎是什么?    计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。    全文搜索引擎主要有:Lucene、Elasticsearch、Solr。   Lucene,是一个开放源代码的全文检索引擎工具包,不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系

TrueType字体文件_雨落的博客-程序员ITS203

转自:http://blog.csdn.net/zixue_pudn/article/details/5202259TrueType字体通常包含在单个TrueType字体文件中,其文件后缀为.TTF。OpenType字体是以类似   于TrueType字体的格式编码的POSTSCRIPT字体。OPENTYPE字体使用.OTF文件后缀。OPENTYPE还允许把多个OPENTYPE字体组合

ESP8266网络时钟、天气(STM32+ESP-12F)_一灯大师_Alex的博客-程序员ITS203

一、需求1)网络时间获取:获取NTP时间。2)指定地区天气获取:指定网址获取指定地区的天气。3)闹钟设置4)时间设置5)闹铃功能二、前期准备1)单片机最小系统板:smartESP开发板2)开发环境:MDK5.143)库函数:CubeMX5.6默认的HAL库版本4)ESP:ESP-12F5)显示:0.96 OLED IIC6)闹铃:蜂鸣器三、小项目效果图四、驱动原理1)ESP-12F:标准AT2)5向按键:AD检测3)蜂鸣器:PWM4)0.96 OLED:硬件I

推荐文章

热门文章

相关标签