gstreamer的rtsp转rtmp

简介: gstreamer的rtsp转rtmp

VideoPusher.h

#pragma once
#include <iostream>
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
#include <glib.h>
#include <boost/shared_ptr.hpp>
#include <mutex>
#ifndef INT64_C 
#define INT64_C(c) (c ## LL) 
#define UINT64_C(c) (c ## ULL) 
#endif 
class VideoPusher
{
    struct Exception : std::exception{};
    template<typename T>
    T* chk(T* pointer) {
        if (pointer == nullptr) {
            throw Exception();
        }
        return pointer;
    }
    template<typename T>
    void delptr(T* pointer)
    {
        if (pointer != nullptr)
        {
            delete pointer;
            pointer = nullptr;
        }
    }
public:
    VideoPusher();
    VideoPusher(std::string strlocation, std::string strCode);
    virtual ~VideoPusher();
    bool Run(std::string strlocation, std::string strCode, std::string strrequest);
protected:
    static void _onPadAdded(GstElement *src, GstPad *src_pad, gpointer user_data);
    void SetElesNull();
protected:
    GMainLoop  *_loop;
    GstBus*     _bus;
    GstElement* _pipeline;
    GstElement* _source;
    GstElement* _depay;
    GstElement* _parse;
    GstElement* _capsfilter;
    GstElement* _queue1;
    GstElement* _rtmpsink;
    GstElement* _flvmux;
    std::mutex _mutex;
  bool _bStopPush;
};
typedef boost::shared_ptr<VideoPusher> VideoPusherPtr;

VideoPusher.cpp

void VideoPusher::_onPadAdded(GstElement *src, GstPad *src_pad, gpointer user_data)
{
    GstPad* sink_pad = (GstPad*)user_data;
    gst_pad_link(src_pad, sink_pad);
}
void VideoPusher::SetElesNull()
{
    _loop = nullptr;
    _bus = nullptr;
    _pipeline = nullptr;
    _source = nullptr;
    _depay = nullptr;
    _parse = nullptr;
    _capsfilter = nullptr;
    _queue1 = nullptr;
    _rtmpsink = nullptr;
    _flvmux = nullptr;
}
bool VideoPusher::Run(std::string strLocation,
    std::string strCode, std::string strrequest)
{
  _bStopPush = false;
  while (!_bStopPush)
  {
    SetElesNull();
    gboolean terminate = FALSE;
    gst_init(nullptr, nullptr);
    std::stringstream stream;
    stream << "pipeline" << g_pipelinenum++;
    std::string strname;
    strname = stream.str();
    _pipeline = chk(gst_pipeline_new(strname.c_str()));
    _source = chk(gst_element_factory_make("rtspsrc", "src"));
    _depay = chk(gst_element_factory_make(("rtp" + strCode + "depay").c_str(), "depay"));
    _parse = chk(gst_element_factory_make((strCode + "parse").c_str(), "parse"));
    _flvmux = chk(gst_element_factory_make("flvmux", "flvmux"));
    _queue1 = chk(gst_element_factory_make("queue", "queue"));
    _capsfilter = chk(gst_element_factory_make("capsfilter", "filter"));
    _rtmpsink = chk(gst_element_factory_make("rtmpsink", "sink"));
    //g_object_set(_source, "protocols", 0x00000004, NULL);
    g_object_set(_source, "latency", 0, NULL);
    g_object_set(_capsfilter, "caps-change-mode", 1, NULL);
    g_object_set(_rtmpsink, "location", strLocation.c_str(), NULL);
    gst_bin_add_many(GST_BIN(_pipeline), _source, _depay, _parse, _flvmux, _capsfilter, _queue1, _rtmpsink, NULL);
    g_signal_connect(_source, "pad-added", G_CALLBACK(&_onPadAdded), gst_element_get_static_pad(_depay, "sink"));
    gboolean bsuccess = gst_element_link_many(_depay, _parse, _flvmux, _capsfilter, _queue1, _rtmpsink, NULL);
    if (!bsuccess) {
      g_print("Failed to link one or more elements!\n");
      gst_element_unlink_many(_depay, _parse, _flvmux, _capsfilter, _queue1, _rtmpsink, NULL);
      Sleep(1000);
      continue;
    }
    g_object_set(_source, "location", strrequest.c_str(), NULL);
    GstCaps* caps = gst_caps_new_simple(
      "video/x-raw",
      "format", G_TYPE_STRING, "rgb",
      "width", G_TYPE_INT, 426,
      "height", G_TYPE_INT, 240,
      "framerate", GST_TYPE_FRACTION, 25, 1,
      NULL);
    g_object_set(_capsfilter, "caps", caps, NULL);
    gst_caps_unref(caps);
    GstStateChangeReturn res = gst_element_set_state(_pipeline, GST_STATE_PLAYING);
    if (res == GST_STATE_CHANGE_FAILURE)
    {
      g_printerr("Unable to set the pipeline to the playing state.\n");
      gst_object_unref(_pipeline);
      Sleep(1000);
      continue;
    }
    GstMessage *msg;
    /* Listen to the bus */
    //_bus = gst_element_get_bus(_pipeline);
    _bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline));
    do
    {
      msg = gst_bus_timed_pop_filtered(_bus, GST_CLOCK_TIME_NONE,
        GstMessageType(GST_MESSAGE_STATE_CHANGED |
        GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
      /* Parse message */
      if (msg != NULL)
      {
        GError *err;
        gchar *debug_info;
        switch (GST_MESSAGE_TYPE(msg))
        {
        case GST_MESSAGE_ERROR:
        {
          gst_message_parse_error(msg, &err, &debug_info);
          g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
          g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
          g_clear_error(&err);
          g_free(debug_info);
          terminate = TRUE;
        }
        break;
        case GST_MESSAGE_EOS:
        {
          g_print("End-Of-Streamreached.\n");
          terminate = TRUE;
        }
        break;
        case GST_MESSAGE_STATE_CHANGED:
        {
          /* We are onlyinterested in state-changed messages from the pipeline */
          if (GST_MESSAGE_SRC(msg) == GST_OBJECT(_pipeline))
          {
            GstState old_state, new_state, pending_state;
            gst_message_parse_state_changed(msg,
              &old_state,
              &new_state,
              &pending_state);
            g_print("Pipeline state changed from %s to %s:\n",
              gst_element_state_get_name(old_state),
              gst_element_state_get_name(new_state));
            if (pending_state == GST_STATE_NULL)
            {
              terminate = TRUE;
            }
          }
        }
        break;
        default:
        {
          /* We shouldnot reach here */
          g_printerr("Unexpected message received.\n");
          break;
        }
        }
        gst_message_unref(msg);
        //  std::this_thread::sleep_for(std::chrono::milliseconds(200));
      }
    } while (!terminate);
    /* Free resources */
    try
    {
      std::lock_guard<std::mutex> lock(_mutex);
      gst_object_unref(_bus);
      gst_element_set_state(_pipeline, GST_STATE_PAUSED);
      gst_element_set_state(_pipeline, GST_STATE_READY);
      gst_element_set_state(_pipeline, GST_STATE_NULL);
      gst_object_unref(_pipeline);
    }
    catch (std::exception &e)
    {
      cout << e.what();
      return true;
    }
    catch (...)
    {
      return true;
    }
  }
    return true;
}

