基于RTP协议的打包及解包
解包和打包exe文件的方法

解包和打包exe文件的方法1.引言1.1 概述概述:在软件开发过程中,我们经常会遇到需要解包和打包exe文件的情况。
解包exe文件是指将经过编译的可执行文件进行还原,以获取其中的源代码、资源文件等内容。
而打包exe文件则是将源代码和相关资源文件重新打包成可执行文件。
这两个操作在软件开发、软件逆向工程和软件调试等领域中都有广泛的应用。
解包exe文件的方法可以分为使用解包工具和手动解包两种方式。
使用解包工具是指使用专门的软件工具来进行解包操作,它能够自动分析可执行文件的结构并提取其中的内容。
手动解包则是通过一些常见的手段,如二进制文件编辑器或调试器,以手动的方式逆向还原可执行文件中的内容。
打包exe文件的方法也可以分为使用打包工具和手动打包两种方式。
使用打包工具可以方便地将源代码和相关资源文件打包成可执行文件,它提供了简单易用的图形界面和各种打包选项。
手动打包则需要开发人员手动进行文件的整理和编译操作,相对来说比较繁琐。
总结起来,解包和打包exe文件是软件开发中常见的操作,通过解包我们可以获取到可执行文件中的源代码和资源文件,有助于我们理解和调试软件;而打包exe文件则可以将我们的源代码和资源文件重新打包成可执行文件,方便我们发布和分发软件。
在进行解包和打包操作时,可以根据需要选择使用相应的工具或手动操作的方式,以达到我们的目的。
1.2 文章结构文章结构负责为读者介绍本文的组织和内容安排。
本文主要围绕解包和打包exe文件的方法展开讨论。
在本文中,我们将首先提供一个引言部分,概述本文的背景和目的。
接下来,将详细介绍解包exe文件的方法,包括使用解包工具和手动解包。
然后,我们将探讨打包exe文件的方法,包括使用打包工具和手动打包。
最后,我们将通过总结解包和打包exe文件的方法,提供一些结论和建议。
通过本文的阅读,读者将能够全面了解解包和打包exe文件的技术和方法,并且可以根据自己的需求选择适合的方式进行操作。
路由器固件的解包与打包

路由器固件的解包与打包一、概述当前大学生都被校园网的客户端困扰,然而南京工程学院公布了Linux客户度解决方案,或者Mentohust解决方案,可以在Ubuntu系统的计算机上运行了。
但进一步的工作就是如何令其在路由器上工作,以达到真正的路由功能。
假定笔者已经把电脑上完美运行的客户端进行了交叉编译,生成了要在路由上运行的拨号程序(假定为Client),且笔者的路由器有合适的固件(假定为firm.bin)。
那么要在路由器上运行Client有三种方法:1.可以把Client上传到路由器的/jffs目录下。
(本文不讨论这种情形)2.刷写dd后,由于剩余容量太小导致无法加载jffs,那么每次启动路由后,可以将程序Client 上传到刷写了firm.bin路由的/tmp目录下,然后令其运行。
简单的说,就是在内存里运行Client。
其缺点就是每次路由断电,你必须重新上传。
(本文不讨论这种情形)3.当路由器无法加载jffs时,可以考虑将Client程序增添至固件,并且在自启动命令里输入正确的命令方式,以达到每次路由插上电,都可以自动运行拨号程序的完美效果。
以下讨论的为如何将Client固化至固件的方法。
所需软件为firmware-mod-kit,大致步骤为:1.先用解包软件解包路由器固件将会得到固件核心文件。
2.再把Client复制到固件的某个文件夹内,且注意赋予可执行的权限。
3.用build-ng.sh进行最终的封包,生成新的固件。
操作环境:Ubuntu 11.04版参考资料:/p/mentohust-wrt//p/firmware-mod-kit/ Firmware Modification Kit并感谢第一个项目的作者给我的指导和帮助。
我只是把他没有写明白的步骤,以我自己的理解方式重述而已。
二、详细步骤1.首先下载firmware-mod-kit封包软件,并进行编译,将会得到所需文件。
1.1下载firmware-mod-kit封包软件并在终端窗口里输入以下命令:svn checkout /svn/ firmware-mod-kit-read-only耐心的等待之后,会在你的本地硬盘上生成一个目录firmware-mod-kit-read-only,其中包含branches,tags,trunk,wiki四个文件夹。
路由器固件的解包与打包2024

