/* GStreamer RTP ASF depayloader
 * Copyright (C) 2006 Tim-Philipp Müller  <tim centricular net>
 *               2009 Wim Taymans  <wim.taymans@gmail.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 "gstrtpasfdepay.h"
#include <gst/rtp/gstrtpbuffer.h>

#include <string.h>
#include <stdlib.h>

GST_DEBUG_CATEGORY_STATIC (rtpasfdepayload_debug);
#define GST_CAT_DEFAULT rtpasfdepayload_debug

static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-ms-asf")
    );

/* Other parameters: config, maxps */
#define SINK_CAPS \
  "application/x-rtp, "                                          \
  "media = (string) { \"application\", \"video\", \"audio\" }, " \
  "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "         \
  "clock-rate = (int) [1, MAX ], "                               \
  "encoding-name = (string) \"X-ASF-PF\""

static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (SINK_CAPS)
    );

#define gst_rtp_asf_depay_parent_class parent_class
G_DEFINE_TYPE (GstRtpAsfDepay, gst_rtp_asf_depay, GST_TYPE_RTP_BASE_DEPAYLOAD);

static void gst_rtp_asf_depay_finalize (GObject * object);

static GstStateChangeReturn gst_rtp_asf_depay_change_state (GstElement *
    element, GstStateChange transition);

static gboolean gst_rtp_asf_depay_setcaps (GstRTPBaseDepayload * depay,
    GstCaps * caps);
static GstBuffer *gst_rtp_asf_depay_process (GstRTPBaseDepayload * basedepay,
    GstBuffer * buf);

static void
gst_rtp_asf_depay_class_init (GstRtpAsfDepayClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
  GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;

  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
  gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;

  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&src_factory));
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&sink_factory));

  gst_element_class_set_static_metadata (gstelement_class,
      "RTP ASF packet depayloader", "Codec/Depayloader/Network",
      "Extracts ASF streams from RTP",
      "Tim-Philipp Müller <tim centricular net>, "
      "Wim Taymans <wim.taymans@gmail.com>");

  gobject_class->finalize = gst_rtp_asf_depay_finalize;

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_rtp_asf_depay_change_state);

  gstrtpbasedepayload_class->set_caps =
      GST_DEBUG_FUNCPTR (gst_rtp_asf_depay_setcaps);
  gstrtpbasedepayload_class->process =
      GST_DEBUG_FUNCPTR (gst_rtp_asf_depay_process);

  GST_DEBUG_CATEGORY_INIT (rtpasfdepayload_debug, "rtpasfdepayload", 0,
      "RTP asf depayloader element");
}

static void
gst_rtp_asf_depay_init (GstRtpAsfDepay * depay)
{
  depay->adapter = gst_adapter_new ();
}

static void
gst_rtp_asf_depay_finalize (GObject * object)
{
  GstRtpAsfDepay *depay;

  depay = GST_RTP_ASF_DEPAY (object);

  g_object_unref (depay->adapter);

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

static const guint8 asf_marker[16] = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66,
  0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c
};

static gboolean
gst_rtp_asf_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
{
  GstRtpAsfDepay *depay;
  GstStructure *s;
  const gchar *config_str, *ps_string;
  GstBuffer *buf;
  GstCaps *src_caps;
  guint8 *headers;
  gsize headers_len;
  gint clock_rate;

  depay = GST_RTP_ASF_DEPAY (depayload);

  s = gst_caps_get_structure (caps, 0);

  if (!gst_structure_get_int (s, "clock-rate", &clock_rate) || clock_rate < 0)
    clock_rate = 1000;
  depayload->clock_rate = clock_rate;

  /* config contains the asf headers in base64 coding */
  config_str = gst_structure_get_string (s, "config");
  if (config_str == NULL || *config_str == '\0')
    goto no_config;

  ps_string = gst_structure_get_string (s, "maxps");
  if (ps_string == NULL || *ps_string == '\0')
    goto no_packetsize;

  if (depay->packet_size) {
    /* header sent again following seek;
     * discard to avoid confusing upstream */
    if (depay->packet_size == atoi (ps_string)) {
      goto duplicate_header;
    } else {
      /* since we should fiddle with downstream state to handle this */
      goto refuse_renegotiation;
    }
  } else
    depay->packet_size = atoi (ps_string);
  if (depay->packet_size <= 16)
    goto invalid_packetsize;

  headers = (guint8 *) g_base64_decode (config_str, &headers_len);

  if (headers == NULL || headers_len < 16
      || memcmp (headers, asf_marker, 16) != 0)
    goto invalid_headers;

  src_caps = gst_caps_new_empty_simple ("video/x-ms-asf");
  gst_pad_set_caps (depayload->srcpad, src_caps);
  gst_caps_unref (src_caps);

  buf = gst_buffer_new ();
  gst_buffer_append_memory (buf,
      gst_memory_new_wrapped (0, headers, headers_len, 0, headers_len, headers,
          g_free));

  gst_rtp_base_depayload_push (depayload, buf);

  return TRUE;

  /* ERRORS */
no_config:
  {
    GST_WARNING_OBJECT (depay, "caps without 'config' field with asf headers");
    return FALSE;
  }
no_packetsize:
  {
    GST_WARNING_OBJECT (depay, "caps without 'maxps' (packet size) field");
    return FALSE;
  }
invalid_packetsize:
  {
    GST_WARNING_OBJECT (depay, "packet size %u invalid", depay->packet_size);
    return FALSE;
  }
invalid_headers:
  {
    GST_WARNING_OBJECT (depay, "headers don't look like valid ASF headers");
    g_free (headers);
    return FALSE;
  }
duplicate_header:
  {
    GST_DEBUG_OBJECT (depayload, "discarding duplicate header");
    return TRUE;
  }
refuse_renegotiation:
  {
    GST_WARNING_OBJECT (depayload, "cannot renegotiate to different header");
    return FALSE;
  }
}

