您当前的位置: 首页 > 

phymat.nico

暂无认证

  • 0浏览

    0关注

    1967博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

通过live555实现H264 RTSP直播

phymat.nico 发布时间:2017-12-31 04:04:11 ,浏览量:0

转载自:http://blog.csdn.net/firehood_/article/details/16844397

      前面的文章中介绍了《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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #pragma once  
  2.   
  3. #include "liveMedia.hh"  
  4. #include "BasicUsageEnvironment.hh"  
  5. #include "GroupsockHelper.hh"  
  6.   
  7. #include "OnDemandServerMediaSubsession.hh"  
  8. #include "WW_H264VideoSource.h"  
  9.   
  10. class WW_H264VideoServerMediaSubsession : public OnDemandServerMediaSubsession  
  11. {  
  12. public:  
  13.     WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source);  
  14.     ~WW_H264VideoServerMediaSubsession(void);  
  15.   
  16. public:  
  17.     virtual char const * getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource);  
  18.     virtual FramedSource * createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate); // "estBitrate" is the stream's estimated bitrate, in kbps  
  19.     virtual RTPSink * createNewRTPSink(Groupsock * rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource * inputSource);  
  20.   
  21.     static WW_H264VideoServerMediaSubsession * createNew(UsageEnvironment & env, FramedSource * source);  
  22.   
  23.     static void afterPlayingDummy(void * ptr);  
  24.   
  25.     static void chkForAuxSDPLine(void * ptr);  
  26.     void chkForAuxSDPLine1();  
  27.   
  28. private:  
  29.     FramedSource * m_pSource;  
  30.     char * m_pSDPLine;  
  31.     RTPSink * m_pDummyRTPSink;  
  32.     char m_done;  
  33. };  

        

WW_H264VideoServerMediaSubsession.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "WW_H264VideoServerMediaSubsession.h"  
  2.   
  3. WW_H264VideoServerMediaSubsession::WW_H264VideoServerMediaSubsession(UsageEnvironment & env, FramedSource * source) : OnDemandServerMediaSubsession(env, True)  
  4. {  
  5.     m_pSource = source;  
  6.     m_pSDPLine = 0;  
  7. }  
  8.   
  9. WW_H264VideoServerMediaSubsession::~WW_H264VideoServerMediaSubsession(void)  
  10. {  
  11.     if (m_pSDPLine)  
  12.     {  
  13.         free(m_pSDPLine);  
  14.     }  
  15. }  
  16.   
  17. WW_H264VideoServerMediaSubsession * WW_H264VideoServerMediaSubsession::createNew(UsageEnvironment & env, FramedSource * source)  
  18. {  
  19.     return new WW_H264VideoServerMediaSubsession(env, source);  
  20. }  
  21.   
  22. FramedSource * WW_H264VideoServerMediaSubsession::createNewStreamSource(unsigned clientSessionId, unsigned & estBitrate)  
  23. {  
  24.     return H264VideoStreamFramer::createNew(envir(), new WW_H264VideoSource(envir()));  
  25. }  
  26.   
  27. RTPSink * WW_H264VideoServerMediaSubsession::createNewRTPSink(Groupsock * rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource * inputSource)  
  28. {  
  29.     return H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);  
  30. }  
  31.   
  32. char const * WW_H264VideoServerMediaSubsession::getAuxSDPLine(RTPSink * rtpSink, FramedSource * inputSource)  
  33. {  
  34.     if (m_pSDPLine)  
  35.     {  
  36.         return m_pSDPLine;  
  37.     }  
  38.   
  39.     m_pDummyRTPSink = rtpSink;  
  40.   
  41.     //mp_dummy_rtpsink->startPlaying(*source, afterPlayingDummy, this);  
  42.     m_pDummyRTPSink->startPlaying(*inputSource, 0, 0);  
  43.   
  44.     chkForAuxSDPLine(this);  
  45.   
  46.     m_done = 0;  
  47.   
  48.     envir().taskScheduler().doEventLoop(&m_done);  
  49.   
  50.     m_pSDPLine = strdup(m_pDummyRTPSink->auxSDPLine());  
  51.   
  52.     m_pDummyRTPSink->stopPlaying();  
  53.   
  54.     return m_pSDPLine;  
  55. }  
  56.   
  57. void WW_H264VideoServerMediaSubsession::afterPlayingDummy(void * ptr)  
  58. {  
  59.     WW_H264VideoServerMediaSubsession * This = (WW_H264VideoServerMediaSubsession *)ptr;  
  60.   
  61.     This->m_done = 0xff;  
  62. }  
  63.   
  64. void WW_H264VideoServerMediaSubsession::chkForAuxSDPLine(void * ptr)  
  65. {  
  66.     WW_H264VideoServerMediaSubsession * This = (WW_H264VideoServerMediaSubsession *)ptr;  
  67.   
  68.     This->chkForAuxSDPLine1();  
  69. }  
  70.   
  71. void WW_H264VideoServerMediaSubsession::chkForAuxSDPLine1()  
  72. {  
  73.     if (m_pDummyRTPSink->auxSDPLine())  
  74.     {  
  75.         m_done = 0xff;  
  76.     }  
  77.     else  
  78.     {  
  79.         double delay = 1000.0 / (FRAME_PER_SEC);  // ms  
  80.         int to_delay = delay * 1000;  // us  
  81.   
  82.         nextTask() = envir().taskScheduler().scheduleDelayedTask(to_delay, chkForAuxSDPLine, this);  
  83.     }  
  84. }  
