如何使用GStreamer播放PCM数据数组
How to play a PCM data array with GStreamer
我是gstreamer
的新手,我可以简单地使用gst-launch
来播放这样的PCM文件:
$ gst-launch-1.0 filesrc location=output.pcm ! audio/x-raw, format=S16LE,
channels=1, rate=16000 ! autoaudiosink
但是在我的应用程序中,我得到的是一个带有 PCM 原始数据的字符数组。谷歌之后,我知道我应该使用 appsrc
作为源,但测试代码根本没有输出。
是否有任何示例代码可以告诉我如何播放这个包含一个通道 16K PCM 原始数据的字符数组?
这里附上了我的测试代码:
std::ifstream file("output.pcm");
char data[22120];
file.read(data, 22120);
file.close();
std::cout << "read success";
GstElement *m_pipeline;
GstElement *m_source;
GMainLoop *m_loop;
GstBuffer *m_last_buffer;
GstElement *m_sink;
GstCaps *audioCaps;
gst_init(NULL, NULL);
audioCaps = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING, "S16LE", "rate", G_TYPE_INT, 16000,
"channels", G_TYPE_INT, 1, nullptr);
if (audioCaps == nullptr)
{
std::cout << "error" << std::endl;
return 0;
}
m_source = gst_element_factory_make("appsrc", "source");
m_sink = gst_element_factory_make("autoaudiosink", "sink");
m_pipeline = gst_pipeline_new("audio-pipeline");
m_loop = g_main_loop_new(NULL, FALSE);
gst_bin_add_many(GST_BIN(m_pipeline), m_source, m_sink, NULL);
gst_element_link_many(m_source, m_sink, NULL);
gst_app_src_set_caps(GST_APP_SRC(m_source), audioCaps);
gst_caps_unref(audioCaps);
GstBuffer *buffer = gst_buffer_new_allocate(NULL, 22120, NULL);
gst_buffer_fill(buffer, 0, data, 22120);
gst_app_src_push_buffer(GST_APP_SRC(m_source), buffer);
gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
g_main_loop_run(m_loop);
/* free resources */
gst_element_set_state(m_pipeline, GST_STATE_NULL);
gst_object_unref(m_pipeline);
第
1 步。要创建我自己的输入测试文件:
gst-launch-1.0 audiotestsrc num-buffers=10 ! audio/x-raw, channels=1, rate=16000, format=S16LE ! filesink location=out.raw
第 2 步。下面是一个示例应用程序:
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <stdio.h>
int main()
{
gst_init(NULL, NULL);
GstElement* p = gst_parse_launch("appsrc name=src ! audio/x-raw, channels=1, rate=16000, format=S16LE ! autoaudiosink", NULL);
GstElement* appsrc = gst_bin_get_by_name(GST_BIN(p), "src");
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(p));
gst_element_set_state(p, GST_STATE_PLAYING);
FILE* fp = fopen("out.raw", "rb");
for (int i = 0; i < 10; i++) {
gchar buf[2048];
fread(buf, 2048, 1, fp);
GstBuffer *buffer = gst_buffer_new_allocate(NULL, 2048, NULL);
gst_buffer_fill(buffer, 0, buf, 2048);
gst_app_src_push_buffer(GST_APP_SRC(appsrc), buffer);
}
gst_app_src_end_of_stream(GST_APP_SRC(appsrc));
gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS);
gst_element_set_state(p, GST_STATE_NULL);
gst_object_unref(bus);
gst_object_unref(appsrc);
gst_object_unref(p);
fclose(fp);
}
它通过使用gst_parse_launch()
简化了一些事情。完整的管道创建和上限设置。
进一步简化,创建的示例文件为 2048 字节 * 10 个块。您不需要知道原始块大小(只要它是样本对齐的 - 1 个通道和 16 位为 2 个字节)。我只是不想检查文件的 EOF。
基本上,我认为您应该在发送任何数据之前将管道置于 PLAY 状态。
相关文章:
- C++将文本文件中的数据读取到结构数组中
- 通过JNI传递数据数组的最快方法是什么
- C++数据文件、数组和计算赋值
- 使用指针访问数组中的对象数据成员
- C++ 使用存储在动态数组中的文本文件中的数据查找模式
- C++:__aligned(__alignof__) 导致字符数组数据出现问题?
- 很好的语法来获取对向量/数组数据的大小引用?
- 创建异构顶点数据数组的可移植方法
- 模板 使用数据数组调用函数时扩展参数包
- 如何在 c++ 和 java 之间通过 udp 有效地发送数据数组
- 如何使用模板函数从缓冲区(T* 数据数组)创建 cv::Mat
- 如何连接 2D 数据数组
- 如何使用GStreamer播放PCM数据数组
- P/Invoke使用C#和C++之间的双编组数据数组
- 如何在文件中保存/读取数据数组 (C++)
- Android & JNI 如何将 Byte[] 数据数组传递给 JNI 并取回 Byte []
- C++ 通过多次重复向量来构建数据数组
- 尝试使用pthreads访问共享数据数组时,出现“无法访问内存地址”错误
- Qt存储和访问大数据数组
- 在c++中初始化一些数据数组