• 摄像头采集,264编码,live555直播(1)


    参看 有关live555 

    1.首先需要修改live555,定义从 内存中直接获取source而不是从文件读取source的类。

    自己实现的类命名为 H264FramedLiveSource 

     
    H264FramedLiveSource.hh
    /*
     * Filename: H264FramedLiveSource.hh
     * Auther: chenbin
     * Create date: 2013/ 1/22
     */
    
    #ifndef _H264FRAMEDLIVESOURCE_HH
    #define _H264FRAMEDLIVESOURCE_HH
    
    #include <FramedSource.hh>
    
    
    class H264FramedLiveSource : public FramedSource
    {
    public:
        static H264FramedLiveSource* createNew(UsageEnvironment& env,
            char const* fileName,
            unsigned preferredFrameSize = 0,
            unsigned playTimePerFrame = 0); 
    
    protected:
        H264FramedLiveSource(UsageEnvironment& env,
            char const* fileName, 
            unsigned preferredFrameSize,
            unsigned playTimePerFrame);
        // called only by createNew()
        ~H264FramedLiveSource();
    
    private:
        // redefined virtual functions:
        virtual void doGetNextFrame();
        int TransportData( unsigned char* to, unsigned maxSize );
    
    protected:
        FILE *fp;
    };
    
    #endif
    H264FramedLiveSource.cpp
    /*
     * Filename:  H264FramedLiveSource.cpp
     * Auther:  mlj
     * Create date: 2013/ 1/22
     */
    
    #include "H264FramedLiveSource.hh"
     
    
    
    H264FramedLiveSource::H264FramedLiveSource( UsageEnvironment& env,  
        char const* fileName, 
        unsigned preferredFrameSize, 
        unsigned playTimePerFrame )
        : FramedSource(env)
    {
         fp = fopen( fileName, "rb" ); 
    }
    
    H264FramedLiveSource* H264FramedLiveSource::createNew( UsageEnvironment& env,
                                               char const* fileName, 
                                               unsigned preferredFrameSize /*= 0*/, 
                                               unsigned playTimePerFrame /*= 0*/ )
    { 
        H264FramedLiveSource* newSource = new H264FramedLiveSource(env, fileName, preferredFrameSize, playTimePerFrame);
     
        return newSource;
    }
    
    H264FramedLiveSource::~H264FramedLiveSource()
    {
        fclose(fp);
    }
    
    
    long filesize(FILE *stream)
    {
        long curpos, length;
        curpos = ftell(stream);
        fseek(stream, 0L, SEEK_END);
        length = ftell(stream);
        fseek(stream, curpos, SEEK_SET);
        return length;
    }
    
    void H264FramedLiveSource::doGetNextFrame()
    {
    
        if( filesize(fp) >  fMaxSize)
          fFrameSize = fread(fTo,1,fMaxSize,fp); 
        else
        {
            fFrameSize = fread(fTo,1,filesize(fp),fp);
            fseek(fp, 0, SEEK_SET);
        }
        //fFrameSize = fMaxSize;
        nextTask() = envir().taskScheduler().scheduleDelayedTask( 0,
            (TaskFunc*)FramedSource::afterGetting, this);//表示延迟0秒后再执行 afterGetting 函数
        return;
    }

    在 H264FramedLiveSource::doGetNextFrame() 中,将要发送的内容复制到 fTo,最大为fMaxSize,fFrameSize指示实际发送的内容是多少字节。这里暂时还是从文件读作为测试。

    2、定义自己的ServerMedia 

    H264LiveVideoServerMediaSubssion.hh
    /*
     * Filename: H264LiveVideoServerMediaSubssion.hh
     * Auther: mlj 
     * Create date: 2013/ 1/22
     */
    #ifndef _H264_LIVE_VIDEO_SERVER_MEDIA_SUBSESSION_HH
    #define _H264_LIVE_VIDEO_SERVER_MEDIA_SUBSESSION_HH
    #include "H264VideoFileServerMediaSubsession.hh"
    
    class H264LiveVideoServerMediaSubssion: public H264VideoFileServerMediaSubsession {
    
    public:
      static H264LiveVideoServerMediaSubssion*
      createNew( UsageEnvironment& env,
                   char const* fileName, 
                    Boolean reuseFirstSource );
    
    protected: // we're a virtual base class
      H264LiveVideoServerMediaSubssion( UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource );
       ~H264LiveVideoServerMediaSubssion();
    
    protected: // redefined virtual functions
       FramedSource* createNewStreamSource(unsigned clientSessionId,
                              unsigned& estBitrate);
    public: 
       char fFileName[100];
    
    };
    
    
    #endif
    H264LiveVideoServerMediaSubssion.cpp
    /*
     * Filename: H264LiveVideoServerMediaSubssion.cpp
     * Auther: chenbin
     * Create date: 2012/11/29
     */
    
    #include "H264LiveVideoServerMediaSubssion.hh"
    #include "H264FramedLiveSource.hh"
    #include "H264VideoStreamFramer.hh"
    
    H264LiveVideoServerMediaSubssion*
    H264LiveVideoServerMediaSubssion::createNew( UsageEnvironment& env,
                                                 char const* fileName, 
                                                 Boolean reuseFirstSource )
    {
        return new H264LiveVideoServerMediaSubssion( env, fileName, reuseFirstSource );
    }
    
    H264LiveVideoServerMediaSubssion::H264LiveVideoServerMediaSubssion( UsageEnvironment& env, char const* fileName, Boolean reuseFirstSource )
    : H264VideoFileServerMediaSubsession( env, fileName, reuseFirstSource )
    {
        strcpy(fFileName,fileName);
    }
    
    
    H264LiveVideoServerMediaSubssion::~H264LiveVideoServerMediaSubssion()
    {
    }
     
    FramedSource* H264LiveVideoServerMediaSubssion::createNewStreamSource( unsigned clientSessionId, unsigned& estBitrate )
    {
        /* Remain to do : assign estBitrate */
        estBitrate = 1000; // kbps, estimate
    
        // Create the video source:
        H264FramedLiveSource* liveSource = H264FramedLiveSource::createNew(envir(), fFileName);
        if (liveSource == NULL)
        {
            return NULL;
        }
    
        // Create a framer for the Video Elementary Stream:
        return H264VideoStreamFramer::createNew(envir(), liveSource);
    }

    3、主函数

    testOnDemandRTSPServer.cpp
    /**********
    This library is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation; either version 2.1 of the License, or (at your
    option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
    
    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
    more details.
    
    You should have received a copy of the GNU Lesser General Public License
    along with this library; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
    **********/
    // Copyright (c) 1996-2012, Live Networks, Inc.  All rights reserved
    // A test program that demonstrates how to stream - via unicast RTP
    // - various kinds of file on demand, using a built-in RTSP server.
    // main program
    #include "H264LiveVideoServerMediaSubssion.hh"
    #include "H264FramedLiveSource.hh"
    #include "liveMedia.hh"
    #include "BasicUsageEnvironment.hh"
     
    #pragma comment (lib, "Ws2_32.lib")  
    #pragma comment (lib, "BasicUsageEnvironment.lib")
    #pragma comment (lib, "groupsock.lib")
    #pragma comment (lib, "liveMedia.lib")
    #pragma comment (lib, "UsageEnvironment.lib")
    UsageEnvironment* env;
    
    // To make the second and subsequent client for each stream reuse the same
    // input stream as the first client (rather than playing the file from the
    // start for each client), change the following "False" to "True":
    Boolean reuseFirstSource = False;
    
    // To stream *only* MPEG-1 or 2 video "I" frames
    // (e.g., to reduce network bandwidth),
    // change the following "False" to "True":
    Boolean iFramesOnly = False;
    
    static void announceStream(RTSPServer* rtspServer, ServerMediaSession* sms,
                   char const* streamName, char const* inputFileName); // fwd
    
    static char newMatroskaDemuxWatchVariable;
    static MatroskaFileServerDemux* demux;
    static void onMatroskaDemuxCreation(MatroskaFileServerDemux* newDemux, void* /*clientData*/) {
      demux = newDemux;
      newMatroskaDemuxWatchVariable = 1;
    }
    
    int main(int argc, char** argv) {
      // Begin by setting up our usage environment:
      TaskScheduler* scheduler = BasicTaskScheduler::createNew();
      env = BasicUsageEnvironment::createNew(*scheduler);
    
      UserAuthenticationDatabase* authDB = NULL;
    #ifdef ACCESS_CONTROL
      // To implement client access control to the RTSP server, do the following:
      authDB = new UserAuthenticationDatabase;
      authDB->addUserRecord("username1", "password1"); // replace these with real strings
      // Repeat the above with each <username>, <password> that you wish to allow
      // access to the server.
    #endif
    
      // Create the RTSP server:
      RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);
      if (rtspServer == NULL) {
        *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
        exit(1);
      }
    
      char const* descriptionString
        = "Session streamed by \"testOnDemandRTSPServer\"";
    
      // Set up each of the possible streams that can be served by the
      // RTSP server.  Each such stream is implemented using a
      // "ServerMediaSession" object, plus one or more
      // "ServerMediaSubsession" objects for each audio/video substream.
    
     
      // A H.264 video elementary stream:
      {
        char const* streamName = "h264ESVideoTest";
        char const* inputFileName = "test.264";
        ServerMediaSession* sms
          = ServerMediaSession::createNew(*env, streamName, streamName,
                          descriptionString);
        sms->addSubsession(H264LiveVideoServerMediaSubssion
                   ::createNew(*env, inputFileName, reuseFirstSource));//修改为自己实现的servermedia  H264LiveVideoServerMediaSubssion
        rtspServer->addServerMediaSession(sms);
    
        announceStream(rtspServer, sms, streamName, inputFileName);
      }
    
    
    
      // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
      // Try first with the default HTTP port (80), and then with the alternative HTTP
      // port numbers (8000 and 8080).
    
      //if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
      //  *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
      //} else {
      //  *env << "\n(RTSP-over-HTTP tunneling is not available.)\n";
      //}
    
      env->taskScheduler().doEventLoop(); // does not return
    
      return 0; // only to prevent compiler warning
    }
    
    static void announceStream(RTSPServer* rtspServer, ServerMediaSession* sms,
                   char const* streamName, char const* inputFileName) {
      char* url = rtspServer->rtspURL(sms);
      UsageEnvironment& env = rtspServer->envir();
      env << "\n\"" << streamName << "\" stream, from the file \""
          << inputFileName << "\"\n";
      env << "Play this stream using the URL \"" << url << "\"\n";
      delete[] url;
    }

    使用 ffplay.exe rtsp://115.156.164.19:8554/h264ESVideoTest 可以播放test.264的视频.

    相关配置:live555的四个库放在lib文件夹下。

    库目录:G:\workspace\avs\live555test\live555test\lib

    包含目录:G:\workspace\avs\live555test\live555test\BasicUsageEnvironment\include;G:\workspace\avs\live555test\live555test\UsageEnvironment\include;G:\workspace\avs\live555test\live555test\liveMedia\include;G:\workspace\avs\live555test\live555test\groupsock\include

    源代码 :

    svn checkout http://live555-send-test.googlecode.com/svn/trunk/ live555-send-test-read-only
     
     
     
     
  • 相关阅读:
    SharePoint:扩展DVWP 第33部分:修改DVWP中的合计和分类汇总
    通过SharePoint Web服务更新审批状态
    SharePoint:扩展DVWP 第29部分:修改Remove模版上的表单操作工作流
    SharePoint:扩展DVWP 第27部分:为DVWP添加一个备用编辑模版
    SharePoint 2010之Visio Services入门1-2-3
    一步一步开发属于自己的SharePoint 2010工作流
    在SharePoint 2010中创建自定义字段类型
    SharePoint:扩展DVWP 第25部分:通过SPServices创建列表项实现审计跟踪
    欢迎参加天津PDC Party的活动
    SharePoint:扩展DVWP 赠送部分:当“找不到匹配项”时修复Insert表单操作
  • 原文地址:https://www.cnblogs.com/mlj318/p/2872932.html
Copyright © 2020-2023  润新知