/* gcc `pkg-config --libs --cflags gstreamer-0.10` gstrgb.c -o gstrgb */
#include <gst/gst.h>

#define FLT_BEFORE     1
#define CONVERT_TO_RGB 0

GstElement *pipeline = 0;
GstElement *vsink    = 0;

static void
handoff_cb(GstElement *fakesrc, GstBuffer  *buffer,
           GstPad     *pad, gpointer    user_data)
{
    GstQuery      *query;
    GstStructure  *structure;
    int width, height;

    g_print("Caps: %s\n", gst_caps_to_string(buffer->caps));

    structure = gst_caps_get_structure(GST_CAPS(buffer->caps), 0);
    gst_structure_get_int(structure, "width", &width);
    gst_structure_get_int(structure, "height", &height);

    g_print("Buffer size = %d. %d x %d x 4 = %d\n", GST_BUFFER_SIZE(buffer),
            width, height, width * height * 4);
}

static void
new_decoded_pad_cb(GstElement *decoder, GstPad     *new_pad,
                   gboolean    last,  gpointer    user_data)
{
    GstCaps *caps;
    gchar   *str;


    caps = gst_pad_get_caps(new_pad);
    str = gst_caps_to_string(caps);

    /* video stream */
    if (g_str_has_prefix(str, "video/")) {
        GstElement         *vsink;
        GstElement         *queue;
        GstElement         *conv, *flt;
        GstPad             *videopad;
        GstCaps            *filtercaps;

        queue       = gst_element_factory_make("queue", NULL);
        flt         = gst_element_factory_make("capsfilter", "filter");
        conv        = gst_element_factory_make("ffmpegcolorspace", "conv");
        vsink       = gst_element_factory_make("fakesink", "videosink");

        filtercaps = gst_caps_new_simple("video/x-raw-rgb",
                                         "bpp", G_TYPE_INT, 24,
                                         "endianness", G_TYPE_INT, G_BIG_ENDIAN,
                                         "depth", G_TYPE_INT, 32,
                                         "red_mask", G_TYPE_INT, 0x00FF0000,
                                         "green_mask", G_TYPE_INT, 0x0000FF00,
                                         "blue_mask", G_TYPE_INT, 0x000000FF,
                                         "framerate", GST_TYPE_FRACTION, 30, 1,
                                         NULL);
#if CONVERT_TO_RGB
        g_object_set(G_OBJECT(flt), "caps", filtercaps, NULL);
#endif
        gst_caps_unref(filtercaps);

#if FLT_BEFORE
        gst_bin_add_many(GST_BIN(pipeline), queue, flt, conv,
                         vsink, NULL);
        gst_element_link_many(queue, flt, conv, vsink, NULL);
#else
        gst_bin_add_many(GST_BIN(pipeline), queue, conv, flt,
                         vsink, NULL);
        gst_element_link_many(queue, conv, flt, vsink, NULL);
#endif

        videopad = gst_element_get_pad(queue, "sink");
        gst_pad_link(new_pad, videopad);
        gst_object_unref(videopad);

        g_print("vsink is %p\n", vsink);
        g_object_set(G_OBJECT(vsink), "signal-handoffs", TRUE, NULL);
        g_signal_connect(G_OBJECT (vsink), "handoff",
                         G_CALLBACK(handoff_cb), NULL);
    }
}

int main(int argc, char **argv)
{
    GMainLoop  *loop;
    GstElement *filesrc;
    GstElement *decodebin;


    gst_init(&argc, &argv);
    loop = g_main_loop_new(NULL, FALSE);

    if (argc != 2) {
        g_print("usage: %s <file>\n", argv[0]);
        exit(-1);
    }

    pipeline   = gst_pipeline_new("pipeline");
    filesrc    = gst_element_factory_make("filesrc", "source");
    g_object_set(G_OBJECT(filesrc), "location", argv[1], NULL);
    decodebin  = gst_element_factory_make("decodebin", "decoder");
    g_signal_connect(decodebin, "new-decoded-pad",
                     G_CALLBACK(new_decoded_pad_cb), NULL);

    gst_bin_add_many(GST_BIN(pipeline), filesrc, decodebin, NULL);
    gst_element_link(filesrc, decodebin);

    gst_element_set_state(pipeline, GST_STATE_PLAYING);

    g_main_loop_run(loop);

    /* cleanup */
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(GST_OBJECT(pipeline));

    return 0;
}
