在本教程中,将向你展示如何使用本地的 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