linux 使用jrtplib收发h.264视频文件

    之前介绍过自己直接使用RTP收发h.264数据,这样有一个麻烦就是RTP协议的各个参数需要自己一个一个位的去填充,这样不利于发送也不方便接收。jrtplib库就刚好解决了这样的麻烦,同时它还提供了很多RTCP的信息查询接口,这样为实现实时流控制提供了方便。

    在本文中,将介绍h264 通过jrtplib库来实现实时的发送和接收。发送方发送,按照编码的习惯,我们习惯上是每完成一帧数据的编码就整一帧数据的发送。与此类似,在接收端,我们也是喜欢将整一帧的数据接收完整后再进行解码等处理。但是,这样会带来一个问题,我们网络最大传输单位MUT 一般是1400个字节,而我们进行h.264数据编码的时候,很多数据帧会大于1400帧,所以需要分开几个数据包来发送,在接收的时候,需要将分开的数据包再合成一个数据帧。

注明:

    下面代码是在我电脑写的最简程序。

    发送端IP:192.168.0.5

    接收端IP:192.168.0.6

    发送端口:6666

    接收端口:6664

注意几点:

    (1)jrtplib不能使用基数端口,基数端口用来建立RTCP

    (2)jrtplib设置的默认MUT是1400,但是实际每包数据不能发送1400字节,因为它还有TCP 头数据

receive.c

/*=============================================================================  
 *     FileName: receive.cpp  
 *         Desc: reveive h.264 from RTP server 
 *       Author: licaibiao  
 *   LastChange: 2017-04-22  
 * =============================================================================*/
#include <jrtplib3/rtpsession.h>
#include <jrtplib3/rtpudpv4transmitter.h>
#include <jrtplib3/rtpipv4address.h>
#include <jrtplib3/rtpsessionparams.h>
#include <jrtplib3/rtperrors.h>
#include <jrtplib3/rtplibraryversion.h>
#include <jrtplib3/rtppacket.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace jrtplib;

void checkerror(int rtperr)
{
	if (rtperr < 0)
	{
		std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
		exit(-1);
	}
}

int main(void)
{	
	RTPSession sess;
	uint16_t portbase = 6664;
	int status;
	bool done = false;

	RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;
	sessparams.SetOwnTimestampUnit(1.0/10.0);		
	
	sessparams.SetAcceptOwnPackets(true);

	transparams.SetPortbase(portbase);
	status = sess.Create(sessparams,&transparams);	
	checkerror(status);

	sess.BeginDataAccess();
	RTPTime delay(0.001);
	RTPTime starttime = RTPTime::CurrentTime();
	
	FILE *fd;
	size_t len;
	uint8_t *loaddata;
	RTPPacket *pack;
	uint8_t buff[1024*100] = {0};
	int pos = 0;
	
	fd = fopen("./test_recv.h264","wb+");
	while (!done)
	{
		status = sess.Poll();
		checkerror(status);
			
		if (sess.GotoFirstSourceWithData())
		{
			do
			{
				while ((pack = sess.GetNextPacket()) != NULL)
				{
					
					loaddata = pack->GetPayloadData();
					len		 = pack->GetPayloadLength();
					
					if(pack->GetPayloadType() == 96) //H264
					{
						if(pack->HasMarker()) // the last packet
						{
							memcpy(&buff[pos],loaddata,len);	
							fwrite(buff, 1, pos+len, fd);
							pos = 0;
						}
						else
						{
							memcpy(&buff[pos],loaddata,len);
							pos = pos + len;	
						}
					}else
					{
						printf("!!!  GetPayloadType = %d !!!! \n ",pack->GetPayloadType());
					}

					sess.DeletePacket(pack);
				}
			} while (sess.GotoNextSourceWithData());
		}
				
		RTPTime::Wait(delay);
		RTPTime t = RTPTime::CurrentTime();
		t -= starttime;
		if (t > RTPTime(40.0))
			done = true;
	}
	fclose(fd);
	
	sess.EndDataAccess();
	delay = RTPTime(10.0);
	sess.BYEDestroy(delay,0,0);
    
	return 0;
}