static gint
field_size (guint8 field)
{
  switch (field) {
      /* DWORD - 32 bits */
    case 3:
      return 4;

      /* WORD - 16 bits */
    case 2:
      return 2;

      /* BYTE - 8 bits */
    case 1:
      return 1;

      /* non-exitent */
    case 0:
    default:
      return 0;
  }
}

/* Set the padding field to te correct value as the spec
 * says it should be se to 0 in the rtp packets
 */
static GstBuffer *
gst_rtp_asf_depay_update_padding (GstRtpAsfDepay * depayload, GstBuffer * buf)
{
  GstBuffer *result;
  GstMapInfo map;
  guint8 *data;
  gint offset = 0;
  guint8 aux;
  guint8 seq_type;
  guint8 pad_type;
  guint8 pkt_type;
  gsize plen, padding;

  plen = gst_buffer_get_size (buf);
  if (plen == depayload->packet_size)
    return buf;

  padding = depayload->packet_size - plen;

  GST_LOG_OBJECT (depayload,
      "padding buffer size %" G_GSIZE_FORMAT " to packet size %d", plen,
      depayload->packet_size);

  result = gst_buffer_new_and_alloc (depayload->packet_size);

  gst_buffer_map (result, &map, GST_MAP_READ);
  data = map.data;
  memset (data + plen, 0, padding);

  gst_buffer_extract (buf, 0, data, plen);
  gst_buffer_unref (buf);

  aux = data[offset++];
  if (aux & 0x80) {
    guint8 err_len = 0;
    if (aux & 0x60) {
      GST_WARNING_OBJECT (depayload, "Error correction length type should be "
          "set to 0");
      /* this packet doesn't follow the spec */
      gst_buffer_unmap (result, &map);
      return result;
    }
    err_len = aux & 0x0F;
    offset += err_len;

    aux = data[offset++];
  }
  seq_type = (aux >> 1) & 0x3;
  pad_type = (aux >> 3) & 0x3;
  pkt_type = (aux >> 5) & 0x3;

  offset += 1;                  /* skip property flags */
  offset += field_size (pkt_type);      /* skip packet length */
  offset += field_size (seq_type);      /* skip sequence field */

  /* write padding */
  switch (pad_type) {
      /* DWORD */
    case 3:
      GST_WRITE_UINT32_LE (&(data[offset]), padding);
      break;

      /* WORD */
    case 2:
      GST_WRITE_UINT16_LE (&(data[offset]), padding);
      break;

      /* BYTE */
    case 1:
      data[offset] = (guint8) padding;
      break;

      /* non-existent */
    case 0:
    default:
      break;
  }
  gst_buffer_unmap (result, &map);

  return result;
}

/* Docs: 'RTSP Protocol PDF' document from http://sdp.ppona.com/ (page 8) */

