live555 rtsp码流服务器移植应用

一、编译

1.1下载源码

可以登陆live555的官网获取live555最新版源代码,也可从下面这个地址获取到本文移植所使用的源代码:

http://download.csdn.net/detail/yxtouch/7482263

解压源代码,进入解压后的目录,输入如下命令生成makefile文件:

./genMakefiles linux

用于生成ubuntu中makefile,然后运行make&make install完成编译和安装。

1.2交叉编译

创建所需的config文件用于生成makefile。本文用目录中的config.armlinux文件进行修改的得到所需配置文件。

cp config.armlinux config.hi3536

编辑config.hi3536,将第一行的CROSS_COMPILE?= arm-elf-改为自己使用的交叉工具链,如本文修改为arm-linux-。修改后保存。
如下:

CROSS_COMPILE?=         arm-hisiv400-linux- //自家工具链名称
COMPILE_OPTS =          $(INCLUDES) -I/usr/local/include -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -DNO_OPENSSL=1 -DLOCALE_NOT_USED -DDEBUG
//-DNO_OPENSSL=1 -DLOCALE_NOT_USED 添加这两个去除编译错误 -DDEBUG添加debug打印 
C =                     c
C_COMPILER =            $(CROSS_COMPILE)gcc
C_FLAGS =               $(COMPILE_OPTS)
CPP =                   cpp
CPLUSPLUS_COMPILER =    $(CROSS_COMPILE)g++
CPLUSPLUS_FLAGS =       $(COMPILE_OPTS) -Wall -DBSD=1
OBJ =                   o
LINK =                  $(CROSS_COMPILE)g++ -o
LINK_OPTS =
CONSOLE_LINK_OPTS =     $(LINK_OPTS)
LIBRARY_LINK =          $(CROSS_COMPILE)ar cr
LIBRARY_LINK_OPTS =     $(LINK_OPTS)
LIB_SUFFIX =                    a
LIBS_FOR_GUI_APPLICATION =
EXE =
PREFIX =                /home/cks/live555_install //安装目录

执行如下命令生成makefile

./genMakefiles hi3536 //后面参数hi3536 是根据config.hi3536的后缀来的。

执行make、make install进行编译和安装,安装后的测试案列及lib include被拷贝到/home/cks/live555_install目录下。

二、在编辑自己的live555 rtsp流服务器

流程如下:

2.1、初始化

2.1.1 设置rtsp码流双缓冲区

设置输出缓冲区5M的大小 live555里会根据缓存区块大小自动划分成双缓冲即两个缓冲块切换填充使用。

OutPacketBuffer::maxSize = MEM_BLOCK_SIZE_5M;
2.1.2 提供h264取帧队列:

队列类VideoFrameQueue请自行实现

VideoFrameQueue *pRtspMainVideoFrameQueue = new VideoFrameQueue();

思路是实现读帧函数,将帧缓冲队列中数据填充完成的块地址给到live555 的FramedSource类的fTo,该指针指向当前live里的填充缓存块

  // The following variables are typically accessed/set by doGetNextFrame()
  unsigned char* fTo; // in

通过memcpy循环读取直到一帧读取完成
pbyFrameBuffer 为VideoFrameQueue中队列的帧缓存块地址

memcpy(fTo, pbyFrameBuffer + dwReadSize, fFrameSize);
2.1.3 初始化基础运行环境
TaskScheduler *scheduler = BasicTaskScheduler::createNew();
UsageEnvironment *env = BasicUsageEnvironment::createNew(*scheduler);
if (scheduler == NULL || env == NULL)
{
    LOG(LOG_INF,"UsageEnvironment or TaskScheduler Error.");
}
2.1.4 创建rtsp服务
// 2、创建rtsp服务器,10秒垃圾回收时间 vlc一直重连会占用端口导致服务创建不成功
RTSPServer *rtspServer = RTSPServer::createNew(*env, 554, NULL, 10);
if (rtspServer == NULL)
{
    LOG(LOG_ERR,"RTSPServer::createNew port 554 Error.");
    rtspServer = RTSPServer::createNew(*env, 8554, NULL, 10);
    if(rtspServer == NULL)
    {
        LOG(LOG_ERR,"RTSPServer::createNew port 8554 Error.");
        system("killall vwReviewNode");
        return NULL;
    }
}
2.1.5 添加会话

添加会话后可通过rtsp://192.168.1.11:554/main访问:

Boolean bReuseSource = True;
char strResourceName[] = "main";

ServerMediaSession *sms = ServerMediaSession::createNew(
    *env, strResourceName, strResourceName,
    "MainStream");
//会话内会初始化FramedSource将缓冲队列类放置进去    
sms->addSubsession(
H264Subsession::createNew(*env, bReuseSource, pRtspMainVideoFrameQueue));   
//将会话加入rtsp服务
rtspServer->addServerMediaSession(sms);

setRtspFrameQueue(pRtspMainVideoFrameQueue);

会话里加入FramedSource 后如果有连接请求则会调用createNewStreamSource创建FramedSource 及VideoStreamSource (继承FramedSource )

FramedSource *
H264Subsession::createNewStreamSource(unsigned /*clientSessionId*/,
                                      unsigned &estBitrate)
{
    estBitrate = 160000; // kbps, estimate,考虑最多支持5路,所以缓冲区固定160M,
    // streamBitrate * 25 / 2; // 1 kbps * 0.1 s = 12.5 bytes
    VideoStreamSource *source = VideoStreamSource::createNew(envir(), pVideoQueue);
    if (source == NULL)
        return NULL;
    return H264VideoStreamFramer::createNew(envir(), source);
}
2.1.6 进入事件循环
// 进入事件反应堆,正常情况下不返回
LOG(LOG_INF, "runRtsp doEventLoop **********************************************");
env->taskScheduler().doEventLoop();

2.2 接收连接读取码流

实现FramedSource的虚函数doGetNextFrame,这个函数在连接建立后会自动回调
开启任务

nextTask() = envir().taskScheduler().scheduleDelayedTask(
    dwDelayMs * 1000, (TaskFunc *)VideoStreamSource::ReadableHandler, this);

然后使用pVideoQueue(_pVideoQueue)的getframe拿到帧数据
接着等待

nextTask() = envir().taskScheduler().scheduleDelayedTask(
    0, (TaskFunc *)FramedSource::afterGetting, this);

关于afterGetting

  static void afterGetting(FramedSource* source);
      // doGetNextFrame() should arrange for this to be called after the
      // frame has been read (*iff* it is read successfully)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值