发送端程序 sender

/*=============================================================================  
 *     FileName: sender.cpp  
 *         Desc: sending h.264 data to client    
 *       Author: licaibiao  
 *   LastChange: 2017-04-22  
 * =============================================================================*/
#include <jrtplib3/rtpsession.h>
#include <jrtplib3/rtpudpv4transmitter.h>
#include <jrtplib3/rtpipv4address.h>
#include <jrtplib3/rtpsessionparams.h>
#include <jrtplib3/rtperrors.h>
#include <jrtplib3/rtplibraryversion.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace jrtplib;

#define MAXLEN	(RTP_DEFAULTPACKETSIZE - 100)

void checkerror(int rtperr){
	if (rtperr < 0){
		std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;
		exit(-1);
	}
}

class MyRTPSession : public RTPSession{
    public:  
        MyRTPSession(void);  
        ~MyRTPSession(void); 
        void SendH264Nalu(RTPSession* sess,uint8_t* m_h264Buf,int buflen);   
    protected:  
        

};

MyRTPSession::MyRTPSession(void){}  
MyRTPSession::~MyRTPSession(void){}

int main(void)
{	
    int i;
    int num;
	int status;
    
	RTPSession sess;
    MyRTPSession sender;
	uint16_t portbase = 6666;  
    uint16_t destport = 6664;
	uint8_t destip[]={192,168,0,6};

	RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;

    /* set h264 param */
    sessparams.SetUsePredefinedSSRC(true);  //设置使用预先定义的SSRC    
    sessparams.SetOwnTimestampUnit(1.0/9000.0); /* 设置采样间隔 */
    sessparams.SetAcceptOwnPackets(true);   //接收自己发送的数据包  
    
    transparams.SetPortbase(portbase);
	status = sess.Create(sessparams,&transparams);	
	checkerror(status);
	
	RTPIPv4Address addr(destip,destport);
	status = sess.AddDestination(addr);
	checkerror(status);

    sess.SetDefaultTimestampIncrement(3600);/* 设置时间戳增加间隔 */
    sess.SetDefaultPayloadType(96);
    sess.SetDefaultMark(true);    

    FILE *fd;
    int pos = 0;
    int header_flag = 0; 
    uint8_t buff[1024*100] = {0};

    fd = fopen("./test.h264","rb");
    fread(buff, 1, 4, fd);
    if((buff[0]==0)&&(buff[1]==0)&&(buff[2]==0)&&(buff[3]==1)){
        header_flag = 1;
    	pos = 4;
    }else{
        header_flag = 0;
    	pos = 3;
    }
    
    while((feof(fd)==0))
    {
        buff[pos++] = fgetc(fd);
		
        if(header_flag == 1){  //00 00 00 01
            if((buff[pos-1]==1)&&(buff[pos-2]==0)&&(buff[pos-3]==0)&&(buff[pos-4]==0)){
               	sender.SendH264Nalu(&sess, buff,pos-4);
                buff[0] = 0x00;
                buff[1] = 0x00;
                buff[2] = 0x00;
                buff[3] = 0x01;
				pos = 4;

				RTPTime::Wait(0.03);
             }
			
        }
        else{   
            if((buff[pos-1]==1)&&(buff[pos-2]==0)&&(buff[pos-3]==0)){
               	sender.SendH264Nalu(&sess, buff, pos-3);
               	buff[0] = 0x00;
               	buff[1] = 0x00;
               	buff[3] = 0x01;
               	pos = 3;

				RTPTime::Wait(0.03);
            }
		 
        }
    }
    if(pos != 0){
        sender.SendH264Nalu(&sess,buff,pos);
    }
	fclose(fd);
	printf("end of the read\n");
	sess.BYEDestroy(RTPTime(10,0),0,0);    
	return 0;
}


在上面的代码中,去掉了void SendH264Nalu(RTPSession* sess,uint8_t* m_h264Buf,int buflen) 函数的实现

完整的代码可以在这里下载:linux 使用jrtplib收发h.264视频文件

 

 

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li_wen01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值