WW_H264VideoSource.h

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _WW_H264VideoSource_H  
  2. #define _WW_H264VideoSource_H  
  3.   
  4. #include "liveMedia.hh"  
  5. #include "BasicUsageEnvironment.hh"  
  6. #include "GroupsockHelper.hh"  
  7. #include "FramedSource.hh"  
  8.   
  9. #define FRAME_PER_SEC 25  
  10.   
  11. class WW_H264VideoSource : public FramedSource  
  12. {  
  13. public:  
  14.     WW_H264VideoSource(UsageEnvironment & env);  
  15.     ~WW_H264VideoSource(void);  
  16.   
  17. public:  
  18.     virtual void doGetNextFrame();  
  19.     virtual unsigned int maxFrameSize() const;  
  20.   
  21.     static void getNextFrame(void * ptr);  
  22.     void GetFrameData();  
  23.   
  24. private:  
  25.     void *m_pToken;  
  26.     char *m_pFrameBuffer;  
  27.     int  m_hFifo;  
  28. };  
  29.   
  30. #endif  

WW_H264VideoSource.cpp

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "WW_H264VideoSource.h"  
  2. #include   
  3. #ifdef WIN32  
  4. #include   
  5. #else  
  6. #include   
  7. #include   
  8. #include   
  9. #include   
  10. #include   
  11. #include   
  12. #endif  
  13.   
  14. #define FIFO_NAME     "/tmp/H264_fifo"  
  15. #define BUFFER_SIZE   PIPE_BUF  
  16. #define REV_BUF_SIZE  (1024*1024)  
  17.   
  18. #ifdef WIN32  
  19. #define mSleep(ms)    Sleep(ms)  
  20. #else  
  21. #define mSleep(ms)    usleep(ms*1000)  
  22. #endif  
  23.   
  24.   
  25. WW_H264VideoSource::WW_H264VideoSource(UsageEnvironment & env) :   
  26. FramedSource(env),  
  27. m_pToken(0),  
  28. m_pFrameBuffer(0),  
  29. m_hFifo(0)  
  30. {  
  31.     m_hFifo = open(FIFO_NAME,O_RDONLY);  
  32.         printf("[MEDIA SERVER] open fifo result = [%d]\n",m_hFifo);  
  33.     if(m_hFifo == -1)  
  34.     {  
  35.         return;  
  36.     }  
  37.       
  38.     m_pFrameBuffer = new char[REV_BUF_SIZE];  
  39.     if(m_pFrameBuffer == NULL)  
  40.     {  
  41.         printf("[MEDIA SERVER] error malloc data buffer failed\n");  
  42.         return;  
  43.     }  
  44.     memset(m_pFrameBuffer,0,REV_BUF_SIZE);  
  45. }  
  46.   
  47. WW_H264VideoSource::~WW_H264VideoSource(void)  
  48. {  
  49.     if(m_hFifo)  
  50.     {  
  51.         ::close(m_hFifo);  
  52.     }  
  53.       
  54.     envir().taskScheduler().unscheduleDelayedTask(m_pToken);  
  55.   
  56.     if(m_pFrameBuffer)  
  57.     {  
  58.         delete[] m_pFrameBuffer;  
  59.         m_pFrameBuffer = NULL;  
  60.     }  
  61.   
  62.     printf("[MEDIA SERVER] rtsp connection closed\n");  
  63. }  
  64.   
  65. void WW_H264VideoSource::doGetNextFrame()  
  66. {  
  67.     // 根据 fps,计算等待时间  
  68.     double delay = 1000.0 / (FRAME_PER_SEC * 2);  // ms  
  69.     int to_delay = delay * 1000;  // us  
  70.   
  71.     m_pToken = envir().taskScheduler().scheduleDelayedTask(to_delay, getNextFrame, this);  
  72. }  
  73.   
  74. unsigned int WW_H264VideoSource::maxFrameSize() const  
  75. {  
  76.     return 1024*200;  
  77. }  
  78.   
  79. void WW_H264VideoSource::getNextFrame(void * ptr)  
  80. {  
  81.     ((WW_H264VideoSource *)ptr)->GetFrameData();  
  82. }  
  83.   
  84. void WW_H264VideoSource::GetFrameData()  
  85. {  
  86.     gettimeofday(&fPresentationTime, 0);  
  87.   
  88.     fFrameSize = 0;  
  89.   
  90.     int len = 0;  
  91.     unsigned char buffer[BUFFER_SIZE] = {0};  
  92.     while((len = read(m_hFifo,buffer,BUFFER_SIZE))>0)  
  93.     {  
  94.         memcpy(m_pFrameBuffer+fFrameSize,buffer,len);  
  95.         fFrameSize+=len;  
  96.     }  
  97.     //printf("[MEDIA SERVER] GetFrameData len = [%d],fMaxSize = [%d]\n",fFrameSize,fMaxSize);  
  98.   
  99.     // fill frame data  
  100.     memcpy(fTo,m_pFrameBuffer,fFrameSize);  
  101.   
  102.     if (fFrameSize > fMaxSize)  
  103.     {  
  104.         fNumTruncatedBytes = fFrameSize - fMaxSize;  
  105.         fFrameSize = fMaxSize;  
  106.     }  
  107.     else  
  108.     {  
  109.         fNumTruncatedBytes = 0;  
  110.     }  
  111.                    
  112.     afterGetting(this);  
  113. }  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.   

