之前文章《使用GStreamer将网络摄像头数据传输到RTMP服务器》展示了如何将本地网络摄像头流式传输到 RTMP 服务器,这次我将向您展示如何使用 C++ 和 GStreamer 播放上述示例(或任何其他 RTMP 流)。
要求
- C++知识
- GStreamer基础知识
- 安装了 GStreamer 开发库
编写程序
导入,打开一个名为“main.cpp”的文件并添加以下一行以导入 GStreamer:
#include <gst/gst.h>
接下来我们需要添加一个回调方法来监听 “on_pad_added “事件,与发送流不同的是,当你接收流时,你不会立即得到流,这将给你在尝试链接元素时带来链接器问题。
当接收时,最好添加一个回调,当流被实际接收时运行。像这样:
static void on_pad_added(GstElement *element, GstPad* pad, gpointer user_data)
{
GstPad *sinkpad;
GstElement *decoder = (GstElement *)user_data;
sinkpad = gst_element_get_static_pad(decoder, "sink");
gst_pad_link(pad, sinkpad);
gst_object_unref(sinkpad);
}
以上将在添加 pad 时运行,并将元素添加到另一个元素 sinkpad(在本例中为 h264parse)。
接下来我们将创建一个主要方法并创建管道所需的元素等:
int main(int argc, char *argv[])
{
GstElement *pipeline;
GstElement *source;
GstElement *demuxer;
GstElement *parser;
GstElement *decoder;
GstElement *converter;
GstElement *sink;
GstBus *bus;
GstMessage *message;
GstStateChangeReturn ret;
上面只是创建了元素,接下来需要通过以下方式初始化 GStreamer:
gst_init(&argc, &argv);
最好在尝试初始化和其他 GStreamer 元素之前调用上面的方法。
接下来我们将通过以下方式初始化其他元素和管道:
source = gst_element_factory_make("rtmpsrc", NULL);
demuxer = gst_element_factory_make("flvdemux", NULL);
parser = gst_element_factory_make("h264parse", NULL);
decoder = gst_element_factory_make("avdec_h264", NULL);
converter = gst_element_factory_make("videoconvert", NULL);
sink = gst_element_factory_make("autovideosink", NULL);
pipeline = gst_pipeline_new("pipeline");
接下来我们将检查元素是否已正确创建,这是通过以下 if 语句完成的,如果无法创建元素,我们将结束程序:
if (!pipeline || !source || !demuxer || !parser || !decoder || !sink)
{
g_printerr("Not all elements could be created.\n");
return -1;
}
接下来我们通过以下方式将元素添加到管道中:
gst_bin_add_many(GST_BIN(pipeline), source, demuxer, parser, decoder, converter, sink, NULL);
最后,我们现在可以通过以下方式将所有元素链接在一起:
if (!gst_element_link(source, demuxer))
{
g_printerr("Elements could not be linked\n");
gst_object_unref(pipeline);
return -1;
}
if (!gst_element_link_many(parser, decoder, converter, sink, NULL))
{
g_printerr("Element could not be linked\n");
gst_object_unref(pipeline);
return -1;
}
分离器和解析器将通过“on_pad_added”方法链接,所以我们不在这里做,在这里做可能会导致链接器错误,因为还没有流。
接下来我们将上面的“on_pad_added”回调添加到解复用器:
g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), parser);
使用以下内容设置 rtmpsrc url(注意,确保将 RTMP url 替换为您自己的)
g_object_set(source, "location", "rtmp://localhost:1935/stream/video", NULL);
最后,通过将其设置为播放状态来启动 GStreamer 管道:
ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
要检查更改是否成功,我们可以使用以下 if 语句:
if (ret == GST_STATE_CHANGE_FAILURE)
{
g_printerr("Unable to set pipeline to the playing state\n");
gst_object_unref(pipeline);
return -1;
}
如果失败,程序将停止。
接下来我们还需要监听任何错误消息和/或 EOS 消息,这可以通过以下方式完成:
bus = gst_element_get_bus(pipeline);
message = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GstMessageType(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));
if (message != NULL)
{
GError * error;
gchar *debug_info;
switch (GST_MESSAGE_TYPE(message))
{
case GST_MESSAGE_ERROR:
gst_message_parse_error(message, &error, &debug_info);
g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(message->src), error->message);
g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error(&error);
g_free(debug_info);
break;
case GST_MESSAGE_EOS:
g_print("End of stream");
break;
default:
g_printerr("Unknown message received\n");
break;
}
gst_message_unref(message);
}
上面只是监听任何错误和/或 EOS 消息并显示日志信息,根据您要完成的任务,您可能需要实现更多逻辑。例如,如果您想将 RTMP 保存到视频文件。
最后我们通过以下方式清理代码:
gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
完毕!😃 现在我们需要构建项目,我将向您展示如何通过 CMakeLists 来构建项目。
创建 CMakeLists 文件
要构建项目,需要创建一个 CMakeLists.txt 文件,创建该文件并添加以下内容:
cmake_minimum_required(VERSION 3.10)
project(rtmprecv)
set(CMAKE_CXX_STANDARD 14)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GST REQUIRED gstreamer-1.0)
include_directories(${GST_INCLUDE_DIRS})
add_executable(rtmprecv main.cpp)
target_link_libraries(rtmprecv ${GST_LIBRARIES})
上面只是将代码与开发GStreamer依赖项链接起来,现在我们可以真正构建项目了!
这可以通过以下命令完成:
mkdir build && cd build
cmake ..
make
运行 make 后,会在构建目录中看到“rtmprecv”可执行文件。😆
运行示例
要运行该示例,需要一个 RTMP 源,这可以是我之前写的示例或你自己的 RTMP 源。请注意,如果您使用我之前的示例,则需要将 url 更改为以下“rtmp://localhost:1935/stream/video”。
./rtmprecv
如果一切顺利,应该能够在本地看到 RTMP 流。😎
结论
在本教程中,我向您展示了如何创建接收和显示 RTMP 流的 GStreamer/C++ 程序。我希望它对你有帮助,就像我制作它的乐趣一样。
如果您有任何问题或改进等,请在评论中告诉我,一如既往,你可以在我的存储库中找到示例代码:https://github.com/ethand91/rtmp-to-local
作者:Ethan Denvir
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。