/* GStreamer plugin for forward error correction
 * Copyright (C) 2017 Pexip
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Author: Mikhail Fludkov <misha@pexip.com>
 */

/**
 * SECTION:element-rtpulpfecdec
 * @short_description: Generic RTP Forward Error Correction (FEC) decoder
 * @title: rtpulpfecdec
 *
 * Generic Forward Error Correction (FEC) decoder for Uneven Level
 * Protection (ULP) as described in RFC 5109.
 *
 * This element will work in combination with an upstream #GstRtpStorage
 * element and attempt to recover packets declared lost through custom
 * 'GstRTPPacketLost' events, usually emitted by #GstRtpJitterBuffer.
 *
 * As such, this element cannot be usefully used from the command line,
 * because a reference to the upstream storage object needs to be
 * provided to it through its #GstRtpUlpFecDec:storage property, example
 * programs are available at
 * <https://github.com/sdroege/gstreamer-rs/blob/master/examples/src/bin/rtpfecserver.rs>
 * and
 * <https://github.com/sdroege/gstreamer-rs/blob/master/examples/src/bin/rtpfecclient.rs>.
 *
 * Additionally, the payload types of the protection packets *must* be
 * provided to this element via its #GstRtpUlpFecDec:pt property.
 *
 * When using #GstRtpBin, this element should be inserted through the
 * #GstRtpBin::request-fec-decoder signal.
 *
 * See also: #GstRtpUlpFecEnc, #GstRtpBin, #GstRtpStorage
 * Since: 1.14
 */

#include <gst/rtp/gstrtpbuffer.h>
#include <gst/rtp/gstrtp-enumtypes.h>

#include "rtpulpfeccommon.h"
#include "gstrtpulpfecdec.h"

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

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

enum
{
  PROP_0,
  PROP_PT,
  PROP_STORAGE,
  PROP_RECOVERED,
  PROP_UNRECOVERED,
  N_PROPERTIES
};

#define DEFAULT_FEC_PT 0

static GParamSpec *klass_properties[N_PROPERTIES] = { NULL, };

GST_DEBUG_CATEGORY (gst_rtp_ulpfec_dec_debug);
#define GST_CAT_DEFAULT (gst_rtp_ulpfec_dec_debug)

G_DEFINE_TYPE (GstRtpUlpFecDec, gst_rtp_ulpfec_dec, GST_TYPE_ELEMENT);

#define RTP_FEC_MAP_INFO_NTH(dec, data) (&g_array_index (\
    ((GstRtpUlpFecDec *)dec)->info_arr, \
    RtpUlpFecMapInfo, \
    GPOINTER_TO_UINT(data)))

static gint
_compare_fec_map_info (gconstpointer a, gconstpointer b, gpointer userdata)
{
  guint16 aseq =
      gst_rtp_buffer_get_seq (&RTP_FEC_MAP_INFO_NTH (userdata, a)->rtp);
  guint16 bseq =
      gst_rtp_buffer_get_seq (&RTP_FEC_MAP_INFO_NTH (userdata, b)->rtp);
  return gst_rtp_buffer_compare_seqnum (bseq, aseq);
}

