C/C++ code
HRESULT CRtpRender::DoRenderSample( IMediaSample *pSample )
{
HRESULT hr;
ValidateReadPtr(pSample,sizeof(IMediaSample));
//Add media sample data
byte* pbPayload=0;
hr=pSample->GetPointer(&pbPayload);
if(FAILED(hr))
{
return hr;
}
int status=0;
size_t dataLength;
dataLength=pSample->GetActualDataLength();
//把pSample分块发送
SendDismantleFrame(dataLength,pbPayload,1024,sess);
checkerror(status);
return hr;
}
//这个函数是进行分块发送,可能是所谓的拆帧
void CRtpRender::SendDismantleFrame( int count,byte* buf,int groupCount,RTPSession& sess )
{
int status=0;
int sumCount=count;
if(count<=groupCount)
{
status = sess.SendPacket(buf,count,0,false,33);//发送数据包
}
else
{
int packetCount=0;
int curCount=0;
while(sumCount>0)
{
if(sumCount-groupCount<=0)
{
status = sess.SendPacket(buf,sumCount,0,false,33);//发送数据包
sumCount=0;
}
else
{
status = sess.SendPacket(buf,groupCount,0,false,0);//发送数据包
sumCount=sumCount-groupCount;
buf=&buf[groupCount];
}
packetCount++;
}
}
}
//初始化Session
STDMETHODIMP CRtpRender::Initialize()
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);//指示程序所采用的socket的版本
#endif // WIN32
uint16_t portbase,destport;
uint32_t destip;
std::string ipstr;
int status,i,num;
portbase=6000;
ipstr="127.0.0.1";
destip = inet_addr(ipstr.c_str());
if (destip == INADDR_NONE)
{
std::cerr << "Bad IP address specified" << std::endl;
return -1;
}
destip = ntohl(destip);
destport=8000;
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/33.0);//设置发送频率
sessparams.SetAcceptOwnPackets(true);//允许接受自身的的数据包
transparams.SetPortbase(portbase);//设置端口用于接受数据或发送数据
status = sess.Create(sessparams,&transparams); //创建RTP任务
checkerror(status);
//RTPIPv4Address addr(destip,destport);//目标地址
//status = sess.AddDestination(addr);//将目标地址添加会话中
return NOERROR;
}
接收端....
//接收数据线程函数
DWORD WINAPI ReceiveData( LPVOID lpParameter )
{
while(TRUE)
{
g_pRtpStream->sess.Poll();
g_pRtpStream->sess.BeginDataAccess();//对访问的数据进行加锁
uint32_t intTimestampPrev=0;
uint32_t intTimestamp;
byte* sumByte=NULL;
byte* sumByteBegin=NULL;
UINT intSumCount=0;
// check incoming packets
if (g_pRtpStream->sess.GotoFirstSourceWithData())//遍历数据源中的所有数据
{
do
{
RTPPacket *pack;
while ((pack = g_pRtpStream->sess.GetNextPacket()) != NULL)
{
intTimestamp = pack->GetTimestamp();
UINT segmentCount=pack->GetPacketLength();
segmentCount=pack->GetPayloadLength();
byte* bufByte=NULL;
intSumCount+=segmentCount;
bufByte=(byte *)pack->GetPayloadData();//获得数据
if (intTimestamp!=intTimestampPrev)
{
if (sumByte!=NULL)
{
InsertFrameHead(sumByte,intSumCount-segmentCount);//加入一个链表
intSumCount=segmentCount;
}
sumByte=(byte*)malloc(segmentCount);
}
else
{
sumByte=(byte *)realloc((void*)sumByte,intSumCount);
}
memcpy(sumByte+intSumCount-segmentCount,bufByte,segmentCount);
intTimestampPrev=intTimestamp;
g_pRtpStream->sess.DeletePacket(pack);
//delete buf;
}
} while (g_pRtpStream->sess.GotoNextSourceWithData());
free((void*) sumByte);
}
g_pRtpStream->sess.EndDataAccess();//解锁
RTPTime::Wait(RTPTime(1,0));
}
return 0;
}
HRESULT CRtpStream::FillBuffer( IMediaSample *pms )
{
CheckPointer(pms,E_POINTER);
Frame* frameData=NULL;
frameData=(Frame*)malloc(sizeof(Frame));
while (1)
{
GetHeadFrame(frameData);
Sleep(10);
if(frameData->count<0)
continue;
else
break;
}
HRESULT hr=S_OK;
byte* payload;
hr = pms->GetPointer(&payload);
if(FAILED(hr))
{
return hr;
}
pms->SetActualDataLength(frameData->count);
long pmsSize;
pmsSize=pms->GetSize();
memcpy((void*)payload,(void*)frameData->data,frameData->count>pmsSize?pmsSize:frameData->count);
free(frameData->data);
free(frameData);
return NOERROR;
}
HRESULT CRtpRender::DoRenderSample( IMediaSample *pSample )
{
HRESULT hr;
ValidateReadPtr(pSample,sizeof(IMediaSample));
//Add media sample data
byte* pbPayload=0;
hr=pSample->GetPointer(&pbPayload);
if(FAILED(hr))
{
return hr;
}
int status=0;
size_t dataLength;
dataLength=pSample->GetActualDataLength();
//把pSample分块发送
SendDismantleFrame(dataLength,pbPayload,1024,sess);
checkerror(status);
return hr;
}
//这个函数是进行分块发送,可能是所谓的拆帧
void CRtpRender::SendDismantleFrame( int count,byte* buf,int groupCount,RTPSession& sess )
{
int status=0;
int sumCount=count;
if(count<=groupCount)
{
status = sess.SendPacket(buf,count,0,false,33);//发送数据包
}
else
{
int packetCount=0;
int curCount=0;
while(sumCount>0)
{
if(sumCount-groupCount<=0)
{
status = sess.SendPacket(buf,sumCount,0,false,33);//发送数据包
sumCount=0;
}
else
{
status = sess.SendPacket(buf,groupCount,0,false,0);//发送数据包
sumCount=sumCount-groupCount;
buf=&buf[groupCount];
}
packetCount++;
}
}
}
//初始化Session
STDMETHODIMP CRtpRender::Initialize()
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);//指示程序所采用的socket的版本
#endif // WIN32
uint16_t portbase,destport;
uint32_t destip;
std::string ipstr;
int status,i,num;
portbase=6000;
ipstr="127.0.0.1";
destip = inet_addr(ipstr.c_str());
if (destip == INADDR_NONE)
{
std::cerr << "Bad IP address specified" << std::endl;
return -1;
}
destip = ntohl(destip);
destport=8000;
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/33.0);//设置发送频率
sessparams.SetAcceptOwnPackets(true);//允许接受自身的的数据包
transparams.SetPortbase(portbase);//设置端口用于接受数据或发送数据
status = sess.Create(sessparams,&transparams); //创建RTP任务
checkerror(status);
//RTPIPv4Address addr(destip,destport);//目标地址
//status = sess.AddDestination(addr);//将目标地址添加会话中
return NOERROR;
}
接收端....
//接收数据线程函数
DWORD WINAPI ReceiveData( LPVOID lpParameter )
{
while(TRUE)
{
g_pRtpStream->sess.Poll();
g_pRtpStream->sess.BeginDataAccess();//对访问的数据进行加锁
uint32_t intTimestampPrev=0;
uint32_t intTimestamp;
byte* sumByte=NULL;
byte* sumByteBegin=NULL;
UINT intSumCount=0;
// check incoming packets
if (g_pRtpStream->sess.GotoFirstSourceWithData())//遍历数据源中的所有数据
{
do
{
RTPPacket *pack;
while ((pack = g_pRtpStream->sess.GetNextPacket()) != NULL)
{
intTimestamp = pack->GetTimestamp();
UINT segmentCount=pack->GetPacketLength();
segmentCount=pack->GetPayloadLength();
byte* bufByte=NULL;
intSumCount+=segmentCount;
bufByte=(byte *)pack->GetPayloadData();//获得数据
if (intTimestamp!=intTimestampPrev)
{
if (sumByte!=NULL)
{
InsertFrameHead(sumByte,intSumCount-segmentCount);//加入一个链表
intSumCount=segmentCount;
}
sumByte=(byte*)malloc(segmentCount);
}
else
{
sumByte=(byte *)realloc((void*)sumByte,intSumCount);
}
memcpy(sumByte+intSumCount-segmentCount,bufByte,segmentCount);
intTimestampPrev=intTimestamp;
g_pRtpStream->sess.DeletePacket(pack);
//delete buf;
}
} while (g_pRtpStream->sess.GotoNextSourceWithData());
free((void*) sumByte);
}
g_pRtpStream->sess.EndDataAccess();//解锁
RTPTime::Wait(RTPTime(1,0));
}
return 0;
}
HRESULT CRtpStream::FillBuffer( IMediaSample *pms )
{
CheckPointer(pms,E_POINTER);
Frame* frameData=NULL;
frameData=(Frame*)malloc(sizeof(Frame));
while (1)
{
GetHeadFrame(frameData);
Sleep(10);
if(frameData->count<0)
continue;
else
break;
}
HRESULT hr=S_OK;
byte* payload;
hr = pms->GetPointer(&payload);
if(FAILED(hr))
{
return hr;
}
pms->SetActualDataLength(frameData->count);
long pmsSize;
pmsSize=pms->GetSize();
memcpy((void*)payload,(void*)frameData->data,frameData->count>pmsSize?pmsSize:frameData->count);
free(frameData->data);
free(frameData);
return NOERROR;
}