/* RTP Retransmission queue element for GStreamer
 *
 * gstrtprtxqueue.c:
 *
 * Copyright (C) 2013 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.
 */

/**
 * SECTION:element-rtprtxqueue
 */

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

#include <gst/gst.h>
#include <gst/rtp/gstrtpbuffer.h>
#include <string.h>

#include "gstrtprtxqueue.h"

GST_DEBUG_CATEGORY_STATIC (gst_rtp_rtx_queue_debug);
#define GST_CAT_DEFAULT gst_rtp_rtx_queue_debug

#define DEFAULT_MAX_SIZE_TIME    0
#define DEFAULT_MAX_SIZE_PACKETS 100

enum
{
  PROP_0,
  PROP_MAX_SIZE_TIME,
  PROP_MAX_SIZE_PACKETS
};

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

static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("application/x-rtp")
    );

static gboolean gst_rtp_rtx_queue_src_event (GstPad * pad, GstObject * parent,
    GstEvent * event);
static GstFlowReturn gst_rtp_rtx_queue_chain (GstPad * pad, GstObject * parent,
    GstBuffer * buffer);
static GstFlowReturn gst_rtp_rtx_queue_chain_list (GstPad * pad,
    GstObject * parent, GstBufferList * list);

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

static void gst_rtp_rtx_queue_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_rtp_rtx_queue_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_rtp_rtx_queue_finalize (GObject * object);

G_DEFINE_TYPE (GstRTPRtxQueue, gst_rtp_rtx_queue, GST_TYPE_ELEMENT);

static void
gst_rtp_rtx_queue_class_init (GstRTPRtxQueueClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;

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

  gobject_class->get_property = gst_rtp_rtx_queue_get_property;
  gobject_class->set_property = gst_rtp_rtx_queue_set_property;
  gobject_class->finalize = gst_rtp_rtx_queue_finalize;

  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME,
      g_param_spec_uint ("max-size-time", "Max Size Times",
          "Amount of ms to queue (0 = unlimited)", 0, G_MAXUINT,
          DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_PACKETS,
      g_param_spec_uint ("max-size-packets", "Max Size Packets",
          "Amount of packets to queue (0 = unlimited)", 0, G_MAXUINT,
          DEFAULT_MAX_SIZE_PACKETS,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
  gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);

  gst_element_class_set_static_metadata (gstelement_class,
      "RTP Retransmission Queue", "Codec",
      "Keep RTP packets in a queue for retransmission",
      "Wim Taymans <wim.taymans@gmail.com>");

  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_rtp_rtx_queue_change_state);
}

static void
gst_rtp_rtx_queue_reset (GstRTPRtxQueue * rtx, gboolean full)
{
  g_mutex_lock (&rtx->lock);
  g_queue_foreach (rtx->queue, (GFunc) gst_buffer_unref, NULL);
  g_queue_clear (rtx->queue);
  g_list_foreach (rtx->pending, (GFunc) gst_buffer_unref, NULL);
  g_list_free (rtx->pending);
  rtx->pending = NULL;
  g_mutex_unlock (&rtx->lock);
}

static void
gst_rtp_rtx_queue_finalize (GObject * object)
{
  GstRTPRtxQueue *rtx = GST_RTP_RTX_QUEUE (object);

  gst_rtp_rtx_queue_reset (rtx, TRUE);
  g_queue_free (rtx->queue);
  g_mutex_clear (&rtx->lock);

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

static void
gst_rtp_rtx_queue_init (GstRTPRtxQueue * rtx)
{
  GstElementClass *klass = GST_ELEMENT_GET_CLASS (rtx);

  rtx->srcpad =
      gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
          "src"), "src");
  GST_PAD_SET_PROXY_CAPS (rtx->srcpad);
  GST_PAD_SET_PROXY_ALLOCATION (rtx->srcpad);
  gst_pad_set_event_function (rtx->srcpad,
      GST_DEBUG_FUNCPTR (gst_rtp_rtx_queue_src_event));
  gst_element_add_pad (GST_ELEMENT (rtx), rtx->srcpad);

  rtx->sinkpad =
      gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
          "sink"), "sink");
  GST_PAD_SET_PROXY_CAPS (rtx->sinkpad);
  GST_PAD_SET_PROXY_ALLOCATION (rtx->sinkpad);
  gst_pad_set_chain_function (rtx->sinkpad,
      GST_DEBUG_FUNCPTR (gst_rtp_rtx_queue_chain));
  gst_pad_set_chain_list_function (rtx->sinkpad,
      GST_DEBUG_FUNCPTR (gst_rtp_rtx_queue_chain_list));
  gst_element_add_pad (GST_ELEMENT (rtx), rtx->sinkpad);

  rtx->queue = g_queue_new ();
  g_mutex_init (&rtx->lock);

  rtx->max_size_time = DEFAULT_MAX_SIZE_TIME;
  rtx->max_size_packets = DEFAULT_MAX_SIZE_PACKETS;
}

typedef struct
{
  GstRTPRtxQueue *rtx;
  guint seqnum;
  gboolean found;
} RTXData;

static void
push_seqnum (GstBuffer * buffer, RTXData * data)
{
  GstRTPRtxQueue *rtx = data->rtx;
  GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
  guint16 seqnum;

  if (data->found)
    return;

  if (!gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtpbuffer))
    return;

  seqnum = gst_rtp_buffer_get_seq (&rtpbuffer);
  gst_rtp_buffer_unmap (&rtpbuffer);

  if (seqnum == data->seqnum) {
    data->found = TRUE;
    GST_DEBUG_OBJECT (rtx, "found %d", seqnum);
    rtx->pending = g_list_prepend (rtx->pending, gst_buffer_ref (buffer));
  }
}

