#include <gst/gst.h>
#include <gst/pbutils/pbutils.h>
#include <gst/pbutils/encoding-profile.h>

static GstElement *pipeline, *uridecodebin, *encodebin, *sink;

static void
bus_message_cb (GstBus * bus, GstMessage * message, GMainLoop * mainloop)
{
  switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR:
      g_print ("ERROR\n");
      gst_bus_set_flushing (bus, TRUE);
      g_main_loop_quit (mainloop);
      break;
    case GST_MESSAGE_EOS:
      g_print ("EOS\n");
      g_main_loop_quit (mainloop);
      break;
    default:
      break;
  }
}

static void
pad_added_cb (GstElement * uridecodebin, GstPad * pad, gpointer user_data)
{
  GstCaps *caps;
  GstStructure *s;
  const gchar *name;
  GstPad *sinkpad;

  g_print ("pad-added\n");

  caps = gst_pad_get_caps (pad);
  s = gst_caps_get_structure (caps, 0);
  name = gst_structure_get_name (s);

  g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad);
  if (g_str_has_prefix (name, "audio/")) {
    gst_pad_link (pad, sinkpad);
  } else if (g_str_has_prefix (name, "video/")) {
    GstElement *videoflip;
    GstPad *tmp;

    videoflip = gst_element_factory_make ("videoflip", NULL);
    gst_bin_add (GST_BIN (pipeline), videoflip);
    gst_element_sync_state_with_parent (videoflip);

    tmp = gst_element_get_static_pad (videoflip, "sink");
    gst_pad_link (pad, tmp);
    gst_object_unref (tmp);
    tmp = gst_element_get_static_pad (videoflip, "src");
    gst_pad_link (tmp, sinkpad);
    gst_object_unref (tmp);
  } else {
    g_assert_not_reached ();
  }

  gst_object_unref (sinkpad);
  gst_caps_unref (caps);
}

int
main (int argc, char **argv)
{
  GMainLoop *loop;
  GstBus *bus;
  GstCaps *caps;
  GstEncodingContainerProfile *containerprofile;

  gst_init (NULL, NULL);

  pipeline = gst_pipeline_new ("pipeline");
  uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
  encodebin = gst_element_factory_make ("encodebin", NULL);
  sink = gst_element_factory_make ("filesink", NULL);
  gst_bin_add_many (GST_BIN (pipeline), uridecodebin, encodebin, sink, NULL);

  caps = gst_caps_new_simple ("video/x-matroska", NULL);
  containerprofile =
      gst_encoding_container_profile_new ("mkv", NULL, caps, NULL);
  gst_caps_unref (caps);

  caps = gst_caps_new_simple ("video/x-vp8", NULL);
  gst_encoding_container_profile_add_profile (containerprofile,
      (GstEncodingProfile *) gst_encoding_video_profile_new (caps, NULL, NULL, 0));
  gst_caps_unref (caps);

  caps = gst_caps_new_simple ("audio/x-vorbis", NULL);
  gst_encoding_container_profile_add_profile (containerprofile,
      (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL, NULL, 0));
  gst_caps_unref (caps);

  g_object_set (encodebin, "profile", containerprofile, NULL);
  gst_encoding_profile_unref (containerprofile);

  g_signal_connect (uridecodebin, "pad-added", G_CALLBACK (pad_added_cb), NULL);
  g_object_set (uridecodebin, "uri", "file:///home/slomo/Desktop/test.ogg", NULL);

  g_object_set (sink, "location", "/tmp/test.ogg", NULL);
  gst_element_link_pads (encodebin, "src", sink, "sink");

  loop = g_main_loop_new (NULL, FALSE);
  bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
  gst_bus_add_signal_watch (bus);
  g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), 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);
  gst_object_unref (pipeline);
  g_main_loop_unref (loop);

  return 0;
}
