/* GStreamer
 * Copyright (C) <2010> Thiago Santos <thiago.sousa.santos@collabora.co.uk>
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "gstgeometrictransform.h"
#include "geometricmath.h"
#include <string.h>

GST_DEBUG_CATEGORY_STATIC (geometric_transform_debug);
#define GST_CAT_DEFAULT geometric_transform_debug

static GstStaticPadTemplate gst_geometric_transform_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ ARGB, BGR, BGRA, BGRx, RGB, "
            "RGBA, RGBx, AYUV, xBGR, xRGB, GRAY8, GRAY16_BE, GRAY16_LE }"))
    );

static GstStaticPadTemplate gst_geometric_transform_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ ARGB, BGR, BGRA, BGRx, RGB, "
            "RGBA, RGBx, AYUV, xBGR, xRGB, GRAY8, GRAY16_BE, GRAY16_LE }"))
    );

static GstVideoFilterClass *parent_class = NULL;

enum
{
  PROP_0,
  PROP_OFF_EDGE_PIXELS
};

#define GST_GT_OFF_EDGES_PIXELS_METHOD_TYPE ( \
    gst_geometric_transform_off_edges_pixels_method_get_type())
static GType
gst_geometric_transform_off_edges_pixels_method_get_type (void)
{
  static GType method_type = 0;

  static const GEnumValue method_types[] = {
    {GST_GT_OFF_EDGES_PIXELS_IGNORE, "Ignore", "ignore"},
    {GST_GT_OFF_EDGES_PIXELS_CLAMP, "Clamp", "clamp"},
    {GST_GT_OFF_EDGES_PIXELS_WRAP, "Wrap", "wrap"},
    {0, NULL, NULL}
  };

  if (!method_type) {
    method_type =
        g_enum_register_static ("GstGeometricTransformOffEdgesPixelsMethod",
        method_types);
  }
  return method_type;
}

#define DEFAULT_OFF_EDGE_PIXELS GST_GT_OFF_EDGES_PIXELS_IGNORE

/* must be called with the object lock */
static gboolean
gst_geometric_transform_generate_map (GstGeometricTransform * gt)
{
  gint x, y;
  gdouble in_x, in_y;
  gboolean ret = TRUE;
  GstGeometricTransformClass *klass;
  gdouble *ptr;

  GST_INFO_OBJECT (gt, "Generating new transform map");

  /* cleanup old map */
  g_free (gt->map);
  gt->map = NULL;

  klass = GST_GEOMETRIC_TRANSFORM_GET_CLASS (gt);

  /* subclass must have defined the map_func */
  g_return_val_if_fail (klass->map_func, FALSE);

  /*
   * (x,y) pairs of the inverse mapping
   */
  gt->map = g_malloc0 (sizeof (gdouble) * gt->width * gt->height * 2);
  ptr = gt->map;

  for (y = 0; y < gt->height; y++) {
    for (x = 0; x < gt->width; x++) {
      if (!klass->map_func (gt, x, y, &in_x, &in_y)) {
        /* child should have warned */
        ret = FALSE;
        goto end;
      }

      ptr[0] = in_x;
      ptr[1] = in_y;
      ptr += 2;
    }
  }

end:
  if (!ret) {
    GST_WARNING_OBJECT (gt, "Generating transform map failed");
    g_free (gt->map);
    gt->map = NULL;
  } else
    gt->needs_remap = FALSE;
  return ret;
}

