首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > 多媒体 >

jrtplib可以传输h.264吗 封包传输nalu解决办法

2012-12-31 
jrtplib可以传输h.264吗 封包传输nalu/*---------------------------------------*//* main.cpp/*--------

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

热点排行