2016-02-10 3 views
1

Я хочу декодировать аудиофайл и хранить значения PCM/int в массиве. Для этого я использую gstreamer и giostreamsink, что дает мне GMemoryOutputStream. До сих пор так хорошо, но как я могу теперь получить доступ или выполнить цикл через GMemoryOutputStream?Как получить доступ к данным из GMemoryOutputStream

То, что я сделал, чтобы получить gpointer:

gpointer out_data = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(stream));

но что я могу сделать сейчас с этим gpointer? Как я могу получить доступ к данным потока?

Полный код, который я до сих пор:

#include <string> 
#include <stdio.h> 
#include <gst/gst.h> 
#include <gio/gio.h> 
#include <boost/thread.hpp> 

static void on_pad_added(GstElement *decodebin, 
         GstPad *pad, 
         gpointer data) { 
    GstElement *convert = (GstElement *) data; 

    GstCaps *caps; 
    GstStructure *str; 
    GstPad *audiopad; 

    audiopad = gst_element_get_static_pad(convert, "sink"); 
    if (GST_PAD_IS_LINKED(audiopad)) { 
     g_object_unref(audiopad); 
     return; 
    } 

    caps = gst_pad_get_caps(pad); 
    str = gst_caps_get_structure(caps, 0); 
    printf("here %s\n",gst_structure_get_name(str)); 
    if (!g_strrstr(gst_structure_get_name(str), "audio")) { 
     gst_caps_unref(caps); 
     gst_object_unref(audiopad); 
     return; 
    } 
    gst_caps_unref(caps); 
    gst_pad_link(pad, audiopad); 
    g_object_unref(audiopad); 
} 

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

int main (int argc, char **argv) { 
    gst_init(&argc, &argv); 

    GstElement *pipeline, *source, *decode, *sink, *convert; 
    int rate = 44100; 
    int channels = 1; 
    int depth = 16; 
    bool output_signed = true; 
    GMainLoop *loop; 
    GstBus *bus; 
    guint bus_watch_id; 
    GMemoryOutputStream *stream; 
    gpointer out_data; 

    // loop 
    loop = g_main_loop_new(NULL, false); 
    // pipeline 
    pipeline = gst_pipeline_new("test_pipeline"); 
    // sink 
    stream = G_MEMORY_OUTPUT_STREAM(g_memory_output_stream_new(NULL, 0, (GReallocFunc)g_realloc, (GDestroyNotify)g_free)); 
    sink = gst_element_factory_make ("giostreamsink", "sink"); 
    g_object_set(G_OBJECT(sink), "stream", stream, NULL); 
    // source 
    source = gst_element_factory_make("filesrc", "source"); 
    g_object_set(G_OBJECT(source), "location", "/home/sam/Desktop/audio/audio.wav", NULL); 
    // convert 
    convert = gst_element_factory_make("audioconvert", "convert"); 
    // decode 
    decode = gst_element_factory_make("decodebin", "decoder"); 
    // link decode to convert 
    g_signal_connect(decode, "pad-added", G_CALLBACK(on_pad_added), convert); 

    // bus 
    bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline)); 
    bus_watch_id = gst_bus_add_watch(bus, bus_call, loop); 
    gst_object_unref(bus); 

    // add elements into pipeline 
    gst_bin_add_many(GST_BIN(pipeline), source, decode, convert, sink, NULL); 
    // link source to decode 
    gst_element_link(source, decode); 
    // caps 
    GstCaps *caps; 
    caps = gst_caps_new_simple("audio/x-raw-int", 
           "rate", G_TYPE_INT, rate, 
           "channels", G_TYPE_INT, channels, 
           "width", G_TYPE_INT, depth, 
           "depth", G_TYPE_INT, depth, 
           "signed", G_TYPE_BOOLEAN, output_signed, 
           NULL); 
    // link convert to sink 
    gst_element_link_filtered(convert, sink, caps); 
    gst_caps_unref(caps); 
    // start playing 
    gst_element_set_state(GST_ELEMENT(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); 

    // get data 
    g_print("get data\n"); 
    out_data = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(stream)); 

    unsigned long size = g_memory_output_stream_get_size(G_MEMORY_OUTPUT_STREAM(stream)); 
    unsigned long sizeData = g_memory_output_stream_get_data_size(G_MEMORY_OUTPUT_STREAM(stream)); 
    std::cout << "stream size: " << size << std::endl; 
    std::cout << "stream data size: " << sizeData << std::endl; 

    for (int i = 0; i < 5; ++i) { 
//  std::cout << out_data[i] << std::endl; // not working 
    } 
    return 0; 
} 

