基于Live555实现RTSP服务器来推送H264实时码流

这篇具有很好参考价值的文章主要介绍了基于Live555实现RTSP服务器来推送H264实时码流。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

实现了一个单播的rtsp服务器来推送实时的h264码流,参考了官方的testProgs目录下的testOnDemandRTSPServer例程和liveMedia目录下的DeviceSource.cpp文件。我这边是把编码出来的h264码流放入了一个缓冲队列,然后从缓冲队列里取出来进行推流。

rtsp.h:

#ifndef _RTSP_H_
#define _RTSP_H_

#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"

void create_rtsp_server(void);

class H264LiveServerMediaSession : public OnDemandServerMediaSubsession
{
public:
    static H264LiveServerMediaSession *createNew(UsageEnvironment &env, Boolean reuseFirstSource);
    void checkForAuxSDPLine1();
    void afterPlayingDummy1();

protected:
    H264LiveServerMediaSession(UsageEnvironment &env, Boolean reuseFirstSource);
    virtual ~H264LiveServerMediaSession(void);
    void setDoneFlag() { fDoneFlag = ~0; }

protected:
    virtual char const *getAuxSDPLine(RTPSink *rtpSink, FramedSource *inputSource);
    virtual FramedSource *createNewStreamSource(unsigned clientSessionId, unsigned &estBitrate);
    virtual RTPSink *createNewRTPSink(Groupsock *rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource *inputSource);

private:
    char *fAuxSDPLine;
    char fDoneFlag;
    RTPSink *fDummyRTPSink;
};

// 创建一个自定义的实时码流数据源类
class H264VideoStreamSource : public FramedSource
{
public:
    static H264VideoStreamSource *createNew(UsageEnvironment &env);
    unsigned maxFrameSize() const;

protected:
    H264VideoStreamSource(UsageEnvironment &env);
    virtual ~H264VideoStreamSource();

private:
    virtual void doGetNextFrame();
    virtual void doStopGettingFrames();
};

#endif // _RTSP_H_

rtsp.cpp:
 文章来源地址https://www.toymoban.com/news/detail-743881.html

#include <iostream>
#include "rtsp.h"
#include "ringQueue.h"

extern ringQueue *rQueue;

void create_rtsp_server(void)
{
    TaskScheduler *scheduler;
    UsageEnvironment *env;
    RTSPServer *rtspServer;

    scheduler = BasicTaskScheduler::createNew();
    env = BasicUsageEnvironment::createNew(*scheduler);
    rtspServer = RTSPServer::createNew(*env, 8554);
    if (rtspServer == NULL)
    {
        *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
        return;
    }

    ServerMediaSession *sms = ServerMediaSession::createNew(*env);
    sms->addSubsession(H264LiveServerMediaSession::createNew(*env, true));
    rtspServer->addServerMediaSession(sms);
    char *url = rtspServer->rtspURL(sms);
    *env << "Play the stream using url " << url << "\n";
    delete[] url;
    env->taskScheduler().doEventLoop(); // 进入事件循环
}

// H264LiveServerMediaSession 实现:
H264LiveServerMediaSession *H264LiveServerMediaSession::createNew(UsageEnvironment &env, Boolean reuseFirstSource)
{
    return new H264LiveServerMediaSession(env, reuseFirstSource);
}

H264LiveServerMediaSession::H264LiveServerMediaSession(UsageEnvironment &env, Boolean reuseFirstSource) : OnDemandServerMediaSubsession(env, reuseFirstSource)
{
    fAuxSDPLine = NULL;
    fDoneFlag = 0;
    fDummyRTPSink = NULL;
}

H264LiveServerMediaSession::~H264LiveServerMediaSession()
{
    delete[] fAuxSDPLine;
}

static void afterPlayingDummy(void *clientData)
{
    H264LiveServerMediaSession *subsess = (H264LiveServerMediaSession *)clientData;
    subsess->afterPlayingDummy1();
}

void H264LiveServerMediaSession::afterPlayingDummy1()
{
    envir().taskScheduler().unscheduleDelayedTask(nextTask());
    setDoneFlag();
}

