好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用jrtplib(RTP)传输H.264视频文件(2)

http://blog.csdn.net/liushu1231/article/details/9203593 [cpp] view plaincopy JRTP传输: 好了,下面是我写的使用JRTP进行发送H264数据包的例子,具体解释可以看注释。发送端也可以接收接收端发送过来的RTCP数据包。 #define WIN32 #define DEBUG #defin


[cpp] view plaincopy

JRTP传输: 好了,下面是我写的使用JRTP进行发送H264数据包的例子,具体解释可以看注释。发送端也可以接收接收端发送过来的RTCP数据包。 #define WIN32
#define DEBUG
#define MAX_RTP_PKT_LENGTH 1360
#define H264 96


#include "rtpsession.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtpsessionparams.h"
#include "rtperrors.h"
#include "rtcpapppacket.h"
#ifndef WIN32
#include
#include
#else
#include
#endif // WIN32
#include
#include
#include
#include


#include
extern "C"
{
#include "x264.h"
#include "x264_config.h"
};


using namespace jrtplib;
using namespace std; bool CheckError( int rtperr); class CRTPSender : public RTPSession { public : CRTPSender( void ); ~CRTPSender( void ); protected : void OnAPPPacket(RTCPAPPPacket *apppacket, const RTPTime &receivetime, const RTPAddress *senderaddress); void OnBYEPacket(RTPSourceData *srcdat); void OnBYETimeout(RTPSourceData *srcdat); public : void SendH264Nalu(unsigned char * m_h264Buf, int buflen); void SetParamsForSendingH264(); }; bool CheckError( int rtperr) { if (rtperr { std::cout "ERROR: " return false ; } return true ; } CRTPSender::CRTPSender( void ) { } CRTPSender::~CRTPSender( void ) { } void CRTPSender::OnAPPPacket(RTCPAPPPacket *apppacket, const RTPTime &receivetime, const RTPAddress *senderaddress) { //收到RTCP APP数据 std::cout "Got RTCP packet from: " std::cout "Got RTCP subtype: " std::cout "Got RTCP data: " char *)apppacket->GetAPPData() return ; } void CRTPSender::SendH264Nalu(unsigned char * m_h264Buf, int buflen) { unsigned char *pSendbuf; //发送数据指针 pSendbuf = m_h264Buf; //去除前导码0x000001 或者0x00000001 //if( 0x01 == m_h264Buf[2] ) //{ // pSendbuf = &m_h264Buf[3]; // buflen -= 3; //} //else //{ // pSendbuf = &m_h264Buf[4]; // buflen -= 4; //} char sendbuf[1430]; //发送的数据缓冲 memset(sendbuf,0,1430); int status; printf( "send packet length %d \n" ,buflen); if ( buflen { memcpy(sendbuf,pSendbuf,buflen); status = this ->SendPacket(( void *)sendbuf,buflen); CheckError(status); } else if (buflen > MAX_RTP_PKT_LENGTH) { //设置标志位Mark为0 this ->SetDefaultMark( false ); //printf("buflen = %d\n",buflen); //得到该需要用多少长度为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 = pSendbuf[0]; // NALU 头a?¤ while ( t 0 ) ) { if ( (0 == t ) || ( t //第一包到最后包的前一包 { /*sendbuf[0] = (nalHeader & 0x60)|28; sendbuf[1] = (nalHeader & 0x1f); if ( 0 == t ) { sendbuf[1] |= 0x80; } memcpy(sendbuf+2,&pSendbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH); status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2);*/ memcpy(sendbuf,&pSendbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH); status = this ->SendPacket(( void *)sendbuf,MAX_RTP_PKT_LENGTH); CheckError(status); t++; } //最后一包 else if ( ( k==t && l>0 ) || ( t== (k-1) && l==0 )) { //设置标志位Mark为1 this ->SetDefaultMark( true ); 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,&pSendbuf[t*MAX_RTP_PKT_LENGTH],iSendLen); //status = this->SendPacket((void *)sendbuf,iSendLen+2); memcpy(sendbuf,&pSendbuf[t*MAX_RTP_PKT_LENGTH],iSendLen); status = this ->SendPacket(( void *)sendbuf,iSendLen); CheckError(status); t++; } } } } void CRTPSender::SetParamsForSendingH264() { this ->SetDefaultPayloadType(H264); //设置传输类型 this ->SetDefaultMark( true ); //设置位 this ->SetTimestampUnit(1.0/9000.0); //设置采样间隔 this ->SetDefaultTimestampIncrement(3600); //设置时间戳增加间隔 } void CRTPSender::OnBYEPacket(RTPSourceData *srcdat) { } void CRTPSender::OnBYETimeout(RTPSourceData *srcdat) { } #define SSRC 100 #define DEST_IP_STR "192.168.1.252" #define DEST_PORT 1234 #define BASE_PORT 2222 #include "RTPSender.h"
int iNal = 0; x264_nal_t* pNals = NULL; void SetRTPParams(CRTPSender& sess,uint32_t destip,uint16_t destport,uint16_t baseport) { int status; //RTP+RTCP库初始化SOCKET环境 RTPUDPv4TransmissionParams transparams; RTPSessionParams sessparams; sessparams.SetOwnTimestampUnit(1.0/9000.0); //时间戳单位 sessparams.SetAcceptOwnPackets( true ); //接收自己发送的数据包 sessparams.SetUsePredefinedSSRC( true ); //设置使用预先定义的SSRC sessparams.SetPredefinedSSRC(SSRC); //定义SSRC transparams.SetPortbase(baseport); status = sess.Create(sessparams,&transparams); CheckError(status); destip = ntohl(destip); RTPIPv4Address addr(destip,destport); status = sess.AddDestination(addr); CheckError(status); //为发送H264包设置参数 //sess.SetParamsForSendingH264(); } bool InitSocket() { int Error; WORD VersionRequested; WSADATA WsaData; VersionRequested=MAKEWORD(2,2); Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2 if (Error!=0) { printf( "Error:Start WinSock failed!\n" ); return false ; } else { if (LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2) { printf( "Error:The version is WinSock2!\n" ); WSACleanup(); return false ; } } return true ; } void CloseSocket(CRTPSender sess) { //发送一个BYE包离开会话最多等待秒钟超时则不发送 sess.BYEDestroy(RTPTime(3,0),0,0); WSACleanup(); } int main( int argc, char ** argv) { InitSocket(); CRTPSender sender; string destip_str = "127.0.0.1" ; uint32_t dest_ip = inet_addr(destip_str.c_str()); SetRTPParams(sender,dest_ip,DEST_PORT,BASE_PORT); sender.SetParamsForSendingH264(); //…x264设置参数等步骤,具体参见上篇博客 for ( int i = 0; i { //读取一帧 read_frame_y4m(pPicIn,(hnd_t*)y4m_hnd,i); if ( i ==0 ) pPicIn->i_pts = i; else pPicIn->i_pts = i - 1; //编码 int frame_size = x264_encoder_encode(pX264Handle,&pNals,&iNal,pPicIn,pPicOut); if (frame_size >0) { for ( int i = 0; i { //将编码数据写入文件t //fwrite(pNals[i].p_payload, 1, pNals[i].i_payload, pFile); //发送编码文件 sender.SendH264Nalu(pNals[i].p_payload,pNals[i].i_payload); RTPTime::Wait(RTPTime(1,0)); } } } CloseSocket(sender); //一些清理工作… }

查看更多关于使用jrtplib(RTP)传输H.264视频文件(2)的详细内容...

  阅读:53次