rtp.c ~ 5KB
/*
* rtp.c
*
* Created on: Jun 24, 2013
* Author: Administrator
*/
#include "rtp.h"
//创建sock套接字
int socket_dgram_setup(SOCKCONFIG *socketconfig)
{
int s;
if ((s=socket(AF_INET, (socketconfig->type), (socketconfig->protocol)))== -1)
{
fail("socket: %s\n", strerror(errno));
}
return s;
}
//填充sockets结构
struct sockets *get_dgram_sockets(int sock)
{
struct sockets *soc;
soc = malloc(sizeof(struct sockets));
if (soc == NULL)
{
warn("malloc failed.\n");
return NULL;
}
soc->local = sock;
soc->in = fdopen(sock, "r");
soc->out = fdopen(sock, "w");
return soc;
}
//创建rtp包
void *creat_rtp_pack(struct rtp_data *data)
{
unsigned char *buf;
//数据长度检测,数据长度大于最大包长,则分包。
if(data->datalen>MAX_PACK_LEN&&data->datalen>(data->bufrelen+data->rtpdatakcount))
{
//分包
unsigned int templen=(data->datalen-data->bufrelen-1);
data->rtpdatakcount+=1;
if(templen>MAX_PACK_LEN-1)
{
buf=(unsigned char *)malloc(MAX_PACK_LEN);
memset(buf,0,MAX_PACK_LEN);
if(data->bufrelen==0)
{
//第一个分包
memcpy((buf+RTP_HEAD_LEN+1),(data->buff+data->offset),(MAX_PACK_LEN-RTP_HEAD_LEN-1));
data->rtp_fui=((*(buf+RTP_HEAD_LEN+1)&0xE0));
data->rtp_fuh=(*(buf+RTP_HEAD_LEN+1)&0x1f);
*(buf+RTP_HEAD_LEN+1)=(data->rtp_fuh|(0x80));
data->bufrelen+=MAX_PACK_LEN;
data->offset+=MAX_PACK_LEN-RTP_HEAD_LEN-1;
}else{
//中间分包
memcpy((buf+RTP_HEAD_LEN+2),(data->buff+data->offset),(MAX_PACK_LEN-RTP_HEAD_LEN-2));
*(buf+RTP_HEAD_LEN+1)=(data->rtp_fuh|(0x00));
data->bufrelen+=MAX_PACK_LEN;
data->offset+=MAX_PACK_LEN-RTP_HEAD_LEN-2;
}
*(buf+RTP_HEAD_LEN)=(data->rtp_fui|(0x1c));
}else{
//最后一个分包
templen=data->datalen-data->offset;
buf=(unsigned char *)malloc(templen+RTP_HEAD_LEN+2);
memset(buf,0,templen+RTP_HEAD_LEN+2);
memcpy((buf+RTP_HEAD_LEN+2),(data->buff+data->offset),templen);
*(buf+RTP_HEAD_LEN)=(0x1c|data->rtp_fui);
*(buf+RTP_HEAD_LEN+1)=(data->rtp_fuh|(0x40));
data->bufrelen+=templen+RTP_HEAD_LEN+2;
data->offset+=templen-1;
}
}else if(data->datalen>data->bufrelen){
//数据长度小于包长,则不分包
buf=(unsigned char *)malloc(data->datalen+RTP_HEAD_LEN);
memset(buf,0,data->datalen+RTP_HEAD_LEN);
memcpy((buf+RTP_HEAD_LEN),data->buff,data->datalen);
data->bufrelen+=data->datalen+RTP_HEAD_LEN;
}else
return NULL;
return buf;
}
struct rtp_pack *rtp_pack(struct rtp_data *pdata,struct rtp_pack_head *head)
{
char *rtp_buff;
int len=pdata->bufrelen;
//获取封包后的rtp数据包
rtp_buff=creat_rtp_pack(pdata);
struct rtp_pack *pack;
if(rtp_buff!=NULL)
{
//固定头部填充
SET_RTP_FIXHEAD();
//创建rtp_pack结构
pack=(struct rtp_pack *)malloc(sizeof(struct rtp_pack));
pack->databuff=rtp_buff;
pack->packlen=pdata->bufrelen-len;
}else{
free(pdata->buff);
pdata->buff=NULL;
return NULL;
}
return pack;
}
//H264 开始码检测
char checkend(unsigned char *p)
{
if((*(p+0)==0x00)&&(*(p+1)==0x00)&&(*(p+2)==0x00)&&(*(p+3)==0x01))
return 1;
else
return 0;
}
//压入新读取的字节
void puttochar(unsigned char *tempbuff,unsigned char c)
{
*(tempbuff+0)=*(tempbuff+1);
*(tempbuff+1)=*(tempbuff+2);
*(tempbuff+2)=*(tempbuff+3);
*(tempbuff+3)=c;
}
//获取H264 数据
void *getdata(FILE *file)
{
if(feof(file)!=0)
return NULL;
unsigned int len=0;
unsigned char *buf=(unsigned char *)malloc((sizeof(char)*1024*1024));
if(buf==NULL)
{
return NULL;
}
memset(buf,0,(sizeof(char)*1024*1024));
unsigned char tempbuff[4];
unsigned char c;
unsigned int i=0;
//跳过文件头的开始码
if(ftell(file)==0)
fread(tempbuff,sizeof(char),4,file);
//首次读取数据,填满temp缓冲区。
fread(tempbuff,sizeof(char),4,file);
//开始码检测
while(!checkend(tempbuff))
{
//向数据缓存区,压入数据
*(buf+i)=tempbuff[0];
len+=fread(&c,sizeof(char),1,file);
//将下一个字节压入缓冲区。
puttochar(tempbuff,c);
i++;
if(feof(file)!=0)
{
memcpy((buf+i),tempbuff,sizeof(tempbuff));
len+=4;
break;
}
}
unsigned char *databuf=(unsigned char *)malloc(len);
memcpy(databuf,buf,len);
free(buf);
buf=NULL;
//rtp_data结构创建,填充
struct rtp_data *rtp_data=(struct rtp_data *)malloc(sizeof(struct rtp_data));
memset(rtp_data,0,sizeof(struct rtp_data));
rtp_data->buff=databuf;
rtp_data->datalen=len;
rtp_data->bufrelen=0;
return rtp_data;
}
//rtp数据包发送
char rtp_send(struct rtp_pack *rtp,struct sockets *sock)
{
int num=0;
//通过网络将数据发送出去
if((num=sendto(sock->local,rtp->databuff,rtp->packlen,0,sock->cliaddr,sizeof(struct sockaddr_in)))==-1)
{
fail("socket: %s\n", strerror(errno));
}
debug("number is : %d\n", num);
//释放缓冲区
free(rtp->databuff);
rtp->databuff=NULL;
return 0;
}
Error.h ~ 328B
/*
* Error.h
*
* Created on: Jun 1, 2013
* Author: Administrator
*/
#ifndef ERROR_H_
#define ERROR_H_
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int debug(char *, ...);
int fail(char *, ...);
int warn(char *, ...);
#endif /* ERROR_H_ */
test.c ~ 1KB
/*
* test.c
*
* Created on: Jun 24, 2013
* Author: Administrator
*/
#include "rtp.h"
int main(void)
{
//创建配置信息
SOCKCONFIG config;
config.time=5;
config.type=SOCK_DGRAM;
config.protocol=0;
//建立网络套接字
int s=socket_dgram_setup(&config);
struct sockets *sock=get_dgram_sockets(s);
//创建,填充客户端地址
struct sockaddr_in * sockcli;
sockcli=(struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
memset(sockcli,0,sizeof(struct sockaddr_in));
sockcli->sin_port=htons(9000);
sockcli->sin_family = AF_INET;
sockcli->sin_addr.s_addr=inet_addr("192.168.1.103");
sock->cliaddr=sockcli;
//打开H264视频文件
FILE *file=fopen("D:/video/stream/test.264","r");
temp=fopen("D:/video/stream/temp01.264","a+");
struct rtp_pack *rtp;
struct rtp_data *pdata;
//创建rtp头
struct rtp_pack_head head;
head.sernum=0x5372;
head.ssrc=0x69257765;
head.timtamp=0x9afcaf27;
//获取H264数据
while((pdata=getdata(file))!=NULL)
{
//数据封包
while((rtp=rtp_pack(pdata,&head))!=NULL)
{
//数据发送
rtp_send(rtp,sock);
free(rtp);
rtp=NULL;
//序列号增加
head.sernum++;
usleep(10*1000);
}
//时间戳增加
head.timtamp+=3000;
free(pdata);
pdata=NULL;
}
fclose(file);
fclose(temp);
return 0;
}
rtp.h ~ 3KB
/*
* rtp.h
*
* Created on: Jun 24, 2013
* Author: Administrator
*/
#ifndef RTP_H_
#define RTP_H_
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <netdb.h>
#include <pthread.h>
#include "Error.h"
#define SPS (1)
#define PPS (2)
#define RTP_VERSION_OFFSET (0)
#define RTP_MARK_OFFSET (1)
#define RTP_SEQ_OFFSET (2)
#define RTP_TIMETAMP_OFFSET (4)
#define RTP_SSRC_OFFSET (8)
#define MAX_PACK_LEN (1448)
#define RTP_HEAD_LEN (12)
#define H264_TYPE (0x60)
//rtp头 版本号设置
#define SET_RTP_VERSION() {*(rtp_buff+RTP_VERSION_OFFSET)=0x80;}
#define SET_RTP_MARK() {*(rtp_buff+RTP_MARK_OFFSET)=(H264_TYPE&0x7f);}
//rtp头 序列号设置
#define SET_RTP_SEQ() {*(rtp_buff+RTP_SEQ_OFFSET+1)=(head->sernum>>0)&0xff;\
*(rtp_buff+RTP_SEQ_OFFSET)=(head->sernum>>8)&0xff;\
}
//rtp头 时间戳设置
#define SET_RTP_TIMETAMP() {*(rtp_buff+RTP_TIMETAMP_OFFSET+3)=(head->timtamp>>0)&0xff;\
*(rtp_buff+RTP_TIMETAMP_OFFSET+2)=(head->timtamp>>8)&0xff;\
*(rtp_buff+RTP_TIMETAMP_OFFSET+1)=(head->timtamp>>16)&0xff;\
*(rtp_buff+RTP_TIMETAMP_OFFSET+0)=(head->timtamp>>24)&0xff;\
}
//rtp头 ssrc流标记设置
#define SET_RTP_SSRC() {*(rtp_buff+RTP_SSRC_OFFSET+3)=(head->ssrc>>0)&0xff;\
*(rtp_buff+RTP_SSRC_OFFSET+2)=(head->ssrc>>8)&0xff;\
*(rtp_buff+RTP_SSRC_OFFSET+1)=(head->ssrc>>16)&0xff;\
*(rtp_buff+RTP_SSRC_OFFSET+0)=(head->ssrc>>24)&0xff;\
}
#define SET_RTP_FIXHEAD() {SET_RTP_VERSION();\
SET_RTP_MARK();\
SET_RTP_SEQ();\
SET_RTP_TIMETAMP();\
SET_RTP_SSRC();\
}
//rtp头结构
struct rtp_pack_head
{
unsigned short sernum;
unsigned int timtamp;
unsigned int ssrc;
};
//rtp数据结构
struct rtp_data
{
void *buff;
char rtp_fui;
char rtp_fuh;
unsigned int offset;
unsigned int datalen;
unsigned int bufrelen;
unsigned int rtpdatakcount;
};
//rtp 包结构
struct rtp_pack
{
void *databuff;
unsigned int packlen;
unsigned int packtype;
};
struct sockets
{
int local;
int reclen;
FILE *in,*out;
struct sockaddr_in *cliaddr;
};
//配置信息
typedef struct config {
char* ip;
char time;
int port;
int type;
int protocol;
}SOCKCONFIG;
FILE *temp;
//创建rtp头
void creat_rtp_head(struct rtp_pack *rtp,struct rtp_pack_head *head);
//rtp封包
struct rtp_pack *rtp_pack(struct rtp_data *pdata,struct rtp_pack_head *head);
//获取264数据
void *getdata(FILE *file);
//rtp数据发送
char rtp_send(struct rtp_pack *rtp,struct sockets *sock);
//网络结构体创建
int socket_dgram_setup(SOCKCONFIG *socketconfig);
struct sockets *get_dgram_sockets(int sock);
#endif /* RTP_H_ */
Error.c ~ 544B
/*
* Error.c
*
* Created on: Jun 1, 2013
* Author: Administrator
*/
#include "Error.h"
int debug(char *fmt, ...) {
va_list ap;
int r;
va_start(ap, fmt);
r = vfprintf(stderr, fmt, ap);
va_end(ap);
return r;
}
int warn(char *fmt, ...) {
int r;
va_list ap;
va_start(ap, fmt);
r = vfprintf(stderr, fmt, ap);
va_end(ap);
return r;
}
int fail(char *fmt, ...) {
int r;
va_list ap;
va_start(ap, fmt);
r = vfprintf(stderr, fmt, ap);
exit(1);
/* notreached */
va_end(ap);
return r;
}