static void
process_video (GstMerger * merger)
{
  GST_DEBUG_OBJECT (merger, "Task function begin");

beg:

  GST_DEBUG_OBJECT (merger, "Task function loop");

  if ((volatile int) merger->stop) {
    GST_INFO_OBJECT (merger, "Task goto end");
    goto end;
  }


  g_mutex_trylock (&merger->task_lock);
  GST_DEBUG_OBJECT (merger, "Task waiting for cond");
  g_cond_wait (&merger->task_cond, &merger->task_lock);

  GST_DEBUG_OBJECT (merger, "Task processing");

  while (1) {
    GstBuffer *buf_l = NULL;
    GstBuffer *buf_r = NULL;

    if (GST_PAD_IS_EOS (merger->sinkl_pad)) {
      goto beg;
    }
    if (GST_PAD_IS_EOS (merger->sinkr_pad)) {
      goto beg;
    }

    if (g_queue_is_empty (&merger->bufs_l)) {
      GST_DEBUG_OBJECT (merger, "No L buffers left");
      goto beg;
    }
    if (g_queue_is_empty (&merger->bufs_r)) {
      GST_DEBUG_OBJECT (merger, "No R buffers left");
      goto beg;
    }

    GST_OBJECT_LOCK (merger);

    GstBuffer *buf_l0 = g_queue_peek_head (&merger->bufs_l);
    GstBuffer *buf_l1 = g_queue_peek_tail (&merger->bufs_l);
    GstBuffer *buf_r0 = g_queue_peek_head (&merger->bufs_r);
    GstBuffer *buf_r1 = g_queue_peek_tail (&merger->bufs_r);

    GST_DEBUG_OBJECT (merger, "L0: %" GST_PTR_FORMAT, buf_l0);
    GST_DEBUG_OBJECT (merger, "L1: %" GST_PTR_FORMAT, buf_l1);
    GST_DEBUG_OBJECT (merger, "R0: %" GST_PTR_FORMAT, buf_r0);
    GST_DEBUG_OBJECT (merger, "R1: %" GST_PTR_FORMAT, buf_r1);

    if (GST_BUFFER_PTS (buf_l0) >= GST_BUFFER_PTS (buf_r0)
        && GST_BUFFER_PTS (buf_l0) <= GST_BUFFER_PTS (buf_r0)
        + GST_BUFFER_DURATION (buf_r0)) {
      buf_l = g_queue_pop_head (&merger->bufs_l);
      buf_r = g_queue_pop_head (&merger->bufs_r);
    } else if (GST_BUFFER_PTS (buf_r0) >= GST_BUFFER_PTS (buf_l0)
        && GST_BUFFER_PTS (buf_r0) <= GST_BUFFER_PTS (buf_l0)
        + GST_BUFFER_DURATION (buf_l0)) {
      buf_l = g_queue_pop_head (&merger->bufs_l);
      buf_r = g_queue_pop_head (&merger->bufs_r);
    } else if (GST_BUFFER_PTS (buf_r0) + GST_BUFFER_DURATION (buf_r0) <
        GST_BUFFER_PTS (buf_l0)) {
      buf_r = g_queue_pop_head (&merger->bufs_r);
      gst_buffer_unref (buf_r);
      buf_r = NULL;
      GST_DEBUG_OBJECT (merger, "Discarding one R");
      GST_OBJECT_UNLOCK (merger);
      continue;
    } else if (GST_BUFFER_PTS (buf_l0) + GST_BUFFER_DURATION (buf_l0) <
        GST_BUFFER_PTS (buf_r0)) {
      buf_l = g_queue_pop_head (&merger->bufs_l);
      gst_buffer_unref (buf_l);
      buf_l = NULL;
      GST_DEBUG_OBJECT (merger, "Discarding one L");
      GST_OBJECT_UNLOCK (merger);
      continue;
    } else {
      GST_DEBUG_OBJECT (merger, "Not implemented");
    }

    if (buf_l == NULL || buf_r == NULL) {
      goto beg;
    }

    GST_OBJECT_UNLOCK (merger);

    GST_DEBUG_OBJECT (merger, "Pushing new buffer");


    gint w = 1280;
    gint h = 480;
    {
      GstCaps *caps = gst_pad_get_current_caps (merger->srcv_pad);
      GstStructure *s = gst_caps_get_structure (caps, 0);
      gst_structure_get_int (s, "width", &w);
      gst_structure_get_int (s, "height", &h);
      gst_caps_unref (caps);
    }


    GstBuffer *buf_out = gst_buffer_new_allocate (NULL, w * h * 4, NULL);

    GstMapInfo map_l;
    GstMapInfo map_r;
    GstMapInfo map_out;
    bool res = gst_buffer_map (buf_out, &map_out, GST_MAP_WRITE);
    g_assert (res);
    res = gst_buffer_map (buf_l, &map_l, GST_MAP_READ);
    g_assert (res);
    res = gst_buffer_map (buf_r, &map_r, GST_MAP_READ);
    g_assert (res);

    guint8 *a_o = (guint8 *) map_out.data;
    guint8 *a_l = (guint8 *) map_l.data;
    guint8 *a_r = (guint8 *) map_r.data;
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w / 2; x++) {
        guint8 r = a_l[3 * (y * w / 2 + x) + 0];
        guint8 g = a_l[3 * (y * w / 2 + x) + 1];
        guint8 b = a_l[3 * (y * w / 2 + x) + 2];
        a_o[4 * (y * w + x) + 0] = r;
        a_o[4 * (y * w + x) + 1] = g;
        a_o[4 * (y * w + x) + 2] = b;
        a_o[4 * (y * w + x) + 3] = 255;
      }
      for (int x = 0; x < w / 2; x++) {
        guint8 r = a_r[3 * (y * w / 2 + x) + 0];
        guint8 g = a_r[3 * (y * w / 2 + x) + 1];
        guint8 b = a_r[3 * (y * w / 2 + x) + 2];
        a_o[4 * (y * w + x + w / 2) + 0] = r;
        a_o[4 * (y * w + x + w / 2) + 1] = g;
        a_o[4 * (y * w + x + w / 2) + 2] = b;
        a_o[4 * (y * w + x + w / 2) + 3] = 255;
      }
    }

    usleep (10000);

    gst_buffer_unmap (buf_l, &map_l);
    gst_buffer_unmap (buf_r, &map_r);
    gst_buffer_unmap (buf_out, &map_out);

    GST_BUFFER_PTS (buf_out) = GST_BUFFER_PTS (buf_l);
    GST_BUFFER_DTS (buf_out) = GST_BUFFER_DTS (buf_l);
    GST_BUFFER_DURATION (buf_out) = GST_BUFFER_DURATION (buf_l);

    gst_buffer_unref (buf_l);
    gst_buffer_unref (buf_r);

    int res2 = gst_pad_push (merger->srcv_pad, buf_out);
    if (res2 != GST_FLOW_OK) {
      GST_WARNING_OBJECT (merger, "Pushing pad returned %d", res2);
      goto error;
    }

  }

  goto beg;

