/* GStreamer PNM encoder
 * Copyright (C) 2009 Lutz Mueller <lutz@users.sourceforge.net>
 *
 * 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.
 */

/**
 * SECTION:element-pnmenc
 *
 * Encodes pnm images. This plugin supports both raw and ASCII encoding.
 * To enable ASCII encoding, set the parameter ascii to TRUE. If you omit
 * the parameter or set it to FALSE, the output will be raw encoded.
 *
 * <refsect2>
 * <title>Example launch line</title>
 * |[
 * gst-launch-1.0 videotestsrc num_buffers=1 ! videoconvert ! "video/x-raw,format=GRAY8" ! pnmenc ascii=true ! filesink location=test.pnm
 * ]| The above pipeline writes a test pnm file (ASCII encoding).
 * </refsect2>
 */

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

#include "gstpnmenc.h"
#include "gstpnmutils.h"

#include <gst/gstutils.h>
#include <gst/video/video.h>
#include <gst/video/gstvideometa.h>
#include <stdio.h>

#include <string.h>

enum
{
  GST_PNMENC_PROP_0,
  GST_PNMENC_PROP_ASCII
      /* Add here. */
};



static GstStaticPadTemplate sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
        ("{ RGB, GRAY8, GRAY16_BE, GRAY16_LE }")));


static GstStaticPadTemplate src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
    GST_STATIC_CAPS (MIME_ALL));

G_DEFINE_TYPE (GstPnmenc, gst_pnmenc, GST_TYPE_VIDEO_ENCODER);
#define parent_class gst_pnmenc_parent_class

static GstFlowReturn
gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame);

static void gst_pnmenc_finalize (GObject * object);