static void
gst_rtp_ulpfec_dec_start (GstRtpUlpFecDec * self, GstBufferList * buflist,
    guint8 fec_pt, guint16 lost_seq)
{
  guint fec_packets = 0;
  gsize i;

  g_assert (NULL == self->info_media);
  g_assert (0 == self->info_fec->len);
  g_assert (0 == self->info_arr->len);

  g_array_set_size (self->info_arr, gst_buffer_list_length (buflist));

  for (i = 0;
      i < gst_buffer_list_length (buflist) && !self->lost_packet_from_storage;
      ++i) {
    GstBuffer *buffer = gst_buffer_list_get (buflist, i);
    RtpUlpFecMapInfo *info = RTP_FEC_MAP_INFO_NTH (self, i);

    if (!rtp_ulpfec_map_info_map (gst_buffer_ref (buffer), info))
      g_assert_not_reached ();

    if (fec_pt == gst_rtp_buffer_get_payload_type (&info->rtp)) {
      GST_DEBUG_RTP_PACKET (self, "rtp header (fec)", &info->rtp);

      ++fec_packets;
      if (rtp_ulpfec_buffer_is_valid (&info->rtp)) {
        GST_DEBUG_FEC_PACKET (self, &info->rtp);
        g_ptr_array_add (self->info_fec, GUINT_TO_POINTER (i));
      }
    } else {
      GST_LOG_RTP_PACKET (self, "rtp header (incoming)", &info->rtp);

      if (lost_seq == gst_rtp_buffer_get_seq (&info->rtp)) {
        GST_DEBUG_OBJECT (self, "Received lost packet from from the storage");
        g_list_free (self->info_media);
        self->info_media = NULL;
        self->lost_packet_from_storage = TRUE;
      }
      self->info_media =
          g_list_insert_sorted_with_data (self->info_media,
          GUINT_TO_POINTER (i), _compare_fec_map_info, self);
    }
  }
  if (!self->lost_packet_from_storage) {
    self->fec_packets_received += fec_packets;
    self->fec_packets_rejected += fec_packets - self->info_fec->len;
  }
}

static void
gst_rtp_ulpfec_dec_stop (GstRtpUlpFecDec * self)
{
  g_array_set_size (self->info_arr, 0);
  g_ptr_array_set_size (self->info_fec, 0);
  g_list_free (self->info_media);
  self->info_media = NULL;
  self->lost_packet_from_storage = FALSE;
  self->lost_packet_returned = FALSE;
}

static guint64
gst_rtp_ulpfec_dec_get_media_buffers_mask (GstRtpUlpFecDec * self,
    guint16 fec_seq_base)
{
  guint64 mask = 0;
  GList *it;

  for (it = self->info_media; it; it = it->next) {
    RtpUlpFecMapInfo *info = RTP_FEC_MAP_INFO_NTH (self, it->data);
    mask |=
        rtp_ulpfec_packet_mask_from_seqnum (gst_rtp_buffer_get_seq (&info->rtp),
        fec_seq_base, TRUE);
  }
  return mask;
}

static gboolean
gst_rtp_ulpfec_dec_is_recovered_pt_valid (GstRtpUlpFecDec * self, gint media_pt,
    guint8 recovered_pt)
{
  GList *it;
  if (media_pt == recovered_pt)
    return TRUE;

  for (it = self->info_media; it; it = it->next) {
    RtpUlpFecMapInfo *info = RTP_FEC_MAP_INFO_NTH (self, it->data);
    if (gst_rtp_buffer_get_payload_type (&info->rtp) == recovered_pt)
      return TRUE;
  }
  return FALSE;
}

static GstBuffer *
gst_rtp_ulpfec_dec_recover_from_fec (GstRtpUlpFecDec * self,
    RtpUlpFecMapInfo * info_fec, guint32 ssrc, gint media_pt, guint16 seq,
    guint8 * dst_pt)
{
  guint64 fec_mask = rtp_ulpfec_buffer_get_mask (&info_fec->rtp);
  gboolean fec_mask_long = rtp_ulpfec_buffer_get_fechdr (&info_fec->rtp)->L;
  guint16 fec_seq_base = rtp_ulpfec_buffer_get_seq_base (&info_fec->rtp);
  GstBuffer *ret;
  GList *it;

  g_array_set_size (self->scratch_buf, 0);
  rtp_buffer_to_ulpfec_bitstring (&info_fec->rtp, self->scratch_buf, TRUE,
      fec_mask_long);

  for (it = self->info_media; it; it = it->next) {
    RtpUlpFecMapInfo *info = RTP_FEC_MAP_INFO_NTH (self, it->data);
    guint64 packet_mask =
        rtp_ulpfec_packet_mask_from_seqnum (gst_rtp_buffer_get_seq (&info->rtp),
        fec_seq_base, TRUE);

    if (fec_mask & packet_mask) {
      fec_mask ^= packet_mask;
      rtp_buffer_to_ulpfec_bitstring (&info->rtp, self->scratch_buf, FALSE,
          fec_mask_long);
    }
  }

  ret =
      rtp_ulpfec_bitstring_to_media_rtp_buffer (self->scratch_buf,
      fec_mask_long, ssrc, seq);
  if (ret) {
    /* We are about to put recovered packet back in self->info_media to be able
     * to reuse it later for recovery of other packets
     **/
    gint i = self->info_arr->len;
    RtpUlpFecMapInfo *info;
    guint8 recovered_pt;

    g_array_set_size (self->info_arr, self->info_arr->len + 1);
    info = RTP_FEC_MAP_INFO_NTH (self, i);

    if (!rtp_ulpfec_map_info_map (gst_buffer_ref (ret), info)) {
      GST_WARNING_OBJECT (self, "Invalid recovered packet");
      goto recovered_packet_invalid;
    }

    recovered_pt = gst_rtp_buffer_get_payload_type (&info->rtp);
    if (!gst_rtp_ulpfec_dec_is_recovered_pt_valid (self, media_pt,
            recovered_pt)) {
      GST_WARNING_OBJECT (self,
          "Recovered packet has unexpected payload type (%u)", recovered_pt);
      goto recovered_packet_invalid;
    }

    GST_DEBUG_RTP_PACKET (self, "rtp header (recovered)", &info->rtp);
    self->info_media =
        g_list_insert_sorted_with_data (self->info_media, GUINT_TO_POINTER (i),
        _compare_fec_map_info, self);
    *dst_pt = recovered_pt;
  }
  return ret;

recovered_packet_invalid:
  g_array_set_size (self->info_arr, self->info_arr->len - 1);
  gst_buffer_unref (ret);
  return NULL;
}

