jrtplib发送自定义数据包序号

        jrtplib提供的SendPacket()函数不能实现发送自定义的数据包序号,只能从一个随机数开始依次相加。

        如果想要实现发送自定义的数据包序号则需要对源码进行修改。

        修改方法如下:

       第一步:打开源码的rtpsession.cpp,在文件中加入这么一段代码,重载SendPacket函数。
int RTPSession::SendPacket(const void *data,size_t len,
                uint8_t pt,bool mark,uint32_t timestampinc,uint16_t seqnum)
{
	int status;

	if (!created)
		return ERR_RTP_SESSION_NOTCREATED;
	
	BUILDER_LOCK
	if ((status = packetbuilder.BuildPacket(data,len,pt,mark,timestampinc,seqnum)) < 0)
	{
		BUILDER_UNLOCK
		return status;
	}
	if ((status = SendRTPData(packetbuilder.GetPacket(),packetbuilder.GetPacketLength())) < 0)
	{
		BUILDER_UNLOCK
		return status;
	}
	BUILDER_UNLOCK
	
	SOURCES_LOCK
	sources.SentRTPPacket();
	SOURCES_UNLOCK
	PACKSENT_LOCK
	sentpackets = true;
	PACKSENT_UNLOCK
	return 0;
}

在rtpsession.h文件中将其进行声明:

	/** Sends the RTP packet with payload \c data which has length \c len.
	 *  It will use payload type \c pt, marker \c mark and after the packet has been built, the 
	 *  timestamp will be incremented by \c timestampinc 
	 * 	and the sequence number will be set to \c seqnum.
	 */				
	int SendPacket(const void *data, size_t len,
							   uint8_t pt, bool mark, uint32_t timestampinc, uint16_t seqnum);
第二步:重载int RTPPacketBuilder::BuildPacket函数

源码中的SendPacket函数中调用的代码是这样的

if ((status = packetbuilder.BuildPacket(data,len,pt,mark,timestampinc)) < 0)
	{
		BUILDER_UNLOCK
		return status;
	}

其中BuildPacket参数没有数据包序号这一项,我们需要重载它,让它能够传递数据包序号。

从第一步的代码中可以看出我们对它进行了修改:

if ((status = packetbuilder.BuildPacket(data,len,pt,mark,timestampinc,seqnum)) < 0)
	{
		BUILDER_UNLOCK
		return status;
	}

传递的参数数量发生了变话,多出了一个seqnum。

重载方法:在rtppacketbuilder.cpp中加入以下代码,并在rtppacketbuider.h中声明它,与第一步方法相同,就不再赘述了。

int RTPPacketBuilder::BuildPacket(const void *data,size_t len,
                uint8_t pt,bool mark,uint32_t timestampinc,uint16_t seqnum)
{
	if (!init)
		return ERR_RTP_PACKBUILD_NOTINIT;
	return PrivateBuildPacket(data,len,seqnum,pt,mark,timestampinc,false);
}

其中的PrivateBuildPacket函数也是重载过的,否则不可以传递seqnum这个参数。

第三步 重载PrivateBuildPacket函数

在在rtppacketbuilder.cpp中加入以下代码,并在rtppacketbuider.h中声明它,与前两步方法相同,就不再赘述了。

int RTPPacketBuilder::PrivateBuildPacket(const void *data,size_t len,uint16_t seqnum,
	                  uint8_t pt,bool mark,uint32_t timestampinc,bool gotextension,
	                  uint16_t hdrextID,const void *hdrextdata,size_t numhdrextwords)
{
	// RTPPacket p(pt,data,len,seqnum,timestamp,ssrc,mark,numcsrcs,csrcs,gotextension,hdrextID,
	//             (uint16_t)numhdrextwords,hdrextdata,buffer,maxpacksize,GetMemoryManager());
	RTPPacket p(pt,data,len,seqnum,timestamp,ssrc,mark,numcsrcs,csrcs,gotextension,hdrextID,
	            (uint16_t)numhdrextwords,hdrextdata,buffer,maxpacksize,GetMemoryManager());			
	int status = p.GetCreationError();

	if (status < 0)
		return status;
	packetlength = p.GetPacketLength();

	if (numpackets == 0) // first packet
	{
		lastwallclocktime = RTPTime::CurrentTime();
		lastrtptimestamp = timestamp;
		prevrtptimestamp = timestamp;
	}
	else if (timestamp != prevrtptimestamp)
	{
		lastwallclocktime = RTPTime::CurrentTime();
		lastrtptimestamp = timestamp;
		prevrtptimestamp = timestamp;
	}
	
	numpayloadbytes += (uint32_t)p.GetPayloadLength();
	numpackets++;
	timestamp += timestampinc;
	//seqnr++;

	return 0;
}

