使用RTP协议发送视频数据,要先弄清楚RTP协议的格式,自己组包发送。下面具体说明了RTP固定头的内容和组包时的值。

rtp包格式

V:2 P:0 X:0
CC:CSRC 计数,4位。表示跟在RTP固定包头后面CSRC的数目,对于本文所要实现的基本的流媒体服务器来说,没有用到混合器,该位也设为0x0。
M:如果当前 NALU为一个接入单元最后的那个NALU,那么将M位置1;或者当前RTP数据包为一个NALU的最后的那个分片时(NALU的分片在后面讲述),M位置1。其余情况下M位保持为0。
PT:负载类型 H264(96)
SQ:序号,16位。序号的起始值为随机值,此处设为0,每发送一个RTP数据包,序号值加1。
TS:时间戳,32位。同序号一样,时间戳的起始值也为随机值,此处设为0。根据RFC3984,与时间戳相应的时钟频率必须为90000HZ。
        timestamp_increse=(unsigned int)(90000.0 / framerate); //+0.5);
        ts_current = ts_current + timestamp_increse;
        htonl(ts_current);
SSRC:同步源标示,32位。SSRC应该被随机生成,以使在同一个RTP会话期中没有任何两个同步源具有相同的SSRC识别符。此处仅有一个同步源,因此将其设为0x12345678

对于 NALU的长度小于MTU大小的包,一般采用单一NAL单元模式.对于一个原始的H.264 NALU单元常由[Start Code] [NALU Header] [NALU Payload]三部分组成,其中Start Code用于标示这是一个NALU单元的开始,必须是"00 00 00 01"或"00 00 01", NALU头仅一个字节,其后都是NALU单元内容.打包时去除"00 00 01"或"00 00 00 01"的开始码,把其他数据封包的RTP包即可。

经过测试发现,经过压缩后的一帧数据的大小一般是大于MTU的,所以不能通过单个RTP包传输一帧数据,所以我们采用FU-A来分片发送一帧数据FU indicator占一个字节,Type的值设置为29,指示该包不是完整的一帧数据,而是FU—A分片类型的RTP包。FU header中的S和E用来指示分片的开始和结束,其中R必须为0。根据这些原则就可以自己组包发送视频数据了。组包具体格式见下图。



部分代码

