1 /* GStreamer plugin for forward error correction 2 * Copyright (C) 2017 Pexip 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * Author: Mikhail Fludkov <misha@pexip.com> 19 */ 20 21 #ifndef __RTP_ULPFEC_COMMON_H__ 22 #define __RTP_ULPFEC_COMMON_H__ 23 24 #include <gst/gst.h> 25 #include <gst/rtp/rtp.h> 26 27 G_BEGIN_DECLS 28 29 #define GST_WARNING_RTP_PACKET(obj, name, pkt) rtp_ulpfec_log_rtppacket (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj, name, pkt) 30 #define GST_LOG_RTP_PACKET(obj, name, pkt) rtp_ulpfec_log_rtppacket (GST_CAT_DEFAULT, GST_LEVEL_LOG, obj, name, pkt) 31 #define GST_DEBUG_RTP_PACKET(obj, name, pkt) rtp_ulpfec_log_rtppacket (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, obj, name, pkt) 32 #define GST_INFO_RTP_PACKET(obj, name, pkt) rtp_ulpfec_log_rtppacket (GST_CAT_DEFAULT, GST_LEVEL_INFO, obj, name, pkt) 33 #define GST_WARNING_FEC_PACKET(obj, pkt) rtp_ulpfec_log_fec_packet (GST_CAT_DEFAULT, GST_LEVEL_WARNING, obj, pkt) 34 #define GST_DEBUG_FEC_PACKET(obj, pkt) rtp_ulpfec_log_fec_packet (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, obj, pkt) 35 #define GST_INFO_FEC_PACKET(obj, pkt) rtp_ulpfec_log_fec_packet (GST_CAT_DEFAULT, GST_LEVEL_INFO, obj, pkt) 36 37 #define RTP_ULPFEC_PROTECTED_PACKETS_MAX(L) ((L) ? 48 : 16) 38 #define RTP_ULPFEC_SEQ_BASE_OFFSET_MAX(L) (RTP_ULPFEC_PROTECTED_PACKETS_MAX(L) - 1) 39 40 /** 41 * RtpUlpFecMapInfo: Helper wrapper around GstRTPBuffer 42 * 43 * @rtp: mapped RTP buffer 44 **/ 45 typedef struct { 46 // FIXME: it used to contain more fields now we are left with only GstRTPBuffer. 47 // it will be nice to use it directly 48 GstRTPBuffer rtp; 49 } RtpUlpFecMapInfo; 50 51 /* FIXME: parse/write these properly instead of relying in packed structs */ 52 #ifdef _MSC_VER 53 #pragma pack(push, 1) 54 #define ATTRIBUTE_PACKED 55 #else 56 #define ATTRIBUTE_PACKED __attribute__ ((packed)) 57 #endif 58 59 /* RFC 5109 */ 60 /* 61 0 1 2 3 62 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 63 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 64 |E|L|P|X| CC |M| PT recovery | SN base | 65 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 66 | TS recovery | 67 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 68 | length recovery | 69 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 70 71 Figure 3: FEC Header Format 72 */ 73 #if G_BYTE_ORDER == G_LITTLE_ENDIAN 74 typedef struct { 75 guint8 CC:4; 76 guint8 X:1; 77 guint8 P:1; 78 guint8 L:1; 79 guint8 E:1; 80 81 guint8 pt:7; 82 guint8 M:1; 83 84 guint16 seq; 85 guint32 timestamp; 86 guint16 len; 87 } ATTRIBUTE_PACKED RtpUlpFecHeader; 88 #else 89 typedef struct { 90 guint8 E:1; 91 guint8 L:1; 92 guint8 P:1; 93 guint8 X:1; 94 guint8 CC:4; 95 96 guint8 M:1; 97 guint8 pt:7; 98 99 guint16 seq; 100 guint32 timestamp; 101 guint16 len; 102 } ATTRIBUTE_PACKED RtpUlpFecHeader; 103 #endif 104 105 /* 106 0 1 2 3 107 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 108 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 109 | Protection Length | mask | 110 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 111 | mask cont. (present only when L = 1) | 112 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 113 114 Figure 4: ULP Level Header Format 115 */ 116 typedef struct 117 { 118 guint16 protection_len; 119 guint16 mask; 120 guint32 mask_continued; 121 } ATTRIBUTE_PACKED RtpUlpFecLevelHeader; 122 123 #ifdef _MSC_VER 124 #pragma pack(pop) 125 #else 126 #undef ATTRIBUTE_PACKED 127 #endif 128 129 gboolean rtp_ulpfec_map_info_map (GstBuffer *buffer, RtpUlpFecMapInfo *info); 130 void rtp_ulpfec_map_info_unmap (RtpUlpFecMapInfo *info); 131 void rtp_buffer_to_ulpfec_bitstring (GstRTPBuffer *rtp, GArray *dst_arr, 132 gboolean fec_buffer, gboolean fec_mask_long); 133 GstBuffer * rtp_ulpfec_bitstring_to_media_rtp_buffer (GArray *arr, 134 gboolean fec_mask_long, guint32 ssrc, guint16 seq); 135 GstBuffer * rtp_ulpfec_bitstring_to_fec_rtp_buffer (GArray *arr, guint16 seq_base, gboolean fec_mask_long, 136 guint64 fec_mask, gboolean marker, guint8 pt, guint16 seq, 137 guint32 timestamp, guint32 ssrc); 138 139 #ifndef GST_DISABLE_GST_DEBUG 140 void rtp_ulpfec_log_rtppacket (GstDebugCategory * cat, GstDebugLevel level, 141 gpointer object, const gchar *name, 142 GstRTPBuffer *rtp); 143 144 void rtp_ulpfec_log_fec_packet (GstDebugCategory * cat, GstDebugLevel level, 145 gpointer object, GstRTPBuffer *fecrtp); 146 #else 147 #define rtp_ulpfec_log_rtppacket(cat,level,obj,name,rtp) /* NOOP */ 148 #define rtp_ulpfec_log_fec_packet(cat,level,obj,fecrtp) /* NOOP */ 149 #endif 150 151 RtpUlpFecHeader * rtp_ulpfec_buffer_get_fechdr (GstRTPBuffer *rtp); 152 guint rtp_ulpfec_get_headers_len (gboolean fec_mask_long); 153 guint16 rtp_ulpfec_hdr_get_protection_len (RtpUlpFecHeader const *fec_hdr); 154 guint64 rtp_ulpfec_packet_mask_from_seqnum (guint16 seq, guint16 fec_seq_base, gboolean fec_mask_long); 155 guint64 rtp_ulpfec_buffer_get_mask (GstRTPBuffer *rtp); 156 guint16 rtp_ulpfec_buffer_get_seq_base (GstRTPBuffer *rtp); 157 gboolean rtp_ulpfec_mask_is_long (guint64 mask); 158 gboolean rtp_ulpfec_buffer_is_valid (GstRTPBuffer * rtp); 159 160 G_END_DECLS 161 162 #endif 163