main.cpp

#include "VideoPusher.h"
int main()
{
    VideoPusher pusher;
    std::string strRtmp = "rtmp://localhost:1945/live/room";
    std::string strRtsp = "rtsp://admin:HuaWei123@59.51.115.31/LiveMedia/ch1/Media1";
    std::string strCode = "h264";
    bool bSuccess = pusher.Run(strRtmp, strCode, strRtsp);
    getchar();
    return 0;
}
相关文章
|
11天前
|
存储 监控 网络协议
什么是RTSP
RTSP,即实时流传输协议,英文全称为Real-Time Streaming Protocol
16 0
|
6月前
|
网络协议 网络安全 流计算
【流媒体】RTMP、RTSP、HLS、HTTP协议的介绍与对比
【流媒体】RTMP、RTSP、HLS、HTTP协议的介绍与对比
205 0
|
3月前
|
应用服务中间件 nginx Windows
ffmpeg推流到nginx服务器,并使用vlc播放rtmp视频
ffmpeg推流到nginx服务器,并使用vlc播放rtmp视频
|
7月前
|
存储 网络协议 开发工具
多路RTSP-RTMP转RTMP定制版
大牛直播SDK多路RTMP/RTSP转RTMP转发软件,系原有转发SDK基础上,官方推出的Windows平台定制版。在秉承低延迟、灵活稳定、低资源占用的前提下,客户无需关注开发细节,只需图形化配置转发等各类参数,实现产品快速上线目的。
|
7月前
|
开发工具 开发者 Windows
QT实现低延迟的RTSP、RTMP播放器
好多开发者在QT环境下实现RTMP或RTSP播放时,首先考虑到的是集成VLC,集成后,却发现VLC在延迟、断网重连、稳定性等各个方面不尽人意,无法满足上线环境需求。本文以调用大牛直播SDK(官方)的Windows平台播放端SDK为例,介绍下如何在QT下实现低延迟的RTMP|RTSP播放器,废话不多说,先上图:
276 0
|
7月前
|
网络协议 开发工具 C#
Windows平台如何快速实现RTSP/RTMP直播播放
前段时间,我们在 https://blog.csdn.net/renhui1112/article/details/104143794 提到“RTSP播放器开发过程中需要考虑哪些关键因素”,本次主要介绍,如何调用SDK实现RTSP/RTMP播放能力。
354 0
|
8月前
|
编解码 网络协议 计算机视觉
ffmpeg推流rtmp指定udp传输
ffmpeg推流rtmp指定udp传输
374 0
|
Web App开发 编解码 移动开发
秒懂流媒体协议 RTMP 与 RTSP
RTMP 与 RTSP 是比较常见的两种流媒体协议,那么什么是RTMP?什么是RTSP?它们两之间有什么区别?使用的时候应该如何选择?
647 1
秒懂流媒体协议 RTMP 与 RTSP
|
编解码 C++
ffmpeg处理rtmp/文件/rtsp的推流和拉流
ffmpeg处理rtmp/文件/rtsp的推流和拉流   本demo演示了利用ffmpeg从服务器拉流或本地文件读取流,更改流url或文件类型名称发送回服务器或存到本地的作用。 由于本程序只写了3个小时,还要忙别的,所以会有一些bug和优化的地方。
5786 0