#include <stdlib.h>
#include <gst/gst.h>
#include <gst/net/gstnetclientclock.h>

#define PIPELINE "rtspsrc location=rtsp://84.88.40.158:8554/test ntp-time-source=3 buffer-mode=4 ntp-sync=1 latency=40 ! rtph264depay ! h264parse ! avdec_h264 ! fakesink sync=1 qos=1 name=sink"

typedef struct Data_ {
  GstClock *client_clock1;
  GstClock *client_clock2;
  GstPipeline *pipeline1;
  GstPipeline *pipeline2;
} Data;


void print_last_pts (GstBin *pipeline, GstClock *clock);
void polling_thread (Data *data);

void
print_last_pts (GstBin *pipeline, GstClock *clock)
{
    GstElement *sink;
    GstSample *sample;
    GstBuffer *buffer;

    sink = gst_bin_get_by_name (pipeline, "sink");
    g_object_get (sink, "last-sample", &sample, NULL);
    gst_object_unref(sink);
    if (sample) {
        buffer = gst_sample_get_buffer(sample);
        g_print ("%s: %" GST_TIME_FORMAT " Current: %" GST_TIME_FORMAT "\n",
                GST_OBJECT_NAME (pipeline),
                GST_TIME_ARGS (GST_BUFFER_PTS(buffer)),
                GST_TIME_ARGS (gst_clock_get_time(clock)));
        gst_sample_unref(sample);
    }
}

void
polling_thread (Data *data)
{
    while (1) {
        g_usleep (10000);
        print_last_pts (GST_BIN(data->pipeline1), data->client_clock1);
        print_last_pts (GST_BIN(data->pipeline2), data->client_clock2);
    }
}

gint
main (gint argc, gchar * argv[])
{
  GMainLoop *loop;
  gchar *host;
  guint16 port;
  Data data;
  GError *error = NULL;

  gst_init (&argc, &argv);

  if (argc < 3) {
    g_print ("Usage: netclock-client <host> <port>\n");
    return 1;
  }

  host = argv[1];
  port = atoi (argv[2]);

  data.client_clock1 = gst_net_client_clock_new (NULL, host, port, 0);
  data.client_clock2 = gst_net_client_clock_new (NULL, host, port, 0);
  if (data.client_clock1 == NULL || data.client_clock2 == NULL) {
    g_printerr ("Failed to create network clock clients\n");
    return 1;
  }
  gst_clock_wait_for_sync(data.client_clock1, 30 * GST_SECOND);
  gst_clock_wait_for_sync(data.client_clock2, 30 * GST_SECOND);

  data.pipeline1 = GST_PIPELINE (gst_parse_launch(PIPELINE, &error));
  if (error) {
      g_print("ERROR: %s", error->message);
      g_error_free(error);
  }
  gst_pipeline_use_clock (data.pipeline1, data.client_clock1);
  gst_pipeline_set_latency (data.pipeline1, 500 * GST_MSECOND);
  data.pipeline2 = GST_PIPELINE (gst_parse_launch(PIPELINE, NULL));
  gst_pipeline_use_clock (data.pipeline2, data.client_clock2);
  gst_pipeline_set_latency (data.pipeline2, 500 * GST_MSECOND);

  gst_element_set_state(GST_ELEMENT(data.pipeline1), GST_STATE_PLAYING);
  gst_element_set_state(GST_ELEMENT(data.pipeline2), GST_STATE_PLAYING);

  g_thread_new ("Polling thread", (GThreadFunc)polling_thread, &data);
  loop = g_main_loop_new (NULL, FALSE);

  g_main_loop_run (loop);

  /* cleanup */
  g_main_loop_unref (loop);
  gst_element_set_state(GST_ELEMENT(data.pipeline1), GST_STATE_NULL);
  gst_element_set_state(GST_ELEMENT(data.pipeline2), GST_STATE_NULL);

  gst_object_unref (data.pipeline1);
  gst_object_unref (data.pipeline2);

  return 0;
}
