/* Farsight
 * Copyright (C) 2006 Marcel Moreaux <marcelm@spacelabs.nl>
 *           (C) 2008 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.
 */

/*
 * RTP DV depayloader.
 *
 * Important note for NTSC-users:
 *
 * Because the author uses PAL video, and he does not have proper DV
 * documentation (the DV format specification is not freely available),
 * this code may very well contain PAL-specific assumptions.
 */

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

#include "gstrtpdvdepay.h"
#include "gstrtputils.h"

GST_DEBUG_CATEGORY (rtpdvdepay_debug);
#define GST_CAT_DEFAULT (rtpdvdepay_debug)
/* Filter signals and args */
enum
{
  /* FILL ME */
  LAST_SIGNAL
};

enum
{
  PROP_0,
};

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

static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("application/x-rtp, "
        "media = (string) { \"video\", \"audio\" },"
        "encoding-name = (string) \"DV\", "
        "clock-rate = (int) 90000,"
        "encode = (string) { \"SD-VCR/525-60\", \"SD-VCR/625-50\", \"HD-VCR/1125-60\","
        "\"HD-VCR/1250-50\", \"SDL-VCR/525-60\", \"SDL-VCR/625-50\","
        "\"306M/525-60\", \"306M/625-50\", \"314M-25/525-60\","
        "\"314M-25/625-50\", \"314M-50/525-60\", \"314M-50/625-50\" }"
        /* optional parameters can't go in the template
         * "audio = (string) { \"bundled\", \"none\" }"
         */
    )
    );

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

static GstBuffer *gst_rtp_dv_depay_process (GstRTPBaseDepayload * base,
    GstRTPBuffer * rtp);
static gboolean gst_rtp_dv_depay_setcaps (GstRTPBaseDepayload * depayload,
    GstCaps * caps);

#define gst_rtp_dv_depay_parent_class parent_class
G_DEFINE_TYPE (GstRTPDVDepay, gst_rtp_dv_depay, GST_TYPE_RTP_BASE_DEPAYLOAD);


static void
gst_rtp_dv_depay_class_init (GstRTPDVDepayClass * klass)
{
  GstElementClass *gstelement_class = (GstElementClass *) klass;
  GstRTPBaseDepayloadClass *gstrtpbasedepayload_class =
      (GstRTPBaseDepayloadClass *) klass;

  GST_DEBUG_CATEGORY_INIT (rtpdvdepay_debug, "rtpdvdepay", 0,
      "DV RTP Depayloader");

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_rtp_dv_depay_change_state);

  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 DV Depayloader",
      "Codec/Depayloader/Network/RTP",
      "Depayloads DV from RTP packets (RFC 3189)",
      "Marcel Moreaux <marcelm@spacelabs.nl>, Wim Taymans <wim.taymans@gmail.com>");

  gstrtpbasedepayload_class->process_rtp_packet =
      GST_DEBUG_FUNCPTR (gst_rtp_dv_depay_process);
  gstrtpbasedepayload_class->set_caps =
      GST_DEBUG_FUNCPTR (gst_rtp_dv_depay_setcaps);
}

/* initialize the new element
 * instantiate pads and add them to element
 * set functions
 * initialize structure
 */
static void
gst_rtp_dv_depay_init (GstRTPDVDepay * filter)
{
}

static gboolean
parse_encode (GstRTPDVDepay * rtpdvdepay, const gchar * encode)
{
  rtpdvdepay->width = 720;
  if (!strcmp (encode, "314M-25/525-60")) {
    rtpdvdepay->frame_size = 240000;
    rtpdvdepay->height = 480;
    rtpdvdepay->rate_num = 30000;
    rtpdvdepay->rate_denom = 1001;
  } else if (!strcmp (encode, "SD-VCR/525-60")) {
    rtpdvdepay->frame_size = 120000;
    rtpdvdepay->height = 480;
    rtpdvdepay->rate_num = 30000;
    rtpdvdepay->rate_denom = 1001;
  } else if (!strcmp (encode, "314M-50/625-50")) {
    rtpdvdepay->frame_size = 288000;
    rtpdvdepay->height = 576;
    rtpdvdepay->rate_num = 25;
    rtpdvdepay->rate_denom = 1;
  } else if (!strcmp (encode, "SD-VCR/625-50")) {
    rtpdvdepay->frame_size = 144000;
    rtpdvdepay->height = 576;
    rtpdvdepay->rate_num = 25;
    rtpdvdepay->rate_denom = 1;
  } else if (!strcmp (encode, "314M-25/625-50")) {
    rtpdvdepay->frame_size = 144000;
    rtpdvdepay->height = 576;
    rtpdvdepay->rate_num = 25;
    rtpdvdepay->rate_denom = 1;
  } else
    rtpdvdepay->frame_size = -1;

  return rtpdvdepay->frame_size != -1;
}

