#include <gst/gst.h>

GstElement *video_encoder;

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 *err;

      gst_message_parse_error (msg, &err, &debug);
      g_printerr ("Debugging info: %s\n", (debug) ? debug : "none");
      g_free (debug);

      g_print ("Error: %s\n", err->message);
      g_error_free (err);

      g_main_loop_quit (loop);

      break;
    }
    default:
      break;
  }
  return TRUE;
}

void sighandle (gint signo)
{
	GstPad *pad, *peerpad;
	pad = gst_element_get_static_pad (video_encoder, "src");
	peerpad = gst_pad_get_peer (pad);

	gst_object_unref (pad);
	gst_pad_send_event (peerpad, gst_event_new_eos());
	gst_object_unref (peerpad);
}

GstPadProbeReturn probe_cb (GstPad *pad, GstPadProbeInfo *info)
{
	return GST_PAD_PROBE_DROP;
}

gint
main (gint argc, gchar * argv[])
{
  GstElement *videotestsrc, *mux, *sink, *pipeline;
	GstPad *pad;
  GMainLoop *loop;
  GstBus *bus;
  guint bus_watch_id;

  gst_init (&argc, &argv);

	videotestsrc = gst_element_factory_make ("videotestsrc", NULL);
	video_encoder = gst_element_factory_make ("x264enc", NULL);
	mux = gst_element_factory_make ("avimux", NULL);
	sink = gst_element_factory_make ("fakesink", NULL);

	g_object_set (sink, "dump", TRUE, NULL);

	pipeline = gst_pipeline_new (NULL);

	gst_bin_add_many (GST_BIN (pipeline), mux, sink,
			videotestsrc, video_encoder, NULL);
	gst_element_link_many (videotestsrc, video_encoder, mux, sink, NULL);

	pad = gst_element_get_static_pad (video_encoder, "src");
	gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCK,
			(GstPadProbeCallback) probe_cb, NULL, NULL);

	gst_object_unref (pad);

  /* create and event loop and feed gstreamer bus mesages to it */
  loop = g_main_loop_new (NULL, FALSE);

  bus = gst_element_get_bus (pipeline);
  bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
  g_object_unref (bus);

	signal (SIGINT, sighandle);

  /* start play back and listed to events */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  g_main_loop_run (loop);

  /* cleanup */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  g_object_unref (pipeline);
  g_source_remove (bus_watch_id);
  g_main_loop_unref (loop);

  return 0;
}