到此为止,对源码的修改就结束了,下面我们来进行测试。

将源码给的例程进行修改来调用我们自己重载的sendPacket函数

代码如下:

/*
   Here's a small IPv4 example: it asks for a portbase and a destination and 
   starts sending packets to that destination.
*/

#include "rtpsession.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtplibraryversion.h"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>

using namespace jrtplib;

//
// This function checks if there was a RTP error. If so, it displays an error
// message and exists.
//

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

//
// The main routine
//

int main(void)
{
#ifdef RTP_SOCKETTYPE_WINSOCK
	WSADATA dat;
	WSAStartup(MAKEWORD(2,2),&dat);
#endif // RTP_SOCKETTYPE_WINSOCK
	
	RTPSession sess;
	uint16_t portbase,destport;
	uint32_t destip;
	std::string ipstr;
	int status,i,num;

	std::cout << "Using version " << RTPLibraryVersion::GetVersion().GetVersionString() << std::endl;

	// First, we'll ask for the necessary information
		
	std::cout << "Enter local portbase:" << std::endl;
	std::cin >> portbase;
	std::cout << std::endl;
	
	std::cout << "Enter the destination IP address" << std::endl;
	std::cin >> ipstr;
	destip = inet_addr(ipstr.c_str());
	if (destip == INADDR_NONE)
	{
		std::cerr << "Bad IP address specified" << std::endl;
		return -1;
	}
	
	// The inet_addr function returns a value in network byte order, but
	// we need the IP address in host byte order, so we use a call to
	// ntohl
	destip = ntohl(destip);
	
	std::cout << "Enter the destination port" << std::endl;
	std::cin >> destport;
	
	std::cout << std::endl;
	std::cout << "Number of packets you wish to be sent:" << std::endl;
	std::cin >> num;
	
	// Now, we'll create a RTP session, set the destination, send some
	// packets and poll for incoming data.
	
	RTPUDPv4TransmissionParams transparams;
	RTPSessionParams sessparams;
	
	// IMPORTANT: The local timestamp unit MUST be set, otherwise
	//            RTCP Sender Report info will be calculated wrong
	// In this case, we'll be sending 10 samples each second, so we'll
	// put the timestamp unit to (1.0/10.0)
	sessparams.SetOwnTimestampUnit(1.0/10.0);		
	
	sessparams.SetAcceptOwnPackets(true);
	transparams.SetPortbase(portbase);
	status = sess.Create(sessparams,&transparams);	
	checkerror(status);
	
	RTPIPv4Address addr(destip,destport);
	
	status = sess.AddDestination(addr);
	checkerror(status);
	
	for (i = 1 ; i <= num ; i++)
	{
		printf("\nSending packet %d/%d\n",i,num);
		
		// send the packet
		status = sess.SendPacket((void *)"1234567890",10,0,false,10,0xffff);
		checkerror(status);
		status = sess.SendPacket((void *)"1234567890",10,0,false,10);
		checkerror(status);
		sess.BeginDataAccess();
		
		// check incoming packets
		if (sess.GotoFirstSourceWithData())
		{
			do
			{
				RTPPacket *pack;
				
				while ((pack = sess.GetNextPacket()) != NULL)
				{
					// You can examine the data here
					printf("Got packet !\n");
					
					// we don't longer need the packet, so
					// we'll delete it
					sess.DeletePacket(pack);
				}
			} while (sess.GotoNextSourceWithData());
		}
		
		sess.EndDataAccess();

#ifndef RTP_SUPPORT_THREAD
		status = sess.Poll();
		checkerror(status);
#endif // RTP_SUPPORT_THREAD
		
		RTPTime::Wait(RTPTime(1,0));
	}
	
	sess.BYEDestroy(RTPTime(10,0),0,0);

#ifdef RTP_SOCKETTYPE_WINSOCK
	WSACleanup();
#endif // RTP_SOCKETTYPE_WINSOCK
	return 0;
}

在网络调试助手中我们可以看到:

程序一次发送两个数据包,一个是调用我们自己修改的SendPacket函数,第二次是发送代码中原本的SendPacket函数,从数据中可以看到第一行的FF FF是我们自定义的数据包序号,而第二行是jrtplib给的数据包序号。下面的数据也是,我们自定义的数据包序号固定不变,jrtplib发送的数据包序号会自动+1。

到此我们就完成了给出自定义数据包序号的接口。

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值