jrtplib nalu

场景:jrtplib可以传输h.264吗 封包传输nalu解决方法

jrtplib可以传输h.264吗 封包传输nalu
/*---------------------------------------*/
/* main.cpp
/*---------------------------------------*/
#include <crtdbg.h> //for _ASSERT
//JRTP includes
#include <RTPSession.h>
#include <RTPIPv4Address.h>
#include <RTPSessionParams.h>
#include <RTPUDPv4Transmitter.h>

#pragma comment(lib,"jthread.lib")
#pragma comment(lib,"jrtplib.lib")
#pragma comment(lib,"Ws2_32.lib")

#define MCAST_IP "192.168.60.183"
#define MCAST_PORT 1234
#define SERVER_PORT 8000

#define MAX_PACKET_SIZE 9400

/*-------------------------------------------------------*/
/* ReportError
/* Checking & display of RTP status codes
/* Returns true if there was an error, false otherwise
/*-------------------------------------------------------*/
int ReportError(int errCode)
{
int isErr = (errCode < 0);
if (isErr) {
std::string stdErrStr = RTPGetErrorString(errCode);
printf("Error %d: %s\n", errCode, stdErrStr.c_str());
printf("======================================\nPress Enter to exit\n");
getchar();
}
return isErr;
}

/*-------------------------------------------------------*/
/* RunRtpServer
/*-------------------------------------------------------*/
void RunRtpServer()
{
RTPSession rtpSession;
//setup session parameters
RTPSessionParams sessParams;
sessParams.SetOwnTimestampUnit(1.0 / 115.0); //30 video frames per second
sessParams.SetUsePollThread(1); //background thread to call virtual callbacks - set by default, but just to be sure
sessParams.SetMaximumPacketSize(MAX_PACKET_SIZE);
//setup transmission parameters
RTPUDPv4TransmissionParams transParams;
transParams.SetPortbase(SERVER_PORT); // portbase 是本地端口的意思。
//CREATE THE SESSION
int status = rtpSession.Create(sessParams, &transParams);
if (ReportError(status))
return; //unable to create the session
printf("RTP session created with portbase %d\n", SERVER_PORT);

//ADD THE MULTICAST to our destination
unsigned long intIP = inet_addr(MCAST_IP);
_ASSERT(intIP != INADDR_NONE);
intIP = ntohl(intIP); //put in host byte order
RTPIPv4Address rtpAddr(intIP, MCAST_PORT);
status = rtpSession.AddDestination(rtpAddr); //将客户端的ip和端口号事先添加进来。(不事先添加不行吗?)
//liyani add  
FILE *fp;
fp = fopen("./my.h264","rb");
if (fp == NULL)
{
printf("Can not open file \n");
}
//liyani add
if (!ReportError(status)) {
printf("Transmitting to multicast group %s port %d\n\n", MCAST_IP, MCAST_PORT);
char testBuf[MAX_PACKET_SIZE];
while (1) {
printf("\n_______________________________________________________\nPress Enter key to send data - 'x' to exit\n");
int ch = getchar();
if (tolower(ch) == 'x')
break;
//SEND a packet
//int byteCnt = rand() % sizeof(testBuf); //这个%不是取余,而是指0~sizeof(testBuf)之间的随机数。
while(!feof(fp))
{
memset(testBuf,0,sizeof(testBuf));
//DWORD dwRead = fread(testBuf,1,sizeof(testBuf),fp);
DWORD dwRead = fread(testBuf,1,940,fp); //一次发送的长度,不可以是sizeof(testBuf),65535太大了。
if (0 == dwRead)
{
printf("Read data from mobile.mpg is 0 \n");
}
rtpSession.SendPacket(testBuf, dwRead, 33, false, 160);
//printf("%d bytes sent\n", byteCnt);
printf("%d bytes sent\n", dwRead);
//Sleep(2);
}

}

fclose(fp);
//LEAVE THE MULTICAST
rtpSession.DeleteDestination(rtpAddr);
}
rtpSession.Destroy();
}

/*-------------------------------------------------------*/
/* main
/* entry point for the application
/*-------------------------------------------------------*/
int main()
{
//MUST call WSAStartup() to use WS2_32.DLL
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD( 2, 2 );
WSAStartup(wVersionRequested, &wsaData); //WSACleanup called in OnDestroy

RunRtpServer();

WSACleanup();
return 0;
}


------解决方案--------------------
可以的,呵呵
------解决方案--------------------
#include "StdAfx.h"
#include "RTPClass.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>


//////

CRTPClass::CRTPClass(void)
{
bInitRTP = false;
}

//////////////////////////////////////////////////////////////////////////