error:
end:

  GST_INFO_OBJECT (merger, "Task bye bye?");

  //gst_task_pause (merger->task);

  GST_INFO_OBJECT (merger, "Task bye bye");

  g_mutex_unlock (&merger->task_lock);
}
static void
_audiodecoder_flush_events (gboolean send_buffers)
{
  GstSegment segment;
  GstBuffer *buffer;
  guint64 i;
  GList *events_iter;
  GstMessage *msg;

  setup_audiodecodertester ();

  gst_pad_set_active (mysrcpad, TRUE);
  gst_element_set_state (dec, GST_STATE_PLAYING);
  gst_pad_set_active (mysinkpad, TRUE);

  send_startup_events ();

  /* push a new segment */
  gst_segment_init (&segment, GST_FORMAT_TIME);
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));

  if (send_buffers) {
    /* push buffers, the data is actually a number so we can track them */
    for (i = 0; i < NUM_BUFFERS; i++) {
      if (i % 10 == 0) {
        GstTagList *tags;

        tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL);
        fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
      } else {
        buffer = create_test_buffer (i);

        fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
      }
    }
  } else {
    /* push sticky event */
    GstTagList *tags;
    tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, 0, NULL);
    fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
  }

  msg =
      gst_message_new_element (GST_OBJECT (mysrcpad),
      gst_structure_new_empty ("test"));
  fail_unless (gst_pad_push_event (mysrcpad,
      gst_event_new_sink_message ("test", msg)));
  gst_message_unref (msg);

  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));

  events_iter = events;
  /* make sure the usual events have been received */
  {
    GstEvent *sstart = events_iter->data;
    fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START);
    events_iter = g_list_next (events_iter);
  }
  if (send_buffers) {
    {
      GstEvent *caps_event = events_iter->data;
      fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS);
      events_iter = g_list_next (events_iter);
    }
    {
      GstEvent *segment_event = events_iter->data;
      fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT);
      events_iter = g_list_next (events_iter);
    }
    for (int i=0; i< NUM_BUFFERS / 10; i++)
    {
      GstEvent *tag_event = events_iter->data;
      fail_unless (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG);
      events_iter = g_list_next (events_iter);
    }
  }
  {
    GstEvent *eos_event = events_iter->data;
    fail_unless (GST_EVENT_TYPE (eos_event) == GST_EVENT_EOS);
    events_iter = g_list_next (events_iter);
  }

  /* check that EOS was received */
  fail_unless (GST_PAD_IS_EOS (mysrcpad));
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ()));
  fail_unless (GST_PAD_IS_EOS (mysrcpad));

  /* Check that we have tags */
  {
    GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0);

    fail_unless (tags != NULL);
    gst_event_unref (tags);
  }

  /* Check that we still have a segment set */
  {
    GstEvent *segment =
        gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0);

    fail_unless (segment != NULL);
    gst_event_unref (segment);
  }

  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE)));
  fail_if (GST_PAD_IS_EOS (mysrcpad));

  /* Check that the segment was flushed on FLUSH_STOP */
  {
    GstEvent *segment =
        gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0);

    fail_unless (segment == NULL);
  }

  /* Check the tags were not lost on FLUSH_STOP */
  {
    GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0);

    fail_unless (tags != NULL);
    gst_event_unref (tags);

  }

  g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
  buffers = NULL;

  gst_element_set_state (dec, GST_STATE_NULL);
  cleanup_audiodecodertest ();
}