/* 
 * Copyright (C) 2013 Sebastian Dröge <sebastian@centricular.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 St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

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

#include "gstopenexrdec.h"

#include <gst/base/base.h>
#include <string.h>

#include <ImfRgbaFile.h>
#include <ImfIO.h>
using namespace Imf;
using namespace Imath;

/* Memory stream reader */
class MemIStream:public IStream
{
public:
  MemIStream (const char *file_name, const guint8 * data,
      gsize size):IStream (file_name), data (data), offset (0), size (size)
  {
  }

  virtual bool read (char c[], int n);
  virtual Int64 tellg ();
  virtual void seekg (Int64 pos);
  virtual void clear ();

private:
  const guint8 *data;
  gsize offset, size;
};

bool MemIStream::read (char c[], int n)
{
  if (offset + n > size)
    throw
    Iex::InputExc ("Unexpected end of file");

  memcpy (c, data + offset, n);
  offset += n;

  return (offset == size);
}

Int64 MemIStream::tellg ()
{
  return offset;
}

void
MemIStream::seekg (Int64 pos)
{
  offset = pos;
  if (offset > size)
    offset = size;
}

void
MemIStream::clear ()
{

}

GST_DEBUG_CATEGORY_STATIC (gst_openexr_dec_debug);
#define GST_CAT_DEFAULT gst_openexr_dec_debug

static gboolean gst_openexr_dec_start (GstVideoDecoder * decoder);
static gboolean gst_openexr_dec_stop (GstVideoDecoder * decoder);
static GstFlowReturn gst_openexr_dec_parse (GstVideoDecoder * decoder,
    GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos);
static gboolean gst_openexr_dec_set_format (GstVideoDecoder * decoder,
    GstVideoCodecState * state);
static GstFlowReturn gst_openexr_dec_handle_frame (GstVideoDecoder * decoder,
    GstVideoCodecFrame * frame);
static gboolean gst_openexr_dec_decide_allocation (GstVideoDecoder * decoder,
    GstQuery * query);

static GstStaticPadTemplate gst_openexr_dec_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("image/x-exr")
    );

static GstStaticPadTemplate gst_openexr_dec_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("ARGB64"))
    );

#define parent_class gst_openexr_dec_parent_class
G_DEFINE_TYPE (GstOpenEXRDec, gst_openexr_dec, GST_TYPE_VIDEO_DECODER);

static void
gst_openexr_dec_class_init (GstOpenEXRDecClass * klass)
{
  GstElementClass *element_class;
  GstVideoDecoderClass *video_decoder_class;

  element_class = (GstElementClass *) klass;
  video_decoder_class = (GstVideoDecoderClass *) klass;

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&gst_openexr_dec_src_template));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&gst_openexr_dec_sink_template));

  gst_element_class_set_static_metadata (element_class,
      "OpenEXR decoder",
      "Codec/Decoder/Video",
      "Decode EXR streams", "Sebastian Dröge <sebastian@centricular.com>");

  video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_openexr_dec_start);
  video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_openexr_dec_stop);
  video_decoder_class->parse = GST_DEBUG_FUNCPTR (gst_openexr_dec_parse);
  video_decoder_class->set_format =
      GST_DEBUG_FUNCPTR (gst_openexr_dec_set_format);
  video_decoder_class->handle_frame =
      GST_DEBUG_FUNCPTR (gst_openexr_dec_handle_frame);
  video_decoder_class->decide_allocation = gst_openexr_dec_decide_allocation;

  GST_DEBUG_CATEGORY_INIT (gst_openexr_dec_debug, "openexrdec", 0,
      "OpenEXR Decoder");
}

static void
gst_openexr_dec_init (GstOpenEXRDec * self)
{
  GstVideoDecoder *decoder = (GstVideoDecoder *) self;

  gst_video_decoder_set_packetized (decoder, FALSE);
  gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
      (self), TRUE);
  GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (self));
}

static gboolean
gst_openexr_dec_start (GstVideoDecoder * decoder)
{
  GstOpenEXRDec *self = GST_OPENEXR_DEC (decoder);

  GST_DEBUG_OBJECT (self, "Starting");

  return TRUE;
}

static gboolean
gst_openexr_dec_stop (GstVideoDecoder * video_decoder)
{
  GstOpenEXRDec *self = GST_OPENEXR_DEC (video_decoder);

  GST_DEBUG_OBJECT (self, "Stopping");

  if (self->output_state) {
    gst_video_codec_state_unref (self->output_state);
    self->output_state = NULL;
  }

  if (self->input_state) {
    gst_video_codec_state_unref (self->input_state);
    self->input_state = NULL;
  }

  GST_DEBUG_OBJECT (self, "Stopped");

  return TRUE;
}