static gboolean
gst_geometric_transform_set_info (GstVideoFilter * vfilter, GstCaps * incaps,
    GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
{
  GstGeometricTransform *gt;
  gboolean ret = TRUE;
  gint old_width;
  gint old_height;
  GstGeometricTransformClass *klass;

  gt = GST_GEOMETRIC_TRANSFORM_CAST (vfilter);
  klass = GST_GEOMETRIC_TRANSFORM_GET_CLASS (gt);

  old_width = gt->width;
  old_height = gt->height;

  gt->width = in_info->width;
  gt->height = in_info->height;
  gt->row_stride = in_info->stride[0];
  gt->pixel_stride = GST_VIDEO_INFO_COMP_PSTRIDE (in_info, 0);

  /* regenerate the map */
  GST_OBJECT_LOCK (gt);
  if (gt->map == NULL || old_width == 0 || old_height == 0
      || gt->width != old_width || gt->height != old_height) {
    if (klass->prepare_func)
      if (!klass->prepare_func (gt)) {
        GST_OBJECT_UNLOCK (gt);
        return FALSE;
      }
    if (gt->precalc_map)
      gst_geometric_transform_generate_map (gt);
  }
  GST_OBJECT_UNLOCK (gt);
  return ret;
}

static void
gst_geometric_transform_do_map (GstGeometricTransform * gt, guint8 * in_data,
    guint8 * out_data, gint x, gint y, gdouble in_x, gdouble in_y)
{
  gint in_offset;
  gint out_offset;

  out_offset = y * gt->row_stride + x * gt->pixel_stride;

  /* operate on out of edge pixels */
  switch (gt->off_edge_pixels) {
    case GST_GT_OFF_EDGES_PIXELS_CLAMP:
      in_x = CLAMP (in_x, 0, gt->width - 1);
      in_y = CLAMP (in_y, 0, gt->height - 1);
      break;

    case GST_GT_OFF_EDGES_PIXELS_WRAP:
      in_x = mod_float (in_x, gt->width);
      in_y = mod_float (in_y, gt->height);
      if (in_x < 0)
        in_x += gt->width;
      if (in_y < 0)
        in_y += gt->height;
      break;

    default:
      break;
  }

  {
    gint trunc_x = (gint) in_x;
    gint trunc_y = (gint) in_y;
    /* only set the values if the values are valid */
    if (trunc_x >= 0 && trunc_x < gt->width && trunc_y >= 0 &&
        trunc_y < gt->height) {
      in_offset = trunc_y * gt->row_stride + trunc_x * gt->pixel_stride;

      memcpy (out_data + out_offset, in_data + in_offset, gt->pixel_stride);
    }
  }
}

static void
gst_geometric_transform_before_transform (GstBaseTransform * trans,
    GstBuffer * outbuf)
{
  GstGeometricTransform *gt = GST_GEOMETRIC_TRANSFORM_CAST (trans);
  GstClockTime timestamp, stream_time;

  timestamp = GST_BUFFER_TIMESTAMP (outbuf);
  stream_time =
      gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, timestamp);

  GST_DEBUG_OBJECT (gt, "sync to %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));

  if (GST_CLOCK_TIME_IS_VALID (stream_time))
    gst_object_sync_values (GST_OBJECT (gt), stream_time);
}

static GstFlowReturn
gst_geometric_transform_transform_frame (GstVideoFilter * vfilter,
    GstVideoFrame * in_frame, GstVideoFrame * out_frame)
{
  GstGeometricTransform *gt;
  GstGeometricTransformClass *klass;
  gint x, y, i;
  GstFlowReturn ret = GST_FLOW_OK;
  gdouble *ptr;
  guint8 *in_data;
  guint8 *out_data;

  gt = GST_GEOMETRIC_TRANSFORM_CAST (vfilter);
  klass = GST_GEOMETRIC_TRANSFORM_GET_CLASS (gt);

  in_data = GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0);
  out_data = GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0);

  if (GST_VIDEO_FRAME_FORMAT (out_frame) == GST_VIDEO_FORMAT_AYUV) {
    /* in AYUV black is not just all zeros:
     * 0x10 is black for Y,
     * 0x80 is black for Cr and Cb */
    for (i = 0; i < out_frame->map[0].size; i += 4)
      GST_WRITE_UINT32_BE (out_data + i, 0xff108080);
  } else {
    memset (out_data, 0, out_frame->map[0].size);
  }

  GST_OBJECT_LOCK (gt);
  if (gt->precalc_map) {
    if (gt->needs_remap) {
      if (klass->prepare_func)
        if (!klass->prepare_func (gt)) {
          ret = FALSE;
          goto end;
        }
      gst_geometric_transform_generate_map (gt);
    }
    g_return_val_if_fail (gt->map, GST_FLOW_ERROR);
    ptr = gt->map;
    for (y = 0; y < gt->height; y++) {
      for (x = 0; x < gt->width; x++) {
        /* do the mapping */
        gst_geometric_transform_do_map (gt, in_data, out_data, x, y, ptr[0],
            ptr[1]);
        ptr += 2;
      }
    }
  } else {
    for (y = 0; y < gt->height; y++) {
      for (x = 0; x < gt->width; x++) {
        gdouble in_x, in_y;

        if (klass->map_func (gt, x, y, &in_x, &in_y)) {
          gst_geometric_transform_do_map (gt, in_data, out_data, x, y, in_x,
              in_y);
        } else {
          GST_WARNING_OBJECT (gt, "Failed to do mapping for %d %d", x, y);
          ret = GST_FLOW_ERROR;
          goto end;
        }
      }
    }
  }