修改live555MediaServer.cpp文件如下

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /********** 
  2. This library is free software; you can redistribute it and/or modify it under 
  3. the terms of the GNU Lesser General Public License as published by the 
  4. Free Software Foundation; either version 2.1 of the License, or (at your 
  5. option) any later version. (See .) 
  6.  
  7. This library is distributed in the hope that it will be useful, but WITHOUT 
  8. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  9. FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for 
  10. more details. 
  11.  
  12. You should have received a copy of the GNU Lesser General Public License 
  13. along with this library; if not, write to the Free Software Foundation, Inc., 
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA 
  15. **********/  
  16. // Copyright (c) 1996-2013, Live Networks, Inc.  All rights reserved  
  17. // LIVE555 Media Server  
  18. // main program  
  19.   
  20. #include   
  21. #include "DynamicRTSPServer.hh"  
  22. #include "version.hh"  
  23. #include "WW_H264VideoSource.h"  
  24. #include "WW_H264VideoServerMediaSubsession.h"  
  25.   
  26. int main(int argc, char** argv) {  
  27.     // Begin by setting up our usage environment:  
  28.     TaskScheduler* scheduler = BasicTaskScheduler::createNew();  
  29.     UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);  
  30.   
  31.     UserAuthenticationDatabase* authDB = NULL;  
  32. #ifdef ACCESS_CONTROL  
  33.     // To implement client access control to the RTSP server, do the following:  
  34.     authDB = new UserAuthenticationDatabase;  
  35.     authDB->addUserRecord("username1", "password1"); // replace these with real strings  
  36.     // Repeat the above with each ,  that you wish to allow  
  37.     // access to the server.  
  38. #endif  
  39.   
  40.     // Create the RTSP server:  
  41.     RTSPServer* rtspServer = RTSPServer::createNew(*env, 554, authDB);  
  42.     if (rtspServer == NULL) {  
  43.         *env taskScheduler().doEventLoop();  
  44.   
  45.     rtspServer->removeServerMediaSession(sms);  
  46.   
  47.     Medium::close(rtspServer);  
  48.   
  49.     env->reclaim();  
  50.   
  51.     delete scheduler;  
  52.   
  53.     return 1;  
  54. }  
