2016-07-23 126 views
0

实际的gst版本是1.8.1。使用gstreamer 1.0解码流音频并访问波形数据?

目前我有接收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

我可以从下面的修改回调中解释数据(有一个脚本将它绘制到屏幕上),它看起来像是在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); 
    } 
    } 

https://github.com/lucasw/audio_common/tree/appsink

1

的GstFlowReturn仅仅是用于底层的基类返回值。如果你会返回一个错误,那么管道很可能会停止,因为......出现严重错误。

cb_need_data事件由您的appsrc元素触发。如果需要,这可以用作节流机制。由于您可能以纯推模式使用appsrc(只要有东西到达appsink,就会将其推送到appsrc),您可以忽略它们。您还显式禁用appsrc元素上的这些事件。 (或者你仍然使用那个?)

缓冲区中的数据格式取决于解码器和appsink达成一致的上限。这通常是解码器的首选格式。根据解码器的不同,您可能会对此格式有所控制或将其转换为您的首选格式。可能是值得的检查格式,浮点32并不是少见..

我有点忘了您的实际问题是什么,我怕..

+0

谢谢!我目前正在手动转换为Float32,但如果我可以设置它来为我完成它,那么这将变得更加脆弱。 –