/* GStreamer
 *
 * unit test for videofilter elements
 *
 * Copyright (C) <2006> Mark Nauwelaerts <manauw@skynet.be>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <unistd.h>
#include <stdarg.h>

#include <gst/video/video.h>
#include <gst/check/gstcheck.h>

gboolean have_eos = FALSE;

/* For ease of programming we use globals to keep refs for our floating
 * src and sink pads we create; otherwise we always have to do get_pad,
 * get_peer, and then remove references in every test function */
GstPad *mysrcpad, *mysinkpad;

#define VIDEO_CAPS_TEMPLATE_STRING \
  GST_VIDEO_CAPS_MAKE ("{ I420, AYUV, YUY2, UYVY, YVYU, xRGB }")

static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING)
    );
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING)
    );

/* takes over reference for outcaps */
static GstElement *
setup_filter (const gchar * name, const gchar * prop, va_list var_args)
{
  GstElement *element;

  GST_DEBUG ("setup_element");
  element = gst_check_setup_element (name);
  g_object_set_valist (G_OBJECT (element), prop, var_args);
  mysrcpad = gst_check_setup_src_pad (element, &srctemplate);
  gst_pad_set_active (mysrcpad, TRUE);
  mysinkpad = gst_check_setup_sink_pad (element, &sinktemplate);
  gst_pad_set_active (mysinkpad, TRUE);

  return element;
}

static void
cleanup_filter (GstElement * filter)
{
  GST_DEBUG ("cleanup_element");

  gst_check_teardown_src_pad (filter);
  gst_check_teardown_sink_pad (filter);
  gst_check_teardown_element (filter);
}

static void
check_filter_caps (const gchar * name, GstEvent * event, GstCaps * caps,
    gint size, gint num_buffers, const gchar * prop, va_list varargs)
{
  GstElement *filter;
  GstBuffer *inbuffer, *outbuffer;
  gint i;
  GstSegment segment;

  filter = setup_filter (name, prop, varargs);
  fail_unless (gst_element_set_state (filter,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
      "could not set to playing");

  gst_check_setup_events (mysrcpad, filter, caps, GST_FORMAT_TIME);

  /* ensure segment (format) properly setup */
  gst_segment_init (&segment, GST_FORMAT_TIME);
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));

  if (event)
    fail_unless (gst_pad_push_event (mysrcpad, event));

  for (i = 0; i < num_buffers; ++i) {
    inbuffer = gst_buffer_new_and_alloc (size);
    /* makes valgrind's memcheck happier */
    gst_buffer_memset (inbuffer, 0, 0, size);
    GST_BUFFER_TIMESTAMP (inbuffer) = 0;
    ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
    fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
  }

  fail_unless (g_list_length (buffers) == num_buffers);

  /* clean up buffers */
  for (i = 0; i < num_buffers; ++i) {
    outbuffer = GST_BUFFER (buffers->data);
    fail_if (outbuffer == NULL);

    switch (i) {
      case 0:
        fail_unless (gst_buffer_get_size (outbuffer) == size);
        /* no check on filter operation itself */
        break;
      default:
        break;
    }
    buffers = g_list_remove (buffers, outbuffer);

    ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
    gst_buffer_unref (outbuffer);
    outbuffer = NULL;
  }

  cleanup_filter (filter);
  g_list_free (buffers);
  buffers = NULL;
}

static void
check_filter_varargs (const gchar * name, GstEvent * event, gint num_buffers,
    const gchar * prop, va_list varargs)
{
  static const struct
  {
    const int width, height;
  } resolutions[] = { {
  384, 288}, {
  385, 289}, {
  385, 385}};
  gint i, n, r;
  gint size;
  GstCaps *allcaps, *templ = gst_caps_from_string (VIDEO_CAPS_TEMPLATE_STRING);

  allcaps = gst_caps_normalize (templ);

  n = gst_caps_get_size (allcaps);

  for (i = 0; i < n; i++) {
    GstStructure *s = gst_caps_get_structure (allcaps, i);
    GstCaps *caps = gst_caps_new_empty ();

    gst_caps_append_structure (caps, gst_structure_copy (s));

    /* try various resolutions */
    for (r = 0; r < G_N_ELEMENTS (resolutions); ++r) {
      GstVideoInfo info;
      va_list args_cp;

      caps = gst_caps_make_writable (caps);
      gst_caps_set_simple (caps, "width", G_TYPE_INT, resolutions[r].width,
          "height", G_TYPE_INT, resolutions[r].height,
          "framerate", GST_TYPE_FRACTION, 25, 1, NULL);

      GST_DEBUG ("Testing with caps: %" GST_PTR_FORMAT, caps);
      gst_video_info_from_caps (&info, caps);
      size = GST_VIDEO_INFO_SIZE (&info);

      if (event)
        gst_event_ref (event);

      va_copy (args_cp, varargs);
      check_filter_caps (name, event, caps, size, num_buffers, prop, args_cp);
      va_end (args_cp);
    }

    gst_caps_unref (caps);
  }

  gst_caps_unref (allcaps);
  if (event)
    gst_event_unref (event);
}

static void
check_filter (const gchar * name, gint num_buffers, const gchar * prop, ...)
{
  va_list varargs;
  va_start (varargs, prop);
  check_filter_varargs (name, NULL, num_buffers, prop, varargs);
  va_end (varargs);
}

static void
check_filter_with_event (const gchar * name, GstEvent * event,
    gint num_buffers, const gchar * prop, ...)
{
  va_list varargs;
  va_start (varargs, prop);
  check_filter_varargs (name, event, num_buffers, prop, varargs);
  va_end (varargs);
}

GST_START_TEST (test_videobalance)
{
  check_filter ("videobalance", 2, NULL);
  check_filter ("videobalance", 2, "saturation", 0.5, "hue", 0.8, NULL);
}

GST_END_TEST;


GST_START_TEST (test_videoflip)
{
  GstEvent *event;

  /* these we can handle with the caps */
  check_filter ("videoflip", 2, "method", 0, NULL);
  check_filter ("videoflip", 2, "method", 2, NULL);
  check_filter ("videoflip", 2, "method", 4, NULL);
  check_filter ("videoflip", 2, "method", 5, NULL);

  event = gst_event_new_tag (gst_tag_list_new_empty ());
  check_filter_with_event ("videoflip", event, 2, "method", 8, NULL);

  event = gst_event_new_tag (gst_tag_list_new (GST_TAG_IMAGE_ORIENTATION,
          "rotate-180", NULL));
  check_filter_with_event ("videoflip", event, 2, "method", 8, NULL);

  event = gst_event_new_tag (gst_tag_list_new (GST_TAG_IMAGE_ORIENTATION,
          "invalid", NULL));
  check_filter_with_event ("videoflip", event, 2, "method", 8, NULL);
}

GST_END_TEST;

GST_START_TEST (test_gamma)
{
  check_filter ("gamma", 2, NULL);
  check_filter ("gamma", 2, "gamma", 2.0, NULL);
}

GST_END_TEST;


static Suite *
videofilter_suite (void)
{
  Suite *s = suite_create ("videofilter");
  TCase *tc_chain = tcase_create ("general");

  suite_add_tcase (s, tc_chain);
  tcase_add_test (tc_chain, test_videobalance);
  tcase_add_test (tc_chain, test_videoflip);
  tcase_add_test (tc_chain, test_gamma);

  return s;
}

GST_CHECK_MAIN (videofilter);