void CRTPClass::SetRTPParam(CString ip,int port)
{
rtp_ip = ip;
rtp_port = port;

}
bool CRTPClass::InitRTP()
{
//rtp_ip = ip;
//rtp_port = port;

if ( InitSocket())
{
//RTP+RTCP库初始化SOCKET环境
RTPUDPv4TransmissionParams transparams;
RTPSessionParams sessparams;
sessparams.SetOwnTimestampUnit(1.0/90000.0); //时间戳单位
sessparams.SetAcceptOwnPackets(true);


uint16_t portbase = rtp_port*10; //PORT_LOCAL;
transparams.SetPortbase(portbase);

int status;

status = sess.Create(sessparams,&transparams);
if (!checkerror(status))
{
return false;
}

uint32_t destip;
destip = inet_addr(rtp_ip);
destip = ntohl(destip);
uint16_t destport = rtp_port;
RTPIPv4Address addr(destip,rtp_port);
status = sess.AddDestination(addr);
if (!checkerror(status))
{
return false;
}

sess.SetDefaultPayloadType(96);
sess.SetDefaultMark(false);
sess.SetDefaultTimestampIncrement(3600);

bInitRTP = true;
return true;
}

return false;
}
bool CRTPClass::InitSocket()
{
int Error;
WORD VersionRequested;
WSADATA WsaData;
VersionRequested=MAKEWORD(2,2);
Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
if(Error!=0)
{
return false;
}
else
{
if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
{
WSACleanup();
return false;
}

}
return true;

}
void CRTPClass::SendRTPH264(unsigned char* m_h264Buf,int buflen) 
{
if (!bInitRTP)
{
if (!InitRTP())
{
TRACE("InitRTP fail\n");
return;
}
}

unsigned char *pbuf = new unsigned char[buflen];
memcpy(pbuf,m_h264Buf,buflen);

char sendbuf[1400];
memset(sendbuf,0,1400);

int status;

if (buflen<=MAX_RTP_PKT_LENGTH)
{
memcpy(sendbuf,pbuf,buflen);
status = sess.SendPacket((void *)sendbuf,buflen/*,payload,false,timestamp*/);

checkerror(status);

}
else if(buflen>=MAX_RTP_PKT_LENGTH)
{
//TRACE("buflen = %d\n",buflen);
//得到该nalu需要用多少长度为MAX_RTP_PKT_LENGTH字节的RTP包来发送
int k=0,l=0;
k=buflen/MAX_RTP_PKT_LENGTH;
l=buflen%MAX_RTP_PKT_LENGTH;
int t=0;//用于指示当前发送的是第几个分片RTP包

char nalHeader =pbuf[0]; // NALU 头
while(t<k||(t==k&&l>0))
{
if((0==t)||(t<k&&0!=t))//第一包到最后一包的前一包
{
sendbuf[0] = (nalHeader & 0x60)|28;
sendbuf[1] = (nalHeader & 0x1f);
if (0==t)
{
sendbuf[1] |= 0x80;
}

memcpy(sendbuf+2,&pbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH+2);


status = sess.SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2/*,payload,false,timestamp*/);

checkerror(status);

t++;

}
//最后一包
else if((k==t&&l>0)||(t==(k-1)&&l==0)
{

int iSendLen;
if (l>0)
{
iSendLen = buflen-t*MAX_RTP_PKT_LENGTH;
}
else
iSendLen = MAX_RTP_PKT_LENGTH;

sendbuf[0] = (nalHeader & 0x60)|28;
sendbuf[1] = (nalHeader & 0x1f);
sendbuf[1] |= 0x40;

memcpy(sendbuf+2,&pbuf[t*MAX_RTP_PKT_LENGTH],iSendLen+2);
//TRACE("start = %d,len = %d\n",t*MAX_RTP_PKT_LENGTH,iSendLen);
status = sess.SendPacket((void *)sendbuf,iSendLen+2/*,payload,false,timestamp*/);

checkerror(status);
t++;
// Sleep(100);
}
}

#ifndef RTP_SUPPORT_THREAD
status = sess.Poll();
checkerror(status);
#endif 
RTPTime::Wait(RTPTime(0,500)); //第一个参数为秒,第二个参数为毫秒
}

delete []pbuf;

}
void CRTPClass::CloseSocket()
{

if (bInitRTP)
{

//发送一个BYE包离开会话,最多等待3秒钟,超时则不发送
sess.BYEDestroy(RTPTime(3,0),0,0);

#ifdef WIN32
WSACleanup();
#endif // WIN32
}
}

bool CRTPClass::checkerror(int rtperr)
{
if (rtperr < 0)
{
TRACE("ERROR:%s\n",RTPGetErrorString(rtperr));
return false;
}
return true;
}