linux 使用jrtplib收發h.264視頻檔案__linux

來源:互聯網
上載者:User

    之前介紹過自己直接使用RTP收發h.264資料,這樣有一個麻煩就是RTP協議的各個參數需要自己一個一個位的去填充,這樣不利於發送也不方便接收。jrtplib庫就剛好解決了這樣的麻煩,同時它還提供了很多RTCP的資訊查詢介面,這樣為實現即時資料流控制提供了方便。

    在本文中,將介紹h264 通過jrtplib庫來實現即時的發送和接收。發送方發送,按照編碼的習慣,我們習慣上是每完成一幀資料的編碼就整一幀資料的發送。與此類似,在接收端,我們也是喜歡將整一幀的資料接收完整後再進行解碼等處理。但是,這樣會帶來一個問題,我們網路最大傳輸單位MUT 一般是1400個位元組,而我們進行h.264資料編碼的時候,很多資料幀會大於1400幀,所以需要分開幾個資料包來發送,在接收的時候,需要將分開的資料包再合成一個資料幀。

註明:

    下面代碼是在我電腦寫的最簡程式。

    發送端IP:192.168.0.5

    接收端IP:192.168.0.6

    傳送埠:6666

    接收埠:6664

注意幾點:

    (1)jrtplib不能使用基數連接埠,基數連接埠用來建立RTCP

    (2)jrtplib設定的預設MUT是1400,但是實際每包資料不能發送1400位元組,因為它還有TCP 頭資料

receive.c

/*=============================================================================   *     FileName: receive.cpp   *         Desc: reveive h.264 from RTP server  *       Author: licaibiao   *   LastChange: 2017-04-22   * =============================================================================*/#include <jrtplib3/rtpsession.h>#include <jrtplib3/rtpudpv4transmitter.h>#include <jrtplib3/rtpipv4address.h>#include <jrtplib3/rtpsessionparams.h>#include <jrtplib3/rtperrors.h>#include <jrtplib3/rtplibraryversion.h>#include <jrtplib3/rtppacket.h>#include <stdlib.h>#include <stdio.h>#include <iostream>#include <string>using namespace jrtplib;void checkerror(int rtperr){if (rtperr < 0){std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;exit(-1);}}int main(void){RTPSession sess;uint16_t portbase = 6664;int status;bool done = false;RTPUDPv4TransmissionParams transparams;RTPSessionParams sessparams;sessparams.SetOwnTimestampUnit(1.0/10.0);sessparams.SetAcceptOwnPackets(true);transparams.SetPortbase(portbase);status = sess.Create(sessparams,&transparams);checkerror(status);sess.BeginDataAccess();RTPTime delay(0.001);RTPTime starttime = RTPTime::CurrentTime();FILE *fd;size_t len;uint8_t *loaddata;RTPPacket *pack;uint8_t buff[1024*100] = {0};int pos = 0;fd = fopen("./test_recv.h264","wb+");while (!done){status = sess.Poll();checkerror(status);if (sess.GotoFirstSourceWithData()){do{while ((pack = sess.GetNextPacket()) != NULL){loaddata = pack->GetPayloadData();len = pack->GetPayloadLength();if(pack->GetPayloadType() == 96) //H264{if(pack->HasMarker()) // the last packet{memcpy(&buff[pos],loaddata,len);fwrite(buff, 1, pos+len, fd);pos = 0;}else{memcpy(&buff[pos],loaddata,len);pos = pos + len;}}else{printf("!!!  GetPayloadType = %d !!!! \n ",pack->GetPayloadType());}sess.DeletePacket(pack);}} while (sess.GotoNextSourceWithData());}RTPTime::Wait(delay);RTPTime t = RTPTime::CurrentTime();t -= starttime;if (t > RTPTime(40.0))done = true;}fclose(fd);sess.EndDataAccess();delay = RTPTime(10.0);sess.BYEDestroy(delay,0,0);    return 0;}
發送端程式 sender