static gboolean
gst_rtp_dv_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
{
  GstStructure *structure;
  GstRTPDVDepay *rtpdvdepay;
  GstCaps *srccaps;
  gint clock_rate;
  gboolean systemstream, ret;
  const gchar *encode, *media;

  rtpdvdepay = GST_RTP_DV_DEPAY (depayload);

  structure = gst_caps_get_structure (caps, 0);

  if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
    clock_rate = 90000;         /* default */
  depayload->clock_rate = clock_rate;

  /* we really need the encode property to figure out the frame size, it's also
   * required by the spec */
  if (!(encode = gst_structure_get_string (structure, "encode")))
    goto no_encode;

  /* figure out the size of one frame */
  if (!parse_encode (rtpdvdepay, encode))
    goto unknown_encode;

  /* check the media, this tells us that the stream has video or not */
  if (!(media = gst_structure_get_string (structure, "media")))
    goto no_media;

  systemstream = FALSE;

  if (!strcmp (media, "audio")) {
    /* we need a demuxer for audio only */
    systemstream = TRUE;
  } else if (!strcmp (media, "video")) {
    const gchar *audio;

    /* check the optional audio field, if it's present and set to bundled, we
     * are dealing with a system stream. */
    if ((audio = gst_structure_get_string (structure, "audio"))) {
      if (!strcmp (audio, "bundled"))
        systemstream = TRUE;
    }
  }

  /* allocate accumulator */
  rtpdvdepay->acc = gst_buffer_new_and_alloc (rtpdvdepay->frame_size);

  /* Initialize the new accumulator frame.
   * If the previous frame exists, copy that into the accumulator frame.
   * This way, missing packets in the stream won't show up badly. */
  gst_buffer_memset (rtpdvdepay->acc, 0, 0, rtpdvdepay->frame_size);

  srccaps = gst_caps_new_simple ("video/x-dv",
      "systemstream", G_TYPE_BOOLEAN, systemstream,
      "width", G_TYPE_INT, rtpdvdepay->width,
      "height", G_TYPE_INT, rtpdvdepay->height,
      "framerate", GST_TYPE_FRACTION, rtpdvdepay->rate_num,
      rtpdvdepay->rate_denom, NULL);
  ret = gst_pad_set_caps (depayload->srcpad, srccaps);
  gst_caps_unref (srccaps);

  return ret;

  /* ERRORS */
no_encode:
  {
    GST_ERROR_OBJECT (rtpdvdepay, "required encode property not found in caps");
    return FALSE;
  }
unknown_encode:
  {
    GST_ERROR_OBJECT (rtpdvdepay, "unknown encode property %s found", encode);
    return FALSE;
  }
no_media:
  {
    GST_ERROR_OBJECT (rtpdvdepay, "required media property not found in caps");
    return FALSE;
  }
}

/* A DV frame consists of a bunch of 80-byte DIF blocks.
 * Each DIF block contains a 3-byte header telling where in the DV frame the
 * DIF block should go. We use this information to calculate its position.
 */
static guint
calculate_difblock_location (guint8 * block)
{
  gint block_type, dif_sequence, dif_block;
  guint location;

  block_type = block[0] >> 5;
  dif_sequence = block[1] >> 4;
  dif_block = block[2];

  location = dif_sequence * 150;

  switch (block_type) {
    case 0:                    /* Header block, no offset */
      break;
    case 1:                    /* Subcode block */
      location += (1 + dif_block);
      break;
    case 2:                    /* VAUX block */
      location += (3 + dif_block);
      break;
    case 3:                    /* Audio block */
      location += (6 + dif_block * 16);
      break;
    case 4:                    /* Video block */
      location += (7 + (dif_block / 15) + dif_block);
      break;
    default:                   /* Something bogus */
      GST_DEBUG ("UNKNOWN BLOCK");
      location = -1;
      break;
  }
  return location;
}

