2014-03-24 54 views
2

我正在寫一個C應用程序,它使用gstreamer從麥克風錄製音頻。 我希望能夠解析該音頻並顯示該音頻的可視化效果。我如何使用gstreamer解析音頻原始數據記錄器?

我有以下代碼:

#include <gst/gst.h> 
#include <glib.h> 


static gboolean 
bus_call (GstBus  *bus, 
     GstMessage *msg, 
     gpointer data) 
{ 
GMainLoop *loop = (GMainLoop *) data; 

switch (GST_MESSAGE_TYPE (msg)) { 

case GST_MESSAGE_EOS: 
    g_print ("End of stream\n"); 
    g_main_loop_quit (loop); 
    break; 

case GST_MESSAGE_ERROR: { 
    gchar *debug; 
    GError *error; 

    gst_message_parse_error (msg, &error, &debug); 
    g_free (debug); 

    g_printerr ("Error: %s\n", error->message); 
    g_error_free (error); 

    g_main_loop_quit (loop); 
    break; 
} 
default: 
    break; 
} 

return TRUE; 
} 


void create_loop() 
{ 
GMainLoop *loop; 

GstElement *pipeline, *source, *sink; 
GstBus *bus; 
guint bus_watch_id; 

/* Initialisation */ 

loop = g_main_loop_new (NULL, FALSE); 



/* Create gstreamer elements */ 
pipeline = gst_pipeline_new ("audio-player"); 
source = gst_element_factory_make ("alsasrc",  "alsa-source"); 
sink  = gst_element_factory_make ("autoaudiosink", "audio-output"); 

if (!pipeline || !source || !sink) { 
g_printerr ("One element could not be created. Exiting.\n"); 
return; 
} 

g_object_set (G_OBJECT(source),"device","hw:3,0",NULL); 

/* we add a message handler */ 
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); 
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); 
gst_object_unref (bus); 

gst_bin_add_many (GST_BIN (pipeline), 
       source, sink, NULL); 

gst_element_link (source, sink); 
gst_element_set_state (pipeline, GST_STATE_PLAYING); 


/* Iterate */ 
g_print ("Running...\n"); 
g_main_loop_run (loop); 


/* Out of the main loop, clean up nicely */ 
g_print ("Returned, stopping playback\n"); 
gst_element_set_state (pipeline, GST_STATE_NULL); 

g_print ("Deleting pipeline\n"); 
gst_object_unref (GST_OBJECT (pipeline)); 
g_source_remove (bus_watch_id); 
g_main_loop_unref (loop); 

} 

int main(int argc, char** argv) { 
    gst_init(&argc,&argv); 
    create_loop(); 
    return 0; 
} 

,你可以在我的代碼中看到我創建一個alsasrc和autoaudiosink。我測試過,我可以 正確聽取該設備。

我該如何寫一些東西來解析數據以創建可視化。

有關問題的任何信息,將不勝感激。

回答

2

appsink元素允許您從管道中獲取數據。

你有三個選擇:

我認爲第三個選項是最簡單和最有效的。

所以,只需將autoaudiosink替換爲appsink,註冊回調並處理其中的數據。

您可以在manual中閱讀關於appsrcappsink的一些信息。

2

您需要爲您的gsteamer應用程序創建一個「插件」或平板。 有關如何創建墊的完整說明: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/chapter-building-boiler.html#section-boiler-source

在大多數情況下,您需要使用gobject創建一個類。https://developer.gnome.org/gobject/stable/

方法如下:你https://developer.gnome.org/gobject/stable/chapter-gobject.html

而且至少需要:

/* Definition of structure storing data for this element. */ 
typedef struct _GstMyFilter { 
    GstElement element; 

    GstPad *sinkpad, *srcpad; 

    gboolean silent; 

} GstMyFilter; 


static GstStaticPadTemplate sink_factory = 
GST_STATIC_PAD_TEMPLATE (
    "sink", 
    GST_PAD_SINK, 
    GST_PAD_ALWAYS, 
    GST_STATIC_CAPS ("ANY") 
); 

//... likewise for your src 

