RTP/RTCP 視頻資料轉送 (續)

來源:互聯網
上載者:User

      直接進入正題,經過JPEG壓縮後的資料時通過RTP/RTCP協議傳輸到網路上去的,本課題使用的是Jrtplib的RTP/RTCP協議棧,首先在網上擷取Jrtplib包的源碼,解壓縮配置編譯安裝,沒有bugs就ok了

      在源碼包裡面有好幾個examples,都可以借鑒。在設定Server端的時候,與TCP/IP協議不一樣,首先在初始化開啟的Session的時候,設定一個baseport連接埠,同時設定Client端的ip和port,然後再根據視頻採樣的頻率設定時間戳記,具體的設定函數都可以在examples中找到並且能很好的複用。

     這裡講一下發送和接收的代碼,發送和接收都是通過線程來實現的:

     發送:

      ret = Send_rtppacket((unsigned char*)videoIn.ptframe[frameout],sizeof(struct frame_t)+headerframe->size);

      在發送線程函數中直接發送ptframe[]指標指向的資料,資料大小為sizeof(struct frame_t)+headerframe->size,包含了該frame的資料,以及對該frame參數描述的資料結構。

    int Send_rtppacket(unsigned char* framepointer,int framelength)
{
 int done = 0;
 int flage;
 int sendbyte = 0;
 int n;
 do{
 if(framelength > PacketMaxsize)   //設定packetmaxsize: 1400 ,oversize情況下就要分割傳輸
  flage = 0;
  else flage =1;
 
 if(flage = 1)
 { 
  n = session.SendPacket(framepointer,framelength,26,1,1000);   //發送函數 第四個參數決定是否是該frame最後

                                                                                                                         小於1400的資料
  done = 1;                                                                                                    //如果是 標示完成
  sendbyte = framelength;
 }else{
  n = session.SendPacket(framepointer,PacketMaxsize,26,0,1000);
  framepointer = framepointer + PacketMaxsize ;                               //update發送指標
  framelength = framelength - PacketMaxsize ;
  sendbyte = sendbyte + PacketMaxsize;
  }
  if(n<0)
  { return -1;}
  RTPTime::Wait (delay);
 }while(!done);
 return  sendbyte;
}

接收:

            do {
      // 檢索RTP資料來源
       sess.BeginDataAccess();
      if (sess.GotoFirstSourceWithData() ) {
        do {
          RTPPacket* packet;
   RTPSourceData *srcdata;
          // 擷取RTP資料報
          packetflage =0;
         recvlength =0;     //初始化接收資料 以及資料接收標示
     while ((packet = sess.GetNextPacket()) != NULL && packetflage==0) {  //標示為零 接收同一packet的剩餘資料
             //printf("Got packet !/n");
       
             if(processpacket(*srcdata,*packet)){
             packetflage = 1; //processpacket() 返回1 已經接受到所有的packet 可以調用解碼,SDL顯示
           //printf("Debug...packetflage: %d/n",packetflage);
    jpegsize = readjpeg(&buf,headerframe);
             //printf("Debug...jpegsize: %d/n",jpegsize);
             if(!jpegsize && videoOk)
     close_sdlvideo();
      if(jpegsize && !videoOk)
             {
               init_sdlvideo();  
      pscreen = SDL_SetVideoMode (owidth, oheight, bpp * 8,SDL_DOUBLEBUF | SDL_SWSURFACE);
      p=(unsigned char*)pscreen->pixels;
    }
  
      if(jpegsize && videoOk)
      {
             jpeg_decode(&picture,buf,&width,&height);
    resize (p,picture,owidth,oheight,width,height) ;
    SDL_WM_SetCaption (titre, NULL);
    SDL_Flip (pscreen); 
            }
            if(SDL_PollEvent (&sdlevent)<0) goto error;
          }  
            else packetflage =0;   //返回0,packet還沒接受完 繼續sess.GetNextPacket()
           
  delete packet;  // 刪除RTP資料報
        }
      } while (sess.GotoNextSourceWithData());   //接收另一個packet
    }
     sess.EndDataAccess();
      // 接受RTP資料
     status = sess.Poll();
     checkerror(status);
     RTPTime::Wait(RTPTime(1,0));
  } while(1);

int processpacket(const RTPSourceData &srcdat,const RTPPacket &rtppack)
{
 unsigned char* payloadpointer = rtppack.GetPayloadData();    //接收該資料包資料
     bool packetmarker = rtppack.HasMarker();   //察看部否是已經傳完該資料包
     int flage =1;
        //printf("Debug..........1/n");
 if(!packetmarker)   //未傳完資料包
 {
  memcpy(recvpointer+recvoffset,payloadpointer,rtppack.GetPayloadLength());
  recvlength += rtppack.GetPayloadLength();
      recvoffset += rtppack.GetPayloadLength();  //更新接收資料儲存的指標
 // printf("Debug..........2/n");
  flage = 0;   //標示接受位 繼續執行sess.GetNextPacket()
     }
 else{
  memcpy(recvpointer +recvoffset,payloadpointer,rtppack.GetPayloadLength());
  
  recvlength += rtppack.GetPayloadLength();
  recvoffset = 0;                     //傳完,初始化
 // printf("Debug..........3/n");
 }
 return flage;
}

 

小結:

      RTP/RTCP傳輸資料的流程:

Server端:

       發送定長的資料報到Client端,發送的時候是分批以packet的形式發送到Client,就是說發送一個資料包需要幾次packet發送來完成。發送成功以後發送下一個資料包,始終調用函數:session.SendPacket();

Client端:

      依次迴圈調用sess.GetNextPacket()來接收某一資料包的packet資料,packet的到來不是按順序到來的,完全接收到資料包所用的packets以後,RTP庫在根據時間戳記對接受的packet重新排序產生最終的資料包。接收資料包成功後,調用sess.GotoNextSourceWithData()開始接收下一個資料包

     

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.