自己动手写RTP服务器——用RTP协议传输TS流
来源:互联网 发布:xp设置网络打印机 编辑:程序博客网 时间:2024/04/29 03:56
预备知识
关于TS流的格式:TS流封装的具体格式请参考文档ISO/IEC 13818-1。这里我们只需要了解一些简单的信息就好。首先TS流是有许多的TS Packet组成的,每个TS Packet的长度固定为188 bytes,每个packet都是以sync_byte:0x47开头。
MTU(Maximum Transmission Unit): 最大传输单元。是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。最大传输单元这个参数通常与通信接口有关(网络接口卡、串口等)。例如:以太网无法接收大于1500 字节的数据包。
参考代码
下面我会把自己写的简单的代码贴出来,并且一步步地说明。
新建main.c文件,内容如下
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define TS_PACKET_SIZE 188
#define MTU 1500
说明:包含一些必要的头文件,并且定义了TS Packet的长度(188 bytes),MTU的限制(1500 bytes)。
struct rtp_header{
unsigned char cc:4;
unsigned char x:1;
unsigned char p:1;
unsigned char v:2;
unsigned char pt:7;
unsigned char m:1;
unsigned short sequence_number;
unsigned int timestamp;
unsigned int ssrc;
};
void init_rtp_header(struct rtp_header *h){
h->v = 2;
h->p = 0;
h->x = 0;
h->cc = 0;
h->m = 0;
h->pt = 33;
h->sequence_number = 123;
h->timestamp = 123;
h->ssrc = 123;
}
需要注意的是:
你会发现这里定义RTP Header的时候,上一篇讲到的具体顺序不同。原因是本机和网络字节流的顺序相反,如果按照v p x cc的顺序来定义一个byte,在这个byte内部v p x cc就会按照从低位到高位的顺序放置;而在RTP流中,应该是顺序从高位到低位放置的。所以每个byte我都把顺序做了倒置。
初始化RTP Header的函数的初始化值的意义请参考rfc3550。为了实现简单,其中的sequence_number、timestamp、ssrc,都是随意填写的。在发送包的时候需要将sequence_number递增。
- void sequence_number_increase(struct rtp_header *header){
- unsigned short sequence = ntohs(header->sequence_number);
- sequence++;
- header->sequence_number = htons(sequence);
- }
- int main(){
- // RTP Packet we will send
- char buf[MTU];
- unsigned int count = 0;
- // Init RTP Header
- init_rtp_header((struct rtp_header*)buf);
- count = sizeof(struct rtp_header);
- // Init socket
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
- struct sockaddr_in dest_addr;
- dest_addr.sin_family=AF_INET;
- dest_addr.sin_port = htons(6666);
- dest_addr.sin_addr.s_addr = INADDR_ANY;
- bzero(&(dest_addr.sin_zero),8);
- // Open TS file
- FILE *ts_file = fopen("/home/baby/Videos/480p.ts", "r+");
- while(!feof(ts_file)){
- int read_len = fread(buf+count, 1, TS_PACKET_SIZE, ts_file);
- if(*(buf+count) != 0x47){
- fprintf(stderr, "Bad sync header!\n");
- continue;
- }
- count += read_len;
- if (count + TS_PACKET_SIZE > MTU){// We should send
- sequence_number_increase((struct rtp_header*)buf);
- sendto(sock, buf, count, 0, (const struct sockaddr*)&dest_addr, sizeof(dest_addr));
- count = sizeof(struct rtp_header);
- usleep(10000);
- }
- }
- fclose(ts_file);
测试
短短几十行代码是否就能完成一个RTP服务器?我们需要用实验来验证。
我的测试环境是Linux,用gcc编译通过,使用VLC(MPlayer 测试也可以通过了)作为接收端。
首先启动我们的发送端程序,然后再执行“vlc rtp://127.0.0.1:6666”,等待几秒后,发现真的可以进行播放啦!
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——用RTP协议传输TS流
- 自己动手写RTP服务器——关于RTP协议
- 自己动手写RTP服务器——关于RTP协议
- 自己动手写RTP服务器——关于RTP协议
- 自己动手写RTP服务器——关于RTP协议
- 自己动手写RTP服务器——关于RTP协议
- 自己动手写RTP服务器——关于RTP协议
- 自己动手写RTP服务器——关于RTP协议
- Redis禁用命令、危险命令及规避方法
- Ubuntu14.04下载&编译Android(2)
- 【动画2】CALayer动画
- ORB-SLAM 与RGB-SLAM的区别
- Visual Studio 添加自定义菜单
- 自己动手写RTP服务器——用RTP协议传输TS流
- Java 内置异常类
- ANDROID代码实现APK文件的安装与卸载
- TOMCAT 安装及配置
- iOS 某格式日期替换成另一种格式日期
- 自定义Android Studio方法注释模板
- sha
- chm文件不能显示内容的解决办法
- 常用代码备份--vector中字符串去重