static void checkForAuxSDPLine(void *clientData)
{
    H264LiveServerMediaSession *subsess = (H264LiveServerMediaSession *)clientData;
    subsess->checkForAuxSDPLine1();
}

void H264LiveServerMediaSession::checkForAuxSDPLine1()
{
    nextTask() = NULL;

    char const *dasl;
    if (fAuxSDPLine != NULL)
    {
        setDoneFlag();
    }
    else if (fDummyRTPSink != NULL && (dasl = fDummyRTPSink->auxSDPLine()) != NULL)
    {
        fAuxSDPLine = strDup(dasl);
        fDummyRTPSink = NULL;
        setDoneFlag();
    }
    else if (!fDoneFlag)
    {
        // try again after a brief delay:
        int uSecsToDelay = 100000; // 100 ms
        nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
                                                                 (TaskFunc *)checkForAuxSDPLine, this);
    }
}

char const *H264LiveServerMediaSession::getAuxSDPLine(RTPSink *rtpSink, FramedSource *inputSource)
{
    if (fAuxSDPLine != NULL)
    {
        return fAuxSDPLine;
    }

    if (fDummyRTPSink == NULL)
    {
        fDummyRTPSink = rtpSink;
        fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);
        checkForAuxSDPLine(this);
    }
    envir().taskScheduler().doEventLoop(&fDoneFlag);

    return fAuxSDPLine;
}

FramedSource *H264LiveServerMediaSession::createNewStreamSource(unsigned clientSessionId, unsigned &estBitrate)
{
    estBitrate = 5000; // kbps, estimate

    H264VideoStreamSource *videoSource = H264VideoStreamSource::createNew(envir());
    if (videoSource == NULL)
    {
        return NULL;
    }

    return H264VideoStreamFramer::createNew(envir(), videoSource);
}

RTPSink *H264LiveServerMediaSession ::createNewRTPSink(Groupsock *rtpGroupsock,
                                                       unsigned char rtpPayloadTypeIfDynamic,
                                                       FramedSource *inputSource)
{
    // OutPacketBuffer::maxSize = 2000000;
    return H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
}

// H264VideoStreamSource 实现:
H264VideoStreamSource *H264VideoStreamSource::createNew(UsageEnvironment &env)
{
    return new H264VideoStreamSource(env);
}

H264VideoStreamSource::H264VideoStreamSource(UsageEnvironment &env) : FramedSource(env)
{
}

H264VideoStreamSource::~H264VideoStreamSource()
{
}

unsigned  int H264VideoStreamSource::maxFrameSize() const
{
    return 100000; // 设置fMaxSize的值
}

void H264VideoStreamSource::doGetNextFrame()
{
    rQueue_data e;
    uint32_t timestamp = 0;
    static uint8_t buffer_data[1024 * 512] = {0};

    // 还没准备好要数据
    if (!isCurrentlyAwaitingData())
    {
        std::cout << "isCurrentlyAwaitingData" << std::endl;
        return;
    }

    // 从队列中取出数据
    e.buffer = buffer_data;
    e.len = sizeof(buffer_data);
    if(rQueue_de(rQueue, &e) == -1)
    {
        FramedSource::afterGetting(this);
        return;
    }

    if (e.len > fMaxSize)
    {
        fFrameSize = fMaxSize;
        fNumTruncatedBytes = e.len - fMaxSize;
    }
    else
    {
        fFrameSize = e.len;
    }
    gettimeofday(&fPresentationTime, NULL);
    memcpy(fTo, buffer_data, fFrameSize);
    FramedSource::afterGetting(this);
}

void H264VideoStreamSource::doStopGettingFrames()
{
    std::cout << "doStopGettingFrames" << std::endl;
}

