Using GStreamer to play raw PCM-data
<p>Ok, I have written some code below that is supposed to open and audio output device, and whenever actual PCM-data is available I would call Sound_WriteFrame() and pile up more data to be played.</p>

<p>The data is raw, with no headers, so when I call Sound_Open() I pass this information to let GStreamer know what kind of data that will arrive.</p>

<p>This code does not work - Frankly I have no idea what I am <em>doing</em>, I find GStreamer a bit difficult to work with, I would hope that could change eventually.</p>

<p>I am using GStreamer 1.0. Help is appreciated.</p>

<pre><code>#include &lt;gstreamer-1.0/gst/gst.h&gt;
#include &lt;gstreamer-1.0/gst/gstelement.h&gt;
#include &lt;gtk/gtk.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

typedef struct _sound_t {
    GstElement *source, *sink, *pipeline;
    GMemoryInputStream *giostream;
    GstPad *sourcepad;
    GstCaps *gcaps;
    int bDeviceOpen;
} SOUND_CTX;

int Sound_Close(SOUND_CTX *p){
    printf("Closing\n");
    gst_element_set_state(p-&gt;pipeline, GST_STATE_NULL);
    return 1;
}

void Sound_SetState(SOUND_CTX *p, GstState state){
    GstStateChangeReturn r = gst_element_set_state(p-&gt;pipeline, state);
    switch(r){
        case GST_STATE_CHANGE_FAILURE: printf("GST_STATE_CHANGE_FAILURE\n"); break;
        case GST_STATE_CHANGE_SUCCESS: printf("GST_STATE_CHANGE_SUCCESS\n"); break;
        case GST_STATE_CHANGE_ASYNC: printf("GST_STATE_CHANGE_ASYNC\n"); break;
        case GST_STATE_CHANGE_NO_PREROLL: printf("GST_STATE_CHANGE_NO_PREROLL\n"); break;
        default: printf("Unknown state\n"); break;
    }
    return;
}

int Sound_Open(SOUND_CTX *p, int nSamplesPerSec, int nChannels){

    p-&gt;source = gst_element_factory_make("giostreamsrc", "source");
    p-&gt;giostream = G_MEMORY_INPUT_STREAM(g_memory_input_stream_new());
    g_object_set(G_OBJECT(p-&gt;source), "stream", G_INPUT_STREAM(p-&gt;giostream), NULL);
    p-&gt;sourcepad = gst_element_get_static_pad(p-&gt;source, "src");

    p-&gt;gcaps = gst_caps_new_simple(
        "audio/x-raw",
        "rate", G_TYPE_INT, nSamplesPerSec,
        "channels", G_TYPE_INT, nChannels,
        "width", G_TYPE_INT, 16,
        "depth", G_TYPE_INT, 16,
        "signed", G_TYPE_BOOLEAN, TRUE,
        NULL
    );

    gst_pad_set_caps(p-&gt;sourcepad, p-&gt;gcaps);
    gst_object_unref(p-&gt;sourcepad);

    p-&gt;sink = gst_element_factory_make("alsasink", "sink");
    p-&gt;pipeline = gst_pipeline_new("pipeline_name");
    gst_bin_add_many(GST_BIN(p-&gt;pipeline), p-&gt;source, p-&gt;sink, NULL);
    gst_element_link_many(p-&gt;source, p-&gt;sink, NULL);

    Sound_SetState(p, GST_STATE_PLAYING);

    return 1;
}

int Sound_WriteFrame(SOUND_CTX *p, void *lpData, unsigned int size){
    g_memory_input_stream_add_data(
        G_MEMORY_INPUT_STREAM(p-&gt;giostream),
        lpData, size, NULL
    );
    return 0;
}

int timer_callback(const void *data){
    g_main_loop_quit((GMainLoop *)data);
    return FALSE;
}



int main(int argc, char *argv[]){
    gst_init(&amp;argc, &amp;argv);
    GMainLoop *loop = NULL;
    SOUND_CTX a;
    memset(&amp;a, 0x00, sizeof(SOUND_CTX));
    if(Sound_Open(&amp;a, 44100, 2)){
        FILE *handle;
        unsigned char tmp[4096];
        if((handle = fopen("test.pcm", "rb")) != NULL){
            while(fread(tmp, 1, sizeof(tmp), handle) == sizeof(tmp)){
                Sound_WriteFrame(&amp;a, tmp, sizeof(tmp));
            }
            fclose(handle);
        }
    }

    loop = g_main_loop_new(NULL, FALSE);
    g_timeout_add(5500, (GSourceFunc)timer_callback, loop);
    g_main_loop_run(loop);
    Sound_Close(&amp;a);
    g_main_loop_unref(loop);

    return 0;
}
</code></pre>