#ifndef _RTP_H_
#define _RTP_H_#define UDP_DEST_IP                "192.168.2.1"
#define UDP_DEST_PORT            3333
#define H264                    96typedef struct
{  /**//* byte 0 */  unsigned char csrc_len:4;        /**//* expect 0 */  unsigned char extension:1;        /**//* expect 1, see RTP_OP below */  unsigned char padding:1;        /**//* expect 0 */  unsigned char version:2;        /**//* expect 2 */  /**//* byte 1 */  unsigned char payload:7;        /**//* RTP_PAYLOAD_RTSP */  unsigned char marker:1;        /**//* expect 1 */  /**//* bytes 2, 3 */  unsigned short seq_no;              /**//* bytes 4-7 */  unsigned  long timestamp;          /**//* bytes 8-11 */  unsigned long ssrc;            /**//* stream number is used here. */
} RTP_FIXED_HEADER;  typedef struct {  //byte 0  unsigned char TYPE;// 5bit  unsigned char NRI;//2 bit  unsigned char F;//1 bit
} NALU_HEADER; /**//* 1 BYTES */  //Fragmentation
typedef struct {  //byte 0  unsigned char TYPE;//:5;  unsigned char NRI;//:2;   unsigned char F;//;//:1;
} FU_INDICATOR; /**//* 1 BYTES */  typedef struct {  //byte 0  unsigned char TYPE;//:5;  unsigned char R;//:1;  unsigned char E;//:1;  unsigned char S;//:1;
} FU_HEADER; /**//* 1 BYTES */  int TCP_init(int port);
int UDP_init();
int RTP_send(int socketfd,char *buf,unsigned int len);
int TCP_send(int socketfd,char *buf,unsigned int len);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "rtp.h"int UDP_init()
{int    udpsocket; struct sockaddr_in server;  int len =sizeof(server);  server.sin_family=AF_INET;  server.sin_port=htons(UDP_DEST_PORT);            server.sin_addr.s_addr=inet_addr(UDP_DEST_IP);   udpsocket=socket(AF_INET,SOCK_DGRAM,0);  if(udpsocket==-1){fprintf(stderr,"UDP create socket error:%s\n\a",strerror(errno));exit(1);} if(connect(udpsocket, (const struct sockaddr *)&server, len) == -1)//none three handshake{printf("UDP connect error\n"); exit(1);}return udpsocket;
}
int RTP_send(int socketfd,char *buf,unsigned int len)
{static unsigned short seq_num =0;static unsigned int ts_current=0;   FU_INDICATOR    fu_ind;  FU_HEADER       fu_hdr;  NALU_HEADER     nalu_hdr;char* nalu_payload;int bytes=0; float framerate=25;  unsigned int timestamp_increase=0;  timestamp_increase=(unsigned int)(90000.0 / framerate); //+0.5);   len = len -4; //delete the 00 00 00 01len=len-1;//the length of pure dataRTP_FIXED_HEADER  *rtp_hdr;char sendbuf[1500];  memset(sendbuf,0,1500);rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0];   //设置RTP HEADER,  rtp_hdr->payload     = H264;  //负载类型号,  rtp_hdr->version     = 2;  //版本号,此版本固定为2  rtp_hdr->marker    = 0;   //标志位,由具体协议规定其值。  rtp_hdr->ssrc        = htonl(10);    //随机指定为10,并且在本RTP会话中全局唯一   nalu_hdr.F = buf[4] &  0x80; //1 bit  nalu_hdr.NRI = buf[4] &  0x60; // 2 bit nalu_hdr.TYPE = buf[4] &  0x1f;// 5 bit   if(len <= 1400) {//设置rtp M 位;  rtp_hdr->marker=1;  rtp_hdr->seq_no     = htons(seq_num ++); //序列号,每发送一个RTP包增1 ts_current=ts_current+timestamp_increase;  rtp_hdr->timestamp=htonl(ts_current);  memcpy(&sendbuf[12],&buf[4],len+1);send( socketfd, sendbuf, len+13, 0 );}else if(len>1400){int k=0,l=0;  k=len/1400; l=len%1400;int t=0;//用于指示当前发送的是第几个分片RTP包  ts_current=ts_current+timestamp_increase;  rtp_hdr->timestamp=htonl(ts_current);  // There are same timestamp in one NALU while(t<=k)  //there are k + l RTP packages,because index = 0 1...k{  rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1  if(!t) {  rtp_hdr->marker=0;  fu_ind.F=nalu_hdr.F;  fu_ind.NRI=nalu_hdr.NRI;  fu_ind.TYPE=28;  sendbuf[12] = fu_ind.F | fu_ind.NRI | fu_ind.TYPE;fu_hdr.E=0;  fu_hdr.R=0;  fu_hdr.S=1;  fu_hdr.TYPE=nalu_hdr.TYPE;      sendbuf[13] = fu_hdr.S <<7 | fu_hdr.E <<6 | fu_hdr.R <<5 | fu_hdr.TYPE; nalu_payload=&sendbuf[14];memcpy(nalu_payload,&buf[5],1400);//去掉NALU头    bytes=1400+14;                                 send( socketfd, sendbuf, bytes, 0 );//printf("第一个分包 ");t++;  }else if(k==t){  if(l==0)break;else{rtp_hdr->marker=1;  fu_ind.F=nalu_hdr.F;    fu_ind.NRI=nalu_hdr.NRI; fu_ind.TYPE=28;  sendbuf[12] = fu_ind.F  | fu_ind.NRI | fu_ind.TYPE;       fu_hdr.R=0;  fu_hdr.S=0;  fu_hdr.TYPE=nalu_hdr.TYPE;fu_hdr.E=1;  sendbuf[13] = fu_hdr.S <<7 | fu_hdr.E <<6 | fu_hdr.R <<5 | fu_hdr.TYPE;nalu_payload=&sendbuf[14];memcpy(nalu_payload,&buf[t*1400+5],l);bytes=l+14;    send( socketfd, sendbuf, bytes, 0 );//printf("最后一个分包%d ",l);t++;  }}else if(t<k&&0!=t){ if(l==0&&t==k-1){rtp_hdr->marker=1;  fu_ind.F=nalu_hdr.F;    fu_ind.NRI=nalu_hdr.NRI; fu_ind.TYPE=28;  sendbuf[12] = fu_ind.F  | fu_ind.NRI | fu_ind.TYPE;    fu_hdr.R=0;  fu_hdr.S=0;  fu_hdr.TYPE=nalu_hdr.TYPE;fu_hdr.E=1;  sendbuf[13] = fu_hdr.S <<7 | fu_hdr.E <<6 | fu_hdr.R <<5 | fu_hdr.TYPE;}else{rtp_hdr->marker=0;  fu_ind.F=nalu_hdr.F ; fu_ind.NRI=nalu_hdr.NRI;  fu_ind.TYPE=28;  sendbuf[12] = fu_ind.F  | fu_ind.NRI  | fu_ind.TYPE;         fu_hdr.R=0;  fu_hdr.S=0; fu_hdr.E=0;  fu_hdr.TYPE=nalu_hdr.TYPE;  sendbuf[13] = fu_hdr.S <<7 | fu_hdr.E <<6 | fu_hdr.R <<5 | fu_hdr.TYPE;}nalu_payload=&sendbuf[14];memcpy(nalu_payload,&buf[t*1400+5],1400);bytes=1400+14;send( socketfd, sendbuf, bytes, 0 );//printf("中间分包");                 t++;  }    }}return 0;
}

