/* GStreamer
 * Copyright (C) 2006 Wim Taymans <wim@fluendo.com>
 *
 * gstoggaviparse.c: ogg avi stream parser
 *
 * 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.
 */

/*
 * Ogg in AVI is mostly done for vorbis audio. In the codec_data we receive the
 * first 3 packets of the raw vorbis data. On the sinkpad we receive full-blown Ogg
 * pages. 
 * Before extracting the packets out of the ogg pages, we push the raw vorbis
 * header packets to the decoder.
 * We don't use the incomming timestamps but use the ganulepos on the ogg pages
 * directly.
 * This parser only does ogg/vorbis for now.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <ogg/ogg.h>
#include <string.h>

#include "gstogg.h"

GST_DEBUG_CATEGORY_STATIC (gst_ogg_avi_parse_debug);
#define GST_CAT_DEFAULT gst_ogg_avi_parse_debug

#define GST_TYPE_OGG_AVI_PARSE (gst_ogg_avi_parse_get_type())
#define GST_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse))
#define GST_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse))
#define GST_IS_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_AVI_PARSE))
#define GST_IS_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_AVI_PARSE))

static GType gst_ogg_avi_parse_get_type (void);

typedef struct _GstOggAviParse GstOggAviParse;
typedef struct _GstOggAviParseClass GstOggAviParseClass;

struct _GstOggAviParse
{
  GstElement element;

  GstPad *sinkpad;
  GstPad *srcpad;

  gboolean discont;
  gint serial;

  ogg_sync_state sync;
  ogg_stream_state stream;
};

struct _GstOggAviParseClass
{
  GstElementClass parent_class;
};

static void gst_ogg_avi_parse_base_init (gpointer g_class);
static void gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass);
static void gst_ogg_avi_parse_init (GstOggAviParse * ogg);
static GstElementClass *parent_class = NULL;

static GType
gst_ogg_avi_parse_get_type (void)
{
  static GType ogg_avi_parse_type = 0;

  if (!ogg_avi_parse_type) {
    static const GTypeInfo ogg_avi_parse_info = {
      sizeof (GstOggAviParseClass),
      gst_ogg_avi_parse_base_init,
      NULL,
      (GClassInitFunc) gst_ogg_avi_parse_class_init,
      NULL,
      NULL,
      sizeof (GstOggAviParse),
      0,
      (GInstanceInitFunc) gst_ogg_avi_parse_init,
    };

    ogg_avi_parse_type =
        g_type_register_static (GST_TYPE_ELEMENT, "GstOggAviParse",
        &ogg_avi_parse_info, 0);
  }
  return ogg_avi_parse_type;
}

enum
{
  PROP_0
};

static GstStaticPadTemplate ogg_avi_parse_src_template_factory =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("audio/x-vorbis")
    );

static GstStaticPadTemplate ogg_avi_parse_sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("application/x-ogg-avi")
    );

static void gst_ogg_avi_parse_finalize (GObject * object);
static GstStateChangeReturn gst_ogg_avi_parse_change_state (GstElement *
    element, GstStateChange transition);
static gboolean gst_ogg_avi_parse_event (GstPad * pad, GstObject * parent,
    GstEvent * event);
static GstFlowReturn gst_ogg_avi_parse_chain (GstPad * pad, GstObject * parent,
    GstBuffer * buffer);
static gboolean gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps);

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

  gst_element_class_set_static_metadata (element_class,
      "Ogg AVI parser", "Codec/Parser",
      "parse an ogg avi stream into pages (info about ogg: http://xiph.org)",
      "Wim Taymans <wim@fluendo.com>");

  gst_element_class_add_static_pad_template (element_class,
      &ogg_avi_parse_sink_template_factory);
  gst_element_class_add_static_pad_template (element_class,
      &ogg_avi_parse_src_template_factory);
}

static void
gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass)
{
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  parent_class = g_type_class_peek_parent (klass);

  gstelement_class->change_state = gst_ogg_avi_parse_change_state;

  gobject_class->finalize = gst_ogg_avi_parse_finalize;
}

static void
gst_ogg_avi_parse_init (GstOggAviParse * ogg)
{
  /* create the sink and source pads */
  ogg->sinkpad =
      gst_pad_new_from_static_template (&ogg_avi_parse_sink_template_factory,
      "sink");
  gst_pad_set_event_function (ogg->sinkpad, gst_ogg_avi_parse_event);
  gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_avi_parse_chain);
  gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);

  ogg->srcpad =
      gst_pad_new_from_static_template (&ogg_avi_parse_src_template_factory,
      "src");
  gst_pad_use_fixed_caps (ogg->srcpad);
  gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad);
}