static GstBuffer *
gst_rtp_ulpfec_dec_recover_from_storage (GstRtpUlpFecDec * self,
    guint8 * dst_pt, guint16 * dst_seq)
{
  RtpUlpFecMapInfo *info;

  if (self->lost_packet_returned)
    return NULL;

  g_assert (g_list_length (self->info_media) == 1);

  info = RTP_FEC_MAP_INFO_NTH (self, self->info_media->data);
  *dst_seq = gst_rtp_buffer_get_seq (&info->rtp);
  *dst_pt = gst_rtp_buffer_get_payload_type (&info->rtp);
  self->lost_packet_returned = TRUE;
  GST_DEBUG_RTP_PACKET (self, "rtp header (recovered)", &info->rtp);
  return gst_buffer_ref (info->rtp.buffer);
}

/* __has_builtin only works with clang, so test compiler version for gcc */
/* Intel compiler and MSVC probably have their own things as well */
/* TODO: make sure we use builtin for clang as well */
#if defined(__GNUC__) && __GNUC__ >= 4
#define rtp_ulpfec_ctz64 __builtin_ctzll
#else
static inline gint
rtp_ulpfec_ctz64_inline (guint64 mask)
{
  gint nth_bit = 0;

  do {
    if ((mask & 1))
      return nth_bit;
    mask = mask >> 1;
  } while (++nth_bit < 64);

  return -1;                    /* should not be reached, since mask must not be 0 */
}

#define rtp_ulpfec_ctz64 rtp_ulpfec_ctz64_inline
#endif

