【视频开发】【Live555】摄像头采集,264编码,live555直播(0)

摘要:
请参见live5551。首先,您需要修改live555以定义一个直接从内存中获取源代码的类,而不是从文件中读取源代码。暂时,从文件中读取作为测试。

参看 有关live555 

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

自己实现的类命名为 H264FramedLiveSource 

 
【视频开发】【Live555】摄像头采集,264编码,live555直播(0)第1张
复制代码
/*
 * 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
复制代码
【视频开发】【Live555】摄像头采集,264编码,live555直播(0)第1张
复制代码
/*
 * 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 

【视频开发】【Live555】摄像头采集,264编码,live555直播(0)第1张
复制代码
/*
 * 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
复制代码
【视频开发】【Live555】摄像头采集,264编码,live555直播(0)第1张
复制代码
/*
 * 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、主函数

【视频开发】【Live555】摄像头采集,264编码,live555直播(0)第1张
复制代码
/**********
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() << "
";
    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 << "
(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)
";
  //} else {
  //  *env << "
(RTSP-over-HTTP tunneling is not available.)
";
  //}

  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 << "
"" << streamName << "" stream, from the file ""
      << inputFileName << ""
";
  env << "Play this stream using the URL "" << url << ""
";
  delete[] url;
}
复制代码

 

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

 

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

库目录:G:workspaceavslive555testlive555testlib

包含目录:G:workspaceavslive555testlive555testBasicUsageEnvironmentinclude;G:workspaceavslive555testlive555testUsageEnvironmentinclude;G:workspaceavslive555testlive555testliveMediainclude;G:workspaceavslive555testlive555testgroupsockinclude

源代码 :

svn checkout http://live555-send-test.googlecode.com/svn/trunk/ live555-send-test-read-only



FROM:  http://www.cnblogs.com/mlj318/archive/2013/01/23/2872932.html

免责声明:文章转载自《【视频开发】【Live555】摄像头采集,264编码,live555直播(0)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ELK-Windows下系统安装(1)利用ARCGIS和LocaSpace Viewer无限制免费下载高清的谷歌卫星影像下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

CPU亲和度

CPU亲和度(CPU Affinity),就是将一个进程或者线程强制绑定在CPU的某一个core上运行。 参考:https://www.cnblogs.com/zhangxuan/p/6427533.html https://www.cnblogs.com/LubinLew/p/cpu_affinity.html demo是将ljj_test进程强制绑定在...

c/c++实现获取NOD32升级账号密码

功能有待完善和添加 #include <iostream> #include <ctime> #include <cstring> #include <string> #include <fstream> #include <sstream> #include <cstdlib...

转载:嵌入式C语言面试题(二)

BSS段 是“Block Started by Symbol”的缩写,意为“以符号开始的块”。   BSS是Unix链接器产生的未初始化数据段。其他的段分别是包含程序代码的“text”段和包含已初始化数据的“data”段。BSS段的变量只有名称和大小却没有值。此名后来被许多文件格式使用,包括PE。“以符号开始的块”指的是编译器处理未初始化数据的地方。BS...

引领Boost(五)(Boost::array)

一 Boost::array       在以前,如果我们要处理一组数据,我们可能使用一般数组存储,或者需要许多的对数组的数据的操作的时候,我们使用STL容器存储。但是如果我们的需求是,我们能够提前固定一组数据的大小,或提前知道这组数据的大小,但是我们又想这组数据进行一些操作,比如排序。。。显然对这个情况,上面的使用原始数组或STL容器都有点不太合适,因为...

网络IPC:套接字

摘要: UNIX系统进程间通信机制(IPC),例如管道,FIFO,消息队列,信号量和共享存储,可以允许一台计算机上的进程通信。 而套接字网络进程通信接口,不仅实现了一台计算机的通信,还能够进行网络进程间通信。 一、四层协议栈 数据链路层 网卡接口的网络驱动程序,处理数据在物理媒介上的传输;不同的物理网络具有不同的电气特性,网络驱动程序隐藏实现细节,为上层协...

电赛菜鸟营培训(五)——OLED屏幕的使用

一、取模软件的使用        首先进行设置         然后可以生成显示这个字母的代码,列优先,先按列画8行,然后再继续画下一列。汉字为16*16,字母为8*8,对应生成相应个数的ox代码。 二、STM32烤写OLED #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include...