引言概述:路由器固件解包与打包是指将嵌入式设备(如路由器)上的固件进行解开和重新打包的过程。
这个过程对于嵌入式设备的软件开发和定制化非常重要。
本文将详细介绍用于解包和打包固件的工具和步骤。
正文内容:一、解包固件1.1提取固件文件:从路由器设备中提取固件文件,可以使用DD命令或者串口控制台提取。
1.2解压固件文件:使用解压工具,如binwalk,将固件文件进行解压,得到固件的各个组成部分。
1.3分析固件:通过分析解压后的固件文件,了解各个组成部分的结构和功能。
二、打包固件2.1修改固件:根据需求,对固件文件进行修改,如添加新的软件包、修改配置文件等。
2.2重新打包固件:将修改后的文件重新打包成固件格式,可以使用mkimage等工具进行打包。
三、固件的烧录与更新3.1硬件烧录:将打包好的固件通过串口或者JTAG接口烧录到设备的闪存中。
3.2固件更新:将新的固件通过WEB界面或者命令行进行更新,确保设备上的固件是最新版本。
四、错误处理与调试4.1解包错误处理:解包固件时可能会遇到一些错误,如文件损坏或者解压失败,需要进行错误处理。
4.2打包错误处理:打包固件时可能会遇到一些错误,如文件格式不兼容或者依赖关系错误,需要进行错误处理。
4.3调试固件:使用调试工具,如GDB,对固件进行调试,查找和修复潜在问题。
五、固件安全性5.1固件签名:为了确保固件的可靠性和完整性,可以对固件进行签名,防止被篡改或者恶意替换。
5.2固件加密:对固件进行加密,防止固件被逆向工程或者泄露敏感信息。
5.3固件验证:通过验证机制,如校验和或者哈希值等,确保固件在传输和存储过程中的完整性。
总结:路由器固件的解包与打包对于定制化和软件开发非常重要。
通过解包固件,可以深入了解嵌入式设备的软件和硬件组成部分。
通过打包固件,可以将所需的修改和定制化应用到设备上。
固件的烧录与更新、错误处理与调试以及固件的安全性也是不可忽视的。
通过掌握解包与打包固件的技术,可以更好地定制和管理嵌入式设备的固件。
RTP协议分析

RTP协议分析协议名称:RTP协议分析一、引言RTP(Real-time Transport Protocol)是一种用于实时传输音频和视频数据的协议。
该协议提供了一种标准化的方式,用于在多媒体应用程序之间传输实时数据。
本协议旨在分析RTP协议的基本原理、功能和特点,并提供相应的标准格式。
二、协议概述RTP协议是一个基于UDP的传输协议,用于在互联网上传输实时数据。
它提供了一种可靠的、实时的数据传输机制,适用于音频、视频和其他多媒体数据的传输。
RTP协议通过将数据分割成小的数据包(称为RTP包)并添加头部信息来实现数据的传输和同步。
三、协议结构1. RTP包头部RTP包头部包含以下字段:- 版本(V):标识RTP协议的版本号。
- 填充(P):指示是否在RTP包的末尾添加了额外的填充字节。
- 扩展(X):指示是否在RTP包中包含了扩展头部。
- CSRC计数(CC):指示后续包头中CSRC标识符的数量。
- 标记(M):用于指示RTP包是否为一个帧的最后一个包。
- 负载类型(PT):指示RTP包中负载的类型,例如音频或视频。
- 序列号(Sequence Number):用于标识RTP包的顺序。
- 时间戳(Timestamp):提供了RTP包中数据的时间信息。
- 同步源(SSRC):用于唯一标识RTP流的源。
- CSRC列表(CSRC List):包含了参与混合的媒体流的CSRC标识符的列表。
2. RTP包负载RTP包的负载部分包含了实时传输的音频、视频或其他多媒体数据。
四、协议功能1. 实时传输RTP协议提供了实时传输数据的功能,适用于音频和视频等多媒体数据的传输。
它通过将数据分割成小的数据包,并在每个包中添加时间戳信息,以确保接收方可以按照正确的顺序和时间重建数据。
2. 数据同步RTP协议通过使用时间戳字段来实现数据的同步。
接收方可以根据时间戳信息将多个数据包按照正确的顺序进行播放,从而实现音视频的同步。
java、android可用的rtp封包解包h264案例