static GstBuffer *
gst_rtp_ulpfec_dec_recover (GstRtpUlpFecDec * self, guint32 ssrc, gint media_pt,
    guint8 * dst_pt, guint16 * dst_seq)
{
  guint64 media_mask = 0;
  gint media_mask_seq_base = -1;
  gsize i;

  if (self->lost_packet_from_storage)
    return gst_rtp_ulpfec_dec_recover_from_storage (self, dst_pt, dst_seq);

  /* Looking for a FEC packet which can be used for recovery */
  for (i = 0; i < self->info_fec->len; ++i) {
    RtpUlpFecMapInfo *info = RTP_FEC_MAP_INFO_NTH (self,
        g_ptr_array_index (self->info_fec, i));
    guint16 seq_base = rtp_ulpfec_buffer_get_seq_base (&info->rtp);
    guint64 fec_mask = rtp_ulpfec_buffer_get_mask (&info->rtp);
    guint64 missing_packets_mask;

    if (media_mask_seq_base != (gint) seq_base) {
      media_mask_seq_base = seq_base;
      media_mask = gst_rtp_ulpfec_dec_get_media_buffers_mask (self, seq_base);
    }

    /* media_mask has 1s if packet exist.
     * fec_mask is the mask of protected packets
     * The statement below excludes existing packets from the protected. So
     * we are left with 1s only for missing packets which can be recovered
     * by this FEC packet. */
    missing_packets_mask = fec_mask & (~media_mask);

    /* Do we have any 1s? Checking if current FEC packet can be used for recovery */
    if (0 != missing_packets_mask) {
      guint trailing_zeros = rtp_ulpfec_ctz64 (missing_packets_mask);

      /* Is it the only 1 in the mask? Checking if we lacking single packet in
       * that case FEC packet can be used for recovery */
      if (missing_packets_mask == (G_GUINT64_CONSTANT (1) << trailing_zeros)) {
        GstBuffer *ret;

        *dst_seq =
            seq_base + (RTP_ULPFEC_SEQ_BASE_OFFSET_MAX (TRUE) - trailing_zeros);
        ret =
            gst_rtp_ulpfec_dec_recover_from_fec (self, info, ssrc, media_pt,
            *dst_seq, dst_pt);
        if (ret)
          return ret;
      }
    }
  }
  return NULL;
}

static GstFlowReturn
gst_rtp_ulpfec_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstRtpUlpFecDec *self = GST_RTP_ULPFEC_DEC (parent);

  if (G_LIKELY (GST_FLOW_OK == self->chain_return_val)) {
    if (G_UNLIKELY (self->unset_discont_flag)) {
      self->unset_discont_flag = FALSE;
      buf = gst_buffer_make_writable (buf);
      GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
    }
    return gst_pad_push (self->srcpad, buf);
  }

  gst_buffer_unref (buf);
  return self->chain_return_val;
}

static gboolean
gst_rtp_ulpfec_dec_handle_packet_loss (GstRtpUlpFecDec * self, guint16 seqnum,
    GstClockTime timestamp, GstClockTime duration)
{
  gint caps_pt = self->have_caps_pt ? self->caps_pt : -1;
  gboolean ret = TRUE;
  GstBufferList *buflist =
      rtp_storage_get_packets_for_recovery (self->storage, self->fec_pt,
      self->caps_ssrc, seqnum);

  if (buflist) {
    GstBuffer *recovered_buffer = NULL;
    guint16 recovered_seq = 0;
    guint8 recovered_pt = 0;

    gst_rtp_ulpfec_dec_start (self, buflist, self->fec_pt, seqnum);

    while (NULL != (recovered_buffer =
            gst_rtp_ulpfec_dec_recover (self, self->caps_ssrc, caps_pt,
                &recovered_pt, &recovered_seq))) {
      if (seqnum == recovered_seq) {
        recovered_buffer = gst_buffer_make_writable (recovered_buffer);
        GST_BUFFER_PTS (recovered_buffer) = timestamp;
        /* GST_BUFFER_DURATION (recovered_buffer) = duration;
         * JB does not set the duration, so we will not too */

        if (!self->lost_packet_from_storage)
          rtp_storage_put_recovered_packet (self->storage,
              gst_buffer_ref (recovered_buffer), recovered_pt, self->caps_ssrc,
              recovered_seq);

        GST_DEBUG_OBJECT (self,
            "Pushing recovered packet ssrc=0x%08x seq=%u %" GST_PTR_FORMAT,
            self->caps_ssrc, seqnum, recovered_buffer);

        ret = FALSE;
        self->unset_discont_flag = TRUE;
        self->chain_return_val = gst_pad_push (self->srcpad, recovered_buffer);
        break;
      }

      rtp_storage_put_recovered_packet (self->storage,
          recovered_buffer, recovered_pt, self->caps_ssrc, recovered_seq);
    }

    gst_rtp_ulpfec_dec_stop (self);
    gst_buffer_list_unref (buflist);
  }

  GST_DEBUG_OBJECT (self, "Packet lost ssrc=0x%08x seq=%u", self->caps_ssrc,
      seqnum);

  return ret;
}

