如何使用alsa snd-aloop与gstreamer?

时间:2017-06-12 14:00:15

标签: c gstreamer raspbian alsa pulseaudio

总体目标是我想在我的RPi上用aplay(" aplay example.mp3")播放音轨,输出音频循环回到gstreamer程序。然后该程序进行频谱分析。

我已经将频谱分析工作在静态文件上,并将此代码作为源代码:

data.source = gst_element_factory_make ("uridecodebin", "source");  
g_object_set (data.source, "uri", "file:///home/pi/example.mp3", NULL);  

ofc 我想使用我的RPi的整体输出作为程序的源,但我不知道如何。我知道我需要将音频从输出环回到输入,我发现snd-aloop看起来很有希望。问题是我还不知道如何使用它。我试着这样做:

data.source = gst_element_factory_make(" alsasrc"," source");
  g_object_set(data.source," device",XXX,NULL);

其中XXX =

  1. " alsa_output.platform-snd_aloop.0.analog-stereo.monitor"
  2. " HW:1"
  3. " HW:0"
  4. 错误 - >试图处理元素接收器,但它处于READY而不是NULL状态。在删除最终引用[...]

    之前,需要将Elements显式设置为NULL状态

    加分问题:是否可以将音频管道传输到gstreamer程序中?类似于:" aplay example.mp3> gstreamerCprogram"

    以下是代码:

    #include <gst/gst.h>
    
    #define AUDIOFREQ 32000
    
    /* Structure to contain all our information, so we can pass it to callbacks */
    typedef struct _CustomData {
      GstElement *pipeline;
      GstElement *source;
      GstElement *convert;
      GstElement *sink;
    } CustomData;
    
    /* Handler for the pad-added signal */
    static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);
    
    static gboolean message_handler (GstBus *bus, GstMessage *message, gpointer data){
    
        if(message->type == GST_MESSAGE_EOS){
            g_printerr("EOS\n");
        }
        if(message->type == GST_MESSAGE_ELEMENT){
            const GstStructure *s = gst_message_get_structure (message);
            const gchar *name = gst_structure_get_name(s);
    
            if(strcmp(name, "spectrum") == 0){
                const GValue *magnitudes;
                gdouble freq;
    
                magnitudes = gst_structure_get_value (s,"magnitude");
                int i = 0;            
                for(i = 0; i < 20; ++i){
                    freq = (gdouble)((32000/2) * i + 32000 / 4 / 20);
                    if(freq > 10000){
                    g_printerr("%f\n",freq);
                    }else{
                        g_printerr("|");
                    }
                }
    
            }
    
    
            }
    
    }
    
    int main(int argc, char *argv[]) {
      CustomData data;
      GstCaps *caps;
      GstElement *spectrum;
      GstBus *bus;
      GstMessage *msg;
      GstStateChangeReturn ret;
      gboolean terminate = FALSE;
    
      /* Initialize GStreamer */
      gst_init (&argc, &argv);
    
      //____________________________HERE IS THE PROBLEM________________________
      //data.source = gst_element_factory_make ("uridecodebin", "source");
      //g_object_set (data.source, "uri", "file:///home/pi/example.mp3", NULL);
    
      data.source = gst_element_factory_make ("alsasrc", "source");
      g_object_set(data.source, "device", "alsa_output.platform-snd_aloop.0.analog-stereo.monitor",NULL);
    
      //____________________________HERE ENDS THE PROBLEM________________________
    
      data.convert = gst_element_factory_make ("audioconvert", "convert");
      data.sink = gst_element_factory_make ("autoaudiosink", "sink");
      spectrum = gst_element_factory_make ("spectrum", "spectrum");
      caps = gst_caps_new_simple ("audio/x-raw", "rate",G_TYPE_INT, AUDIOFREQ, NULL);
    
      //SET SOME VARIABLES ON SPECTRUM
      g_object_set (G_OBJECT (spectrum), "bands", 20, "post-messages", TRUE, "message-phase", TRUE, NULL);   
    
      /* Create the empty pipeline */
      data.pipeline = gst_pipeline_new ("test-pipeline");
    
      if (!data.pipeline || !data.source || !data.convert || !data.sink || !caps || !spectrum) {
        g_printerr ("Not all elements could be created.\n");
        return -1;
      }
    
      /* Build the pipeline. Note that we are NOT linking the source at this
       * point. We will do it later. */
      gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert , spectrum,data.sink, NULL);
      if (!gst_element_link_many (data.convert, spectrum, data.sink, NULL)) {
        g_printerr ("Elements could not be linked.\n");
        gst_object_unref (data.pipeline);
        return -1;
      }
    
      /* Connect to the pad-added signal */
      g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);
    
      /* Start playing */
      ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
      if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr ("Unable to set the pipeline to the playing state.\n");
        gst_object_unref (data.pipeline);
        return -1;
      }
    
      GMainLoop *loop;
    
      /* Listen to the bus */
      bus = gst_element_get_bus (data.pipeline);
      gst_bus_add_watch(bus, message_handler, NULL);
      loop = g_main_loop_new (NULL,FALSE);
      g_main_loop_run(loop); 
    
      /* Free resources */
      gst_object_unref (bus);
      gst_element_set_state (data.pipeline, GST_STATE_NULL);
      gst_object_unref (data.pipeline);
      return 0;
    }
    
    /* This function will be called by the pad-added signal */
    static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {
      GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");
      GstPadLinkReturn ret;
      GstCaps *new_pad_caps = NULL;
      GstStructure *new_pad_struct = NULL;
      const gchar *new_pad_type = NULL;
    
      g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));
    
      /* If our converter is already linked, we have nothing to do here */
      if (gst_pad_is_linked (sink_pad)) {
        g_print ("  We are already linked. Ignoring.\n");
        goto exit;
      }
    
      /* Check the new pad's type */
      new_pad_caps = gst_pad_query_caps (new_pad, NULL);
      new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
      new_pad_type = gst_structure_get_name (new_pad_struct);
      if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {
        g_print ("  It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
        goto exit;
      }
    
      /* Attempt the link */
      ret = gst_pad_link (new_pad, sink_pad);
      if (GST_PAD_LINK_FAILED (ret)) {
        g_print ("  Type is '%s' but link failed.\n", new_pad_type);
      } else {
        g_print ("  Link succeeded (type '%s').\n", new_pad_type);
      }
    
    exit:
      /* Unreference the new pad's caps, if we got them */
      if (new_pad_caps != NULL)
        gst_caps_unref (new_pad_caps);
    
      /* Unreference the sink pad */
      gst_object_unref (sink_pad);
    }
    

0 个答案:

没有答案