static gboolean
gst_rtp_rtx_queue_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstRTPRtxQueue *rtx = GST_RTP_RTX_QUEUE (parent);
  gboolean res;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CUSTOM_UPSTREAM:
    {
      const GstStructure *s;

      s = gst_event_get_structure (event);
      if (gst_structure_has_name (s, "GstRTPRetransmissionRequest")) {
        guint seqnum;
        RTXData data;

        if (!gst_structure_get_uint (s, "seqnum", &seqnum))
          seqnum = -1;

        GST_DEBUG_OBJECT (rtx, "request %d", seqnum);

        g_mutex_lock (&rtx->lock);
        data.rtx = rtx;
        data.seqnum = seqnum;
        data.found = FALSE;
        g_queue_foreach (rtx->queue, (GFunc) push_seqnum, &data);
        g_mutex_unlock (&rtx->lock);

        gst_event_unref (event);
        res = TRUE;
      } else {
        res = gst_pad_event_default (pad, parent, event);
      }
      break;
    }
    default:
      res = gst_pad_event_default (pad, parent, event);
      break;
  }
  return res;
}

static void
do_push (GstBuffer * buffer, GstRTPRtxQueue * rtx)
{
  gst_pad_push (rtx->srcpad, buffer);
}

/* Must be called with rtx->lock */
static void
shrink_queue (GstRTPRtxQueue * rtx)
{
  if (rtx->max_size_packets) {
    while (g_queue_get_length (rtx->queue) > rtx->max_size_packets)
      gst_buffer_unref (g_queue_pop_tail (rtx->queue));
  }
}

static GstFlowReturn
gst_rtp_rtx_queue_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstRTPRtxQueue *rtx;
  GstFlowReturn ret;
  GList *pending;

  rtx = GST_RTP_RTX_QUEUE (parent);

  g_mutex_lock (&rtx->lock);
  g_queue_push_head (rtx->queue, gst_buffer_ref (buffer));
  shrink_queue (rtx);

  pending = rtx->pending;
  rtx->pending = NULL;
  g_mutex_unlock (&rtx->lock);

  pending = g_list_reverse (pending);
  g_list_foreach (pending, (GFunc) do_push, rtx);
  g_list_free (pending);

  ret = gst_pad_push (rtx->srcpad, buffer);

  return ret;
}

static gboolean
push_to_queue (GstBuffer ** buffer, guint idx, gpointer user_data)
{
  GQueue *queue = user_data;

  g_queue_push_head (queue, gst_buffer_ref (*buffer));

  return TRUE;
}

static GstFlowReturn
gst_rtp_rtx_queue_chain_list (GstPad * pad, GstObject * parent,
    GstBufferList * list)
{
  GstRTPRtxQueue *rtx;
  GstFlowReturn ret;
  GList *pending;

  rtx = GST_RTP_RTX_QUEUE (parent);

  g_mutex_lock (&rtx->lock);
  gst_buffer_list_foreach (list, push_to_queue, rtx->queue);
  shrink_queue (rtx);

  pending = rtx->pending;
  rtx->pending = NULL;
  g_mutex_unlock (&rtx->lock);

  pending = g_list_reverse (pending);
  g_list_foreach (pending, (GFunc) do_push, rtx);
  g_list_free (pending);

  ret = gst_pad_push_list (rtx->srcpad, list);

  return ret;
}

static void
gst_rtp_rtx_queue_get_property (GObject * object,
    guint prop_id, GValue * value, GParamSpec * pspec)
{
  GstRTPRtxQueue *rtx = GST_RTP_RTX_QUEUE (object);

  switch (prop_id) {
    case PROP_MAX_SIZE_TIME:
      g_value_set_uint (value, rtx->max_size_time);
      break;
    case PROP_MAX_SIZE_PACKETS:
      g_value_set_uint (value, rtx->max_size_packets);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_rtp_rtx_queue_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec)
{
  GstRTPRtxQueue *rtx = GST_RTP_RTX_QUEUE (object);

  switch (prop_id) {
    case PROP_MAX_SIZE_TIME:
      rtx->max_size_time = g_value_get_uint (value);
      break;
    case PROP_MAX_SIZE_PACKETS:
      rtx->max_size_packets = g_value_get_uint (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static GstStateChangeReturn
gst_rtp_rtx_queue_change_state (GstElement * element, GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstRTPRtxQueue *rtx;

  rtx = GST_RTP_RTX_QUEUE (element);

  switch (transition) {
    default:
      break;
  }

  ret =
      GST_ELEMENT_CLASS (gst_rtp_rtx_queue_parent_class)->change_state (element,
      transition);

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_rtp_rtx_queue_reset (rtx, TRUE);
      break;
    default:
      break;
  }

  return ret;
}

gboolean
gst_rtp_rtx_queue_plugin_init (GstPlugin * plugin)
{
  GST_DEBUG_CATEGORY_INIT (gst_rtp_rtx_queue_debug, "rtprtxqueue", 0,
      "rtp retransmission queue");

  return gst_element_register (plugin, "rtprtxqueue", GST_RANK_NONE,
      GST_TYPE_RTP_RTX_QUEUE);
}
