GStreamer C++ 通过 TCP 流式传输网络摄像头教程

在本教程中,将向你展示如何使用本地的 GStreamer(C++) 通过 TCP 流式传输用户的网络摄像头。

要求

  • C++
  • GStreamer
  • GStreamer dev
  • C++ 和 GStreamer 的基础知识

GStreamer 安装将取决于你的环境等。可以通过以下方式找到有关如何安装 GStreamer 的说明:https://gstreamer.freedesktop.org/documentation/installing/index.html?gi-language=c

编写代码

接下来我们需要为项目实际编写代码,创建一个名为 sender.cpp 的新文件并在你喜欢的文本编辑器中打开它。

首先需要包括所需的头文件:

#include <gst/gst.h>
#include <glib-unix.h>

#define HOST "127.0.0.1"

在这里我们包括了GStreamer头文件,如果你像我一样使用Linux,你还需要包括 “glib-unix”。我们还定义了HOST常量,这是流媒体将被发送的地方。

接下来我们需要创建主函数并初始化元素。

int main (gint argc, gchar *argv[])
{ 
  GstElement *pipeline;
  GstElement *src;
  GstElement *videoconvert;
  GstElement *videoscale;
  GstElement *encoder;
  GstElement *capsfilter;
  GstElement *muxer;
  GstElement *sink;
  GstCaps *caps;
  GMainLoop *loop;
  gint ret = -1;

这里创建了一些元素:

  • pipeline 是 GStreamer 管道
  • src 是媒体的来源(WebCam)
  • videoconvert 用于转换视频
  • videoscale 用于是否需要缩放
  • encoder 用来对视频进行编码
  • capsfilter 允许我们更改视频的分辨率等
  • muxer 需要 muxer 将媒体接收到 TCP
  • sink 用于通过 tcp 发送媒体
  • caps 用于设置将传递给 capsfilter 的上限
  • loop 是 GStreamer 主循环
  • ret 基本上是退出代码

接下来我们需要初始化 GStreamer 和 pipeline,我们还将设置源头为用户的网络摄像头。

gst_init(NULL, NULL);

pipeline = gst_pipeline_new("pipeline");

src = gst_element_factory_make("autovideosrc", "autovideosrc");


if (!src)
{
    g_printerr("Failed to create src\n");

    goto no_src;
}

这里已经初始化了 GStreamer 并创建了一个新的管道。我们还将源设置为 autovideosrc 和 autoaudiosrc,它们可以检测到你的网络摄像头和麦克风。

如果由于某种原因我们无法获取源(没有网络摄像头/麦克风),应用程序将停止。

接下来我们将创建 videoconvert/videoscale 元素:

videoconvert = gst_element_factory_make("videoconvert", "videoconvert");
  
if (!videoconvert)
{
    g_printerr("Failed to create videoconvert\n");

    goto no_videoconvert;
}

videoscale = gst_element_factory_make("videoscale", "videoscale");
  
if (!videoscale)
{ 
	g_printerr("Failed to create videoscale\n");

	goto no_videoscale;
}

接着创建 caps 过滤器:

capsfilter = gst_element_factory_make("capsfilter", "capsfilter");
  
if (!capsfilter)
{ 
	g_printerr("Failed to create capsfilter\n");
 
	goto no_caps;
}
  
caps = gst_caps_from_string("video/x-raw,width=640,height=480");
g_object_set(capsfilter, "caps", caps, NULL);
gst_caps_unref(caps);

这里我们将视频的分辨率设置为VGA。这一步不是必须的,但我的很多工作都涉及VGA分辨率。请随意跳过这部分,或尝试使用不同的分辨率等。在设置了上限之后,我们就不再需要上限了,所以它是不需要的。

接下来我们可以创建其他需要的元素:

encoder = gst_element_factory_make("theoraenc", "theoraenc");
  
if (!encoder)
{ 
	g_printerr("Failed to create encoder\n");
    
	goto no_encoder;
  }
  
muxer = gst_element_factory_make("oggmux", "oggmux");
  
if (!muxer)
{ 
	g_printerr("Failed to create muxer\n");
    
	goto no_muxer;
}
  
sink = gst_element_factory_make("tcpserversink", "tcpserversink");
  
if (!sink)
{ 
	g_printerr("Failed to create sink\n");
    
	goto no_sink;
}

在这里,我们初始化将视频转换为 Theora 流的编码器,并创建将视频和音频混合到 ogg 文件中的混合器。然后我们最终创建了一个接收器,即 tcpserversink,它允许我们通过 tcp 流式传输文件。

最后,我们可以添加和链接这些元素,并最终开始流式传输!

g_object_set(sink, "host", HOST, NULL);
  
gst_bin_add_many(GST_BIN(pipeline), src, videoconvert, videoscale, capsfilter, encoder, muxer, sink, NULL);
gst_element_link_many(src, videoconvert, videoscale, capsfilter, encoder, muxer, sink, NULL);
  
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_print("Pipeline playing\n");
  
loop = g_main_loop_new(NULL, TRUE);
g_unix_signal_add(SIGINT, signal_handler, loop);
g_main_loop_run(loop);
g_main_loop_unref(loop);
  
gst_element_set_state(pipeline, GST_STATE_NULL);
g_print("Closed succesfully\n");

ret = 0;
goto no_src;

在这里我们设置 sink 的 host 参数,告诉它流向 localhost。之后,我们开始添加和连接元素,请注意GStreamer对元素的顺序非常严格。

然后我们将管道状态设置为 PLAYING,然后我们告诉它在用户预设 CTRL+R 时停止(这可能因你的操作系统等而异)

一旦用户结束进程,这些元素就会被清理掉。

最后,我们需要添加用于错误处理和清理任何元素的元素:

no_sink:
  gst_object_unref(sink);

no_muxer:
  gst_object_unref(muxer);

no_encoder:
  gst_object_unref(encoder);

no_caps:
  gst_object_unref(capsfilter);

no_videoscale:
  gst_object_unref(videoscale);

no_videoconvert:
  gst_object_unref(videoconvert);

no_src:
  gst_object_unref(pipeline);
  gst_deinit();

  return ret;

没有什么太有趣的事情,但清理一下很重要。

全部完成! 你可以用下面的命令构建源代码:

cc sender.cpp -o sender `pkg-config --cflags --libs gstreamer-1.0`

之后,可以通过以下方式运行该程序:

./sender

如果一切顺利的话,你应该可以通过TCP访问你的数据流了! Chrome似乎不喜欢TCP流,因为它们没有任何反应,但你可以使用其他浏览器,或者像我一样使用VLC。

如果你使用VLC,打开它,点击媒体,然后是网络。该流的地址是 “tcp://localhost:4953″。打开它,你应该能看到/听到流媒体。

结论

在这里我展示了如何用 GStreamer 和 C++ 来捕获用户的本地媒体,并通过 TCP 进行传输。

我希望这个教程对你有用,你可以尝试用不同的元素等进行实验。例如,用 RTMP 代替 TCP 。

该项目的源代码:https://github.com/ethand91/gstreamer-samples。

本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/24688.html

(0)

相关推荐

发表回复

登录后才能评论