java、android可⽤的rtp封包解包h264案例做直播,⾳视频通讯。
经常需要通过rtp协议封装⾳视频数据来发送。
⽹上找到的基本都是c或c++版本的,没有JAVA版本的。
就算千⾟万苦找到⼀篇java版本的,要么不能⽤,要么就是⼀些⽚段,要么有封包没解包。
很是蛋疼,本⼈也是这样,刚开始不太熟悉rtp协议,不太明⽩怎么封包组包,痛苦了⼏天,终于搞出来了,分享给有需要的朋友,希望对你们有所帮助。
直接看代码吧。
不多说了。
⾸先看看关键类:package com.imsdk.socket.udp.codec;import android.os.SystemClock;import android.util.Log;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.math.BigDecimal;import java.util.Random;import java.util.concurrent.Semaphore;public class RtspPacketEncode {private static final String TAG = "RtspPacketEncode";//------------视频转换数据监听-----------public interface H264ToRtpLinsener {void h264ToRtpResponse(byte[] out, int len);}private H264ToRtpLinsener h264ToRtpLinsener;//执⾏回调private void exceuteH264ToRtpLinsener(byte[] out, int len) {if (this.h264ToRtpLinsener != null) {h264ToRtpLinsener.h264ToRtpResponse(out, len);}}// -------视频--------private int framerate = 10;private byte[] sendbuf = new byte[1500];private int packageSize = 1400;private int seq_num = 0;private int timestamp_increse = (int) (90000.0 / framerate);//framerate是帧率private int ts_current = 0;private int bytes = 0;// -------视频END--------public RtspPacketEncode(H264ToRtpLinsener h264ToRtpLinsener) {this.h264ToRtpLinsener = h264ToRtpLinsener;}/*** ⼀帧⼀帧的RTP封包** @param r* @return*/public void h264ToRtp(byte[] r, int h264len) throws Exception {CalculateUtil.memset(sendbuf, 0, 1500);sendbuf[1] = (byte) (sendbuf[1] | 96); // 负载类型号96,其值为:01100000sendbuf[0] = (byte) (sendbuf[0] | 0x80); // 版本号,此版本固定为2sendbuf[1] = (byte) (sendbuf[1] & 254); //标志位,由具体协议规定其值,其值为:01100000sendbuf[11] = 10;//随机指定10,并在本RTP回话中全局唯⼀,java默认采⽤⽹络字节序号不⽤转换(同源标识符的最后⼀个字节)if (h264len <= packageSize) {sendbuf[1] = (byte) (sendbuf[1] | 0x80); // 设置rtp M位为1,其值为:11100000,分包的最后⼀⽚,M位(第⼀位)为0,后7位是⼗进制的96,表⽰负载类型 sendbuf[3] = (byte) seq_num++;System.arraycopy(CalculateUtil.intToByte(seq_num++), 0, sendbuf, 2, 2);//send[2]和send[3]为序列号,共两位{// java默认的⽹络字节序是⼤端字节序(⽆论在什么平台上),因为windows为⼩字节序,所以必须倒序/**参考:* /u011068702/article/details/51857557* /blog/1591261*/byte temp = 0;temp = sendbuf[3];sendbuf[3] = sendbuf[2];sendbuf[2] = temp;}// FU-A HEADER, 并将这个HEADER填⼊sendbuf[12]sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x80)) << 7);sendbuf[12] = (byte) (sendbuf[12] | ((byte) ((r[0] & 0x60) >> 5)) << 5);sendbuf[12] = (byte) (sendbuf[12] | ((byte) (r[0] & 0x1f)));// 同理将sendbuf[13]赋给nalu_payload//NALU头已经写到sendbuf[12]中,接下来则存放的是NAL的第⼀个字节之后的数据。
adts rtp封装流程

adts rtp封装流程ADTS(Audio Data Transport Stream)是一种音频数据传输流格式,而RTP(Real-time Transport Protocol)是一种实时传输协议。
在音频流的封装过程中,ADTS和RTP常常结合使用,以下是它们结合使用的封装流程:1. 音频编码,首先,原始音频数据会经过音频编码器进行压缩,常见的音频编码格式包括AAC、MP3等。
编码后的数据称为音频帧。
2. ADTS封装,接下来,将编码后的音频帧进行ADTS封装。
ADTS封装是将音频帧添加ADTS头部信息的过程,头部信息包括同步字、MPEG版本、层信息、采样率、声道数、帧长度等。
这些信息有助于接收端正确解析音频数据。
3. RTP封装,经过ADTS封装的音频数据再经过RTP封装。
RTP封装是将音频数据打包成RTP数据包的过程,每个RTP数据包包含一个RTP头部和音频数据。
RTP头部包含序列号、时间戳、同步源(SSRC)标识等信息,用于实现实时传输和同步。
4. 网络传输,经过RTP封装的音频数据通过网络进行传输。
在传输过程中,可以通过RTCP(RTP Control Protocol)进行传输质量的监控和反馈。
5. 接收端处理,接收端首先接收RTP数据包,然后根据RTP头部信息进行解析,提取音频数据。
随后进行ADTS解包,将音频数据解析出来,最终进行解码和播放。
总的来说,ADTS和RTP的结合使用可以实现音频数据的封装、传输和接收端处理,保证音频数据在网络中的实时传输和正确解析。
这样的封装流程能够满足实时音频传输的需求,并且有利于网络传输的稳定性和音频数据的质量保障。
RTP协议及编解码

RTP头
0 V=2 P X CC M 1 PT timestamp synchronization source (SSRC) identifier contributing source (CSRC) identifier „„„„„„ payload(audio video) „„„„„„„ 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
统称为“TCP/IP 协议”, INTERNET网络 基础
自定义协议
按照具体业务需要,按照一定标准定义的 协议
多方聊天室协议概述
名称 协议描述 用户登录入聊天室请求,使用用户名,无需密码 用户登录聊天室响应,如果用户名已存在,则要求用户用其他用户名登录 用户发言请求,私聊 用户发言,广播给所有用户 用户离开聊天室 服务器端发送当前用户列表 服务器端转发的私聊内容 服务器端广播某个用户的文本消息 服务器端广播某个用户上线
流媒体传输实现
实现流媒体传输主要有两种方法: 顺序流(progressive streaming)传输 实时流(realtime streaming)传输
顺序流传输
顺序流传输采用顺序下载的方式进行传输,在下载 的同时用户可以在线回放多媒体数据,但给定时刻 只能观看已经下载的部分,不能跳到尚未下载的部 分,也不能在传输期间根据网络状况对下载速度进 行调整。由于标准的HTTP服务器就可以发送这种形 式的流媒体,而不需要其他特殊协议的支持,因此 也常常被称作 HTTP流式传输。顺序流式传输比较 适合于高质量的多媒体片段,如片头、片尾或者广 告等。
在发送端开发人员必需把执行rtp协议的程序写入到创建rtp信息包的应用程序中然后应用程序把rtp信息包发送到udp的套接接口14rtpptsequencenumbertimestampsynchronizationsourcessrcidentifiercontributingsourcecsrcidentifierpayloadaudiovideo15rtp名称说明版本v2位标识rtp版本填充标识p1位如设置填充位在包尾将包含附加填充字它不属于有效载荷扩展x1位如设置扩展位固定头后跟一个扩展头csrc计数cc4位csrc计数包括紧接在固定头后csrc标识符个数标识m1位标识解释由设置定义目的在于允许重要事件在包流中标识出来载荷类型pt7位记录后面资料使用哪种codec接收端找出相应的decoder解码出来16rtp名称说明系列号16位系列号随每个rtp数据包而增加1由接收者用来探测包损失系列号初值是随机的使对加密的文本攻击更难32位时标反映rtp数据包中第一个八进制数的采样时刻采样时刻必须从单调线性增加的时钟导出以允许同步与抖动计算ssrc32位标识同步源此标识不是随机选择的目的在于使同一rtp包连接中没有两个同步源有相同的ssrc标识csrc列表0到15项每项32位
RTP协议全解(H264码流和PS流)

RTP协议全解(H264码流和PS流)写在前面:RTP的解析,网上找了很多资料,但是都不全,所以我力图整理出一个比较全面的解析,其中借鉴了很多文章,我都列在了文章最后,在此表示感谢。
互联网的发展离不开大家的无私奉献,我决定从我做起,希望大家支持。
1、RTP Header解析图11) V:RTP协议的版本号,占2位,当前协议版本号为22) P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
3) X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头4) CC:CSRC计数器,占4位,指示CSRC 标识符的个数5) M: 标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。
6) PT: 有效荷载类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM 图像等,在流媒体中大部分是用来区分音频流和视频流的,这样便于客户端进行解析。
7) 序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。
这个字段当下层的承载协议用UDP的时候,网络状况不好的时候可以用来检查丢包。
同时出现网络抖动的情况可以用来对数据进行重新排序,序列号的初始值是随机的,同时音频包和视频包的sequence是分别记数的。
8) 时戳(Timestamp):占32位,必须使用90 kHz 时钟频率。
时戳反映了该RTP报文的第一个八位组的采样时刻。
接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。
9) 同步信源(SSRC)标识符:占32位,用于标识同步信源。
该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。
10) 特约信源(CSRC)标识符:每个CSRC标识符占32位,可以有0~15个。
每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源。
注:基本的RTP说明并不定义任何头扩展本身,如果遇到X=1,需要特殊处理取一段码流如下:80 e0 00 1e 00 00 d2 f0 00 00 00 00 41 9b 6b 49 €?....??....A?kIe1 0f 26 53 02 1a ff06 59 97 1d d2 2e 8c 50 01 ?.&S....Y?.?.?P.cc 13 ec 52 77 4e e50e 7b fd 16 11 66 27 7c b4 ?.?RwN?.{?..f'|?f6 e1 29 d5 d6 a4 ef3e 12 d8 fd 6c 97 51 e7 e9 ??)>.??l?Q??cfc7 5e c8 a9 51 f6 82 65 d6 48 5a 86 b0 e0 8c ??^??Q??e?HZ其中,80 是V_P_X_CCe0 是M_PT00 1e 是SequenceNum00 00 d2 f0 是Timestamp00 00 00 00是SSRC把前两字节换成二进制如下1000 0000 1110 0000按顺序解释如下:10 是V;0 是P;0 是X;0000 是CC;1 是M;110 0000 是PT;排版不如word看的清晰,大家凑合着看吧。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
H.264视频在android手机端的解码与播放文/南京邮电大学张永芹龚建荣摘要:本文实现了手机终端通过移动无线网络与媒体服务器进行通信,并就开发过程中的几个技术难点的解决方法进行了说明。
首先详细分析说明了rtp 打包,解包的流程,这是视频传输的基础;然后在RTP传输过程中,针对发送数据快而处理速度慢的问题,采用多线程并发机制予以解决;面对大量,而且不稳定的数据包,本文针对各个环节自己的特点,设计了多级缓冲处理机制,使得视频播放更加流畅、平稳。
接着,对于分析和解码的先后次序的问题,则采用线程协作的思想,利用消费者,生产者模式,保证了视频数据的时序性。
最后对于视频解码部分,则利用现有解码方法进行平台移植,深度简化代码,合理处理c层和java层的分工。
最后实践证明,采用本文提供的方法,视频传输、播放成功,而且android手机端视频播放延时短,流畅,平稳。
关键词:H.264 RTP 多级缓冲线程协作 android随着无线网络和智能手机的发展,智能手机与人们日常生活联系越来越紧密,娱乐、商务应用、金融应用、交通出行各种功能的软件大批涌现,使得人们的生活丰富多彩、快捷便利,也让它成为人们生活中不可取代的一部分。
其中,多媒体由于其直观性和实时性,应用范围越来越广,视频的解码与播放也就成为研究的热点。
H.264标准技术日渐成熟,采用了统一的VLC符号编码,高精度、多模式的位移估计,基于4×4块的整数变换、分层的编码语法等。
这些措施使得H.264算法具有很高的编码效率,在相同的重建图像质量下,能够比H.263节约50%左右的码率。
而且H.264的码流结构网络适应性强,增加了差错恢复能力。
正好适用于带宽受限,差错率高的无线网络。
本文结合ffmpeg开源代码中的解码方法,采用多线程接收数据包,多级缓冲数据,接收和解码并行双线程操作等方法,缓解了由于传输的数据量大、速度快而导致的数据堵塞、解码出错、视频画面迟钝、延迟等问题。
使得h.264视频的传输速度快,稳定性好。
最终实现了pc端到android手机端的视频传输,以及在android手机端的解码播放。
该技术可以应用于视频会议、视频监控等应用中。
一、 H.264视频传输播放系统的总体结构H.264视频传输播放系统分为服务器端和客户端2个部分,服务器端负责读取H.264的视频数据,并且以RTP/RTCP格式打包发送给客户端,并且接受客户端的反馈,对传输速度等作相应的控制。
Android手机客户端主要完成从服务器端接收实时码流数据,经过缓冲,进行视频数据解析,然后送去解码,最后在手机上显示播放。
服务器端采用c语言实现,客户端主要用java语言实现。
二、关键技术及其实现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)打包和解包的流程分析:打包:分片时详细说明:①第一个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); byteendBit=(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) 视频数据解析和解码。
由于采用了并发的机制,接收到的数据不止一包,所以对接收到的数据应该做怎样合理的处理,成为我们接下来的难点。
我们需要保证的仍然是数据包的顺序,还且每次只能处理一包,这里涉及到一个线程之间的协作问题。
我们采用消费者生产者这种线程协作模式来做处理。
我们将从存放数据的缓冲区中按顺序取到的包经过分析后放入另外一个缓冲区,通知解码程序可以进行从此缓冲区中获得数据解码,然后分析视频数据的程序进入等待。
解码完成后,通知分析视频数据的程序继续进行视频数据分析,同时解码程序又进入等待。
两个程序在执行和等待中交替进行。
(3) 多级缓冲机制。
上面我们也提到了几个缓冲,总结如下。
①接收后存放数据的缓冲,由于服务器端源源不断的实时码流,和采用了并发机制后带来更大量的数据,我们不可能马上处理完,所以必须设置一个缓冲区。
②接收端和处理端之间的缓冲,由于网络不稳定,接收到的数据可能会有时快有时慢,这直接会造成解码的不稳定和视频播放的不连续,所以在此设置一个缓冲,起到一个平滑,过渡的作用,这个缓冲区既要存放接收到大量的码流还要为视频数据分析提供数据,有个写读入和读出的过程,所以我们使用先入先出的队列Queue容器来做缓冲区。
③解析和解码过程之间的缓冲,由于在此过程中的数据量相较而言不是很大,而这个获取数据的速度直接影响了解码的速度,所以我们要用一个高效的缓冲区来担当此时的缓冲作用,由于stack是由系统自动分配,所以速度比较快,所以我们就在栈上分配一个数组用于存储即可。
④解码后到播放之间的缓冲,这个缓冲区同样除了起到使播放视频连续稳定的作用外,主要就是用来显示图像,还可以对视频图像进行一些处理工作,平滑,滤波等。
3.解码和播放的实现H.264解码是移植了ffmpeg中的H.264解码部分到Android,并且了深度删减优化。
界面部分,文件接收处理以及视频显示都是用java做的,底层的视频解码部分则使用C来做从而满足速度的要求。
H.264码流分割NAl(接受到视频数据的复原工作)是在java层做而没有分装到c中,是因为每次送的数据会受到限制,如果送的数据量大,底层可能会一次解码好几帧视频,但是到界面层只能显示一帧,造成丢帧。
如果每次送的数据量较少,就会使得多次底层调用但并没有进行实质解码的现象发生,所以尽管这样做耦合度差些,速度慢些,但是综合考虑还是将数据分析工作放在java层完成。
我们将解码后的视频数据用bitmap显示,draw到surfaceView的方法显示到手机屏上,由于有些手机不支持rgb24但几乎所有手机都支持rgb565,所以解码后返回的是rgb565数据。
4.程序流程功能架构三、结束语本文完整的设计并实现了从pc端到android手机端的H.264视频传输与解码播放功能。
详细的分析了实现中的技术要点和难点,详细分析了rtp打包,解包的流程,针对发送数据快而处理速度慢的问题,采用多线程并发机制予以解决,面对大量,而且不稳定的数据包,针对各个环节的特点,设置了多级缓冲。
使得视频播放更加流畅、平稳。
对于分析和解码的先后次序问题,采用线程协作的思想,利用消费者,生产者模式,保证了视频数据的时序性。
另外对于解码部分,则利用现有解码方法进行平台移植,合理处理c层和java层的分工,并以实现了这个完整的功能。
在网络状况好的情况下,android手机端视频播放延时短,播放流畅,平稳。
本文技术研究可以运用到视频播放的各个应用中,有着很强的实用价值。