c 使用RTP协议发送视频数据相关推荐

  1. Java做rtp解包封包_基于RTP的H视频数据打包解包类DoubleLi博客园.pdf

    基于RTP的H视频数据打包解包类DoubleLi博客园 15- 10-30 基于RTP的H264视频数据打包解包类 - DoubleLi - 博客园 DoubleLi 博客园 :: 首页 :: 博问 ...

  2. EasyGBS中基于 RTP 的音视频数据 PS 封装

    在国标GB28181协议中,视频传输基本都由两个模块构成,EasyGBS包含两个模块:信令服务和流媒体服务.本节主要为大家解释下流媒体服务中关于音视频数据的PS封装. PS封装介绍: PS是Progr ...

  3. 【FFMPEG】基于RTP的H264视频数据打包解包类

    最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打包.解包的文档和代码.功夫不负有心人,找到不少有价值的文档和代码.参考这些资料,写了H264 RTP打包类.解包类,实现 ...

  4. wireshark提取视频数据之RTP包中提取H264和H265

    wireshark提取视频数据之RTP包中提取H264和H265 文章目录 wireshark提取视频数据之RTP包中提取H264和H265 1 背景 2 提取前工作 3 H264视频从RTP包中提取 ...

  5. android 与后台实时视频,Android实时监控项目第四篇:后台线程发送预览帧视频数据...

    还记得上篇提到的setPreviewCallback(Camera.PreviewCallback cb)函数吗?我们在开始预览帧视频之前,调用的它,这里要注意其内部的Camera.PreviewCa ...

  6. H264视频传输、编解码----RTP协议对H264数据帧拆包、打包、解包过程

    H264帧需要通过RTP协议进行传输,这其中就涉及到H264数据帧的封包.拆包和解包等过程. RTP协议格式 下面是 RFC 3550 中规定的 RTP 头的结构: 0 1 2 3 40 1 2 3 ...

  7. 流媒体服务器之rtp协议,rtcp协议,rtsp协议,sdp协议,sip协议简析

    0.前言 流媒体服务器做音视频媒体传输主要就两件事:媒体回话协商,媒体数据传输:下面这几种协议就围绕着这两个需求而产生. 1.rtp协议 rtp的全称是实时传输协议RTP(Real-time Tran ...

  8. 从WebRtc学习RTP协议

    文章目录 TCP为何不适用于实时音视频 UDP->RTP RTP协议结构 Jittbuffer RTP扩展头 RTP填充数据 参考 TCP为何不适用于实时音视频 可靠性是以牺牲实时性为代价的.按 ...

  9. 基于RTP协议的IP电话QoS监测及提高策略

    基于RTP协议的IP电话QoS监测及提高策略 本文转自 http://jxic.jiangxi.gov.cn/Html/2008321143656-1.html 1. 概述  随着Internet和多 ...

最新文章

  1. Linux文件系统映像:Initranfs 和 Initrd
  2. 算法提高课-搜索-DFS之搜索顺序-AcWing 1116. 马走日:dfs
  3. c语言 判断一个图是否全连通_C语言:程序运行流程图与顺序结构语句
  4. AI基础:机器学习简易入门
  5. abp框架java,【Net】ABP框架学习之正面硬钢
  6. 使用frp进行内网穿透的实例
  7. nginx 常用命令 保持启动 重载 开机启动等
  8. 局网满猿关不住,一波码农出墙来。
  9. 服务器需不需要虚拟内存,服务器要不要虚拟内存
  10. oracle 表复制 long,关于oracle的数据库的数据Long和Number的转化字段
  11. jmeter学习指南之中文乱码
  12. 新建SVN Repository
  13. 如何用PS制作1寸证件照
  14. iOS 实时录音和播放
  15. 业绩爆发,押注“泛半导体”,TCL押对了吗?
  16. liunx开发板使用交叉网线连接电脑,通过电脑连接外网的方法
  17. Linux TCP Timestamps 没鸟用
  18. patreon cg人物插画作品合集分享
  19. html画流程图插件,基于SVG的流程图插件Flowchart.js
  20. 华为机试真题 Java 实现【数字涂色】

热门文章

  1. Nginx工作原理及相关介绍
  2. free,ps,抓包,网络状态
  3. 看我打脸Message Pack
  4. asp.net程序的问题原来是IE造成的,改用firefox就没问题了!
  5. 轻量级 HTTP(s) 代理 TinyProxy
  6. pytorch学习笔记(5):vgg实现以及一些tricks
  7. ubuntu 16.04下安装mysql
  8. java控制进程_⑨进程控制
  9. java 作业调度_Java使用quartz实现作业调度
  10. Github排序(转载)