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

原文出处:http://blog.csdn.net/liushu1231/article/details/9203593

上一篇我们介绍了RTP协议的一些基本知识,下面我们介绍如何使用jrtplib这个库传输H264编码。

  1. JRTP传输:  
  2. 好了,下面是我写的使用JRTP进行发送H264数据包的例子,具体解释可以看注释。发送端也可以接收接收端发送过来的RTCP数据包。  
  3. #define MAX_RTP_PKT_LENGTH 1360  
  4. #define H264               96  
  5.   
  6. bool CheckError(int rtperr);  
  7.   
  8.   
  9. class CRTPSender :  
  10.     public RTPSession  
  11. {  
  12. public:  
  13.     CRTPSender(void);  
  14.     ~CRTPSender(void);  
  15.   
  16. protected:  
  17.     void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,const RTPAddress *senderaddress);  
  18.     void OnBYEPacket(RTPSourceData *srcdat);  
  19.     void OnBYETimeout(RTPSourceData *srcdat);  
  20. public:  
  21.     void SendH264Nalu(unsigned char* m_h264Buf,int buflen);  
  22.     void SetParamsForSendingH264();  
  23. };  
  24.   
  25.   
  26. bool CheckError(int rtperr)  
  27. {  
  28.     if (rtperr < 0)  
  29.     {  
  30.         std::cout<<"ERROR: "<<RTPGetErrorString(rtperr)<<std::endl;  
  31.         return false;  
  32.     }  
  33.     return true;  
  34. }  
  35.   
  36.   
  37. CRTPSender::CRTPSender(void)  
  38. {  
  39. }  
  40.   
  41.   
  42. CRTPSender::~CRTPSender(void)  
  43. {  
  44. }  
  45.   
  46. void CRTPSender::OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,const RTPAddress *senderaddress)  
  47. {//收到RTCP APP数据  
  48.     std::cout<<"Got RTCP packet from: "<<senderaddress<<std::endl;  
  49.     std::cout<<"Got RTCP subtype: "<<apppacket->GetSubType()<<std::endl;  
  50.     std::cout<<"Got RTCP data: "<<(char *)apppacket->GetAPPData()<<std::endl;  
  51.     return ;  
  52. }  
  53.   
  54. void CRTPSender::SendH264Nalu(unsigned char* m_h264Buf,int buflen)   
  55. {  
  56.     unsigned char *pSendbuf; //发送数据指针  
  57.     pSendbuf = m_h264Buf;  
  58.       
  59.     //去除前导码0x000001 或者0x00000001  
  60.     //if( 0x01 == m_h264Buf[2] )  
  61.     //{  
  62.     //  pSendbuf = &m_h264Buf[3];  
  63.     //  buflen -= 3;  
  64.     //}  
  65.     //else  
  66.     //{  
  67.     //  pSendbuf = &m_h264Buf[4];  
  68.     //  buflen -= 4;  
  69.     //}  
  70.       
  71.   
  72.     char sendbuf[1430];   //发送的数据缓冲  
  73.     memset(sendbuf,0,1430);  
  74.   
  75.     int status;    
  76.   
  77.     printf("send packet length %d \n",buflen);  
  78.   
  79.     if ( buflen <= MAX_RTP_PKT_LENGTH )  
  80.     {    
  81.         memcpy(sendbuf,pSendbuf,buflen);    
  82.         status = this->SendPacket((void *)sendbuf,buflen);  
  83.      
  84.         CheckError(status);  
  85.   
  86.     }    
  87.     else if(buflen > MAX_RTP_PKT_LENGTH)  
  88.     {  
  89.         //设置标志位Mark为0  
  90.         this->SetDefaultMark(false);  
  91.         //printf("buflen = %d\n",buflen);  
  92.         //得到该需要用多少长度为MAX_RTP_PKT_LENGTH字节的RTP包来发送  
  93.         int k=0,l=0;    
  94.         k = buflen / MAX_RTP_PKT_LENGTH;  
  95.         l = buflen % MAX_RTP_PKT_LENGTH;  
  96.         int t=0;//用指示当前发送的是第几个分片RTP包  
  97.   
  98.         char nalHeader = pSendbuf[0]; // NALU 头ª¡¤  
  99.         while( t < k || ( t==k && l>0 ) )    
  100.         {    
  101.             if( (0 == t ) || ( t<k && 0!=t ) )//第一包到最后包的前一包  
  102.             {  
  103.                 /*sendbuf[0] = (nalHeader & 0x60)|28;   
  104.                 sendbuf[1] = (nalHeader & 0x1f); 
  105.                 if ( 0 == t ) 
  106.                 { 
  107.                     sendbuf[1] |= 0x80; 
  108.                 } 
  109.                 memcpy(sendbuf+2,&pSendbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH); 
  110.                 status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2);*/  
  111.                 memcpy(sendbuf,&pSendbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH);  
  112.                 status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH);  
  113.                 CheckError(status);  
  114.                 t++;  
  115.             }  
  116.             //最后一包  
  117.             else if( ( k==t && l>0 ) || ( t== (k-1) && l==0 ))  
  118.             {  
  119.                 //设置标志位Mark为1  
  120.                 this->SetDefaultMark(true);  
  121.   
  122.                 int iSendLen;  
  123.                 if ( l > 0)  
  124.                 {  
  125.                     iSendLen = buflen - t*MAX_RTP_PKT_LENGTH;  
  126.                 }  
  127.                 else  
  128.                     iSendLen = MAX_RTP_PKT_LENGTH;  
  129.   
  130.                 //sendbuf[0] = (nalHeader & 0x60)|28;    
  131.                 //sendbuf[1] = (nalHeader & 0x1f);  
  132.                 //sendbuf[1] |= 0x40;  
  133.   
  134.                 //memcpy(sendbuf+2,&pSendbuf[t*MAX_RTP_PKT_LENGTH],iSendLen);  
  135.                 //status = this->SendPacket((void *)sendbuf,iSendLen+2);  
  136.      
  137.                 memcpy(sendbuf,&pSendbuf[t*MAX_RTP_PKT_LENGTH],iSendLen);  
  138.                 status = this->SendPacket((void *)sendbuf,iSendLen);  
  139.   
  140.                 CheckError(status);  
  141.                 t++;  
  142.             }  
  143.         }  
  144.     }  
  145. }  
  146.   
  147.   
  148. void CRTPSender::SetParamsForSendingH264()  
  149. {  
  150.     this->SetDefaultPayloadType(H264);//设置传输类型  
  151.     this->SetDefaultMark(true);      //设置位  
  152.     this->SetTimestampUnit(1.0/9000.0); //设置采样间隔  
  153.     this->SetDefaultTimestampIncrement(3600);//设置时间戳增加间隔  
  154. }  
  155.   
  156. void CRTPSender::OnBYEPacket(RTPSourceData *srcdat)  
  157. {  
  158.   
  159. }  
  160.   
  161. void CRTPSender::OnBYETimeout(RTPSourceData *srcdat)  
  162. {  
  163.   
  164. }  
  165.   
  166.   
  167. Main.cpp  在上一篇博客中的编码之后进行传输  
  168.   
  169. #define SSRC           100  
  170.   
  171. #define DEST_IP_STR   "192.168.1.252"  
  172. #define DEST_PORT     1234  
  173. #define BASE_PORT     2222  
  174.   
  175. int iNal   = 0;  
  176. x264_nal_t* pNals = NULL;  
  177.   
  178.   
  179. void SetRTPParams(CRTPSender& sess,uint32_t destip,uint16_t destport,uint16_t baseport)  
  180. {  
  181.     int status;    
  182.     //RTP+RTCP库初始化SOCKET环境  
  183.     RTPUDPv4TransmissionParams transparams;  
  184.     RTPSessionParams sessparams;  
  185.     sessparams.SetOwnTimestampUnit(1.0/9000.0); //时间戳单位  
  186.     sessparams.SetAcceptOwnPackets(true);   //接收自己发送的数据包  
  187.     sessparams.SetUsePredefinedSSRC(true);  //设置使用预先定义的SSRC  
  188.     sessparams.SetPredefinedSSRC(SSRC);     //定义SSRC  
  189.      
  190.     transparams.SetPortbase(baseport);  
  191.   
  192.     status = sess.Create(sessparams,&transparams);    
  193.     CheckError(status);  
  194.   
  195.     destip = ntohl(destip);  
  196.     RTPIPv4Address addr(destip,destport);  
  197.     status = sess.AddDestination(addr);  
  198.     CheckError(status);  
  199.       
  200.     //为发送H264包设置参数  
  201.     //sess.SetParamsForSendingH264();  
  202.   
  203. }  
  204. bool InitSocket()  
  205. {  
  206.     int Error;  
  207.     WORD VersionRequested;  
  208.     WSADATA WsaData;  
  209.     VersionRequested=MAKEWORD(2,2);  
  210.     Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2  
  211.     if(Error!=0)  
  212.     {  
  213.         printf("Error:Start WinSock failed!\n");  
  214.         return false;  
  215.     }  
  216.     else  
  217.     {  
  218.         if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)  
  219.         {  
  220.             printf("Error:The version is WinSock2!\n");  
  221.             WSACleanup();  
  222.             return false;  
  223.         }  
  224.   
  225.     }  
  226.     return true;  
  227. }  
  228.   
  229. void CloseSocket(CRTPSender sess)  
  230. {  
  231.     //发送一个BYE包离开会话最多等待秒钟超时则不发送  
  232.     sess.BYEDestroy(RTPTime(3,0),0,0);  
  233.     WSACleanup();  
  234. }  
  235.   
  236. int main(int argc, char** argv)  
  237. {  
  238.     InitSocket();  
  239.     CRTPSender sender;  
  240.     string destip_str = "127.0.0.1";  
  241.     uint32_t dest_ip = inet_addr(destip_str.c_str());             
  242.   
  243.     SetRTPParams(sender,dest_ip,DEST_PORT,BASE_PORT);  
  244.     sender.SetParamsForSendingH264();  
  245.   
  246.     //…x264设置参数等步骤,具体参见上篇博客  
  247.     for(int i = 0; i < nFrames ; i++ )  
  248.     {  
  249.         //读取一帧  
  250.         read_frame_y4m(pPicIn,(hnd_t*)y4m_hnd,i);  
  251.         if( i ==0 )  
  252.             pPicIn->i_pts = i;  
  253.         else  
  254.             pPicIn->i_pts = i - 1;  
  255.           
  256.         //编码  
  257.         int frame_size = x264_encoder_encode(pX264Handle,&pNals,&iNal,pPicIn,pPicOut);  
  258.   
  259.         if(frame_size >0)  
  260.         {  
  261.               
  262.             for (int i = 0; i < iNal; ++i)  
  263.             {//将编码数据写入文件t  
  264.                 //fwrite(pNals[i].p_payload, 1, pNals[i].i_payload, pFile);  
  265.                 //发送编码文件  
  266.                 sender.SendH264Nalu(pNals[i].p_payload,pNals[i].i_payload);  
  267.                 RTPTime::Wait(RTPTime(1,0));  
  268.             }  
  269.         }  
  270.     }  
  271.   
  272.      CloseSocket(sender);  
  273.     //一些清理工作…  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值