从零开始写一个发送h264的rtsp服务器(下)
转自:http://blog.csdn.net/jychen105/article/details/47012099
一、H264是如何通过rtsp发送的
简单来说,H264就是通过打包到rtp协议的数据部分发送出去的。
H264打包成rtp数据包有三种方式
- 单一封包模式
- 组合封包模式
分片模式
要想弄明白这三种打包方式,必须先弄清楚h264的组成结构,或者叫组成单元。
二、H264结构单元
H264数据流最基本的结构单元叫nalu单元。
H264的nalu单元组成:
[start code] + [nalu header] + [nalu paload]
start code: 可以为 001 或者 0001, 也就是点3个字节或者4个字节
nalu header: 占一个字节
nalu paload: 长度不定
每一帧画面拥有一个或多个nalu单元,每个nalu单元以start code进行分离
nalu header
nalu header占一个字节,它又分了三个部分:F,NRI,TYPE
7 6-5 4-0
F NRI TYPE
- F:一般为0
- NRI:指示nalu单元的重要性,不同编码器编出来的H264数据不同
- TYPE:nalu类型
TYPE类型:
类型 | 定义 |
---|---|
0 | 未定义 |
1-23 | NAL单元 |
24 | STAP-A 单一时间组合包 |
25 | STAP-B 单一时间组合包 |
26 | MTAP-16 多个时间组合包 |
27 | MTAP-24 多个时间组合包 |
28 | FU-A 分片 |
29 | FU-B 分片 |
30-31 | 未定义 |
特别注意的是7这SPS,8为PPS,发送SDP协议包时需进行base64编码
25,26,27,29这四种类型基本不会出现
三、H264的RTP打包
前面说过有三种打包方式:单一封包模式,组合封包模式,分片模式
打包原则
单一封包模式: nalu单元长度小于MTU长度(通常是1500,live555定义的是2400)用此种方式封包
组合封包模式: nalu单元实在太小,多个nalu长度和都小于MTU长度
分片模式:nalu单元长度大于MTU长度
以上封包模式是按nalu长度来分的,同时也完全符合nalu单元中TYPE类型来分。
TYPE1-23 单一封包,24组合封包, 28分片封包
打包细则
单一封包:
[RTP header] + [nalu header] + [nalu payload]
组合封包:
[RTP header]+[STAP-A头(1字节,低5位为24)] +
[第1个nalu长度(2字节)] + [第1个nalu header] + [第1个nalu payload]+
[第2个nalu长度(2字节)] + [第2个nalu header] + [第2个nalu payload]+
[第N个nalu长度(2字节)] + [第N个nalu header] + [第N个nalu payload]
分片模式封包:
此时要切分成多个RTP包
[RTP header]+[FU Indicator(1字节)]+[FU header(1字节)]+[部分nalu payload]
FU Indicator
7 6-5 4-0
F NRI TYPE
F, NRI为nalu中的F,NRI
TYPE:固定为28
FU header
7 6 5 4-0
S E R TYPE
S:开始标志(start)
E:结束标志(end)
R:保留(reserve)
TYPE: nalu中的TYPE
标志 | S | E | R |
---|---|---|---|
分片开始 | 1 | 0 | 0 |
分片中间 | 0 | 0 | 0 |
分片结束 | 0 | 1 | 0 |
RTP包头的填充
typedef struct
{
/* byte 0 */
unsigned char csrc_len:4; /* CC expect 0 */
unsigned char extension:1; /* X expect 1, see RTP_OP below */
unsigned char padding:1; /* P expect 0 */
unsigned char version:2; /* V expect 2 */
/* byte 1 */
unsigned char payload:7; /* PT RTP_PAYLOAD_RTSP */
unsigned char marker:1; /* M expect 1 */
/* byte 2,3 */
unsigned short seq_no; /*sequence number*/
/* byte 4-7 */
unsigned long timestamp; /*time stamp*/
/* byte 8-11 */
unsigned long ssrc; /* stream number is used here. */
} RTPHeader;/*12 bytes*/
各项值填充:
符号 | 位数 | 定义 | 数值 |
---|---|---|---|
V | 2bit | 版本号 | 2 |
P | 1bit | 填充位 | 0 |
X | 1bit | 扩展位 | 0 |
CC | 4bit | CSRC数目 | 0 |
M | 1bit | 标志位 | 单一封包为1; 分片封包最后一个包为1,其余为0; |
PT | 7bit | 载荷类型 | 96(h264为96) |
SeqNum | 16bit | 序列号 | 每发一个包加1 |
Timestamp | 32bit | 时间戳 | 单一封包 +采样率,h264为3600; 分片封包第一个加采样率,后续不变 |
SSRC | 32bit | 同步源标识 | 任意指定,标准是一个MD5算法值,未明 |
CSRC | 0bit | 贡献源列表 | CC为0,所以此项没有 |
组合模式的M跟Timestamp未调查清楚,但是可以讨巧,打包的时候不采用组合模式,采用单一模式。
从零开始写一个发送h264的rtsp服务器(下)的更多相关文章
- 从零开始写一个发送h264的rtsp服务器(上)
转自:http://blog.csdn.net/jychen105/article/details/47006345 一.什么是RTSP 通常所说的rtsp协议其实包含三个协议: rtsp协议, rt ...
- 从零开始写一个Tomcat(贰)--建立动态服务器
上文书说道如何通过http协议建立一个静态的服务器来访问静态网页,但我们选择tomcat最主要的原因还是因为它能动态的执行servlet,这边文章将引导你实现一个能够运行servlet的服务器,这个简 ...
- 从零开始写一个Tomcat(叁)--请求解析
挖坑挖了这么长时间也该继续填坑了,上文书讲到从零开始写一个Tomcat(贰)--建立动态服务器,讲了如何让服务器解析请求,分离servlet请求和静态资源请求,读取静态资源文件输出或是通过URLCla ...
- 深入浅出React Native 3: 从零开始写一个Hello World
这是深入浅出React Native的第三篇文章. 1. 环境配置 2. 我的第一个应用 将index.ios.js中的代码全部删掉,为什么要删掉呢?因为我们准备从零开始写一个应用~学习技术最好的方式 ...
- 用ASP.Net写一个发送ICQ信息的程序
用ASP.Net写一个发送ICQ信息的程序 这里我给大家提供一个很实用的例子,就是在线发送ICQ信息.想一想我们在网页上直接给朋友发送ICQ信息,那是多么美妙的事情啊.呵呵,在吹牛啊,其实ICQ本来就 ...
- 从零开始写一个武侠冒险游戏-0-开发框架Codea简介
从零开始写一个武侠冒险游戏-0-开发框架Codea简介 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.03 增加对 XCode 项目文件的说明. 概述 本游戏全 ...
- 2019-5-24-WPF-源代码-从零开始写一个-UI-框架
title author date CreateTime categories WPF 源代码 从零开始写一个 UI 框架 lindexi 2019-05-24 15:54:36 +0800 2018 ...
- 从零开始写一个武侠冒险游戏-8-用GPU提升性能(3)
从零开始写一个武侠冒险游戏-8-用GPU提升性能(3) ----解决因绘制雷达图导致的帧速下降问题 作者:FreeBlues 修订记录 2016.06.23 初稿完成. 2016.08.07 增加对 ...
- 从零开始写一个武侠冒险游戏-7-用GPU提升性能(2)
从零开始写一个武侠冒险游戏-7-用GPU提升性能(2) ----把地图处理放在GPU上 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.06 增加对 XCode ...
随机推荐
- IIS7配置HTTPS+默认访问https路径
一.下载证书(这里我使用的是阿里云免费的证书) 文件说明: 1. 1532858285913.key(证书私钥文件).1532858285913.pem(证书文件).1532858285913.pfx ...
- 安装Xampp-配置appche,mysql运行环境遇到的坑(转)
用php编写的web应用程序,需运行在php的web容器中,其中apache server是一个针对php web容器,它是apache下的开源项目.通常要运行一个web程序,我们还需要安装数据库软件 ...
- hdu 1754 线段树(单点替换 区间最值)
Sample Input5 61 2 3 4 5Q 1 5 //1-5结点的最大值U 3 6 //将点3的数值换成6Q 3 4Q 4 5U 2 9Q 1 5 Sample Output5659 # i ...
- 解决连不上dl.google.com和dl-ssl.google.com
http://ping.chinaz.com/ 开发android遇到的最大问题就是Google被墙了,而我们的sdk又需要通过dl.google.com和dl-ssl.google.com去下载一些 ...
- Java第三阶段学习(十四、JSP动态页面、EL表达式、JSTL标签库)
一.JSP技术 1.jsp脚本和注释 jap脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部,比如写在doget.dopost 内的代码 2) ...
- js字符串驼峰和下划线互相转换
// 下划线转换驼峰 function toHump(name) { return name.replace(/\_(\w)/g, function(all, letter){ return lett ...
- Successor hdu 4366 线段树
题意: 现在n个人,其中编号0的是老板,之后n-1个员工,每个员工只有一个上司,有一个忠诚值和能力值.每次要解雇一个人的时候,从他的下属中选取能力值大于他的且忠诚值最高的一个,若不存在则输出-1.共m ...
- NUMA导致的MySQL服务器SWAP问题分析与解决方案
[SWAP产生原理] 先从swap产生的原理来分析,由于linux内存管理比较复杂,下面以问答的方式列了一些重要的点,方便大家理解: 1.swap是如何产生的 swap指的是一个交换分区或文件,主要是 ...
- java中关于锁知识的整理
1.1什么是锁? 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制.锁旨在强制实施互斥排他.并发控制策略. 锁通常需要硬件支持才能有效 ...
- Java NIO-3
http://itindex.net/detail/55603-java-nio-%E6%8A%80%E6%9C%AF