static gboolean
gst_rtp_ulpfec_dec_handle_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
  GstRtpUlpFecDec *self = GST_RTP_ULPFEC_DEC (parent);
  gboolean forward = TRUE;

  GST_LOG_OBJECT (self, "Received event %" GST_PTR_FORMAT, event);

  if (GST_FLOW_OK == self->chain_return_val &&
      GST_EVENT_CUSTOM_DOWNSTREAM == GST_EVENT_TYPE (event) &&
      gst_event_has_name (event, "GstRTPPacketLost")) {
    guint seqnum;
    GstClockTime timestamp, duration;

    g_assert (self->have_caps_ssrc);
    g_assert (self->storage);

    if (!gst_structure_get (gst_event_get_structure (event),
            "seqnum", G_TYPE_UINT, &seqnum,
            "timestamp", G_TYPE_UINT64, &timestamp,
            "duration", G_TYPE_UINT64, &duration, NULL))
      g_assert_not_reached ();

    forward =
        gst_rtp_ulpfec_dec_handle_packet_loss (self, seqnum, timestamp,
        duration);
    if (forward)
      ++self->packets_unrecovered;
    else
      ++self->packets_recovered;
    GST_DEBUG_OBJECT (self, "Unrecovered / Recovered: %lu / %lu",
        (gulong) self->packets_unrecovered, (gulong) self->packets_recovered);
  } else if (GST_EVENT_CAPS == GST_EVENT_TYPE (event)) {
    GstCaps *caps;
    gboolean have_caps_pt = FALSE;
    gboolean have_caps_ssrc = FALSE;
    guint caps_ssrc = 0;
    gint caps_pt = 0;

    gst_event_parse_caps (event, &caps);
    have_caps_ssrc =
        gst_structure_get_uint (gst_caps_get_structure (caps, 0), "ssrc",
        &caps_ssrc);
    have_caps_pt =
        gst_structure_get_int (gst_caps_get_structure (caps, 0), "payload",
        &caps_pt);

    if (self->have_caps_ssrc != have_caps_ssrc || self->caps_ssrc != caps_ssrc)
      GST_DEBUG_OBJECT (self, "SSRC changed %u, 0x%08x -> %u, 0x%08x",
          self->have_caps_ssrc, self->caps_ssrc, have_caps_ssrc, caps_ssrc);
    if (self->have_caps_pt != have_caps_pt || self->caps_pt != caps_pt)
      GST_DEBUG_OBJECT (self, "PT changed %u, %u -> %u, %u",
          self->have_caps_pt, self->caps_pt, have_caps_pt, caps_pt);

    self->have_caps_ssrc = have_caps_ssrc;
    self->have_caps_pt = have_caps_pt;
    self->caps_ssrc = caps_ssrc;
    self->caps_pt = caps_pt;
  }

  if (forward)
    return gst_pad_push_event (self->srcpad, event);
  gst_event_unref (event);
  return TRUE;
}

static void
gst_rtp_ulpfec_dec_init (GstRtpUlpFecDec * self)
{
  self->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
  self->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
  GST_PAD_SET_PROXY_CAPS (self->sinkpad);
  GST_PAD_SET_PROXY_ALLOCATION (self->sinkpad);
  gst_pad_set_chain_function (self->sinkpad,
      GST_DEBUG_FUNCPTR (gst_rtp_ulpfec_dec_chain));
  gst_pad_set_event_function (self->sinkpad,
      GST_DEBUG_FUNCPTR (gst_rtp_ulpfec_dec_handle_sink_event));

  gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
  gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);

  self->fec_pt = DEFAULT_FEC_PT;

  self->chain_return_val = GST_FLOW_OK;
  self->have_caps_ssrc = FALSE;
  self->caps_ssrc = 0;
  self->info_fec = g_ptr_array_new ();
  self->info_arr = g_array_new (FALSE, TRUE, sizeof (RtpUlpFecMapInfo));
  g_array_set_clear_func (self->info_arr,
      (GDestroyNotify) rtp_ulpfec_map_info_unmap);
  self->scratch_buf = g_array_new (FALSE, TRUE, sizeof (guint8));
}