static GstFlowReturn
gst_openexr_dec_parse (GstVideoDecoder * decoder,
    GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos)
{
  guint8 data[8];
  gsize size, parsed_size;
  guint32 magic, flags;
  gssize offset;

  size = gst_adapter_available (adapter);

  parsed_size = gst_video_decoder_get_pending_frame_size (decoder);

  GST_DEBUG_OBJECT (decoder, "Parsing OpenEXR image data %" G_GSIZE_FORMAT,
      size);

  if (parsed_size == 0 && size < 8)
    goto need_more_data;

  /* If we did not parse anything yet, check if the frame starts with the header */
  if (parsed_size == 0) {
    gst_adapter_copy (adapter, data, 0, 8);

    magic = GST_READ_UINT32_LE (data);
    flags = GST_READ_UINT32_LE (data + 4);
    if (magic != 0x01312f76 || ((flags & 0xff) != 1 && (flags & 0xff) != 2) || ((flags & 0x200) && (flags & 0x1800))) {
      offset = gst_adapter_masked_scan_uint32_peek (adapter, 0xffffffff, 0x762f3101, 0, size, NULL);
      if (offset == -1) {
        gst_adapter_flush (adapter, size - 4);
        goto need_more_data;
      }

      /* come back into this function after flushing some data */
      gst_adapter_flush (adapter, offset);
      goto need_more_data;
    }
  } else {
  }

  /* valid header, now let's try to find the next one unless we're EOS */
  if (!at_eos) {
    gboolean found = FALSE;

    while (!found) {
      offset = gst_adapter_masked_scan_uint32_peek (adapter, 0xffffffff, 0x762f3101, 8, size - 8 - 4, NULL);
      if (offset == -1) {        
        gst_video_decoder_add_to_frame (decoder, size - 7);
        goto need_more_data;
      }

      gst_adapter_copy (adapter, data, offset, 8);
      magic = GST_READ_UINT32_LE (data);
      flags = GST_READ_UINT32_LE (data + 4);
      if (magic == 0x01312f76 && ((flags & 0xff) == 1 || (flags & 0xff) == 2) && (!(flags & 0x200) || !(flags & 0x1800)))
        found = TRUE;
    }
    size = offset;
  }

  GST_DEBUG_OBJECT (decoder, "Have complete image of size %" G_GSSIZE_FORMAT, size + parsed_size);

  gst_video_decoder_add_to_frame (decoder, size);

  return gst_video_decoder_have_frame (decoder);

need_more_data:
  GST_DEBUG_OBJECT (decoder, "Need more data");
  return GST_VIDEO_DECODER_FLOW_NEED_DATA;
}

static gboolean
gst_openexr_dec_set_format (GstVideoDecoder * decoder,
    GstVideoCodecState * state)
{
  GstOpenEXRDec *self = GST_OPENEXR_DEC (decoder);

  GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);

  if (self->input_state)
    gst_video_codec_state_unref (self->input_state);
  self->input_state = gst_video_codec_state_ref (state);

  return TRUE;
}

static GstFlowReturn
gst_openexr_dec_negotiate (GstOpenEXRDec * self, RgbaInputFile * file)
{
  GstVideoFormat format;
  gint width, height;
  gfloat par;

  /* TODO: Use displayWindow here and also support output of ARGB_F16 */
  format = GST_VIDEO_FORMAT_ARGB64;
  Box2i dw = file->dataWindow ();
  width = dw.max.x - dw.min.x + 1;
  height = dw.max.y - dw.min.y + 1;
  par = file->pixelAspectRatio ();

  if (!self->output_state ||
      self->output_state->info.finfo->format != format ||
      self->output_state->info.width != width ||
      self->output_state->info.height != height) {
    if (self->output_state)
      gst_video_codec_state_unref (self->output_state);
    self->output_state =
        gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), format,
        width, height, self->input_state);

    GST_DEBUG_OBJECT (self, "Have image of size %dx%d (par %f)", width, height, par);
    gst_util_double_to_fraction (par, &self->output_state->info.par_n, &self->output_state->info.par_d);

    if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self)))
      return GST_FLOW_NOT_NEGOTIATED;
  }

  return GST_FLOW_OK;
}