发送H264视频流的RTSPStream

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /********************************************************************  
  2. filename:   RTSPStream.h 
  3. created:    2013-08-01 
  4. author:     firehood  
  5. purpose:    通过live555实现H264 RTSP直播 
  6. *********************************************************************/   
  7. #pragma once  
  8. #include   
  9. #ifdef WIN32  
  10. #include   
  11. #else  
  12. #include   
  13. #endif  
  14.   
  15. #ifdef WIN32  
  16. typedef HANDLE       ThreadHandle;  
  17. #define mSleep(ms)   Sleep(ms)  
  18. #else  
  19. typedef unsigned int SOCKET;  
  20. typedef pthread_t    ThreadHandle;  
  21. #define mSleep(ms)   usleep(ms*1000)  
  22. #endif  
  23.   
  24. #define FILEBUFSIZE (1024 * 1024)   
  25.   
  26.   
  27. class CRTSPStream  
  28. {  
  29. public:  
  30.     CRTSPStream(void);  
  31.     ~CRTSPStream(void);  
  32. public:  
  33.     // 初始化  
  34.     bool Init();  
  35.     // 卸载  
  36.     void Uninit();  
  37.     // 发送H264文件  
  38.     bool SendH264File(const char *pFileName);  
  39.     // 发送H264数据帧  
  40.     int SendH264Data(const unsigned char *data,unsigned int size);  
  41. };  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /********************************************************************  
  2. filename:   RTSPStream.cpp 
  3. created:    2013-08-01 
  4. author:     firehood  
  5. purpose:    通过live555实现H264 RTSP直播 
  6. *********************************************************************/   
  7. #include "RTSPStream.h"  
  8. #ifdef WIN32  
  9. #else  
  10. #include   
  11. #include   
  12. #include   
  13. #include   
  14. #include   
  15. #include   
  16. #include   
  17. #endif  
  18.   
  19. #define FIFO_NAME    "/tmp/H264_fifo"  
  20. #define BUFFERSIZE   PIPE_BUF  
  21.   
  22. CRTSPStream::CRTSPStream(void)  
  23. {  
  24.       
  25. }  
  26.   
  27. CRTSPStream::~CRTSPStream(void)  
  28. {  
  29.       
  30. }  
  31.   
  32. bool CRTSPStream::Init()  
  33. {  
  34.     if(access(FIFO_NAME,F_OK) == -1)  
  35.     {  
  36.         int res = mkfifo(FIFO_NAME,0777);  
  37.         if(res != 0)  
  38.         {  
  39.             printf("[RTSPStream] Create fifo failed.\n");  
  40.             return false;  
  41.         }  
  42.     }  
  43.     return true;  
  44. }  
  45.   
  46.   
  47. void CRTSPStream::Uninit()  
  48. {  
  49.       
  50. }  
  51.   
  52. bool CRTSPStream::SendH264File(const char *pFileName)  
  53. {  
  54.     if(pFileName == NULL)  
  55.     {  
  56.         return false;  
  57.     }  
  58.     FILE *fp = fopen(pFileName, "rb");    
  59.     if(!fp)    
  60.     {    
  61.         printf("[RTSPStream] error:open file %s failed!",pFileName);  
  62.     }    
  63.     fseek(fp, 0, SEEK_SET);  
  64.   
  65.     unsigned char *buffer  = new unsigned char[FILEBUFSIZE];  
  66.     int pos = 0;  
  67.     while(1)  
  68.     {  
  69.         int readlen = fread(buffer+pos, sizeof(unsigned char), FILEBUFSIZE-pos, fp);  
  70.   
  71.         if(readlen
关注
打赏
1659628745
查看更多评论
立即登录/注册

微信扫码登录

0.0464s