纯C语言--rtp封包h264

 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;
}



  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值