如何在 C 中使用 gstreamer 播放音频?
How to play audio with gstreamer in C?
我正在尝试使用 C 中的 Gstreamer 播放音频。
我正在使用笔记本电脑,Ubuntu 16.
为了玩游戏,我使用了这个管道,它正在运行:
gst-launch-1.0 filesrc location=lambo-engine.mp3 ! decodebin ! audioconvert ! autoaudiosink
但是当我把它转换成 C:
GstElement *pipeline, *source, *decode, *audioconvert, *sink;
GMainLoop *loop;
GstBus *bus;
GstMessage *msg;
int main(int argc, char *argv[]) {
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Create the elements */
source = gst_element_factory_make("filesrc", NULL);
decode = gst_element_factory_make("decodebin", NULL);
audioconvert = gst_element_factory_make("audioconvert", NULL);
sink = gst_element_factory_make("autoaudiosink", NULL);
// Set parameters for some elements
g_object_set(G_OBJECT(source), "location", "lambo-engine.mp3", NULL);
/* Create the empty pipeline */
pipeline = gst_pipeline_new ("pipeline");
/* Build the pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, decode, audioconvert, sink, NULL);
if (gst_element_link_many(source, decode, audioconvert, sink, NULL) != TRUE){
g_error("Failed to link save elements!");
gst_object_unref (pipeline);
return -1;
}
/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
bus = gst_element_get_bus (pipeline);
gst_object_unref (bus);
/* now run */
g_main_loop_run (loop);
/* Free pipeline */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT(pipeline));
return 0;
}
我可以成功构建它。但是当我运行它的时候,它return错误can't link elements:
** (example:2516): ERROR **: 22:59:42.310: Failed to link save elements!
Trace/breakpoint trap (core dumped)
请大家帮我找出错误。
非常感谢
Gstreamer 以作为元素列表的管道为中心。元素有垫来交换数据。在您的示例中,decodebin 有一个输出垫,而 audioconvert 有一个输入垫。在流水线的开始,需要 linked.
这是双方就数据格式以及其他一些信息达成一致的时候,例如谁负责计时,也许还有更多格式细节。
你的问题是因为 decodebin
实际上不是一个真正的元素。在 运行 时,当 filesrc 启动时,它告诉 decodebin 它有什么 pad,decodebin 在内部创建元素来处理该文件。
例如:
filesrc location=test.mp4 ! decodebin
将按以下顺序 运行:
- 延迟 link 因为类型未知
- 启动文件
- filesrc 说“正在尝试 link,我有一个格式为 MP4(h264)
的便笺簿
- decodebin 看到这个请求,然后动态创建一个可以处理 mp4 文件的 h264 解析元素
- decodebin 现在有足够的信息来描述它的 pad,它 link 是管道的其余部分
- 视频开始播放
因为您使用 c 来执行此操作,所以您 link 在 filesrc 加载文件之前的管道。这意味着 decodebin 在启动时不知道它的格式,因此无法 link.
要解决此问题,您有两种选择:
1.) 将 decodebin 换成只支持一种类型的东西。例如,如果您知道您的视频将始终是带有 h264 的 mp4,您可以使用 h264parse 而不是 decodebin。因为 h264parse 只适用于一种格式,它一开始就知道它是填充格式,并且能够 link 没有问题。
2.) 重新实现智能延迟 linking。您可以阅读文档以获取更多信息,但您可以延迟 linking 管道,并在有足够信息时安装回调以完成 linking。这就是 gst-launch-1.0
在幕后所做的。这样做的好处是更加灵活:decodebin 支持的任何东西都可以工作。缺点是它要复杂得多,涉及到您的大量工作,而且更脆弱。如果你能摆脱它,请尝试修复 1
我正在尝试使用 C 中的 Gstreamer 播放音频。 我正在使用笔记本电脑,Ubuntu 16.
为了玩游戏,我使用了这个管道,它正在运行:
gst-launch-1.0 filesrc location=lambo-engine.mp3 ! decodebin ! audioconvert ! autoaudiosink
但是当我把它转换成 C:
GstElement *pipeline, *source, *decode, *audioconvert, *sink;
GMainLoop *loop;
GstBus *bus;
GstMessage *msg;
int main(int argc, char *argv[]) {
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Create the elements */
source = gst_element_factory_make("filesrc", NULL);
decode = gst_element_factory_make("decodebin", NULL);
audioconvert = gst_element_factory_make("audioconvert", NULL);
sink = gst_element_factory_make("autoaudiosink", NULL);
// Set parameters for some elements
g_object_set(G_OBJECT(source), "location", "lambo-engine.mp3", NULL);
/* Create the empty pipeline */
pipeline = gst_pipeline_new ("pipeline");
/* Build the pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, decode, audioconvert, sink, NULL);
if (gst_element_link_many(source, decode, audioconvert, sink, NULL) != TRUE){
g_error("Failed to link save elements!");
gst_object_unref (pipeline);
return -1;
}
/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
bus = gst_element_get_bus (pipeline);
gst_object_unref (bus);
/* now run */
g_main_loop_run (loop);
/* Free pipeline */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT(pipeline));
return 0;
}
我可以成功构建它。但是当我运行它的时候,它return错误can't link elements:
** (example:2516): ERROR **: 22:59:42.310: Failed to link save elements! Trace/breakpoint trap (core dumped)
请大家帮我找出错误。
非常感谢
Gstreamer 以作为元素列表的管道为中心。元素有垫来交换数据。在您的示例中,decodebin 有一个输出垫,而 audioconvert 有一个输入垫。在流水线的开始,需要 linked.
这是双方就数据格式以及其他一些信息达成一致的时候,例如谁负责计时,也许还有更多格式细节。
你的问题是因为 decodebin
实际上不是一个真正的元素。在 运行 时,当 filesrc 启动时,它告诉 decodebin 它有什么 pad,decodebin 在内部创建元素来处理该文件。
例如:
filesrc location=test.mp4 ! decodebin
将按以下顺序 运行:
- 延迟 link 因为类型未知
- 启动文件
- filesrc 说“正在尝试 link,我有一个格式为 MP4(h264) 的便笺簿
- decodebin 看到这个请求,然后动态创建一个可以处理 mp4 文件的 h264 解析元素
- decodebin 现在有足够的信息来描述它的 pad,它 link 是管道的其余部分
- 视频开始播放
因为您使用 c 来执行此操作,所以您 link 在 filesrc 加载文件之前的管道。这意味着 decodebin 在启动时不知道它的格式,因此无法 link.
要解决此问题,您有两种选择:
1.) 将 decodebin 换成只支持一种类型的东西。例如,如果您知道您的视频将始终是带有 h264 的 mp4,您可以使用 h264parse 而不是 decodebin。因为 h264parse 只适用于一种格式,它一开始就知道它是填充格式,并且能够 link 没有问题。
2.) 重新实现智能延迟 linking。您可以阅读文档以获取更多信息,但您可以延迟 linking 管道,并在有足够信息时安装回调以完成 linking。这就是 gst-launch-1.0
在幕后所做的。这样做的好处是更加灵活:decodebin 支持的任何东西都可以工作。缺点是它要复杂得多,涉及到您的大量工作,而且更脆弱。如果你能摆脱它,请尝试修复 1