2016-07-23 37 views
0

Die tatsächliche gst-Version ist 1.8.1.Streaming-Audio mit gstreamer 1.0 decodieren und auf die Wellenformdaten zugreifen?

Derzeit habe ich Code, der einen Gstreamer codierten Stream empfängt und es über meine Soundkarte abspielt. Ich möchte es ändern, um meiner Anwendung stattdessen Zugriff auf die unkomprimierten Rohdaten zu geben. Dies sollte zu einem Array von ganzzahligen Sound - Samples führen, und wenn ich sie plotten würde, würde ich die Audio - Wellenform sehen (zB wäre ein perfekter Ton eine schöne Sinuswelle), und wenn ich das neueste Array an die das letzte, das ich durch einen Rückruf erhalten habe, würde ich keine Diskontinuität sehen.

Dies ist der aktuelle Wiedergabe Code: https://github.com/lucasw/audio_common/blob/master/audio_play/src/audio_play.cpp

Ich glaube, ich brauche die alsasink zu einem appsink zu ändern, und ein Callback-Einrichtung, die das neueste Stück von Audio erhalten wird, nachdem es durch den Decoder bestanden hat. Dies wird von https://github.com/jojva/gst-plugins-base/blob/master/tests/examples/app/appsink-src.c angepasst:

_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); 

Und dann gibt es den Rückruf:

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); 
    } 

Kann ich die Daten in diesem Rückruf erhalten? Was soll ich mit dem GstFlowReturn machen? Wenn das Daten an ein anderes Pipeline-Element weitergibt, möchte ich das nicht tun, ich würde es lieber dort hinbringen und fertig sein.

https://github.com/lucasw/audio_common/blob/appsink/audio_process/src/audio_process.cpp

Ist die genau zu diesem Rückruf übergeben gpointer Daten, was ich will (Umwandlung in einen gint16 Array?), Oder sonst wie kann ich umwandeln und Zugang?

Antwort

0

Ich kann die Daten aus dem modifizierten Callback unten interpretieren (es gibt ein Skript, das es auf den Bildschirm plottet), es sieht aus wie signierte 16-Bit-Samples im Array uint8.

Ich bin nicht klar über den richtigen Rückgabewert für den Rückruf, gibt es eine cb_need_data Callback-Setup an anderer Stelle im Code, der die ganze Zeit mit diesem Code ausgelöst wird.

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

Die GstFlowReturn ist lediglich ein Rückgabewert für die zugrundeliegenden Basisklassen. Wenn Sie dort einen Fehler zurückgeben würden, stoppt die Pipeline wahrscheinlich, weil ... nun, es gab einen kritischen Fehler.

Die cb_need_data-Ereignisse werden von Ihrem appsrc-Element ausgelöst. Dies kann bei Bedarf als Drosselmechanismus verwendet werden. Da Sie den appsrc wahrscheinlich in einem reinen Push-Modus verwenden (sobald etwas am appsink ankommt, schieben Sie es in den appsrc), können Sie diese ignorieren. Sie deaktivieren diese Ereignisse auch explizit für das appsrc-Element. (Oder benutzen Sie den noch?)

Das Datenformat im Puffer hängt von den Caps ab, auf die der Decoder und die Appsink abgestimmt haben. Das ist normalerweise das vom Decoder bevorzugte Format. Sie können dieses Format je nach Decoder steuern oder in das von Ihnen bevorzugte Format konvertieren. sich lohnen kann das Format zu überprüfen, ist Float32 nicht ungewöhnlich, dass ..

I Art vergessen, was Ihre eigentliche Frage war, ich habe Angst ..

+0

Dank! Ich aktualisiere gerade manuell auf Float32, aber das wäre viel weniger spröde, wenn ich Einstellungen dafür hätte, dass es für mich erledigt wird. –