static void 
gst_my_filter_class_init (GstMyFilterClass * klass) 
{ 
    GstElementClass *element_class = GST_ELEMENT_CLASS (klass); 

    //... 
    gst_element_class_set_static_metadata (element_klass, 
    "An example plugin", 
    "Example/FirstExample", 
    "Shows the basic structure of a plugin", 
     "your name <[email protected]>"); 

    gst_element_class_add_pad_template (element_class, 
    gst_static_pad_template_get (&src_factory)); 
    gst_element_class_add_pad_template (element_class, 
    gst_static_pad_template_get (&sink_factory)); 
} 

你還需要描述你的插件

static gboolean 
plugin_init (GstPlugin *plugin) 
{ 
    return gst_element_register (plugin, "my_filter", 
        GST_RANK_NONE, 
        GST_TYPE_MY_FILTER); 
} 

GST_PLUGIN_DEFINE (
    GST_VERSION_MAJOR, 
    GST_VERSION_MINOR, 
    my_filter, 
    "My filter plugin", 
    plugin_init, 
    VERSION, 
    "LGPL", 
    "GStreamer", 
    "http://gstreamer.net/" 
) 


static void 
gst_my_filter_init (GstMyFilter *filter) 
{ 
    /* pad through which data comes in to the element */ 
    filter->sinkpad = gst_pad_new_from_static_template (
    &sink_template, "sink"); 
    /* pads are configured here with gst_pad_set_*_function() */ 


    gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); 

    /* pad through which data goes out of the element */ 
    filter->srcpad = gst_pad_new_from_static_template (
    &src_template, "src"); 
    /* pads are configured here with gst_pad_set_*_function() */ 

    gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); 

    /* configure chain function on the pad before adding 
    * the pad to the element */ 
    gst_pad_set_chain_function (filter->sinkpad, 
     gst_my_filter_chain); 

    /* properties initial value */ 
    filter->silent = FALSE; 
} 

,你的魔法操作鏈

static GstFlowReturn 
gst_my_filter_chain (GstPad *pad, 
        GstObject *parent, 
      GstBuffer *buf) 
{ 
    GstMyFilter *filter = GST_MY_FILTER (parent); 

    if (!filter->silent) 
    g_print ("Have data of size %" G_GSIZE_FORMAT" bytes!\n", 
     gst_buffer_get_size (buf)); 

    return gst_pad_push (filter->srcpad, buf); 
} 

static gboolean 
gst_my_filter_sink_event (GstPad *pad, 
        GstObject *parent, 
        GstEvent *event) 
{ 
    GstMyFilter *filter = GST_MY_FILTER (parent); 

    switch (GST_EVENT_TYPE (event)) { 
    case GST_EVENT_CAPS: 
     /* we should handle the format here */ 
     break; 
    case GST_EVENT_EOS: 
     /* end-of-stream, we should close down all stream leftovers here */ 
     gst_my_filter_stop_processing (filter); 
     break; 
    default: 
     break; 
    } 

    return gst_pad_event_default (pad, parent, event); 
} 

static GstFlowReturn 
gst_my_filter_chain (GstPad *pad, 
      GstObject *parent, 
      GstBuffer *buf) 
{ 
    GstMyFilter *filter = GST_MY_FILTER (parent); 
    GstBuffer *outbuf; 

    outbuf = gst_my_filter_process_data (filter, buf); 
    gst_buffer_unref (buf); 
    if (!outbuf) { 
    /* something went wrong - signal an error */ 
    GST_ELEMENT_ERROR (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL)); 
    return GST_FLOW_ERROR; 
    } 

    return gst_pad_push (filter->srcpad, outbuf); 
} 

用例:

//... your code and elements init... 

//Creating your filter 
filter = gst_element_factory_make ("my_filter", "my_filter"); 

//Adding it 
gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL); 

//Linking it 
if (!gst_element_link_many (source, filter, sink, NULL)) { 
    g_print ("Failed to link one or more elements!\n"); 
    return -1; 
} 

//... here the rest of your code 

加成*有一個簡單的例子:http://siilo.dyndns.org/wiki/index.php/Creating_a_Plugin_template

相關問題