static void
gst_pnmenc_set_property (GObject * object, guint prop_id, const GValue * value,
    GParamSpec * pspec)
{
  GstPnmenc *s = GST_PNMENC (object);

  switch (prop_id) {
    case GST_PNMENC_PROP_ASCII:
      if (g_value_get_boolean (value)) {
        s->info.encoding = GST_PNM_ENCODING_ASCII;
      } else {
        s->info.encoding = GST_PNM_ENCODING_RAW;
      }
      s->info.fields |= GST_PNM_INFO_FIELDS_ENCODING;
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_pnmenc_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstPnmenc *s = GST_PNMENC (object);

  switch (prop_id) {
    case GST_PNMENC_PROP_ASCII:
      g_value_set_boolean (value, s->info.encoding == GST_PNM_ENCODING_ASCII);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_pnmenc_init (GstPnmenc * s)
{
  GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (s));

  /* Set default encoding as RAW as ASCII takes up 4 time more bytes */
  s->info.encoding = GST_PNM_ENCODING_RAW;
}

static void
gst_pnmenc_finalize (GObject * object)
{
  GstPnmenc *pnmenc = GST_PNMENC (object);
  if (pnmenc->input_state)
    gst_video_codec_state_unref (pnmenc->input_state);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static gboolean
gst_pnmenc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
{
  GstPnmenc *pnmenc;
  gboolean ret = TRUE;
  GstVideoInfo *info;
  GstVideoCodecState *output_state;
  const gchar *mime_type = NULL;

  pnmenc = GST_PNMENC (encoder);
  info = &state->info;

  switch (GST_VIDEO_INFO_FORMAT (info)) {
    case GST_VIDEO_FORMAT_RGB:
      pnmenc->info.max = 255;
      pnmenc->info.type = GST_PNM_TYPE_PIXMAP;
      mime_type = MIME_PM;
      break;
    case GST_VIDEO_FORMAT_GRAY8:
      pnmenc->info.max = 255;
      pnmenc->info.type = GST_PNM_TYPE_GRAYMAP;
      mime_type = MIME_GM;
      break;
    case GST_VIDEO_FORMAT_GRAY16_BE:
    case GST_VIDEO_FORMAT_GRAY16_LE:
      pnmenc->info.max = 65535;
      pnmenc->info.type = GST_PNM_TYPE_GRAYMAP;
      mime_type = MIME_GM;
      break;
    default:
      ret = FALSE;
      goto done;
  }

  pnmenc->info.width = GST_VIDEO_INFO_WIDTH (info);
  pnmenc->info.height = GST_VIDEO_INFO_HEIGHT (info);

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

  output_state =
      gst_video_encoder_set_output_state (encoder,
      gst_caps_new_empty_simple (mime_type), state);
  gst_video_codec_state_unref (output_state);

done:
  return ret;
}

static GstFlowReturn
gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
{
  GstPnmenc *pnmenc;
  guint size, pixels, bytesize;
  GstMapInfo omap, imap;
  gchar *header = NULL;
  GstVideoInfo *info;
  GstFlowReturn ret = GST_FLOW_OK;
  guint i_rowstride, o_rowstride;
  guint bytes = 0, index, head_size;
  guint i, j;
  guint maxbytes_per_pixel, str_len;
  gchar format_str[4];
  pnmenc = GST_PNMENC (encoder);
  info = &pnmenc->input_state->info;

  switch (GST_VIDEO_INFO_FORMAT (info)) {
    case GST_VIDEO_FORMAT_RGB:
      pixels = size = pnmenc->info.width * pnmenc->info.height * 3;
      bytesize = 1;
      maxbytes_per_pixel = 4;
      str_len = 3;
      g_strlcpy (format_str, "%3i", 4);
      break;
    case GST_VIDEO_FORMAT_GRAY8:
      pixels = size = pnmenc->info.width * pnmenc->info.height * 1;
      bytesize = 1;
      maxbytes_per_pixel = 4;
      str_len = 3;
      g_strlcpy (format_str, "%3i", 4);
      break;
    case GST_VIDEO_FORMAT_GRAY16_LE:
    case GST_VIDEO_FORMAT_GRAY16_BE:
      pixels = pnmenc->info.width * pnmenc->info.height * 1;
      bytesize = 2;
      size = pixels * bytesize;
      maxbytes_per_pixel = 6;
      str_len = 5;
      g_strlcpy (format_str, "%5i", 4);
      break;
    default:
      ret = FALSE;
      goto done;
  }

  header = g_strdup_printf ("P%i\n%i %i\n%i\n",
      pnmenc->info.type + 3 * (1 - pnmenc->info.encoding), pnmenc->info.width,
      pnmenc->info.height, pnmenc->info.max);

  if (pnmenc->info.encoding == GST_PNM_ENCODING_ASCII) {
    /* Per component 4 bytes are used in case of ASCII encoding */
    size = size * 4 + size / 20;
    size += strlen (header);
    frame->output_buffer =
        gst_video_encoder_allocate_output_buffer (encoder, (size));
  } else {
    size += strlen (header);
    frame->output_buffer =
        gst_video_encoder_allocate_output_buffer (encoder, size);
  }

  if (gst_buffer_map (frame->output_buffer, &omap, GST_MAP_WRITE) == FALSE) {
    ret = GST_FLOW_ERROR;
    goto done;
  }
  if (gst_buffer_map (frame->input_buffer, &imap, GST_MAP_READ) == FALSE) {
    /* Unmap already mapped buffer */
    gst_buffer_unmap (frame->output_buffer, &omap);
    ret = GST_FLOW_ERROR;
    goto done;
  }
  /* Copy out the header first */
  head_size = strlen (header);
  memcpy (omap.data, header, head_size);

  if (pnmenc->info.encoding == GST_PNM_ENCODING_ASCII) {
    /* We need to convert to ASCII */
    /* Convert from gstreamer rowstride to PNM rowstride as we go */
    if (pnmenc->info.type == GST_PNM_TYPE_PIXMAP) {
      o_rowstride = 3 * pnmenc->info.width;
    } else {
      o_rowstride = pnmenc->info.width;
    }
    i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0);

    switch (GST_VIDEO_INFO_FORMAT (info)) {
      case GST_VIDEO_FORMAT_RGB:
      case GST_VIDEO_FORMAT_GRAY8:
        for (i = 0; i < pnmenc->info.height; i++) {
          index = i * i_rowstride;
          for (j = 0; j < o_rowstride; j++, bytes++, index++) {
            g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel,
                format_str, imap.data[index]);
            head_size += str_len;
            omap.data[head_size++] = ' ';
            /* Add new line so that file will not end up with single big line */
            if (!((bytes + 1) % 20))
              omap.data[head_size++] = '\n';
          }
        }
        break;
      case GST_VIDEO_FORMAT_GRAY16_BE:
        for (i = 0; i < pnmenc->info.height; i++) {
          index = i * i_rowstride;
          for (j = 0; j < o_rowstride; j++, bytes++, index += 2) {
            g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel,
                format_str, GST_READ_UINT16_BE (imap.data + index));
            head_size += str_len;
            omap.data[head_size++] = ' ';
            /* Add new line so that file will not end up with single big line */
            if (!((bytes + 1) % 20))
              omap.data[head_size++] = '\n';
          }
        }
        break;
      case GST_VIDEO_FORMAT_GRAY16_LE:
        for (i = 0; i < pnmenc->info.height; i++) {
          index = i * i_rowstride;
          for (j = 0; j < o_rowstride; j++, bytes++, index += 2) {
            g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel,
                format_str, GST_READ_UINT16_LE (imap.data + index));
            head_size += str_len;
            omap.data[head_size++] = ' ';
            /* Add new line so that file will not end up with single big line */
            if (!((bytes + 1) % 20))
              omap.data[head_size++] = '\n';
          }
        }
        break;
      default:
        GST_ERROR_OBJECT (encoder, "Unhandled format %s",
            gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
        gst_buffer_unmap (frame->output_buffer, &omap);
        gst_buffer_unmap (frame->input_buffer, &imap);
        g_free (header);
        return GST_FLOW_ERROR;
    }

    gst_buffer_set_size (frame->output_buffer, head_size);
  } else {
    guint out_index = head_size;

    /* Binary output. 8-bit, or 16-bit BE */
    if (pnmenc->info.type == GST_PNM_TYPE_PIXMAP) {
      o_rowstride = 3 * pnmenc->info.width * bytesize;
    } else {
      o_rowstride = pnmenc->info.width * bytesize;
    }
    i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0);

    switch (GST_VIDEO_INFO_FORMAT (info)) {
      case GST_VIDEO_FORMAT_GRAY16_BE:
        for (i = 0; i < pnmenc->info.height; i++) {
          index = i * i_rowstride;
          for (j = 0; j < o_rowstride; j += 2, index += 2) {
            guint16 val = GST_READ_UINT16_LE (imap.data + index);
            GST_WRITE_UINT16_BE (omap.data + out_index, val);
            out_index += 2;
          }
        }
        break;
      case GST_VIDEO_FORMAT_GRAY16_LE:
        for (i = 0; i < pnmenc->info.height; i++) {
          index = i * i_rowstride;
          for (j = 0; j < o_rowstride; j += 2, index += 2) {
            guint16 val = GST_READ_UINT16_LE (imap.data + index);
            GST_WRITE_UINT16_BE (omap.data + out_index, val);
            out_index += 2;
          }
        }
        break;
      default:
        for (i = 0; i < pnmenc->info.height; i++) {
          memcpy (omap.data + head_size + o_rowstride * i,
              imap.data + i_rowstride * i, o_rowstride);
        }
    }
  }

  gst_buffer_unmap (frame->output_buffer, &omap);
  gst_buffer_unmap (frame->input_buffer, &imap);

  if ((ret = gst_video_encoder_finish_frame (encoder, frame)) != GST_FLOW_OK)
    goto done;

done:
  g_free (header);
  return ret;
}

static void
gst_pnmenc_class_init (GstPnmencClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstVideoEncoderClass *venc_class = (GstVideoEncoderClass *) klass;

  parent_class = g_type_class_peek_parent (klass);
  gobject_class->set_property = gst_pnmenc_set_property;
  gobject_class->get_property = gst_pnmenc_get_property;

  g_object_class_install_property (gobject_class, GST_PNMENC_PROP_ASCII,
      g_param_spec_boolean ("ascii", "ASCII Encoding", "The output will be "
          "ASCII encoded", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  gst_element_class_add_static_pad_template (element_class, &sink_pad_template);
  gst_element_class_add_static_pad_template (element_class, &src_pad_template);

  gst_element_class_set_static_metadata (element_class, "PNM image encoder",
      "Codec/Encoder/Image",
      "Encodes images into portable pixmap or graymap (PNM) format",
      "Lutz Mueller <lutz@users.sourceforge.net>");

  venc_class->set_format = gst_pnmenc_set_format;
  venc_class->handle_frame = gst_pnmenc_handle_frame;
  gobject_class->finalize = gst_pnmenc_finalize;
}