static GstFlowReturn
gst_openexr_dec_handle_frame (GstVideoDecoder * decoder,
    GstVideoCodecFrame * frame)
{
  GstOpenEXRDec *self = GST_OPENEXR_DEC (decoder);
  GstFlowReturn ret = GST_FLOW_OK;
  gint64 deadline;
  GstMapInfo map;
  GstVideoFrame vframe;

  GST_DEBUG_OBJECT (self, "Handling frame");

  deadline = gst_video_decoder_get_max_decode_time (decoder, frame);
  if (deadline < 0) {
    GST_LOG_OBJECT (self, "Dropping too late frame: deadline %" G_GINT64_FORMAT,
        deadline);
    ret = gst_video_decoder_drop_frame (decoder, frame);
    return ret;
  }

  if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) {
    gst_video_codec_frame_unref (frame);

    GST_ELEMENT_ERROR (self, CORE, FAILED,
        ("Failed to map input buffer"), (NULL));
    return GST_FLOW_ERROR;
  }

  /* Now read the file and catch any exceptions */
  MemIStream *istr;
  RgbaInputFile *file;
  try {
    istr =
        new
        MemIStream (gst_pad_get_stream_id (GST_VIDEO_DECODER_SINK_PAD
            (decoder)), map.data, map.size);
  }
  catch (Iex::BaseExc e) {
    gst_video_codec_frame_unref (frame);

    GST_ELEMENT_ERROR (self, CORE, FAILED,
        ("Failed to create input stream"), (NULL));
    return GST_FLOW_ERROR;
  }
  try {
    file = new RgbaInputFile (*istr);
  }
  catch (Iex::BaseExc e) {
    delete istr;
    gst_video_codec_frame_unref (frame);

    GST_ELEMENT_ERROR (self, CORE, FAILED,
        ("Failed to read OpenEXR stream"), (NULL));
    return GST_FLOW_ERROR;
  }

  ret = gst_openexr_dec_negotiate (self, file);
  if (ret != GST_FLOW_OK) {
    delete file;
    delete istr;
    gst_buffer_unmap (frame->input_buffer, &map);
    gst_video_codec_frame_unref (frame);

    GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
        ("Failed to negotiate"), (NULL));
    return ret;
  }

  ret = gst_video_decoder_allocate_output_frame (decoder, frame);
  if (ret != GST_FLOW_OK) {
    delete file;
    delete istr;
    gst_buffer_unmap (frame->input_buffer, &map);
    gst_video_codec_frame_unref (frame);

    GST_ELEMENT_ERROR (self, CORE, FAILED,
        ("Failed to allocate output buffer"), (NULL));
    return ret;
  }

  if (!gst_video_frame_map (&vframe, &self->output_state->info,
          frame->output_buffer, GST_MAP_WRITE)) {
    delete file;
    delete istr;
    gst_buffer_unmap (frame->input_buffer, &map);
    gst_video_codec_frame_unref (frame);

    GST_ELEMENT_ERROR (self, CORE, FAILED,
        ("Failed to map output buffer"), (NULL));
    return GST_FLOW_ERROR;
  }

  /* Decode the file */
  Box2i dw = file->dataWindow ();
  int width = dw.max.x - dw.min.x + 1;
  int height = dw.max.y - dw.min.y + 1;
  Rgba *fb = new Rgba[width * height];

  try {
    file->setFrameBuffer (fb - dw.min.x - dw.min.y * width, 1, width);
    file->readPixels (dw.min.y, dw.max.y);
  } catch (Iex::BaseExc e) {
    delete[](fb);
    delete file;
    delete istr;
    gst_buffer_unmap (frame->input_buffer, &map);
    gst_video_frame_unmap (&vframe);

    GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to read pixels"), (NULL));
    return GST_FLOW_ERROR;
  }

  /* And convert from ARGB64_F16 to ARGB64 */
  gint i, j;
  guint16 *dest = (guint16 *) GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0);
  guint dstride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
  Rgba *ptr = fb;

  /* TODO: Use displayWindow here and also support output of ARGB_F16
   * and add a conversion filter element that can change exposure and
   * other things */
  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      dest[4 * j + 0] = CLAMP (((float) ptr->a) * 65536, 0, 65535);
      dest[4 * j + 1] = CLAMP (((float) ptr->r) * 65536, 0, 65535);
      dest[4 * j + 2] = CLAMP (((float) ptr->g) * 65536, 0, 65535);
      dest[4 * j + 3] = CLAMP (((float) ptr->b) * 65536, 0, 65535);
      ptr++;
    }
    dest += dstride / 2;
  }

  delete[](fb);
  delete file;
  delete istr;
  gst_buffer_unmap (frame->input_buffer, &map);
  gst_video_frame_unmap (&vframe);

  ret = gst_video_decoder_finish_frame (decoder, frame);

  return ret;
}

static gboolean
gst_openexr_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
{
  GstBufferPool *pool;
  GstStructure *config;

  if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
          query))
    return FALSE;

  g_assert (gst_query_get_n_allocation_pools (query) > 0);
  gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
  g_assert (pool != NULL);

  config = gst_buffer_pool_get_config (pool);
  if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
    gst_buffer_pool_config_add_option (config,
        GST_BUFFER_POOL_OPTION_VIDEO_META);
  }
  gst_buffer_pool_set_config (pool, config);
  gst_object_unref (pool);

  return TRUE;
}