static void
gst_ogg_avi_parse_finalize (GObject * object)
{
  GstOggAviParse *ogg = GST_OGG_AVI_PARSE (object);

  GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg);

  ogg_sync_clear (&ogg->sync);
  ogg_stream_clear (&ogg->stream);

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

static gboolean
gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps)
{
  GstOggAviParse *ogg;
  GstStructure *structure;
  const GValue *codec_data;
  GstBuffer *buffer;
  GstMapInfo map;
  guint8 *ptr;
  gsize left;
  guint32 sizes[3];
  GstCaps *outcaps;
  gint i, offs;

  ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));

  structure = gst_caps_get_structure (caps, 0);

  /* take codec data */
  codec_data = gst_structure_get_value (structure, "codec_data");
  if (codec_data == NULL)
    goto no_data;

  /* only buffers are valid */
  if (G_VALUE_TYPE (codec_data) != GST_TYPE_BUFFER)
    goto wrong_format;

  /* Now parse the data */
  buffer = gst_value_get_buffer (codec_data);

  /* first 22 bytes are bits_per_sample, channel_mask, GUID
   * Then we get 3 LE guint32 with the 3 header sizes
   * then we get the bytes of the 3 headers. */
  gst_buffer_map (buffer, &map, GST_MAP_READ);

  ptr = map.data;
  left = map.size;

  GST_LOG_OBJECT (ogg, "configuring codec_data of size %" G_GSIZE_FORMAT, left);

  /* skip headers */
  ptr += 22;
  left -= 22;

  /* we need at least 12 bytes for the packet sizes of the 3 headers */
  if (left < 12)
    goto buffer_too_small;

  /* read sizes of the 3 headers */
  sizes[0] = GST_READ_UINT32_LE (ptr);
  sizes[1] = GST_READ_UINT32_LE (ptr + 4);
  sizes[2] = GST_READ_UINT32_LE (ptr + 8);

  GST_DEBUG_OBJECT (ogg, "header sizes: %u %u %u", sizes[0], sizes[1],
      sizes[2]);

  left -= 12;

  /* and we need at least enough data for all the headers */
  if (left < sizes[0] + sizes[1] + sizes[2])
    goto buffer_too_small;

  /* set caps */
  outcaps = gst_caps_new_empty_simple ("audio/x-vorbis");
  gst_pad_set_caps (ogg->srcpad, outcaps);
  gst_caps_unref (outcaps);

  /* copy header data */
  offs = 34;
  for (i = 0; i < 3; i++) {
    GstBuffer *out;

    /* now output the raw vorbis header packets */
    out = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, offs, sizes[i]);
    gst_pad_push (ogg->srcpad, out);

    offs += sizes[i];
  }
  gst_buffer_unmap (buffer, &map);

  return TRUE;

  /* ERRORS */
no_data:
  {
    GST_DEBUG_OBJECT (ogg, "no codec_data found in caps");
    return FALSE;
  }
wrong_format:
  {
    GST_DEBUG_OBJECT (ogg, "codec_data is not a buffer");
    return FALSE;
  }
buffer_too_small:
  {
    GST_DEBUG_OBJECT (ogg, "codec_data is too small");
    gst_buffer_unmap (buffer, &map);
    return FALSE;
  }
}

static gboolean
gst_ogg_avi_parse_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstOggAviParse *ogg;
  gboolean ret;

  ogg = GST_OGG_AVI_PARSE (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      ret = gst_ogg_avi_parse_setcaps (pad, caps);
      gst_event_unref (event);
      break;
    }
    case GST_EVENT_FLUSH_START:
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
      ogg_sync_reset (&ogg->sync);
      ogg_stream_reset (&ogg->stream);
      ogg->discont = TRUE;
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
    default:
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
  }
  return ret;
}

