/* gcc testcase.c `pkg-config --cflags --libs gstreamer-1.0 gstreamer-base-1.0` */
#include <gst/gst.h>
#include <gst/base/gstpushsrc.h>
#include <gst/base/gstbytewriter.h>

#define TYPE_DATA_TEST_SRC data_test_src_get_type()
G_DECLARE_FINAL_TYPE(DataTestSrc, data_test_src, , DATA_TEST_SRC, GstPushSrc)

struct _DataTestSrc
{
  GstPushSrc parent;
  GstClockTime next_timestamp;
};

G_DEFINE_TYPE (DataTestSrc, data_test_src, GST_TYPE_PUSH_SRC);

static GstStaticPadTemplate src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("text/x-raw"));

static void
data_test_src_init (DataTestSrc *self)
{
  GstBaseSrc *base = GST_BASE_SRC (self);

  gst_base_src_set_automatic_eos (base, FALSE);
  gst_base_src_set_live (base, TRUE);
  gst_base_src_set_format (base, GST_FORMAT_TIME);
}

static void
data_test_src_get_times (GstBaseSrc *src,
    GstBuffer *buffer,
    GstClockTime *start,
    GstClockTime *end)
{
  GstClockTime timestamp = GST_BUFFER_DTS (buffer);
  GstClockTime duration = GST_BUFFER_DURATION (buffer);

  *start = timestamp;
  *end = timestamp + duration;
}

static GstFlowReturn
data_test_src_create (GstPushSrc *src,
    GstBuffer **buffer)
{
  DataTestSrc *self = _DATA_TEST_SRC (src);
  GstByteWriter *bw;

  bw = gst_byte_writer_new ();
  gst_byte_writer_put_string_utf8 (bw, "I am a string!");

  *buffer = gst_byte_writer_free_and_get_buffer (bw);
  GST_BUFFER_DTS (*buffer) = self->next_timestamp;
  GST_BUFFER_PTS (*buffer) = self->next_timestamp;
  GST_BUFFER_DURATION (*buffer) = 0;

  self->next_timestamp += gst_util_uint64_scale_int (GST_SECOND, 60, 1);

  return GST_FLOW_OK;
}

static void
data_test_src_class_init (DataTestSrcClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstBaseSrcClass *base_src_class = GST_BASE_SRC_CLASS (klass);
  GstPushSrcClass *push_src_class = GST_PUSH_SRC_CLASS (klass);

  base_src_class->get_times = data_test_src_get_times;
  push_src_class->create = data_test_src_create;

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&src_pad_template));
}

int
main (int argc, char *argv[])
{
  g_autoptr(GstElement) pipeline;
  g_autoptr(GMainLoop) loop;
  GstElement *datatestsrc;
  GstElement *videotestsrc;
  GstElement *splitmuxsink;
  GstElement *matroskamux;
  GstElement *filesink;

  gst_init (&argc, &argv);

  pipeline = gst_pipeline_new (NULL);
  datatestsrc = g_object_new (TYPE_DATA_TEST_SRC, NULL);
  videotestsrc = gst_parse_bin_from_description (
      "videotestsrc ! capsfilter caps=\"video/x-raw, "
      "width=(int) 1920, height=(int) 1080, "
      "framerate=(fraction) 60/1\" ! x264enc", TRUE, NULL);
  splitmuxsink = gst_element_factory_make ("splitmuxsink", NULL);
  matroskamux = gst_element_factory_make ("matroskamux", NULL);
  filesink = gst_element_factory_make ("filesink", NULL);
  gst_bin_add_many (GST_BIN (pipeline), datatestsrc, videotestsrc, splitmuxsink,
      NULL);

  g_assert (gst_element_link_pads (datatestsrc, "src", splitmuxsink, "subtitle_%u"));
  g_assert (gst_element_link_pads (videotestsrc, "src", splitmuxsink, "video"));
  g_object_set (filesink, "location", "out.mkv", NULL);
  g_object_set (splitmuxsink, "muxer", matroskamux, "sink", filesink,
      "max-size-bytes", 1024, NULL);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (loop);

  gst_element_set_state (pipeline, GST_STATE_NULL);
}
