#include <stdio.h>
#include <gst/gst.h>


/* BUS function for ERROR */

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


static gboolean link_source_element_with_filter (GstElement *element1,
GstElement *element2)

{
/* CAPS to be link:
* 'video/x-raw, format=(string)YUY2, width=(int)800, height=(int)600, framerate=5/1'
* */

gboolean link_ok;
GstCaps *caps;

caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "NV12",
"width", G_TYPE_INT, 1280,
"height", G_TYPE_INT, 720,
"framerate", GST_TYPE_FRACTION, 30, 1,
NULL);

link_ok = gst_element_link_filtered (element1, element2, caps);
gst_caps_unref (caps);

if (!link_ok) {
g_warning ("Failed to link element1 and element2!(v4l2src->vpe)");
}
return link_ok;

}


void
link_to_multiplexer(
    GstElement *tolink_element,
    GstElement *mux)
{
    GstCaps          *pad_caps =NULL;
    GstPad           *pad;
    GstPad           *tolink_pad;
    GstPadLinkReturn  ret;

    tolink_pad = gst_element_get_static_pad(tolink_element, "src");
    pad_caps   = gst_pad_query_caps(tolink_pad, NULL);
    pad        = gst_element_get_compatible_pad(mux, tolink_pad, pad_caps);
    gst_caps_unref(pad_caps);

    ret = gst_pad_link(tolink_pad, pad);
    gst_object_unref(GST_OBJECT(pad));
    g_print("A new pad %s was created and linked to %s\n", gst_pad_get_name(tolink_pad), gst_pad_get_name(pad));
}


/* Main function does atual processing */

int main (int argc , char *argv[])

//gst-launch-1.0 -e v4l2src io-mode=4 device=/dev/video1 ! 'video/x-raw, format=(string)NV12, width=(int)1280, height=(int)720, framerate=(fraction)30/1' ! vpe num-input-buffers=8 ! queue ! ducatih264enc ! queue ! h264parse ! qtmux ! filesink location=x.mov
{
    GstElement *pipeline, *src, *convert, *q1, * enc, *q2, *parse, *q3, *mux, *sink;
    GstBus *bus;
    GstMessage *msg;


    gst_init (&argc, &argv);

    /* Create the empty pipeline */
    pipeline = gst_pipeline_new ("test-pipeline");

    /* Create the elements */
    src = gst_element_factory_make ("v4l2src", "video_source");
    g_object_set(G_OBJECT(src), "device", "/dev/video1", NULL);
    g_object_set(G_OBJECT(src), "io-mode", 4, NULL);
    g_object_set (G_OBJECT (src), "num-buffers", 1000,  NULL);
    convert = gst_element_factory_make ("vpe", "convert");
    g_object_set (G_OBJECT (convert), "num-input-buffers", 8,  NULL);
    q1 = gst_element_factory_make ("queue", "q1");
    enc = gst_element_factory_make ("ducatih264enc", "enc");
    q2 = gst_element_factory_make ("queue", "q2");
    parse = gst_element_factory_make ("h264parse", "parser");
    q3 = gst_element_factory_make ("queue", "q3");
    mux = gst_element_factory_make ("qtmux", "mux");
    sink = gst_element_factory_make ("filesink", "sink");
    g_object_set (G_OBJECT (sink), "location", "/home/root/x.mov",  NULL);




  
   gst_bin_add_many (GST_BIN (pipeline), src, convert, q1, enc, q2, parse, q3, mux, sink, NULL);

 
    
  link_source_element_with_filter (src, convert);
  //gst_element_link_pads (src, "src", convert, "sink");
  gst_element_link_pads (convert, "src", q1, "sink");
  gst_element_link_pads (q1, "src", enc, "sink");
  gst_element_link_pads (enc, "src", parse, "sink");
  gst_element_link_pads (parse, "src", q3, "sink");
  link_to_multiplexer (q3,  mux);
  gst_element_link_pads (mux, "src", sink, "sink");




    /* Start playing the pipeline */
    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    /* Wait until error or EOS */
    bus = gst_element_get_bus (pipeline);
    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);



    /* Free resources */
    if (msg != NULL)
    {
        gst_message_unref (msg);
    }
    gst_object_unref (bus);
    gst_element_set_state (pipeline, GST_STATE_NULL);

    gst_object_unref (pipeline);
    return 0;
}



