欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

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

程序员文章站 2022-06-10 09:54:31
...

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
  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: "GetSubType()
  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
  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 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
  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
  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. }