1. 程式人生 > >通過live555實現H264 RTSP直播

通過live555實現H264 RTSP直播

      前面的文章中介紹了《H264視訊通過RTMP流直播》,下面將介紹一下如何將H264實時視訊通過RTSP直播。

      實現思路是將視訊流傳送給live555, 由live555來實現H264資料流直播。

      視訊採集模組通過FIFO佇列將H264資料幀傳送給live555. live555 在收到客戶端的RTSP播放請求後,開始從FIFO中讀取H264視訊資料並通過RTSP直播出去。整個流程如下圖所示:


調整和修改Live555 MediaServer

        下載live555原始碼,在media目錄下增加四個檔案並修改檔案live555MediaServer.cpp。增加的四個檔案如下:

WW_H264VideoServerMediaSubsession.h

WW_H264VideoServerMediaSubsession.cpp

 WW_H264VideoSource.h

WW_H264VideoSource.cpp

        下面附上四個檔案的原始碼:

WW_H264VideoServerMediaSubsession.h

  1. #pragma once
  2. #include "liveMedia.hh"
  3. #include "BasicUsageEnvironment.hh"
  4. #include "GroupsockHelper.hh"
  5. #include "OnDemandServerMediaSubsession.hh"
  6. #include "WW_H264VideoSource.h"
  7. class WW_H264VideoServerMediaSubsession : public OnDemandServerMediaSubsession  
  8. {  
  9. public:  
  10.     WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source);  
  11.     ~WW_H264VideoServerMediaSubsession(void
    );  
  12. public:  
  13.     virtualcharconst * getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource);  
  14.     virtual FramedSource * createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate); // "estBitrate" is the stream's estimated bitrate, in kbps
  15.     virtual RTPSink * createNewRTPSink(Groupsock * rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource * inputSource);  
  16.     static WW_H264VideoServerMediaSubsession * createNew(UsageEnvironment & env, FramedSource * source);  
  17.     staticvoid afterPlayingDummy(void * ptr);  
  18.     staticvoid chkForAuxSDPLine(void * ptr);  
  19.     void chkForAuxSDPLine1();  
  20. private:  
  21.     FramedSource * m_pSource;  
  22.     char * m_pSDPLine;  
  23.     RTPSink * m_pDummyRTPSink;  
  24.     char m_done;  
  25. };  

WW_H264VideoServerMediaSubsession.cpp

  1. #include "WW_H264VideoServerMediaSubsession.h"
  2. WW_H264VideoServerMediaSubsession::WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source) : OnDemandServerMediaSubsession(env, True)  
  3. {  
  4.     m_pSource = source;  
  5.     m_pSDPLine = 0;  
  6. }  
  7. WW_H264VideoServerMediaSubsession::~WW_H264VideoServerMediaSubsession(void)  
  8. {  
  9.     if (m_pSDPLine)  
  10.     {  
  11.         free(m_pSDPLine);  
  12.     }  
  13. }  
  14. WW_H264VideoServerMediaSubsession * WW_H264VideoServerMediaSubsession::createNew(UsageEnvironment & env, FramedSource * source)  
  15. {  
  16.     returnnew WW_H264VideoServerMediaSubsession(env, source);  
  17. }  
  18. FramedSource * WW_H264VideoServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate)  
  19. {  
  20.     return H264VideoStreamFramer::createNew(envir(), new WW_H264VideoSource(envir()));  
  21. }  
  22. RTPSink * WW_H264VideoServerMediaSubsession::createNewRTPSink(Groupsock * rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource * inputSource)  
  23. {  
  24.     return H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);  
  25. }  
  26. charconst * WW_H264VideoServerMediaSubsession::getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource)  
  27. {  
  28.     if (m_pSDPLine)  
  29.     {  
  30.         return m_pSDPLine;  
  31.     }  
  32.     m_pDummyRTPSink = rtpSink;  
  33.     //mp_dummy_rtpsink->startPlaying(*source, afterPlayingDummy, this);
  34.     m_pDummyRTPSink->startPlaying(*inputSource, 0, 0);  
  35.     chkForAuxSDPLine(this);  
  36.     m_done = 0;  
  37.     envir().taskScheduler().doEventLoop(&m_done);  
  38.     m_pSDPLine = strdup(m_pDummyRTPSink->auxSDPLine());  
  39.     m_pDummyRTPSink->stopPlaying();  
  40.     return m_pSDPLine;  
  41. }  
  42. void WW_H264VideoServerMediaSubsession::afterPlayingDummy(void * ptr)  
  43. {  
  44.     WW_H264VideoServerMediaSubsession * This = (WW_H264VideoServerMediaSubsession *)ptr;  
  45.     This->m_done = 0xff;  
  46. }  
  47. void WW_H264VideoServerMediaSubsession::chkForAuxSDPLine(void * ptr)  
  48. {  
  49.     WW_H264VideoServerMediaSubsession * This = (WW_H264VideoServerMediaSubsession *)ptr;  
  50.     This->chkForAuxSDPLine1();  
  51. }  
  52. void WW_H264VideoServerMediaSubsession::chkForAuxSDPLine1()  
  53. {  
  54.     if (m_pDummyRTPSink->auxSDPLine())  
  55.     {  
  56.         m_done = 0xff;  
  57.     }  
  58.     else
  59.     {  
  60.         double delay = 1000.0 / (FRAME_PER_SEC);  // ms
  61.         int to_delay = delay * 1000;  // us
  62.         nextTask() = envir().taskScheduler().scheduleDelayedTask(to_delay, chkForAuxSDPLine, this);  
  63.     }  
  64. }  

WW_H264VideoSource.h
  1. #ifndef _WW_H264VideoSource_H
  2. #define _WW_H264VideoSource_H
  3. #include "liveMedia.hh"
  4. #include "BasicUsageEnvironment.hh"
  5. #include "GroupsockHelper.hh"
  6. #include "FramedSource.hh"
  7. #define FRAME_PER_SEC 25
  8. class WW_H264VideoSource : public FramedSource  
  9. {  
  10. public:  
  11.     WW_H264VideoSource(UsageEnvironment & env);  
  12.     ~WW_H264VideoSource(void);  
  13. public:  
  14.     virtualvoid doGetNextFrame();  
  15.     virtual unsigned int maxFrameSize() const;  
  16.     staticvoid getNextFrame(void * ptr);  
  17.     void GetFrameData();  
  18. private:  
  19.     void *m_pToken;  
  20.     char *m_pFrameBuffer;  
  21.     int  m_hFifo;  
  22. };  
  23. #endif