static gboolean
foreach_metadata_drop (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
{
  *meta = NULL;
  return TRUE;
}

/* Process one RTP packet. Accumulate RTP payload in the proper place in a DV
 * frame, and return that frame if we detect a new frame, or NULL otherwise.
 * We assume a DV frame is 144000 bytes. That should accomodate PAL as well as
 * NTSC.
 */
static GstBuffer *
gst_rtp_dv_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
{
  GstBuffer *out = NULL;
  GstBuffer *payload_buf;
  guint8 *payload;
  guint32 rtp_ts;
  guint payload_len, location;
  GstRTPDVDepay *dvdepay = GST_RTP_DV_DEPAY (base);
  gboolean marker;
  GstMapInfo map;

  marker = gst_rtp_buffer_get_marker (rtp);

  /* Check if the received packet contains (the start of) a new frame, we do
   * this by checking the RTP timestamp. */
  rtp_ts = gst_rtp_buffer_get_timestamp (rtp);

  /* we cannot copy the packet yet if the marker is set, we will do that below
   * after taking out the data */
  if (dvdepay->prev_ts != -1 && rtp_ts != dvdepay->prev_ts && !marker) {
    /* the timestamp changed */
    GST_DEBUG_OBJECT (dvdepay, "new frame with ts %u, old ts %u", rtp_ts,
        dvdepay->prev_ts);

    /* return copy of accumulator. */
    out = gst_buffer_copy (dvdepay->acc);
    gst_buffer_foreach_meta (dvdepay->acc, foreach_metadata_drop, NULL);
  }

  /* Extract the payload */
  payload_len = gst_rtp_buffer_get_payload_len (rtp);
  payload = gst_rtp_buffer_get_payload (rtp);
  payload_buf = gst_rtp_buffer_get_payload_buffer (rtp);

  /* copy all DIF chunks in their place. */
  gst_buffer_map (dvdepay->acc, &map, GST_MAP_READWRITE);
  while (payload_len >= 80) {
    guint offset;

    /* Calculate where in the frame the payload should go */
    location = calculate_difblock_location (payload);

    if (location < 6) {
      /* part of a header, set the flag to mark that we have the header. */
      dvdepay->header_mask |= (1 << location);
      GST_LOG_OBJECT (dvdepay, "got header at location %d, now %02x", location,
          dvdepay->header_mask);
    } else {
      GST_LOG_OBJECT (dvdepay, "got block at location %d", location);
    }

    if (location != -1) {
      /* get the byte offset of the dif block */
      offset = location * 80;

      /* And copy it in, provided the location is sane. */
      if (offset <= dvdepay->frame_size - 80) {
        memcpy (map.data + offset, payload, 80);
        gst_rtp_copy_meta (GST_ELEMENT_CAST (dvdepay), dvdepay->acc,
            payload_buf, 0);
      }
    }

    payload += 80;
    payload_len -= 80;
  }
  gst_buffer_unmap (dvdepay->acc, &map);
  gst_buffer_unref (payload_buf);

  if (marker) {
    GST_DEBUG_OBJECT (dvdepay, "marker bit complete frame %u", rtp_ts);
    /* only copy the frame when we have a complete header */
    if (dvdepay->header_mask == 0x3f) {
      /* The marker marks the end of a frame that we need to push. The next frame
       * will change the timestamp but we won't copy the accumulator again because
       * we set the prev_ts to -1. */
      out = gst_buffer_copy (dvdepay->acc);
      gst_buffer_foreach_meta (dvdepay->acc, foreach_metadata_drop, NULL);
    } else {
      GST_WARNING_OBJECT (dvdepay, "waiting for frame headers %02x",
          dvdepay->header_mask);
    }
    dvdepay->prev_ts = -1;
  } else {
    /* save last timestamp */
    dvdepay->prev_ts = rtp_ts;
  }
  return out;
}

static void
gst_rtp_dv_depay_reset (GstRTPDVDepay * depay)
{
  if (depay->acc)
    gst_buffer_unref (depay->acc);
  depay->acc = NULL;

  depay->prev_ts = -1;
  depay->header_mask = 0;
}

static GstStateChangeReturn
gst_rtp_dv_depay_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstRTPDVDepay *depay = GST_RTP_DV_DEPAY (element);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_rtp_dv_depay_reset (depay);
      break;
    default:
      break;
  }

  ret = GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
      (element, transition), GST_STATE_CHANGE_FAILURE);

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_rtp_dv_depay_reset (depay);
      break;
    default:
      break;
  }
  return ret;
}

gboolean
gst_rtp_dv_depay_plugin_init (GstPlugin * plugin)
{
  return gst_element_register (plugin, "rtpdvdepay",
      GST_RANK_SECONDARY, GST_TYPE_RTP_DV_DEPAY);
}
