当前位置:Gxlcms > mysql > 使用jrtplib(RTP)传输H.264视频文件(2)

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

时间:2021-07-01 10:21:17 帮助过:119人阅读

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

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


[cpp] view plaincopy

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

  137. int iNal = 0;
  138. x264_nal_t* pNals = NULL;
  139. void SetRTPParams(CRTPSender& sess,uint32_t destip,uint16_t destport,uint16_t baseport)
  140. {
  141. int status;
  142. //RTP+RTCP库初始化SOCKET环境
  143. RTPUDPv4TransmissionParams transparams;
  144. RTPSessionParams sessparams;
  145. sessparams.SetOwnTimestampUnit(1.0/9000.0); //时间戳单位
  146. sessparams.SetAcceptOwnPackets(true); //接收自己发送的数据包
  147. sessparams.SetUsePredefinedSSRC(true); //设置使用预先定义的SSRC
  148. sessparams.SetPredefinedSSRC(SSRC); //定义SSRC
  149. transparams.SetPortbase(baseport);
  150. status = sess.Create(sessparams,&transparams);
  151. CheckError(status);
  152. destip = ntohl(destip);
  153. RTPIPv4Address addr(destip,destport);
  154. status = sess.AddDestination(addr);
  155. CheckError(status);
  156. //为发送H264包设置参数
  157. //sess.SetParamsForSendingH264();
  158. }
  159. bool InitSocket()
  160. {
  161. int Error;
  162. WORD VersionRequested;
  163. WSADATA WsaData;
  164. VersionRequested=MAKEWORD(2,2);
  165. Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
  166. if(Error!=0)
  167. {
  168. printf("Error:Start WinSock failed!\n");
  169. return false;
  170. }
  171. else
  172. {
  173. if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
  174. {
  175. printf("Error:The version is WinSock2!\n");
  176. WSACleanup();
  177. return false;
  178. }
  179. }
  180. return true;
  181. }
  182. void CloseSocket(CRTPSender sess)
  183. {
  184. //发送一个BYE包离开会话最多等待秒钟超时则不发送
  185. sess.BYEDestroy(RTPTime(3,0),0,0);
  186. WSACleanup();
  187. }
  188. int main(int argc, char** argv)
  189. {
  190. InitSocket();
  191. CRTPSender sender;
  192. string destip_str = "127.0.0.1";
  193. uint32_t dest_ip = inet_addr(destip_str.c_str());
  194. SetRTPParams(sender,dest_ip,DEST_PORT,BASE_PORT);
  195. sender.SetParamsForSendingH264();
  196. //…x264设置参数等步骤,具体参见上篇博客
  197. for(int i = 0; i < nFrames ; i++ )
  198. {
  199. //读取一帧
  200. read_frame_y4m(pPicIn,(hnd_t*)y4m_hnd,i);
  201. if( i ==0 )
  202. pPicIn->i_pts = i;
  203. else
  204. pPicIn->i_pts = i - 1;
  205. //编码
  206. int frame_size = x264_encoder_encode(pX264Handle,&pNals,&iNal,pPicIn,pPicOut);
  207. if(frame_size >0)
  208. {
  209. for (int i = 0; i < iNal; ++i)
  210. {//将编码数据写入文件t
  211. //fwrite(pNals[i].p_payload, 1, pNals[i].i_payload, pFile);
  212. //发送编码文件
  213. sender.SendH264Nalu(pNals[i].p_payload,pNals[i].i_payload);
  214. RTPTime::Wait(RTPTime(1,0));
  215. }
  216. }
  217. }
  218. CloseSocket(sender);
  219. //一些清理工作…
  220. }

人气教程排行