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

转自:http://blog.csdn.net/liushu1231/article/details/9203593

本文所有内容均为原创,转载请注明出处!

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

[cpp]   view plain copy
  1. JRTP传输:  
  2. 好了,下面是我写的使用JRTP进行发送H264数据包的例子,具体解释可以看注释。发送端也可以接收接收端发送过来的RTCP数据包。  
  3. #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 <netinet/in.h>
    #include <arpa/inet.h>
    #else
    #include <winsock2.h>
    #endif // WIN32
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>


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


    using namespace jrtplib;
    using namespace std;
  4.   
  5. bool CheckError(int rtperr);  
  6.   
  7.   
  8. class CRTPSender :  
  9.     public RTPSession  
  10. {  
  11. public:  
  12.     CRTPSender(void);  
  13.     ~CRTPSender(void);  
  14.   
  15. protected:  
  16.     void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,const RTPAddress *senderaddress);  
  17.     void OnBYEPacket(RTPSourceData *srcdat);  
  18.     void OnBYETimeout(RTPSourceData *srcdat);  
  19. public:  
  20.     void SendH264Nalu(unsigned char* m_h264Buf,int buflen);  
  21.     void SetParamsForSendingH264();  
  22. };  
  23.   
  24.   
  25. bool CheckError(int rtperr)  
  26. {  
  27.     if (rtperr < 0)  
  28.     {  
  29.         std::cout<<"ERROR: "<<RTPGetErrorString(rtperr)<<std::endl;  
  30.         return false;  
  31.     }  
  32.     return true;  
  33. }  
  34.   
  35.   
  36. CRTPSender::CRTPSender(void)  
  37. {  
  38. }  
  39.   
  40.   
  41. CRTPSender::~CRTPSender(void)  
  42. {  
  43. }  
  44.   
  45. void CRTPSender::OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,const RTPAddress *senderaddress)  
  46. {//收到RTCP APP数据  
  47.     std::cout<<"Got RTCP packet from: "<<senderaddress<<std::endl;  
  48.     std::cout<<"Got RTCP subtype: "<<apppacket->GetSubType()<<std::endl;  
  49.     std::cout<<"Got RTCP data: "<<(char *)apppacket->GetAPPData()<<std::endl;  
  50.     return ;  
  51. }  
  52.   
  53. void CRTPSender::SendH264Nalu(unsigned char* m_h264Buf,int buflen)   
  54. {  
  55.     unsigned char *pSendbuf; //发送数据指针  
  56.     pSendbuf = m_h264Buf;  
  57.       
  58.     //去除前导码0x000001 或者0x00000001  
  59.     //if( 0x01 == m_h264Buf[2] )  
  60.     //{  
  61.     //  pSendbuf = &m_h264Buf[3];  
  62.     //  buflen -= 3;  
  63.     //}  
  64.     //else  
  65.     //{  
  66.     //  pSendbuf = &m_h264Buf[4];  
  67.     //  buflen -= 4;  
  68.     //}  
  69.       
  70.   
  71.     char sendbuf[1430];   //发送的数据缓冲  
  72.     memset(sendbuf,0,1430);  
  73.   
  74.     int status;    
  75.   
  76.     printf("send packet length %d \n",buflen);  
  77.   
  78.     if ( buflen <= MAX_RTP_PKT_LENGTH )  
  79.     {    
  80.         memcpy(sendbuf,pSendbuf,buflen);    
  81.         status = this->SendPacket((void *)sendbuf,buflen);  
  82.      
  83.         CheckError(status);  
  84.   
  85.     }    
  86.     else if(buflen > MAX_RTP_PKT_LENGTH)  
  87.     {  
  88.         //设置标志位Mark为0  
  89.         this->SetDefaultMark(false);  
  90.         //printf("buflen = %d\n",buflen);  
  91.         //得到该需要用多少长度为MAX_RTP_PKT_LENGTH字节的RTP包来发送  
  92.         int k=0,l=0;    
  93.         k = buflen / MAX_RTP_PKT_LENGTH;  
  94.         l = buflen % MAX_RTP_PKT_LENGTH;  
  95.         int t=0;//用指示当前发送的是第几个分片RTP包  
  96.   
  97.         char nalHeader = pSendbuf[0]; // NALU 头ª¡¤  
  98.         while( t < k || ( t==k && l>0 ) )    
  99.         {    
  100.             if( (0 == t ) || ( t<k && 0!=t ) )//第一包到最后包的前一包  
  101.             {  
  102.                 /*sendbuf[0] = (nalHeader & 0x60)|28;   
  103.                 sendbuf[1] = (nalHeader & 0x1f); 
  104.                 if ( 0 == t ) 
  105.                 { 
  106.                     sendbuf[1] |= 0x80; 
  107.                 } 
  108.                 memcpy(sendbuf+2,&pSendbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH); 
  109.                 status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH+2);*/  
  110.                 memcpy(sendbuf,&pSendbuf[t*MAX_RTP_PKT_LENGTH],MAX_RTP_PKT_LENGTH);  
  111.                 status = this->SendPacket((void *)sendbuf,MAX_RTP_PKT_LENGTH);  
  112.                 CheckError(status);  
  113.                 t++;  
  114.             }  
  115.             //最后一包  
  116.             else if( ( k==t && l>0 ) || ( t== (k-1) && l==0 ))  
  117.             {  
  118.                 //设置标志位Mark为1  
  119.                 this->SetDefaultMark(true);  
  120.   
  121.                 int iSendLen;  
  122.                 if ( l > 0)  
  123.                 {  
  124.                     iSendLen = buflen - t*MAX_RTP_PKT_LENGTH;  
  125.                 }  
  126.                 else  
  127.                     iSendLen = MAX_RTP_PKT_LENGTH;  
  128.   
  129.                 //sendbuf[0] = (nalHeader & 0x60)|28;    
  130.                 //sendbuf[1] = (nalHeader & 0x1f);  
  131.                 //sendbuf[1] |= 0x40;  
  132.   
  133.                 //memcpy(sendbuf+2,&pSendbuf[t*MAX_RTP_PKT_LENGTH],iSendLen);  
  134.                 //status = this->SendPacket((void *)sendbuf,iSendLen+2);  
  135.      
  136.                 memcpy(sendbuf,&pSendbuf[t*MAX_RTP_PKT_LENGTH],iSendLen);  
  137.                 status = this->SendPacket((void *)sendbuf,iSendLen);  
  138.   
  139.                 CheckError(status);  
  140.                 t++;  
  141.             }  
  142.         }  
  143.     }  
  144. }  
  145.   
  146.   
  147. void CRTPSender::SetParamsForSendingH264()  
  148. {  
  149.     this->SetDefaultPayloadType(H264);//设置传输类型  
  150.     this->SetDefaultMark(true);      //设置位  
  151.     this->SetTimestampUnit(1.0/9000.0); //设置采样间隔  
  152.     this->SetDefaultTimestampIncrement(3600);//设置时间戳增加间隔  
  153. }  
  154.   
  155. void CRTPSender::OnBYEPacket(RTPSourceData *srcdat)  
  156. {  
  157.   
  158. }  
  159.   
  160. void CRTPSender::OnBYETimeout(RTPSourceData *srcdat)  
  161. {  
  162.   
  163. }  
  164.   
  165.   
  166. Main.cpp  在上一篇博客中的编码之后进行传输  
  167.   
  168. #define SSRC           100  
  169.   
  170. #define DEST_IP_STR   "192.168.1.252"  
  171. #define DEST_PORT     1234  
  172. #define BASE_PORT     2222  
  173. #include "RTPSender.h"  

  174. int iNal   = 0;  
  175. x264_nal_t* pNals = NULL;  
  176.   
  177.   
  178. void SetRTPParams(CRTPSender& sess,uint32_t destip,uint16_t destport,uint16_t baseport)  
  179. {  
  180.     int status;    
  181.     //RTP+RTCP库初始化SOCKET环境  
  182.     RTPUDPv4TransmissionParams transparams;  
  183.     RTPSessionParams sessparams;  
  184.     sessparams.SetOwnTimestampUnit(1.0/9000.0); //时间戳单位  
  185.     sessparams.SetAcceptOwnPackets(true);   //接收自己发送的数据包  
  186.     sessparams.SetUsePredefinedSSRC(true);  //设置使用预先定义的SSRC  
  187.     sessparams.SetPredefinedSSRC(SSRC);     //定义SSRC  
  188.      
  189.     transparams.SetPortbase(baseport);  
  190.   
  191.     status = sess.Create(sessparams,&transparams);    
  192.     CheckError(status);  
  193.   
  194.     destip = ntohl(destip);  
  195.     RTPIPv4Address addr(destip,destport);  
  196.     status = sess.AddDestination(addr);  
  197.     CheckError(status);  
  198.       
  199.     //为发送H264包设置参数  
  200.     //sess.SetParamsForSendingH264();  
  201.   
  202. }  
  203. bool InitSocket()  
  204. {  
  205.     int Error;  
  206.     WORD VersionRequested;  
  207.     WSADATA WsaData;  
  208.     VersionRequested=MAKEWORD(2,2);  
  209.     Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2  
  210.     if(Error!=0)  
  211.     {  
  212.         printf("Error:Start WinSock failed!\n");  
  213.         return false;  
  214.     }  
  215.     else  
  216.     {  
  217.         if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)  
  218.         {  
  219.             printf("Error:The version is WinSock2!\n");  
  220.             WSACleanup();  
  221.             return false;  
  222.         }  
  223.   
  224.     }  
  225.     return true;  
  226. }  
  227.   
  228. void CloseSocket(CRTPSender sess)  
  229. {  
  230.     //发送一个BYE包离开会话最多等待秒钟超时则不发送  
  231.     sess.BYEDestroy(RTPTime(3,0),0,0);  
  232.     WSACleanup();  
  233. }  
  234.   
  235. int main(int argc, char** argv)  
  236. {  
  237.     InitSocket();  
  238.     CRTPSender sender;  
  239.     string destip_str = "127.0.0.1";  
  240.     uint32_t dest_ip = inet_addr(destip_str.c_str());             
  241.   
  242.     SetRTPParams(sender,dest_ip,DEST_PORT,BASE_PORT);  
  243.     sender.SetParamsForSendingH264();  
  244.   
  245.     //…x264设置参数等步骤,具体参见上篇博客  
  246.     for(int i = 0; i < nFrames ; i++ )  
  247.     {  
  248.         //读取一帧  
  249.         read_frame_y4m(pPicIn,(hnd_t*)y4m_hnd,i);  
  250.         if( i ==0 )  
  251.             pPicIn->i_pts = i;  
  252.         else  
  253.             pPicIn->i_pts = i - 1;  
  254.           
  255.         //编码  
  256.         int frame_size = x264_encoder_encode(pX264Handle,&pNals,&iNal,pPicIn,pPicOut);  
  257.   
  258.         if(frame_size >0)  
  259.         {  
  260.               
  261.             for (int i = 0; i < iNal; ++i)  
  262.             {//将编码数据写入文件t  
  263.                 //fwrite(pNals[i].p_payload, 1, pNals[i].i_payload, pFile);  
  264.                 //发送编码文件  
  265.                 sender.SendH264Nalu(pNals[i].p_payload,pNals[i].i_payload);  
  266.                 RTPTime::Wait(RTPTime(1,0));  
  267.             }  
  268.         }  
  269.     }  
  270.   
  271.      CloseSocket(sender);  
  272.     //一些清理工作…  
  273. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值