实际的gst版本是1.8.1。
目前我的代码接收gstreamer编码流并通过我的声卡播放。我想修改它,让我的应用程序访问原始的未压缩音频数据。这应该会产生一个整数声音样本数组,如果我要绘制它们,我会看到音频波形(例如一个完美的音调将是一个很好的正弦波),如果我要将最新的数组追加到最后一个收到的回调我不会看到任何不连续性。
这是当前的播放代码: https://github.com/lucasw/audio_common/blob/master/audio_play/src/audio_play.cpp
我认为我需要将alsasink更改为appsink,并设置一个回调,它将在通过解码器后获得最新的音频块。这改编自https://github.com/jojva/gst-plugins-base/blob/master/tests/examples/app/appsink-src.c:
_sink = gst_element_factory_make("appsink", "sink");
g_object_set (G_OBJECT (_sink), "emit-signals", TRUE,
"sync", FALSE, NULL);
g_signal_connect (_sink, "new-sample",
G_CALLBACK (on_new_sample_from_sink), this);
然后有回调:
static GstFlowReturn
on_new_sample_from_sink (GstElement * elt, gpointer data)
{
RosGstProcess *client = reinterpret_cast<RosGstProcess*>(data);
GstSample *sample;
GstBuffer *app_buffer, *buffer;
GstElement *source;
/* get the sample from appsink */
sample = gst_app_sink_pull_sample (GST_APP_SINK (elt));
buffer = gst_sample_get_buffer (sample);
/* make a copy */
app_buffer = gst_buffer_copy (buffer);
/* we don't need the appsink sample anymore */
gst_sample_unref (sample);
/* get source and push new buffer */
source = gst_bin_get_by_name (GST_BIN (client->_sink), "app_source");
return gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
}
我可以获得该回调中的数据吗?我应该怎么做GstFlowReturn?如果那是将数据传递给另一个管道元素我不想这样做,我宁愿把它拿到那里完成。
https://github.com/lucasw/audio_common/blob/appsink/audio_process/src/audio_process.cpp
是否将gpointer数据传递给我想要的回调(转换为gint16数组?),或者我如何转换和访问它?
答案 0 :(得分:1)
GstFlowReturn只是底层基类的返回值。如果你在那里返回一个错误,那么管道可能会停止,因为......那里有一个严重的错误。
cb_need_data事件由您的appsrc元素触发。如果需要,这可以用作限制机制。由于您可能在纯推模式下使用appsrc(一旦到达appsink,您将其推送到appsrc)您可以忽略这些。您还在appsrc元素上显式禁用这些事件。 (或者你仍然使用那个吗?)
缓冲区中的数据格式取决于解码器和appsink达成一致的上限。这通常是解码器首选格式。您可以根据解码器对此格式进行一些控制,或将其转换为您的首选格式。可能值得检查格式,Float32并不罕见..
我有点忘记了你的实际问题,我很害怕......
答案 1 :(得分:0)
我可以解释下面修改后的回调中的数据(有一个脚本将其绘制到屏幕上),看起来它是在uint8数组中签名的16位样本。
我不清楚回调的正确返回值,代码中的其他地方有一个cb_need_data回调设置,它会随着这段代码一直被触发。
static void // GstFlowReturn
on_new_sample_from_sink (GstElement * elt, gpointer data)
{
RosGstProcess *client = reinterpret_cast<RosGstProcess*>(data);
GstSample *sample;
GstBuffer *buffer;
GstElement *source;
/* get the sample from appsink */
sample = gst_app_sink_pull_sample (GST_APP_SINK (elt));
buffer = gst_sample_get_buffer (sample);
GstMapInfo map;
if (gst_buffer_map (buffer, &map, GST_MAP_READ))
{
audio_common_msgs::AudioData msg;
msg.data.resize(map.size);
// TODO(lucasw) copy this more efficiently
for (size_t i = 0; i < map.size; ++i)
{
msg.data[i] = map.data[i];
}
gst_buffer_unmap (buffer, &map);
client->_pub.publish(msg);
}
}