ответ

1

Я решил проблему, мне пришлось забрасывать gpointer к gint16*:

std::vector<int16_t> data; 
for (unsigned long i = 0; i < sizeData/2; ++i) { 
    data.push_back(((gint16*)out_data)[i]); 
} 

Отливка должна быть изменена, в зависимости от глубина, которую вы используете, например глубину 8 и без знака guint8* и изменить также предел for loop.

Полный код для тех, кто заинтересован:

#include <string> 
#include <stdio.h> 
#include <gst/gst.h> 
#include <gio/gio.h> 
#include <boost/thread.hpp> 

static void on_pad_added(GstElement *decodebin, 
         GstPad *pad, 
         gpointer data) { 
    GstElement *convert = (GstElement *) data; 

    GstCaps *caps; 
    GstStructure *str; 
    GstPad *audiopad; 

    audiopad = gst_element_get_static_pad(convert, "sink"); 
    if (GST_PAD_IS_LINKED(audiopad)) { 
     g_object_unref(audiopad); 
     return; 
    } 

    caps = gst_pad_get_caps(pad); 
    str = gst_caps_get_structure(caps, 0); 
    printf("here %s\n",gst_structure_get_name(str)); 
    if (!g_strrstr(gst_structure_get_name(str), "audio")) { 
     gst_caps_unref(caps); 
     gst_object_unref(audiopad); 
     return; 
    } 
    gst_caps_unref(caps); 
    gst_pad_link(pad, audiopad); 
    g_object_unref(audiopad); 
} 

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

int main (int argc, char **argv) { 
    gst_init(&argc, &argv); 

    GstElement *pipeline, *source, *decode, *sink, *convert; 
    int rate = 44100; 
    int channels = 1; 
    int depth = 16; 
    bool output_signed = true; 
    GMainLoop *loop; 
    GstBus *bus; 
    guint bus_watch_id; 
    GMemoryOutputStream *stream; 
    gpointer out_data; 

    // loop 
    loop = g_main_loop_new(NULL, false); 
    // pipeline 
    pipeline = gst_pipeline_new("test_pipeline"); 
    // sink 
    stream = G_MEMORY_OUTPUT_STREAM(g_memory_output_stream_new(NULL, 0, (GReallocFunc)g_realloc, (GDestroyNotify)g_free)); 
    sink = gst_element_factory_make ("giostreamsink", "sink"); 
    g_object_set(G_OBJECT(sink), "stream", stream, NULL); 
    // source 
    source = gst_element_factory_make("filesrc", "source"); 
    g_object_set(G_OBJECT(source), "location", "/home/sam/Desktop/audio/audio.wav", NULL); 
    // convert 
    convert = gst_element_factory_make("audioconvert", "convert"); 
    // decode 
    decode = gst_element_factory_make("decodebin", "decoder"); 
    // link decode to convert 
    g_signal_connect(decode, "pad-added", G_CALLBACK(on_pad_added), convert); 

    // bus 
    bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline)); 
    bus_watch_id = gst_bus_add_watch(bus, bus_call, loop); 
    gst_object_unref(bus); 

    // add elements into pipeline 
    gst_bin_add_many(GST_BIN(pipeline), source, decode, convert, sink, NULL); 
    // link source to decode 
    gst_element_link(source, decode); 
    // caps 
    GstCaps *caps; 
    caps = gst_caps_new_simple("audio/x-raw-int", 
           "rate", G_TYPE_INT, rate, 
           "channels", G_TYPE_INT, channels, 
           "width", G_TYPE_INT, depth, 
           "depth", G_TYPE_INT, depth, 
           "signed", G_TYPE_BOOLEAN, output_signed, 
           NULL); 
    // link convert to sink 
    gst_element_link_filtered(convert, sink, caps); 
    gst_caps_unref(caps); 
    // start playing 
    gst_element_set_state(GST_ELEMENT(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); 

    // get data 
    g_print("get data\n"); 
    out_data = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(stream)); 

    unsigned long size = g_memory_output_stream_get_size(G_MEMORY_OUTPUT_STREAM(stream)); 
    unsigned long sizeData = g_memory_output_stream_get_data_size(G_MEMORY_OUTPUT_STREAM(stream)); 
    std::cout << "stream size: " << size << std::endl; 
    std::cout << "stream data size: " << sizeData << std::endl; 

    // access data and store in vector 
    std::vector<int16_t> data; 
    for (unsigned long i = 0; i < sizeData/2; ++i) { 
     data.push_back(((gint16*)out_data)[i]); 
    } 
    return 0; 
} 
Смежные вопросы