end:
  GST_OBJECT_UNLOCK (gt);
  return ret;
}

static void
gst_geometric_transform_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstGeometricTransform *gt;

  gt = GST_GEOMETRIC_TRANSFORM_CAST (object);

  switch (prop_id) {
    case PROP_OFF_EDGE_PIXELS:
      GST_OBJECT_LOCK (gt);
      gt->off_edge_pixels = g_value_get_enum (value);
      GST_OBJECT_UNLOCK (gt);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_geometric_transform_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstGeometricTransform *gt;

  gt = GST_GEOMETRIC_TRANSFORM_CAST (object);

  switch (prop_id) {
    case PROP_OFF_EDGE_PIXELS:
      g_value_set_enum (value, gt->off_edge_pixels);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}


static gboolean
gst_geometric_transform_stop (GstBaseTransform * trans)
{
  GstGeometricTransform *gt = GST_GEOMETRIC_TRANSFORM_CAST (trans);

  GST_INFO_OBJECT (gt, "Deleting transform map");

  gt->width = 0;
  gt->height = 0;

  g_free (gt->map);
  gt->map = NULL;

  return TRUE;
}

static void
gst_geometric_transform_base_init (gpointer g_class)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&gst_geometric_transform_sink_template));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&gst_geometric_transform_src_template));
}

static void
gst_geometric_transform_class_init (gpointer klass, gpointer class_data)
{
  GObjectClass *obj_class;
  GstBaseTransformClass *trans_class;
  GstVideoFilterClass *vfilter_class;

  obj_class = (GObjectClass *) klass;
  trans_class = (GstBaseTransformClass *) klass;
  vfilter_class = (GstVideoFilterClass *) klass;

  parent_class = g_type_class_peek_parent (klass);

  obj_class->set_property = gst_geometric_transform_set_property;
  obj_class->get_property = gst_geometric_transform_get_property;

  trans_class->stop = GST_DEBUG_FUNCPTR (gst_geometric_transform_stop);
  trans_class->before_transform =
      GST_DEBUG_FUNCPTR (gst_geometric_transform_before_transform);

  vfilter_class->set_info =
      GST_DEBUG_FUNCPTR (gst_geometric_transform_set_info);
  vfilter_class->transform_frame =
      GST_DEBUG_FUNCPTR (gst_geometric_transform_transform_frame);

  g_object_class_install_property (obj_class, PROP_OFF_EDGE_PIXELS,
      g_param_spec_enum ("off-edge-pixels", "Off edge pixels",
          "What to do with off edge pixels",
          GST_GT_OFF_EDGES_PIXELS_METHOD_TYPE, DEFAULT_OFF_EDGE_PIXELS,
          GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}

static void
gst_geometric_transform_init (GTypeInstance * instance, gpointer g_class)
{
  GstGeometricTransform *gt = GST_GEOMETRIC_TRANSFORM_CAST (instance);

  gt->off_edge_pixels = DEFAULT_OFF_EDGE_PIXELS;
  gt->precalc_map = TRUE;
  gt->needs_remap = TRUE;
}

GType
gst_geometric_transform_get_type (void)
{
  static GType geometric_transform_type = 0;

  if (!geometric_transform_type) {
    static const GTypeInfo geometric_transform_info = {
      sizeof (GstGeometricTransformClass),
      gst_geometric_transform_base_init,
      NULL,
      gst_geometric_transform_class_init,
      NULL,
      NULL,
      sizeof (GstGeometricTransform),
      0,
      gst_geometric_transform_init,
    };

    geometric_transform_type = g_type_register_static (GST_TYPE_VIDEO_FILTER,
        "GstGeometricTransform", &geometric_transform_info,
        G_TYPE_FLAG_ABSTRACT);

    GST_DEBUG_CATEGORY_INIT (geometric_transform_debug, "geometrictransform", 0,
        "Base class for geometric transform elements");
  }
  return geometric_transform_type;
}

/*
 * Must be called with the object lock
 */
void
gst_geometric_transform_set_need_remap (GstGeometricTransform * gt)
{
  gt->needs_remap = TRUE;
}