到了这里,关于基于Live555实现RTSP服务器来推送H264实时码流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从0-1一起学习live555设计思想之二 RTSP交互过程

    本篇文章通过代码去分析rtsp交互过程与工作原理。由于live555的继承关系太过复杂,所以做了个图简单记录一下与h264文件传输相关的类继承关系。 OPTION比较简单,就是客户端向服务端请求可用的方法。服务端收到客户端发来的OPTION指令后,调用函数handleCmd_OPTIONS

    2024年02月12日
    浏览(40)
  • Android平台Unity下如何通过WebCamTexture采集摄像头数据并推送至RTMP服务器或轻量级RTSP服务

    我们在对接Unity下推送模块的时候,遇到这样的技术诉求,开发者希望在Android的Unity场景下,获取到前后摄像头的数据,并投递到RTMP服务器,实现低延迟的数据采集处理。 在此之前,我们已经有了非常成熟的RTMP推送模块,也实现了Android平台Unity环境下的Camera场景采集,针对

    2024年01月21日
    浏览(48)
  • rk3588/rk356x/rv1109/rv1126 live555移植+mpp编译 rtsp拉流

    本文主要是为了记录一下rk板子的踩坑日记。 项目主要是rk3588 rtsp拉流。 1.下载MPP源码:https://github.com/rockchip-linux/mpp 2.rk3588/rk356x的板子进入Mpp源码目录 mpp/build/linux/aarch64 (rk3588/rk356x是64位板子)中,修改 arm.linux.cross.cmake 文件中的配置 修改 make-Makefiles.bash 的配置,主要改

    2023年04月19日
    浏览(32)
  • zlmediakit实现rtsp流服务器

    本次实现是将内存中的H264数据经过zlmediakit实现为rtsp流。 我是用的是CAPI的方式,将zlmediakit作为一个sdk嵌入到自己的程序中而不是作为一个独立的进进程服务。 1.编译完成zkmedialit后会得到bin include lib三个文件夹如图 其中bin中的MediaServer是作为独立的进程使用的zlmediakit服务,

    2024年02月02日
    浏览(29)
  • 从零开始写一个RTSP服务器(二)RTSP协议的实现

    此系列只追求精简,旨在学习RTSP协议的实现过程,不追求复杂完美,所以这里要实现的RTSP服务器为了简单,实现上同一时间只能有一个客户端,下面开始介绍实现过程 在写一个RTSP服务器之前,我们必须知道一个RTSP服务器最简单的包含两部分,一部分是RTSP的交互,一部分是

    2024年04月17日
    浏览(38)
  • RTSP 和 RTMP通过ffmpeg实现将本地摄像头推流到RTSP服务器

    一、流媒体:RTSP 和RTMP 1、RTSP 和 RTMP的工作原理 1)RTSP工作原理 用户设备向视频流平台发送 RTSP 请求 视频流平台返回可以操作的请求列表,比如播放、暂停等 用户设备向视频流平台发送具体的请求,比如播放 视频流平台解析请求并调用指定机制启动视频流处理 由于 RTSP 依

    2024年02月05日
    浏览(34)
  • RTSP 和 RTMP原理 & 通过ffmpeg实现将本地摄像头推流到RTSP服务器

    0、参考资料 秒懂流媒体协议 RTMP 与 RTSP 什么是RTMP 和 RTSP?它们之间有什么区别? RTSP和RTMP的区别是什么? 1、RTSP 和 RTMP的工作原理 1)RTSP工作原理 用户设备向视频流平台发送 RTSP 请求 视频流平台返回可以操作的请求列表,比如 播放、暂停 等 用户设备向视频流平台发送具

    2024年02月08日
    浏览(46)
  • 极光Java 版本服务器端实现别名消息推送

    REST API 文档:

    2024年02月15日
    浏览(31)
  • Android 内置RTSP/RTMP服务器,实现局域网内视频推流与播放

    工作中有一个需求,在同一个局域网内, 需要将Android平板端(车机)上的摄像头上的画面,实时传输到手机上进行播放。 对于这个需求,我们想到了用 RTSP/RTMP 进行推流,然后在手机端拉流进行播放。 这个技术方案的主要技术点有 平板端内置 RTSP/RTMP 服务器 平板端获取摄像头

    2023年04月27日
    浏览(68)
  • Monibucav4(开源流媒体服务器)在Windows上搭建rtmp服务器并实现拉取rtsp视频流以及转换flv播放

    开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放: 开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放_srs按需拉流_霸道流氓气质的博客-CSDN博客 上面讲了ZLMediaKit的使用流

    2024年02月11日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包