/*
 * Farsight
 * GStreamer GSM encoder
 * Copyright (C) 2005 Philippe Khalaf <burger@speedy.org>
 *
 * 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 <string.h>

#include "gstgsmenc.h"

GST_DEBUG_CATEGORY_STATIC (gsmenc_debug);
#define GST_CAT_DEFAULT (gsmenc_debug)

/* GSMEnc signals and args */
enum
{
  /* FILL ME */
  LAST_SIGNAL
};

enum
{
  /* FILL ME */
  ARG_0
};

static gboolean gst_gsmenc_start (GstAudioEncoder * enc);
static gboolean gst_gsmenc_stop (GstAudioEncoder * enc);
static gboolean gst_gsmenc_set_format (GstAudioEncoder * enc,
    GstAudioInfo * info);
static GstFlowReturn gst_gsmenc_handle_frame (GstAudioEncoder * enc,
    GstBuffer * in_buf);

static GstStaticPadTemplate gsmenc_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-gsm, " "rate = (int) 8000, " "channels = (int) 1")
    );

static GstStaticPadTemplate gsmenc_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-raw, "
        "format = (string) " GST_AUDIO_NE (S16) ", "
        "layout = (string) interleaved, "
        "rate = (int) 8000, channels = (int) 1")
    );

G_DEFINE_TYPE (GstGSMEnc, gst_gsmenc, GST_TYPE_AUDIO_ENCODER);

static void
gst_gsmenc_class_init (GstGSMEncClass * klass)
{
  GstElementClass *element_class;
  GstAudioEncoderClass *base_class;

  element_class = (GstElementClass *) klass;
  base_class = (GstAudioEncoderClass *) klass;

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&gsmenc_sink_template));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&gsmenc_src_template));
  gst_element_class_set_static_metadata (element_class, "GSM audio encoder",
      "Codec/Encoder/Audio",
      "Encodes GSM audio", "Philippe Khalaf <burger@speedy.org>");

  base_class->start = GST_DEBUG_FUNCPTR (gst_gsmenc_start);
  base_class->stop = GST_DEBUG_FUNCPTR (gst_gsmenc_stop);
  base_class->set_format = GST_DEBUG_FUNCPTR (gst_gsmenc_set_format);
  base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_gsmenc_handle_frame);

  GST_DEBUG_CATEGORY_INIT (gsmenc_debug, "gsmenc", 0, "GSM Encoder");
}

static void
gst_gsmenc_init (GstGSMEnc * gsmenc)
{
}

static gboolean
gst_gsmenc_start (GstAudioEncoder * enc)
{
  GstGSMEnc *gsmenc = GST_GSMENC (enc);
  gint use_wav49;

  GST_DEBUG_OBJECT (enc, "start");

  gsmenc->state = gsm_create ();

  /* turn off WAV49 handling */
  use_wav49 = 0;
  gsm_option (gsmenc->state, GSM_OPT_WAV49, &use_wav49);

  return TRUE;
}

static gboolean
gst_gsmenc_stop (GstAudioEncoder * enc)
{
  GstGSMEnc *gsmenc = GST_GSMENC (enc);

  GST_DEBUG_OBJECT (enc, "stop");
  gsm_destroy (gsmenc->state);

  return TRUE;
}

static gboolean
gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
{
  GstCaps *srccaps;

  srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template);
  gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (benc), srccaps);
  gst_caps_unref (srccaps);

  /* report needs to base class */
  gst_audio_encoder_set_frame_samples_min (benc, 160);
  gst_audio_encoder_set_frame_samples_max (benc, 160);
  gst_audio_encoder_set_frame_max (benc, 1);

  return TRUE;
}

static GstFlowReturn
gst_gsmenc_handle_frame (GstAudioEncoder * benc, GstBuffer * buffer)
{
  GstGSMEnc *gsmenc;
  gsm_signal *data;
  GstFlowReturn ret = GST_FLOW_OK;
  GstBuffer *outbuf;
  GstMapInfo map, omap;

  gsmenc = GST_GSMENC (benc);

  /* we don't deal with squeezing remnants, so simply discard those */
  if (G_UNLIKELY (buffer == NULL)) {
    GST_DEBUG_OBJECT (gsmenc, "no data");
    goto done;
  }

  gst_buffer_map (buffer, &map, GST_MAP_READ);
  if (G_UNLIKELY (map.size < 320)) {
    GST_DEBUG_OBJECT (gsmenc, "discarding trailing data %d", (gint) map.size);
    gst_buffer_unmap (buffer, &map);
    ret = gst_audio_encoder_finish_frame (benc, NULL, -1);
    goto done;
  }

  outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte));
  gst_buffer_map (outbuf, &omap, GST_MAP_WRITE);

  /* encode 160 16-bit samples into 33 bytes */
  data = (gsm_signal *) map.data;
  gsm_encode (gsmenc->state, data, (gsm_byte *) omap.data);

  GST_LOG_OBJECT (gsmenc, "encoded to %d bytes", (gint) omap.size);
  gst_buffer_unmap (buffer, &map);
  gst_buffer_unmap (buffer, &omap);

  ret = gst_audio_encoder_finish_frame (benc, outbuf, 160);

done:
  return ret;
}
