appsrc + decodebin

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

appsrc + decodebin

baldman88
Hi to everyone. Sorry for my English. I have tried to find answer to my question, but without any results. I need to decode mp3 data to raw PCM data. I tried to change example for stream from github, but made something wrong. I need to get data from external buffer (on the start the size of data in stream is unknown, but for test I read chunks of data from the file), next decode it with decodebin, and finaly push decoded RAW data to appsink. But for begin I tried to push RAW data to alsasink (it is much more easy to test). The problem is that instead of sound i hear some noise (something like a fast forward). It looks like that the every new buffer, readed on "need-data" signal, starts play imediately. I have tried to change different settings of appsrc and decodebin, but it have no any effect. What i do wrong?
Here is the code:

#include <fstream>
 
#include <gst/gst.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
 
 
#define BUF_SIZE 8192
 
std::ifstream inFile("in2.mp3", std::fstream::binary);
 
 
static void onNewPad(GstElement *decodebin, GstPad *pad, GstElement *userData)
{
    GstPad *newpad;
    newpad = gst_element_get_static_pad(GST_ELEMENT(userData), "sink");
    gst_pad_link(pad, newpad);
    g_object_unref(newpad);
}
 
 
static void onNeedData(GstAppSrc *appsrc, guint dataSize, GstElement *userData)
{
    char data[BUF_SIZE];
    inFile.read(data, BUF_SIZE);
    guint realSize = inFile.gcount();
    if (realSize  > 0)
    {
        GstBuffer *buffer;
        buffer = gst_buffer_new_and_alloc(realSize);
        gst_buffer_set_data(buffer, (guint8 *) data, realSize);
        gst_app_src_push_buffer(appsrc, buffer);
    }
    else
    {
        gst_app_src_end_of_stream(appsrc);
    }
}
 
 
static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
{
    GMainLoop *loop = (GMainLoop *) data;
    switch(GST_MESSAGE_TYPE(msg))
    {
        case GST_MESSAGE_EOS:
        {
            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(NULL, NULL);
    GMainLoop *loop;
    GstElement *appsrc;
    GstElement *alsasink;
    GstElement *decodebin;
    GstElement *pipeline;
 
    loop = g_main_loop_new(NULL, FALSE);
    appsrc = gst_element_factory_make("appsrc", "appsrc");
    alsasink = gst_element_factory_make("alsasink", "alsasink");
    decodebin = gst_element_factory_make("decodebin2", "decodebin");
    pipeline = gst_pipeline_new("pipeline");
 
    gst_bin_add_many(GST_BIN(pipeline), appsrc, decodebin, alsasink, NULL);
    gst_element_link_many(appsrc, decodebin, NULL);
 
    g_object_set(G_OBJECT(appsrc), "stream-type", GST_APP_STREAM_TYPE_STREAM, "format", GST_FORMAT_BYTES, "do-timestamp", FALSE, "is-live", TRUE, "min-percent", 20, "block", FALSE, "max-bytes", 1000000, NULL);
 
    g_object_set(G_OBJECT(decodebin), "high-percent", 90, "low-percent", 10, "max-size-buffers", 0, "max-size-time", 0, "max-size-bytes", 0, "use-buffering", TRUE, NULL);
 
    g_signal_connect(G_OBJECT(decodebin), "pad-added", G_CALLBACK(onNewPad), alsasink);
 
    g_signal_connect(G_OBJECT(appsrc), "need-data", G_CALLBACK(onNeedData), appsrc);
 
    GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
    gst_bus_add_watch (bus, bus_call, loop);
    gst_object_unref(bus);
 
    gst_element_set_state(pipeline, GST_STATE_PLAYING);
    g_main_loop_run(loop);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    g_main_loop_quit(loop);
    return 0;
}

Best regards.