/*=============================================================================   *     FileName: sender.cpp   *         Desc: sending h.264 data to client     *       Author: licaibiao   *   LastChange: 2017-04-22   * =============================================================================*/#include <jrtplib3/rtpsession.h>#include <jrtplib3/rtpudpv4transmitter.h>#include <jrtplib3/rtpipv4address.h>#include <jrtplib3/rtpsessionparams.h>#include <jrtplib3/rtperrors.h>#include <jrtplib3/rtplibraryversion.h>#include <stdlib.h>#include <stdio.h>#include <iostream>#include <string>using namespace jrtplib;#define MAXLEN(RTP_DEFAULTPACKETSIZE - 100)void checkerror(int rtperr){if (rtperr < 0){std::cout << "ERROR: " << RTPGetErrorString(rtperr) << std::endl;exit(-1);}}class MyRTPSession : public RTPSession{    public:          MyRTPSession(void);          ~MyRTPSession(void);         void SendH264Nalu(RTPSession* sess,uint8_t* m_h264Buf,int buflen);       protected:          };MyRTPSession::MyRTPSession(void){}  MyRTPSession::~MyRTPSession(void){}int main(void){    int i;    int num;int status;    RTPSession sess;    MyRTPSession sender;uint16_t portbase = 6666;      uint16_t destport = 6664;uint8_t destip[]={192,168,0,6};RTPUDPv4TransmissionParams transparams;RTPSessionParams sessparams;    /* set h264 param */    sessparams.SetUsePredefinedSSRC(true);  //設定使用預先定義的SSRC        sessparams.SetOwnTimestampUnit(1.0/9000.0); /* 設定採樣間隔 */    sessparams.SetAcceptOwnPackets(true);   //接收自己發送的資料包          transparams.SetPortbase(portbase);status = sess.Create(sessparams,&transparams);checkerror(status);RTPIPv4Address addr(destip,destport);status = sess.AddDestination(addr);checkerror(status);    sess.SetDefaultTimestampIncrement(3600);/* 設定時間戳記增加間隔 */    sess.SetDefaultPayloadType(96);    sess.SetDefaultMark(true);        FILE *fd;    int pos = 0;    int header_flag = 0;     uint8_t buff[1024*100] = {0};    fd = fopen("./test.h264","rb");    fread(buff, 1, 4, fd);    if((buff[0]==0)&&(buff[1]==0)&&(buff[2]==0)&&(buff[3]==1)){        header_flag = 1;    pos = 4;    }else{        header_flag = 0;    pos = 3;    }        while((feof(fd)==0))    {        buff[pos++] = fgetc(fd);        if(header_flag == 1){  //00 00 00 01            if((buff[pos-1]==1)&&(buff[pos-2]==0)&&(buff[pos-3]==0)&&(buff[pos-4]==0)){               sender.SendH264Nalu(&sess, buff,pos-4);                buff[0] = 0x00;                buff[1] = 0x00;                buff[2] = 0x00;                buff[3] = 0x01;pos = 4;RTPTime::Wait(0.03);             }        }        else{               if((buff[pos-1]==1)&&(buff[pos-2]==0)&&(buff[pos-3]==0)){               sender.SendH264Nalu(&sess, buff, pos-3);               buff[0] = 0x00;               buff[1] = 0x00;               buff[3] = 0x01;               pos = 3;RTPTime::Wait(0.03);            }         }    }    if(pos != 0){        sender.SendH264Nalu(&sess,buff,pos);    }fclose(fd);printf("end of the read\n");sess.BYEDestroy(RTPTime(10,0),0,0);    return 0;}

在上面的代碼中,去掉了void SendH264Nalu(RTPSession* sess,uint8_t* m_h264Buf,int buflen) 函數的實現

完整的代碼可以在這裡下載:linux 使用jrtplib收發h.264視頻檔案



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.