static GstBuffer *
gst_rtp_asf_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
{
  GstRtpAsfDepay *depay;
  const guint8 *payload;
  GstBuffer *outbuf;
  gboolean S, L, R, D, I;
  guint payload_len, hdr_len, offset;
  guint len_offs;
  GstClockTime timestamp;
  GstRTPBuffer rtpbuf = { NULL };

  depay = GST_RTP_ASF_DEPAY (depayload);

  /* flush remaining data on discont */
  if (GST_BUFFER_IS_DISCONT (buf)) {
    GST_LOG_OBJECT (depay, "got DISCONT");
    gst_adapter_clear (depay->adapter);
    depay->discont = TRUE;
  }

  gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf);
  timestamp = GST_BUFFER_TIMESTAMP (buf);

  payload_len = gst_rtp_buffer_get_payload_len (&rtpbuf);
  payload = gst_rtp_buffer_get_payload (&rtpbuf);
  offset = 0;

  GST_LOG_OBJECT (depay, "got payload len of %u", payload_len);

  do {
    guint packet_len;

    /* packet header is at least 4 bytes */
    if (payload_len < 4)
      goto too_small;

    /*                      1                   2                   3
     *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * |S|L|R|D|I|RES  | Length/Offset                                 |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * | Relative Timestamp (optional)                                 |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * | Duration (optional)                                           |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     * | LocationId (optional)                                         |
     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *
     * S: packet contains a keyframe.
     * L: If 1, Length/Offset contains length, else contains the byte offset
     *    of the fragment's first byte counted from the beginning of the
     *    complete ASF data packet.
     * R: relative timestamp present
     * D: duration present
     * I: locationid present
     */

    S = ((payload[0] & 0x80) != 0);
    L = ((payload[0] & 0x40) != 0);
    R = ((payload[0] & 0x20) != 0);
    D = ((payload[0] & 0x10) != 0);
    I = ((payload[0] & 0x08) != 0);

    hdr_len = 4;

    len_offs = (payload[1] << 16) | (payload[2] << 8) | payload[3];

    if (R) {
      GST_DEBUG ("Relative timestamp field present : %u",
          GST_READ_UINT32_BE (payload + hdr_len));
      hdr_len += 4;
    }
    if (D) {
      GST_DEBUG ("Duration field present : %u",
          GST_READ_UINT32_BE (payload + hdr_len));
      hdr_len += 4;
    }
    if (I) {
      GST_DEBUG ("LocationId field present : %u",
          GST_READ_UINT32_BE (payload + hdr_len));
      hdr_len += 4;
    }

    GST_LOG_OBJECT (depay, "S %d, L %d, R %d, D %d, I %d", S, L, R, D, I);
    GST_LOG_OBJECT (depay, "payload_len:%d, hdr_len:%d, len_offs:%d",
        payload_len, hdr_len, len_offs);

    if (payload_len < hdr_len)
      goto too_small;

    /* skip headers */
    payload_len -= hdr_len;
    payload += hdr_len;
    offset += hdr_len;

    if (L) {
      /* L bit set, len contains the length of the packet */
      packet_len = len_offs;
    } else {
      /* else it contains an offset which we don't handle yet */
      GST_LOG_OBJECT (depay, "We have a fragmented packet");
      packet_len = payload_len;
    }

    if (packet_len > payload_len)
      packet_len = payload_len;

    GST_LOG_OBJECT (depay, "packet len %u, payload len %u, packet_size:%u",
        packet_len, payload_len, depay->packet_size);

    if (!L) {
      guint available;
      GstBuffer *sub;

      /* Fragmented packet handling */
      outbuf = NULL;

      if (len_offs == (available = gst_adapter_available (depay->adapter))) {
        /* fragment aligns with what we have, add it */
        GST_LOG_OBJECT (depay, "collecting fragment");
        sub =
            gst_rtp_buffer_get_payload_subbuffer (&rtpbuf, offset, packet_len);
        gst_adapter_push (depay->adapter, sub);
        /* RTP marker bit M is set if this is last fragment */
        if (gst_rtp_buffer_get_marker (&rtpbuf)) {
          GST_LOG_OBJECT (depay, "last fragment, assembling packet");
          outbuf =
              gst_adapter_take_buffer (depay->adapter, available + packet_len);
        }
      } else {
        if (available) {
          GST_WARNING_OBJECT (depay, "Offset doesn't match previous data?!");
          GST_DEBUG_OBJECT (depay, "clearing for re-sync");
          gst_adapter_clear (depay->adapter);
        } else
          GST_DEBUG_OBJECT (depay, "waiting for start of packet");
      }
    } else {
      GST_LOG_OBJECT (depay, "collecting packet");
      outbuf =
          gst_rtp_buffer_get_payload_subbuffer (&rtpbuf, offset, packet_len);
    }

    /* If we haven't completed a full ASF packet, return */
    if (!outbuf)
      return NULL;

    outbuf = gst_rtp_asf_depay_update_padding (depay, outbuf);

    if (!S)
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);

    if (depay->discont) {
      GST_LOG_OBJECT (depay, "setting DISCONT");
      GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
      depay->discont = FALSE;
    }

    GST_BUFFER_TIMESTAMP (outbuf) = timestamp;

    gst_rtp_base_depayload_push (depayload, outbuf);

    /* only apply the timestamp to the first buffer of this packet */
    timestamp = -1;

    /* skip packet data */
    payload += packet_len;
    offset += packet_len;
    payload_len -= packet_len;
  } while (payload_len > 0);

  gst_rtp_buffer_unmap (&rtpbuf);

  return NULL;

/* ERRORS */
too_small:
  {
    gst_rtp_buffer_unmap (&rtpbuf);
    GST_WARNING_OBJECT (depayload, "Payload too small, expected at least 4 "
        "bytes for header, but got only %d bytes", payload_len);
    return NULL;
  }
}

static GstStateChangeReturn
gst_rtp_asf_depay_change_state (GstElement * element, GstStateChange trans)
{
  GstStateChangeReturn ret;
  GstRtpAsfDepay *depay;

  depay = GST_RTP_ASF_DEPAY (element);

  switch (trans) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_adapter_clear (depay->adapter);
      depay->discont = TRUE;
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans);

  switch (trans) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_adapter_clear (depay->adapter);
      break;
    default:
      break;
  }

  return ret;
}