static void
gst_rtp_ulpfec_dec_dispose (GObject * obj)
{
  GstRtpUlpFecDec *self = GST_RTP_ULPFEC_DEC (obj);

  GST_INFO_OBJECT (self,
      " ssrc=0x%08x pt=%u"
      " packets_recovered=%" G_GSIZE_FORMAT
      " packets_unrecovered=%" G_GSIZE_FORMAT,
      self->caps_ssrc, self->caps_pt,
      self->packets_recovered, self->packets_unrecovered);

  if (self->storage)
    g_object_unref (self->storage);

  g_assert (NULL == self->info_media);
  g_assert (0 == self->info_fec->len);
  g_assert (0 == self->info_arr->len);

  if (self->fec_packets_received) {
    GST_INFO_OBJECT (self,
        " fec_packets_received=%" G_GSIZE_FORMAT
        " fec_packets_rejected=%" G_GSIZE_FORMAT
        " packets_rejected=%" G_GSIZE_FORMAT,
        self->fec_packets_received,
        self->fec_packets_rejected, self->packets_rejected);
  }

  g_ptr_array_free (self->info_fec, TRUE);
  g_array_free (self->info_arr, TRUE);
  g_array_free (self->scratch_buf, TRUE);

  G_OBJECT_CLASS (gst_rtp_ulpfec_dec_parent_class)->dispose (obj);
}

static void
gst_rtp_ulpfec_dec_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstRtpUlpFecDec *self = GST_RTP_ULPFEC_DEC (object);

  switch (prop_id) {
    case PROP_PT:
      self->fec_pt = g_value_get_uint (value);
      break;
    case PROP_STORAGE:
      if (self->storage)
        g_object_unref (self->storage);
      self->storage = g_value_get_object (value);
      if (self->storage)
        g_object_ref (self->storage);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_rtp_ulpfec_dec_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstRtpUlpFecDec *self = GST_RTP_ULPFEC_DEC (object);

  switch (prop_id) {
    case PROP_PT:
      g_value_set_uint (value, self->fec_pt);
      break;
    case PROP_STORAGE:
      g_value_set_object (value, self->storage);
      break;
    case PROP_RECOVERED:
      g_value_set_uint (value, (guint) self->packets_recovered);
      break;
    case PROP_UNRECOVERED:
      g_value_set_uint (value, (guint) self->packets_unrecovered);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_rtp_ulpfec_dec_class_init (GstRtpUlpFecDecClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

  GST_DEBUG_CATEGORY_INIT (gst_rtp_ulpfec_dec_debug,
      "rtpulpfecdec", 0, "RTP FEC Decoder");

  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&srctemplate));
  gst_element_class_add_pad_template (element_class,
      gst_static_pad_template_get (&sinktemplate));

  gst_element_class_set_static_metadata (element_class,
      "RTP FEC Decoder",
      "Codec/Depayloader/Network/RTP",
      "Decodes RTP FEC (RFC5109)", "Mikhail Fludkov <misha@pexip.com>");

  gobject_class->set_property =
      GST_DEBUG_FUNCPTR (gst_rtp_ulpfec_dec_set_property);
  gobject_class->get_property =
      GST_DEBUG_FUNCPTR (gst_rtp_ulpfec_dec_get_property);
  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_rtp_ulpfec_dec_dispose);

  klass_properties[PROP_PT] = g_param_spec_uint ("pt", "pt",
      "FEC packets payload type", 0, 127,
      DEFAULT_FEC_PT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
  klass_properties[PROP_STORAGE] =
      g_param_spec_object ("storage", "RTP storage", "RTP storage",
      G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
  klass_properties[PROP_RECOVERED] =
      g_param_spec_uint ("recovered", "recovered",
      "The number of recovered packets", 0, G_MAXUINT, 0,
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
  klass_properties[PROP_UNRECOVERED] =
      g_param_spec_uint ("unrecovered", "unrecovered",
      "The number of unrecovered packets", 0, G_MAXUINT, 0,
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);

  g_object_class_install_properties (gobject_class, N_PROPERTIES,
      klass_properties);

  g_assert (rtp_ulpfec_ctz64 (G_GUINT64_CONSTANT (0x1)) == 0);
  g_assert (rtp_ulpfec_ctz64 (G_GUINT64_CONSTANT (0x8000000000000000)) == 63);
}