<p>Ok, so here is an updated source, there is however no sound coming out of the speakers</p>

<pre><code>#include &lt;gstreamer-1.0/gst/gst.h&gt;
#include &lt;gstreamer-1.0/gst/gstelement.h&gt;
#include &lt;gstreamer-1.0/gst/app/gstappsrc.h&gt;
#include &lt;gtk/gtk.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

typedef struct _sound_t {
    GstElement *sink, *pipeline;
    GstAppSrc *src;
    GstCaps *pcm_caps;
} SOUND_CTX;

int Sound_Close(SOUND_CTX *p){
    printf("Closing\n");
    gst_element_set_state(p-&gt;pipeline, GST_STATE_NULL);
    return 1;
}

void Sound_SetState(SOUND_CTX *p, GstState state){
    GstStateChangeReturn r = gst_element_set_state(p-&gt;pipeline, state);
    switch(r){
        case GST_STATE_CHANGE_FAILURE: printf("GST_STATE_CHANGE_FAILURE\n"); break;
        case GST_STATE_CHANGE_SUCCESS: printf("GST_STATE_CHANGE_SUCCESS\n"); break;
        case GST_STATE_CHANGE_ASYNC: printf("GST_STATE_CHANGE_ASYNC\n"); break;
        case GST_STATE_CHANGE_NO_PREROLL: printf("GST_STATE_CHANGE_NO_PREROLL\n"); break;
        default: printf("Unknown state\n"); break;
    }
    return;
}

int Sound_Open(SOUND_CTX *p, int nSamplesPerSec, int nChannels){

    p-&gt;pipeline = gst_pipeline_new("pipeline_name");
    p-&gt;sink = gst_element_factory_make("alsasink", "sink");

    p-&gt;src = (GstAppSrc*) gst_element_factory_make("appsrc", "source");
    gst_app_src_set_stream_type(p-&gt;src, GST_APP_STREAM_TYPE_STREAM);

    // I am hardcoding the format, channels, and rate for now
    p-&gt;pcm_caps = gst_caps_from_string("audio/x-raw,format=S16LE,rate=44100,channels=2");
    gst_app_src_set_caps(p-&gt;src, p-&gt;pcm_caps);

    gst_bin_add_many(GST_BIN(p-&gt;pipeline), (GstElement*)p-&gt;src, p-&gt;sink, NULL);
    gst_element_link_many((GstElement*)p-&gt;src, p-&gt;sink, NULL);

    Sound_SetState(p, GST_STATE_PLAYING);

    return 1;
}

int Sound_WriteFrame(SOUND_CTX *p, void *lpData, unsigned int size){
    GstBuffer *buf = NULL;
    void *lpHeapData = NULL;
    if((lpHeapData = g_malloc(size)) == NULL) return 0;
    memcpy(lpHeapData, lpData, size);
    buf = gst_buffer_new_wrapped(lpHeapData, size);
    if(buf == NULL){
        g_free(lpHeapData);
        return 0;
    }
    gst_app_src_push_buffer(p-&gt;src, buf);
    return 0;
}

int timer_callback(const void *data){
    g_main_loop_quit((GMainLoop *)data);
    return FALSE;
}



int main(int argc, char *argv[]){
    gst_init(&amp;argc, &amp;argv);
    GMainLoop *loop = NULL;
    SOUND_CTX a;
    memset(&amp;a, 0x00, sizeof(SOUND_CTX));
    if(Sound_Open(&amp;a, 44100, 2)){
        FILE *handle;
        unsigned char tmp[4096];
        if((handle = fopen("test.pcm", "rb")) != NULL){
            while(fread(tmp, 1, sizeof(tmp), handle) == sizeof(tmp)){
                Sound_WriteFrame(&amp;a, tmp, sizeof(tmp));
            }
            fclose(handle);
        }
    }

    loop = g_main_loop_new(NULL, FALSE);
    g_timeout_add(5500, (GSourceFunc)timer_callback, loop);
    g_main_loop_run(loop);
    Sound_Close(&amp;a);
    g_main_loop_unref(loop);

    return 0;
}
</code></pre>