static GstFlowReturn
gst_ogg_avi_parse_push_packet (GstOggAviParse * ogg, ogg_packet * packet)
{
  GstBuffer *buffer;
  GstFlowReturn result;

  /* allocate space for header and body */
  buffer = gst_buffer_new_and_alloc (packet->bytes);
  gst_buffer_fill (buffer, 0, packet->packet, packet->bytes);

  GST_LOG_OBJECT (ogg, "created buffer %p from page", buffer);

  GST_BUFFER_OFFSET_END (buffer) = packet->granulepos;

  if (ogg->discont) {
    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
    ogg->discont = FALSE;
  }

  result = gst_pad_push (ogg->srcpad, buffer);

  return result;
}

static GstFlowReturn
gst_ogg_avi_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstFlowReturn result = GST_FLOW_OK;
  GstOggAviParse *ogg;
  guint size;
  gchar *oggbuf;
  gint ret = -1;

  ogg = GST_OGG_AVI_PARSE (parent);

  size = gst_buffer_get_size (buffer);

  GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size);

  if (GST_BUFFER_IS_DISCONT (buffer)) {
    ogg_sync_reset (&ogg->sync);
    ogg->discont = TRUE;
  }

  /* write data to sync layer */
  oggbuf = ogg_sync_buffer (&ogg->sync, size);
  gst_buffer_extract (buffer, 0, oggbuf, size);
  ogg_sync_wrote (&ogg->sync, size);
  gst_buffer_unref (buffer);

  /* try to get as many packets out of the stream as possible */
  do {
    ogg_page page;

    /* try to swap out a page */
    ret = ogg_sync_pageout (&ogg->sync, &page);
    if (ret == 0) {
      GST_DEBUG_OBJECT (ogg, "need more data");
      break;
    } else if (ret == -1) {
      GST_DEBUG_OBJECT (ogg, "discont in pages");
      ogg->discont = TRUE;
    } else {
      /* new unknown stream, init the ogg stream with the serial number of the
       * page. */
      if (ogg->serial == -1) {
        ogg->serial = ogg_page_serialno (&page);
        ogg_stream_init (&ogg->stream, ogg->serial);
      }

      /* submit page */
      if (ogg_stream_pagein (&ogg->stream, &page) != 0) {
        GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream");
        ogg_sync_reset (&ogg->sync);
        ogg->discont = TRUE;
        continue;
      }

      /* try to get as many packets as possible out of the page */
      do {
        ogg_packet packet;

        ret = ogg_stream_packetout (&ogg->stream, &packet);
        GST_LOG_OBJECT (ogg, "packetout gave %d", ret);
        switch (ret) {
          case 0:
            break;
          case -1:
            /* out of sync, We mark a DISCONT. */
            ogg->discont = TRUE;
            break;
          case 1:
            result = gst_ogg_avi_parse_push_packet (ogg, &packet);
            if (result != GST_FLOW_OK)
              goto done;
            break;
          default:
            GST_WARNING_OBJECT (ogg,
                "invalid return value %d for ogg_stream_packetout, resetting stream",
                ret);
            break;
        }
      }
      while (ret != 0);
    }
  }
  while (ret != 0);

done:
  return result;
}

static GstStateChangeReturn
gst_ogg_avi_parse_change_state (GstElement * element, GstStateChange transition)
{
  GstOggAviParse *ogg;
  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;

  ogg = GST_OGG_AVI_PARSE (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      ogg_sync_init (&ogg->sync);
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      ogg_sync_reset (&ogg->sync);
      ogg_stream_reset (&ogg->stream);
      ogg->serial = -1;
      ogg->discont = TRUE;
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  result = parent_class->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      ogg_sync_clear (&ogg->sync);
      break;
    default:
      break;
  }
  return result;
}

gboolean
gst_ogg_avi_parse_plugin_init (GstPlugin * plugin)
{
  GST_DEBUG_CATEGORY_INIT (gst_ogg_avi_parse_debug, "oggaviparse", 0,
      "ogg avi parser");

  return gst_element_register (plugin, "oggaviparse", GST_RANK_PRIMARY,
      GST_TYPE_OGG_AVI_PARSE);
}
