/* GStreamer
 * Copyright (C) 2013 FIXME <fixme@example.com>
 *
 * 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 Street, Suite 500,
 * Boston, MA 02110-1335, USA.
 */
/**
 * SECTION:element-gstvideodiff
 *
 * The videodiff element does FIXME stuff.
 *
 * <refsect2>
 * <title>Example launch line</title>
 * |[
 * gst-launch -v fakesrc ! videodiff ! FIXME ! fakesink
 * ]|
 * FIXME Describe what the pipeline does.
 * </refsect2>
 */

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

#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideofilter.h>
#include "gstvideodiff.h"

GST_DEBUG_CATEGORY_STATIC (gst_video_diff_debug_category);
#define GST_CAT_DEFAULT gst_video_diff_debug_category

/* prototypes */

static GstFlowReturn gst_video_diff_transform_frame (GstVideoFilter * filter,
    GstVideoFrame * inframe, GstVideoFrame * outframe);

enum
{
  PROP_0
};

/* pad templates */

/* FIXME: add/remove formats you can handle */
#define VIDEO_SRC_CAPS \
    GST_VIDEO_CAPS_MAKE("{ I420, Y444, Y42B, UYVY, RGBA }")

/* FIXME: add/remove formats you can handle */
#define VIDEO_SINK_CAPS \
    GST_VIDEO_CAPS_MAKE("{ I420, Y444, Y42B, UYVY, RGBA }")


/* class initialization */

G_DEFINE_TYPE_WITH_CODE (GstVideoDiff, gst_video_diff, GST_TYPE_VIDEO_FILTER,
    GST_DEBUG_CATEGORY_INIT (gst_video_diff_debug_category, "videodiff", 0,
        "debug category for videodiff element"));

static void
gst_video_diff_class_init (GstVideoDiffClass * klass)
{
  GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);

  /* Setting up pads and setting metadata should be moved to
     base_class_init if you intend to subclass this class. */
  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
      gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
          gst_caps_from_string (VIDEO_SRC_CAPS)));
  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
      gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
          gst_caps_from_string (VIDEO_SINK_CAPS)));

  gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
      "FIXME Long name", "Generic", "FIXME Description",
      "FIXME <fixme@example.com>");

  video_filter_class->transform_frame =
      GST_DEBUG_FUNCPTR (gst_video_diff_transform_frame);

}

static void
gst_video_diff_init (GstVideoDiff * videodiff)
{
  videodiff->threshold = 10;
}

static GstFlowReturn
gst_video_diff_transform_frame_ip_planarY (GstVideoDiff * videodiff,
    GstVideoFrame * outframe, GstVideoFrame * inframe, GstVideoFrame * oldframe)
{
  int width = inframe->info.width;
  int height = inframe->info.height;
  int i, j;
  int threshold = videodiff->threshold;
  int t = videodiff->t;

  for (j = 0; j < height; j++) {
    guint8 *d = (guint8 *) outframe->data[0] + outframe->info.stride[0] * j;
    guint8 *s1 = (guint8 *) oldframe->data[0] + oldframe->info.stride[0] * j;
    guint8 *s2 = (guint8 *) inframe->data[0] + inframe->info.stride[0] * j;
    for (i = 0; i < width; i++) {
      if ((s2[i] < s1[i] - threshold) || (s2[i] > s1[i] + threshold)) {
        if ((i + j + t) & 0x4) {
          d[i] = 16;
        } else {
          d[i] = 240;
        }
      } else {
        d[i] = s2[i];
      }
    }
  }
  for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (inframe, 1); j++) {
    guint8 *d = (guint8 *) outframe->data[1] + outframe->info.stride[1] * j;
    guint8 *s = (guint8 *) inframe->data[1] + inframe->info.stride[1] * j;
    memcpy (d, s, GST_VIDEO_FRAME_COMP_WIDTH (inframe, 1));
  }
  for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (inframe, 2); j++) {
    guint8 *d = (guint8 *) outframe->data[2] + outframe->info.stride[2] * j;
    guint8 *s = (guint8 *) inframe->data[2] + inframe->info.stride[2] * j;
    memcpy (d, s, GST_VIDEO_FRAME_COMP_WIDTH (inframe, 2));
  }
  return GST_FLOW_OK;
}

static GstFlowReturn
gst_video_diff_transform_frame (GstVideoFilter * filter,
    GstVideoFrame * inframe, GstVideoFrame * outframe)
{
  GstVideoDiff *videodiff = GST_VIDEO_DIFF (filter);

  GST_DEBUG_OBJECT (videodiff, "transform_frame_ip");

  if (videodiff->previous_buffer) {
    GstVideoFrame oldframe;

    gst_video_frame_map (&oldframe, &videodiff->oldinfo,
        videodiff->previous_buffer, GST_MAP_READ);

    switch (inframe->info.finfo->format) {
      case GST_VIDEO_FORMAT_I420:
      case GST_VIDEO_FORMAT_Y41B:
      case GST_VIDEO_FORMAT_Y444:
      case GST_VIDEO_FORMAT_Y42B:
        gst_video_diff_transform_frame_ip_planarY (videodiff, outframe,
            inframe, &oldframe);
        break;
      default:
        g_assert_not_reached ();
    }

    gst_video_frame_unmap (&oldframe);
    gst_buffer_unref (videodiff->previous_buffer);
  } else {
    int k;
    int j;
    for (k = 0; k < 3; k++) {
      for (j = 0; j < GST_VIDEO_FRAME_COMP_HEIGHT (inframe, k); j++) {
        guint8 *d = (guint8 *) outframe->data[k] + outframe->info.stride[k] * j;
        guint8 *s = (guint8 *) inframe->data[k] + inframe->info.stride[k] * j;
        memcpy (d, s, GST_VIDEO_FRAME_COMP_WIDTH (inframe, k));
      }
    }
  }

  videodiff->previous_buffer = gst_buffer_ref (inframe->buffer);
  memcpy (&videodiff->oldinfo, &inframe->info, sizeof (GstVideoInfo));

  return GST_FLOW_OK;
}
