gstreamer之RTSP Server一个进程提供多路不同视频

简介: gstreamer之RTSP Server一个进程提供多路不同视频

柳鲲鹏


rtsp-server本身没有提供类似功能。经过反复测试实验,终于找到了正确办法。


直接提供源码,需要的朋友下载使用。


此源码已反复测试过(在此基础上,可以实现多个进程、多个端口功能。这里就不重复了)。


#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
//这里是值不同的流。实际上一个流可以多路同时访问
#define MAX_VIDEO_COUNT        4
#define DEFAULT_RTSP_PORT      "8555"
#define ATTACH_URL             "/test"
static const char* VIDEO_FILES[] =
{
    //"/home/quantum6/gh4ai/videos/rtsp-server-1.mov",
    "../../videos/rtsp-server-1.mov",
    "../../videos/rtsp-server-2.mov",
    "../../videos/rtsp-server-3.mov",
    "../../videos/rtsp-server-4.mov",
    NULL
};
/* called when a stream has received an RTCP packet from the client */
static void on_ssrc_active (GObject * session, GObject * source, GstRTSPMedia * media)
{
  GstStructure *stats;
  GST_INFO ("source %p in session %p is active", source, session);
  g_object_get (source, "stats", &stats, NULL);
  if (stats) {
    gchar *sstr;
    sstr = gst_structure_to_string (stats);
    g_print ("structure: %s\n", sstr);
    g_free (sstr);
    gst_structure_free (stats);
  }
}
static void on_sender_ssrc_active (GObject * session, GObject * source, GstRTSPMedia * media)
{
  on_ssrc_active(session, source, media);
}
/* signal callback when the media is prepared for streaming. We can get the
 * session manager for each of the streams and connect to some signals. */
static void media_prepared_cb (GstRTSPMedia * media)
{
  guint i, n_streams;
  n_streams = gst_rtsp_media_n_streams (media);
  GST_INFO ("media %p is prepared and has %u streams", media, n_streams);
  for (i = 0; i < n_streams; i++) {
    GstRTSPStream *stream;
    GObject *session;
    stream = gst_rtsp_media_get_stream (media, i);
    if (stream == NULL)
    {
      continue;
    }
    session = gst_rtsp_stream_get_rtpsession (stream);
    GST_INFO ("watching session %p on stream %u", session, i);
    g_signal_connect (session, "on-ssrc-active",        (GCallback) on_ssrc_active,        media);
    g_signal_connect (session, "on-sender-ssrc-active", (GCallback) on_sender_ssrc_active, media);
  }
}
static void media_configure_cb (GstRTSPMediaFactory * factory, GstRTSPMedia * media)
{
  /* connect our prepared signal so that we can see when this media is
   * prepared for streaming */
  g_signal_connect (media, "prepared", (GCallback) media_prepared_cb, factory);
}
int main (int argc, char *argv[])
{
  GMainLoop           *loop    = NULL;
  GstRTSPServer       *server  = NULL;
  GstRTSPMountPoints  *mounts  = NULL;
  GstRTSPMediaFactory *factory = NULL;
  GOptionContext      *optctx  = NULL;
  GError              *error   = NULL;
  gchar               *str     = NULL;
  const char          *file    = NULL;
  char temp_buffer[128]        = {0};
  char temp_buffer[128]        = {0};
  int count = 0;
  int index = 0;
  GOptionEntry entries[] = {
    {"port", 'p', 0, G_OPTION_ARG_STRING, (char*)DEFAULT_RTSP_PORT, NULL, "PORT"},
    {NULL}
  };
  if (argc >= 2)
  {
      count = atoi(argv[1]);
  }
  if (count <= 0)
  {
      count = MAX_VIDEO_COUNT;
  }
  sprintf(temp_buffer, "Port to listen on (default: %s)", DEFAULT_RTSP_PORT);
  entries[0].description = temp_buffer;
  optctx = g_option_context_new ("<filename.mp4> - Test RTSP Server, MP4");
  g_option_context_add_main_entries (optctx, entries, NULL);
  g_option_context_add_group (optctx, gst_init_get_option_group ());
  if (!g_option_context_parse (optctx, NULL, NULL, &error)) {
    g_printerr ("Error parsing options: %s\n", error->message);
    g_option_context_free (optctx);
    g_clear_error (&error);
    return -1;
  }
  g_option_context_free (optctx);
  loop = g_main_loop_new (NULL, FALSE);
  server = gst_rtsp_server_new ();
  g_object_set (server, "service", DEFAULT_RTSP_PORT, NULL);
  /* get the mount points for this server, every server has a default object
   * that be used to map uri mount points to media factories */
  mounts = gst_rtsp_server_get_mount_points (server);
  for (index=0; index<count; index++)
  {
      file = VIDEO_FILES[index];
      //注意,必须是pay0
      str = g_strdup_printf (
              "filesrc location=\"%s\" ! qtdemux "
              "! h264parse ! rtph264pay pt=96 name=pay0 )",
              file);
      /* make a media factory for a test stream. The default media factory can use
       * gst-launch syntax to create pipelines. 
       * any launch line works as long as it contains elements named pay%d. Each
       * element with pay%d names will be a stream */
      factory = gst_rtsp_media_factory_new ();
      gst_rtsp_media_factory_set_launch (factory, str);
      g_signal_connect (factory, "media-configure", (GCallback) media_configure_cb, factory);
      g_free (str);
      sprintf(temp_buffer, "%s%d", ATTACH_URL, index);
      /* attach the test factory to the /test url */
      gst_rtsp_mount_points_add_factory (mounts, temp_buffer, factory);
      //gst_rtsp_media_factory_set_shared (factory, TRUE);
      g_print ("stream ready at rtsp://127.0.0.1:%s%s\n", DEFAULT_RTSP_PORT, temp_buffer);
  }
  /* don't need the ref to the mapper anymore */
  g_object_unref (mounts);
  /* attach the server to the default maincontext */
  gst_rtsp_server_attach (server, NULL);
  g_main_loop_run (loop);
  return 0;
}
目录
相关文章
|
消息中间件 Java Apache
RocketMQ5.0 搭建 Name Server And Broker+Proxy 同进程部署、搭建RocketMQ控制台图形化界面
RocketMQ5.0 搭建 Name Server And Broker+Proxy 同进程部署、搭建RocketMQ控制台图形化界面
1315 0
|
6月前
【进程通信】用命名管道模拟server和client之间的通信
【进程通信】用命名管道模拟server和client之间的通信
|
6月前
|
SQL 网络协议 Windows
破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”
破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”
739 0
|
6月前
|
JavaScript
uniapp计算视频学习进程,并且下次回来继续播放(不能快进)
uniapp计算视频学习进程,并且下次回来继续播放(不能快进)
209 0
|
监控
【Zabbix】排错:zabbix分部署服务器监控部署后Server进程过多
部署完zabbix服务端后,Zabbix Server进程过多警告
790 0
【Zabbix】排错:zabbix分部署服务器监控部署后Server进程过多
|
计算机视觉 Python
python是如何利用多线进程优化视频应用到的? 原来是这样的
前言如果要用Python播放视频,或者打开摄像头获取视频流,我们可以用OpenCV Python。但是在视频帧获取的时候同时做一些图像识别和处理,可能会因为耗时多而导致卡顿。一般来说,我们首先会想到把这些工作放入到线程中处理。
1892 0

相关实验场景

更多