Commit d5ad50bd authored by Mikhail Fludkov's avatar Mikhail Fludkov Committed by Mathieu Duponchelle

rtp: Implement ULPFEC (RFC 5109)

We expose a set of new elements:

* ULPFEC encoder / decoder
* A storage element, which should be placed before jitterbuffers,
  and is used to store packets in order to attempt reconstruction
  after the jitterbuffer has sent PacketLost events
* RED encoder / decoder (RFC 2198), these are necessary to
  use FEC in webrtc, as browsers will propose and expect ulpfec
  packets to be wrapped in red packets

With contributions from:

Mathieu Duponchelle <mathieu@centricular.com>
Sebastian Dröge <sebastian@centricular.com>

https://bugzilla.gnome.org/show_bug.cgi?id=792696
parent 82d09502
......@@ -93,7 +93,16 @@ libgstrtp_la_SOURCES = \
gstrtpvrawpay.c \
gstrtpstreampay.c \
gstrtpstreamdepay.c \
gstrtputils.c
gstrtputils.c \
rtpulpfeccommon.c \
gstrtpulpfecdec.c \
gstrtpulpfecenc.c \
rtpredcommon.c \
gstrtpredenc.c \
gstrtpreddec.c \
rtpstorage.c \
rtpstoragestream.c \
gstrtpstorage.c
libgstrtp_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
$(GST_CFLAGS) -Dvp8_norm=gst_rtpvp8_vp8_norm \
......
......@@ -113,6 +113,13 @@
#include "gstrtpvrawpay.h"
#include "gstrtpstreampay.h"
#include "gstrtpstreamdepay.h"
#include "gstrtpredenc.h"
#include "gstrtpreddec.h"
#include "gstrtpulpfecdec.h"
#include "gstrtpulpfecenc.h"
#include "gstrtpreddec.h"
#include "gstrtpredenc.h"
#include "gstrtpstorage.h"
static gboolean
plugin_init (GstPlugin * plugin)
......@@ -388,6 +395,34 @@ plugin_init (GstPlugin * plugin)
if (!gst_rtp_stream_depay_plugin_init (plugin))
return FALSE;
if (!gst_element_register (plugin, "rtpredenc", GST_RANK_NONE,
GST_TYPE_RTP_RED_ENC))
return FALSE;
if (!gst_element_register (plugin, "rtpreddec", GST_RANK_NONE,
GST_TYPE_RTP_RED_DEC))
return FALSE;
if (!gst_element_register (plugin, "rtpulpfecdec", GST_RANK_NONE,
GST_TYPE_RTP_ULPFEC_DEC))
return FALSE;
if (!gst_element_register (plugin, "rtpulpfecenc", GST_RANK_NONE,
GST_TYPE_RTP_ULPFEC_ENC))
return FALSE;
if (!gst_element_register (plugin, "rtpreddec", GST_RANK_NONE,
GST_TYPE_RTP_RED_DEC))
return FALSE;
if (!gst_element_register (plugin, "rtpredenc", GST_RANK_NONE,
GST_TYPE_RTP_RED_ENC))
return FALSE;
if (!gst_element_register (plugin, "rtpstorage", GST_RANK_NONE,
GST_TYPE_RTP_STORAGE))
return FALSE;
return TRUE;
}
......
This diff is collapsed.
/* 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>
*/
#ifndef __GST_RTP_RED_DEC_H__
#define __GST_RTP_RED_DEC_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_RTP_RED_DEC \
(gst_rtp_red_dec_get_type())
#define GST_RTP_RED_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_RED_DEC,GstRtpRedDec))
#define GST_RTP_RED_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_RED_DEC,GstRtpRedDecClass))
#define GST_IS_RTP_RED_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_RED_DEC))
#define GST_IS_RTP_RED_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_RED_DEC))
typedef struct _GstRtpRedDec GstRtpRedDec;
typedef struct _GstRtpRedDecClass GstRtpRedDecClass;
struct _GstRtpRedDecClass {
GstElementClass parent_class;
};
struct _GstRtpRedDec {
GstElement parent;
GstPad *srcpad;
GstPad *sinkpad;
gint pt;
guint num_received;
GQueue *rtp_history;
};
GType gst_rtp_red_dec_get_type (void);
G_END_DECLS
#endif /* __GST_RTP_RED_DEC_H__ */
This diff is collapsed.
/* 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>
*/
#ifndef __GST_RTP_RED_ENC_H__
#define __GST_RTP_RED_ENC_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_RTP_RED_ENC \
(gst_rtp_red_enc_get_type())
#define GST_RTP_RED_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_RED_ENC,GstRtpRedEnc))
#define GST_RTP_RED_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_RED_ENC,GstRtpRedEncClass))
#define GST_IS_RTP_RED_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_RED_ENC))
#define GST_IS_RTP_RED_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_RED_ENC))
typedef struct _GstRtpRedEnc GstRtpRedEnc;
typedef struct _GstRtpRedEncClass GstRtpRedEncClass;
struct _GstRtpRedEncClass {
GstElementClass parent_class;
};
struct _GstRtpRedEnc {
GstElement parent;
GstPad *srcpad;
GstPad *sinkpad;
gint pt;
guint num_sent;
guint distance;
gboolean allow_no_red_blocks;
GQueue *rtp_history;
gboolean send_caps;
gboolean is_current_caps_red;
};
GType gst_rtp_red_enc_get_type (void);
G_END_DECLS
#endif /* __GST_RTP_RED_ENC_H__ */
/* 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>
*/
#include "gstrtpstorage.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_SIZE_TIME,
PROP_INTERNAL_STORAGE,
N_PROPERTIES
};
static GParamSpec *klass_properties[N_PROPERTIES] = { NULL, };
#define DEFAULT_SIZE_TIME (0)
GST_DEBUG_CATEGORY_STATIC (gst_rtp_storage_debug);
#define GST_CAT_DEFAULT (gst_rtp_storage_debug)
G_DEFINE_TYPE (GstRtpStorage, gst_rtp_storage, GST_TYPE_ELEMENT);
static GstFlowReturn
gst_rtp_storage_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
GstRtpStorage *self = GST_RTP_STORAGE (parent);;
if (rtp_storage_append_buffer (self->storage, buf))
return gst_pad_push (self->srcpad, buf);
return GST_FLOW_OK;
}
static void
gst_rtp_storage_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstRtpStorage *self = GST_RTP_STORAGE (object);
if (GST_LEVEL_DEBUG <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) {
gchar *val_str = gst_value_serialize (value);
GST_DEBUG_OBJECT (object, "Setting property \"%s\" to %s", pspec->name,
val_str);
g_free (val_str);
}
switch (prop_id) {
case PROP_SIZE_TIME:
rtp_storage_set_size (self->storage, g_value_get_uint64 (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_rtp_storage_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstRtpStorage *self = GST_RTP_STORAGE (object);
switch (prop_id) {
case PROP_SIZE_TIME:
g_value_set_uint64 (value, rtp_storage_get_size (self->storage));
break;
case PROP_INTERNAL_STORAGE:
{
g_value_set_object (value, self->storage);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
if (GST_LEVEL_LOG <= gst_debug_category_get_threshold (GST_CAT_DEFAULT)) {
gchar *val_str = gst_value_serialize (value);
GST_LOG_OBJECT (object, "Returning property \"%s\" %s", pspec->name,
val_str);
g_free (val_str);
}
}
static void
gst_rtp_storage_init (GstRtpStorage * 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_rtp_storage_chain);
gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
self->storage = rtp_storage_new ();
}
static void
gst_rtp_storage_dispose (GObject * obj)
{
GstRtpStorage *self = GST_RTP_STORAGE (obj);
g_object_unref (self->storage);
G_OBJECT_CLASS (gst_rtp_storage_parent_class)->dispose (obj);
}
static void
gst_rtp_storage_class_init (GstRtpStorageClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GST_DEBUG_CATEGORY_INIT (gst_rtp_storage_debug,
"rtpstorage", 0, "RTP Storage");
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 storage",
"Analyzer/RTP",
"Helper element for various purposes "
"(ex. recovering from packet loss using RED/FEC). "
"Saves given number of RTP packets. "
"Should be instantiated before jitterbuffer",
"Mikhail Fludkov <misha@pexip.com>");
gobject_class->set_property = gst_rtp_storage_set_property;
gobject_class->get_property = gst_rtp_storage_get_property;
gobject_class->dispose = gst_rtp_storage_dispose;
klass_properties[PROP_SIZE_TIME] =
g_param_spec_uint64 ("size-time", "Storage size (in ns)",
"The amount of data to keep in the storage (in ns, 0-disable)", 0,
G_MAXUINT64, DEFAULT_SIZE_TIME,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
klass_properties[PROP_INTERNAL_STORAGE] =
g_param_spec_object ("internal-storage", "Internal storage",
"Internal RtpStorage object", G_TYPE_OBJECT,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPERTIES,
klass_properties);
}
/* 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>
*/
#ifndef __GST_RTP_STORAGE_H__
#define __GST_RTP_STORAGE_H__
#include <gst/gst.h>
#include "rtpstorage.h"
G_BEGIN_DECLS
#define GST_TYPE_RTP_STORAGE \
(gst_rtp_storage_get_type())
#define GST_RTP_STORAGE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_STORAGE,GstRtpStorage))
#define GST_RTP_STORAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_STORAGE,GstRtpStorageClass))
#define RTP_IS_STORAGE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_STORAGE))
#define RTP_IS_STORAGE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_STORAGE))
typedef struct _GstRtpStorage GstRtpStorage;
typedef struct _GstRtpStorageClass GstRtpStorageClass;
struct _GstRtpStorageClass {
GstElementClass parent_class;
};
struct _GstRtpStorage {
GstElement parent;
GstPad *srcpad;
GstPad *sinkpad;
RtpStorage *storage;
};
GType gst_rtp_storage_get_type (void);
G_END_DECLS
#endif /* __GST_RTP_STORAGE_H__ */
This diff is collapsed.
/* 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>
*/
#ifndef __GST_RTP_ULPFEC_DEC_H__
#define __GST_RTP_ULPFEC_DEC_H__
#include <gst/gst.h>
#include "rtpstorage.h"
G_BEGIN_DECLS
#define GST_TYPE_RTP_ULPFEC_DEC \
(gst_rtp_ulpfec_dec_get_type())
#define GST_RTP_ULPFEC_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_ULPFEC_DEC,GstRtpUlpFecDec))
#define GST_RTP_ULPFEC_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_ULPFEC_DEC,GstRtpUlpFecDecClass))
#define GST_IS_RTP_ULPFEC_DEC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_ULPFEC_DEC))
#define GST_IS_RTP_ULPFEC_DEC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_ULPFEC_DEC))
typedef struct _GstRtpUlpFecDec GstRtpUlpFecDec;
typedef struct _GstRtpUlpFecDecClass GstRtpUlpFecDecClass;
struct _GstRtpUlpFecDecClass {
GstElementClass parent_class;
};
struct _GstRtpUlpFecDec {
GstElement parent;
GstPad *srcpad;
GstPad *sinkpad;
/* properties */
guint8 fec_pt;
RtpStorage *storage;
gsize packets_recovered;
gsize packets_unrecovered;
/* internal stuff */
GstFlowReturn chain_return_val;
gboolean unset_discont_flag;
gboolean have_caps_ssrc;
gboolean have_caps_pt;
guint32 caps_ssrc;
guint8 caps_pt;
GList *info_media;
GPtrArray *info_fec;
GArray *info_arr;
GArray *scratch_buf;
gboolean lost_packet_from_storage;
gboolean lost_packet_returned;
/* stats */
gsize fec_packets_received;
gsize fec_packets_rejected;
gsize packets_rejected;
};
GType gst_rtp_ulpfec_dec_get_type (void);
G_END_DECLS
#endif /* __GST_RTP_ULPFEC_DEC_H__ */
This diff is collapsed.
/* 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>
*/
#ifndef __GST_FEC_H__
#define __GST_FEC_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_RTP_ULPFEC_ENC \
(gst_rtp_ulpfec_enc_get_type())
#define GST_RTP_ULPFEC_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_ULPFEC_ENC,GstRtpUlpFecEnc))
#define GST_RTP_ULPFEC_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_ULPFEC_ENC,GstRtpUlpFecEncClass))
#define GST_IS_RTP_ULPFEC_ENC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_ULPFEC_ENC))
#define GST_IS_RTP_ULPFEC_ENC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_ULPFEC_ENC))
typedef struct _GstRtpUlpFecEnc GstRtpUlpFecEnc;
typedef struct _GstRtpUlpFecEncClass GstRtpUlpFecEncClass;
struct _GstRtpUlpFecEncClass {
GstElementClass parent_class;
};
struct _GstRtpUlpFecEnc {
GstElement parent;
GstPad *srcpad;
GstPad *sinkpad;
GHashTable *ssrc_to_ctx;
/* properties */
guint pt;
guint32 ssrc;
guint percentage;
guint percentage_important;
gboolean multipacket;
gboolean mux_seq;
guint num_packets_protected;
};
typedef struct {
guint ssrc;
GstElement *parent;
GstPad *srcpad;
/* settings */
guint pt;
guint32 fec_ssrc;
guint percentage;
guint percentage_important;
gboolean multipacket;
gboolean mux_seq;
guint num_packets_protected;
guint16 seqnum;
guint seqnum_offset;
guint num_packets_received;
guint num_packets_fec;
guint fec_nth;
GQueue packets_buf;
gdouble budget;
gdouble budget_inc;
gdouble budget_important;
gdouble budget_inc_important;
GArray *info_arr;
GArray *scratch_buf;
guint fec_packets;
guint fec_packet_idx;
} GstRtpUlpFecEncStreamCtx;
GType gst_rtp_ulpfec_enc_get_type (void);
G_END_DECLS
#endif /* __GST_FEC_H__ */
......@@ -92,6 +92,15 @@ rtp_sources = [
'gstrtpstreampay.c',
'gstrtpstreamdepay.c',
'gstrtputils.c',
'rtpulpfeccommon.c',
'gstrtpulpfecdec.c',
'gstrtpulpfecenc.c',
'rtpredcommon.c',
'gstrtpredenc.c',
'gstrtpreddec.c',
'rtpstorage.c',
'rtpstoragestream.c',
'gstrtpstorage.c',
]
rtp_args = [
......
/* 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>
*/
#include "rtpredcommon.h"
gsize
rtp_red_block_header_get_length (gboolean is_redundant)
{
return is_redundant ? sizeof (RedBlockHeader) : 1;
}
gboolean
rtp_red_block_is_redundant (gpointer red_block)
{
return ((RedBlockHeader *) red_block)->F;
}
guint8
rtp_red_block_get_payload_type (gpointer red_block)
{
return ((RedBlockHeader *) red_block)->pt;
}
guint16
rtp_red_block_get_payload_length (gpointer red_block)
{
RedBlockHeader *hdr = (RedBlockHeader *) red_block;
return (hdr->length_hi << 8) | hdr->length_lo;
}
guint16
rtp_red_block_get_timestamp_offset (gpointer red_block)
{
RedBlockHeader *hdr = (RedBlockHeader *) red_block;
return (hdr->timestamp_offset_hi << 6) | hdr->timestamp_offset_lo;
}
void
rtp_red_block_set_payload_type (gpointer red_block, guint8 pt)
{
((RedBlockHeader *) red_block)->pt = pt;
}
void
rtp_red_block_set_is_redundant (gpointer red_block, gboolean is_redundant)
{
((RedBlockHeader *) red_block)->F = is_redundant;
}
void
rtp_red_block_set_timestamp_offset (gpointer red_block,
guint16 timestamp_offset)
{
RedBlockHeader *hdr = (RedBlockHeader *) red_block;
g_assert (rtp_red_block_is_redundant (red_block));
g_assert_cmpint (timestamp_offset, <=, RED_BLOCK_TIMESTAMP_OFFSET_MAX);
hdr->timestamp_offset_lo = timestamp_offset & 0x3f;
hdr->timestamp_offset_hi = timestamp_offset >> 6;
}
void
rtp_red_block_set_payload_length (gpointer red_block, guint16 length)
{
RedBlockHeader *hdr = (RedBlockHeader *) red_block;
g_assert (rtp_red_block_is_redundant (red_block));
g_assert_cmpint (length, <=, RED_BLOCK_LENGTH_MAX);
hdr->length_lo = length & 0xff;
hdr->length_hi = length >> 8;
}
/* 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>
*/