Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ortp for openSUSE:Factory checked in 
at 2022-03-01 19:07:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ortp (Old)
 and      /work/SRC/openSUSE:Factory/.ortp.new.1958 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ortp"

Tue Mar  1 19:07:05 2022 rev:36 rq:958308 version:5.1.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/ortp/ortp.changes        2022-02-02 
22:45:02.210058388 +0100
+++ /work/SRC/openSUSE:Factory/.ortp.new.1958/ortp.changes      2022-03-01 
19:07:07.652174452 +0100
@@ -1,0 +2,9 @@
+Tue Mar  1 15:31:21 UTC 2022 - Paolo Stivanin <i...@paolostivanin.com>
+
+- Update to version 5.1.3:
+  * New forward error correction (FEC) algorithm implemented
+    according to https://datatracker.ietf.org/doc/html/rfc8627
+  * Standalone compilation (out of linphone-sdk).
+  * Bundle mode warnings and few inconsistencies.
+
+-------------------------------------------------------------------

Old:
----
  ortp-5.0.67.tar.bz2

New:
----
  ortp-5.1.3.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ortp.spec ++++++
--- /var/tmp/diff_new_pack.d4vlBT/_old  2022-03-01 19:07:08.192174435 +0100
+++ /var/tmp/diff_new_pack.d4vlBT/_new  2022-03-01 19:07:08.200174435 +0100
@@ -20,7 +20,7 @@
 %define soname  libortp
 %define sover   15
 Name:           ortp
-Version:        5.0.67
+Version:        5.1.3
 Release:        0
 Summary:        Real-time Transport Protocol Stack
 License:        GPL-3.0-only
@@ -73,7 +73,7 @@
 
 mkdir -p %{buildroot}%{_docdir}/%{name}
 # manually keeping the version here because upstream doesn't (usually) update 
the patch version
-mv -T %{buildroot}%{_datadir}/doc/%{name}-5.0.0 %{buildroot}%{_docdir}/%{name}
+mv -T %{buildroot}%{_datadir}/doc/%{name}-5.1.0 %{buildroot}%{_docdir}/%{name}
 
 # for some reason, pkgconfig file contains wrong libdir
 sed -i "s,-L/usr/lib,-L%{_libdir}," 
%{buildroot}/%{_libdir}/pkgconfig/%{name}.pc

++++++ ortp-5.0.67.tar.bz2 -> ortp-5.1.3.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/CHANGELOG.md new/ortp-5.1.3/CHANGELOG.md
--- old/ortp-5.0.67/CHANGELOG.md        2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/CHANGELOG.md 2022-02-04 11:58:14.000000000 +0100
@@ -6,6 +6,18 @@
 
 ## [Unreleased]
 
+
+## [5.1.0] - 2022-02-14
+
+### Added
+- New forward error correction (FEC) algorithm implemented according to 
https://datatracker.ietf.org/doc/html/rfc8627
+  Eperimental stage, work in progress.
+
+### Fixed
+- Standalone compilation (out of linphone-sdk).
+- Bundle mode warnings and few inconsistencies.
+
+
 ## [5.0.0] - 2021-07-08
 
 ### Fixed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/CMakeLists.txt 
new/ortp-5.1.3/CMakeLists.txt
--- old/ortp-5.0.67/CMakeLists.txt      2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/CMakeLists.txt       2022-02-04 11:58:14.000000000 +0100
@@ -28,7 +28,7 @@
     cmake_policy(SET CMP0077 NEW)
 endif()
 
-project(oRTP VERSION 5.0.0)
+project(oRTP VERSION 5.1.0)
 
 
 set(ORTP_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/include/CMakeLists.txt 
new/ortp-5.1.3/include/CMakeLists.txt
--- old/ortp-5.0.67/include/CMakeLists.txt      2022-01-06 16:42:33.000000000 
+0100
+++ new/ortp-5.1.3/include/CMakeLists.txt       2022-02-04 11:58:14.000000000 
+0100
@@ -22,7 +22,8 @@
 
 set(HEADER_FILES
        b64.h
-       event.h
+        event.h
+        fecstream.h
        logging.h
        nack.h
        ortp.h
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/include/ortp/event.h 
new/ortp-5.1.3/include/ortp/event.h
--- old/ortp-5.0.67/include/ortp/event.h        2022-01-06 16:42:33.000000000 
+0100
+++ new/ortp-5.1.3/include/ortp/event.h 2022-02-04 11:58:14.000000000 +0100
@@ -55,6 +55,7 @@
                bool_t congestion_detected;
                float video_bandwidth_available;
                int jitter_min_size_for_nack;
+        uint16_t reconstructed_packet_seq_number;
        } info;
 };
 
@@ -88,6 +89,7 @@
 #define ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE             19
 #define ORTP_EVENT_ICE_DEACTIVATION_NEEDED             20
 #define ORTP_EVENT_JITTER_UPDATE_FOR_NACK              21
+#define ORTP_EVENT_SOURCE_PACKET_RECONSTRUCTED  22
 
 ORTP_PUBLIC OrtpEventData * ortp_event_get_data(OrtpEvent *ev);
 ORTP_PUBLIC void ortp_event_destroy(OrtpEvent *ev);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/include/ortp/fecstream.h 
new/ortp-5.1.3/include/ortp/fecstream.h
--- old/ortp-5.0.67/include/ortp/fecstream.h    1970-01-01 01:00:00.000000000 
+0100
+++ new/ortp-5.1.3/include/ortp/fecstream.h     2022-02-04 11:58:14.000000000 
+0100
@@ -0,0 +1,58 @@
+#ifndef FECSTREAM_H
+#define FECSTREAM_H
+
+#include "ortp/port.h"
+#include "ortp/str_utils.h"
+
+typedef struct _FecParameters{
+    int L;
+    int D;
+    int source_queue_size;
+    int repair_queue_size;
+} FecParameters;
+
+typedef struct _FecStream{
+    struct _RtpSession *source_session;
+    struct _RtpSession *fec_session;
+    int cpt;
+    size_t max_size;
+    uint32_t SSRC;
+    uint8_t *bitstring;
+    uint16_t *seqnumlist;
+    uint8_t *header_bitstring;
+    uint8_t *payload_bitstring;
+    queue_t source_packets_recvd;
+    queue_t repair_packets_recvd;
+    FecParameters params;
+    int reconstruction_fail;
+    int total_lost_packets;
+    int repair_packet_not_found;
+    int source_packets_not_found;
+    int error;
+    uint16_t *prec;
+    int size_prec;
+} FecStream;
+
+ORTP_PUBLIC FecParameters *fec_params_new(int L, int D, int jitter);
+
+ORTP_PUBLIC FecStream *fec_stream_new(struct _RtpSession *source, struct 
_RtpSession *fec, const FecParameters *params);
+
+ORTP_PUBLIC void fec_stream_destroy(FecStream *fec_stream);
+
+void fec_stream_on_new_source_packet_sent(FecStream *fec_stream, mblk_t 
*source_packet);
+
+void fec_stream_on_new_source_packet_received(FecStream *fec_stream, mblk_t 
*source_packet);
+
+ORTP_PUBLIC mblk_t *fec_stream_reconstruct_missing_packet(FecStream 
*fec_stream, uint16_t seqnum);
+
+mblk_t *fec_stream_reconstruct_packet(FecStream *fec_stream, queue_t 
*source_packets_set, mblk_t *repair_packet, uint16_t seqnum);
+
+uint16_t *fec_stream_create_sequence_numbers_set(FecStream *fec_stream, mblk_t 
*repair_packet);
+
+mblk_t *fec_stream_find_repair_packet(FecStream *fec_stream, uint16_t seqnum);
+
+bool_t fec_stream_find_source_packets(FecStream *fec_stream, mblk_t 
*repair_packet, queue_t *source_packets);
+
+void fec_stream_reconstruction_error(FecStream *fec_stream, uint16_t seqnum);
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/include/ortp/rtp.h 
new/ortp-5.1.3/include/ortp/rtp.h
--- old/ortp-5.0.67/include/ortp/rtp.h  2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/include/ortp/rtp.h   2022-02-04 11:58:14.000000000 +0100
@@ -31,7 +31,8 @@
 #define RTP_DEFAULT_MULTICAST_TTL 5    /*hops*/
 #define RTP_DEFAULT_MULTICAST_LOOPBACK 0  /*false*/
 #define RTP_DEFAULT_DSCP 0x00  /*best effort*/
-
+#define RTP_MAX_MIXER_TO_CLIENT_AUDIO_LEVEL 14 /* 14 because we use 1-byte 
headers */
+#define RTP_MAX_CLIENT_TO_MIXER_AUDIO_LEVEL 14 /* 14 because we use 1-byte 
headers */
 
 
 typedef struct rtp_header
@@ -57,13 +58,6 @@
        uint32_t csrc[16];
 } rtp_header_t;
 
-/* MAX is 15 because we use 1-byte header */
-typedef enum {
-       RTP_EXTENSION_NONE = 0,
-       RTP_EXTENSION_MID = 1,
-       RTP_EXTENSION_MAX = 15
-} rtp_extension_type_t;
-
 typedef struct rtp_stats
 {
        uint64_t packet_sent;           /*number of outgoing packets */
@@ -91,6 +85,20 @@
        float jitter_buffer_size_ms;/* mean jitter buffer size in 
milliseconds.*/
 } jitter_stats_t;
 
+/* MAX is 15 because we use 1-byte header */
+typedef enum {
+       RTP_EXTENSION_NONE = 0,
+       RTP_EXTENSION_MID = 1,
+       RTP_EXTENSION_CLIENT_TO_MIXER_AUDIO_LEVEL = 2,
+       RTP_EXTENSION_MIXER_TO_CLIENT_AUDIO_LEVEL = 3,
+       RTP_EXTENSION_MAX = 15
+} rtp_extension_type_t;
+
+typedef struct rtp_audio_level {
+       uint32_t csrc;
+       int dbov;
+} rtp_audio_level_t;
+
 #define RTP_TIMESTAMP_IS_NEWER_THAN(ts1, ts2) \
        ((uint32_t)((uint32_t)(ts1) - (uint32_t)(ts2)) < ((uint32_t)1 << 31))
 
@@ -111,15 +119,19 @@
 
 /* packet api */
 /* the first argument is a mblk_t. The header is supposed to be not splitted  
*/
-#define rtp_set_markbit(mp,value)      
((rtp_header_t*)((mp)->b_rptr))->markbit=(value)
+#define rtp_set_version(mp,value)      
((rtp_header_t*)((mp)->b_rptr))->version=(value)
+#define rtp_set_padbit(mp,value)       
((rtp_header_t*)((mp)->b_rptr))->padbit=(value)
 #define rtp_set_extbit(mp,value)       
((rtp_header_t*)((mp)->b_rptr))->extbit=(value)
+#define rtp_set_cc(mp,value)   ((rtp_header_t*)((mp)->b_rptr))->cc=(value)
+#define rtp_set_markbit(mp,value)      
((rtp_header_t*)((mp)->b_rptr))->markbit=(value)
+#define rtp_set_payload_type(mp,pt)    
((rtp_header_t*)((mp)->b_rptr))->paytype=(pt)
 #define rtp_set_seqnumber(mp,seq)      
((rtp_header_t*)((mp)->b_rptr))->seq_number=(seq)
 #define rtp_set_timestamp(mp,ts)       
((rtp_header_t*)((mp)->b_rptr))->timestamp=(ts)
 #define rtp_set_ssrc(mp,_ssrc)         
((rtp_header_t*)((mp)->b_rptr))->ssrc=(_ssrc)
 ORTP_PUBLIC void rtp_add_csrc(mblk_t *mp ,uint32_t csrc);
-#define rtp_set_payload_type(mp,pt)    
((rtp_header_t*)((mp)->b_rptr))->paytype=(pt)
 
 #define rtp_get_version(mp)    (((rtp_header_t*)((mp)->b_rptr))->version)
+#define rtp_get_padbit(mp)     (((rtp_header_t*)((mp)->b_rptr))->padbit)
 #define rtp_get_markbit(mp)    (((rtp_header_t*)((mp)->b_rptr))->markbit)
 #define rtp_get_extbit(mp)     (((rtp_header_t*)((mp)->b_rptr))->extbit)
 #define rtp_get_timestamp(mp)  (((rtp_header_t*)((mp)->b_rptr))->timestamp)
@@ -136,6 +148,13 @@
 ORTP_PUBLIC void rtp_add_extension_header(mblk_t *packet, int id, size_t size, 
uint8_t *data);
 ORTP_PUBLIC int rtp_get_extension_header(mblk_t *packet, int id, uint8_t 
**data);
 
+/* Audio Level api */
+ORTP_PUBLIC void rtp_add_client_to_mixer_audio_level(mblk_t *packet, int id, 
bool_t voice_activity, int audio_level);
+ORTP_PUBLIC int rtp_get_client_to_mixer_audio_level(mblk_t *packet, int id, 
bool_t *voice_activity);
+
+ORTP_PUBLIC void rtp_add_mixer_to_client_audio_level(mblk_t *packet, int id, 
size_t size, rtp_audio_level_t *audio_levels);
+ORTP_PUBLIC int rtp_get_mixer_to_client_audio_level(mblk_t *packet, int id, 
rtp_audio_level_t* audio_levels);
+
 #ifdef __cplusplus
 }
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/include/ortp/rtpsession.h 
new/ortp-5.1.3/include/ortp/rtpsession.h
--- old/ortp-5.0.67/include/ortp/rtpsession.h   2022-01-06 16:42:33.000000000 
+0100
+++ new/ortp-5.1.3/include/ortp/rtpsession.h    2022-02-04 11:58:14.000000000 
+0100
@@ -43,6 +43,7 @@
 #include <ortp/utils.h>
 #include <ortp/rtpsignaltable.h>
 #include <ortp/event.h>
+#include <ortp/fecstream.h>
 
 #define ORTP_AVPF_FEATURE_NONE 0
 #define ORTP_AVPF_FEATURE_TMMBR (1 << 0)
@@ -384,7 +385,6 @@
 
 typedef struct _RtpSession RtpSession;
 
-
 /**
  * An object representing a bi-directional RTP session.
  * It holds sockets, jitter buffer, various counters (timestamp, sequence 
numbers...)
@@ -470,6 +470,9 @@
        struct _RtpBundle *bundle; /* back pointer to the rtp bundle object */
        queue_t bundleq;
        ortp_mutex_t bundleq_lock;
+
+    /* fec option */
+    FecStream *fec_stream;
 };
 
 /**
@@ -627,6 +630,7 @@
 ORTP_PUBLIC mblk_t * rtp_session_create_packet_raw(const uint8_t *packet, 
size_t packet_size);
 ORTP_PUBLIC mblk_t * rtp_session_create_packet_with_data(RtpSession *session, 
uint8_t *payload, size_t payload_size, void (*freefn)(void*));
 ORTP_PUBLIC mblk_t * rtp_session_create_packet_in_place(RtpSession 
*session,uint8_t *buffer, size_t size, void (*freefn)(void*) );
+ORTP_PUBLIC mblk_t * 
rtp_session_create_packet_with_mixer_to_client_audio_level(RtpSession *session, 
size_t header_size, int mtc_extension_id, size_t audio_levels_size, 
rtp_audio_level_t *audio_levels);
 ORTP_PUBLIC int rtp_session_sendm_with_ts (RtpSession * session, mblk_t *mp, 
uint32_t userts);
 ORTP_PUBLIC int rtp_session_sendto(RtpSession *session, bool_t is_rtp, mblk_t 
*m, int flags, const struct sockaddr *destaddr, socklen_t destlen);
 ORTP_PUBLIC int rtp_session_recvfrom(RtpSession *session, bool_t is_rtp, 
mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/CMakeLists.txt 
new/ortp-5.1.3/src/CMakeLists.txt
--- old/ortp-5.0.67/src/CMakeLists.txt  2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/src/CMakeLists.txt   2022-02-04 11:58:14.000000000 +0100
@@ -37,6 +37,7 @@
        congestiondetector.c
        event.c
        extremum.c
+        fecstream.c
        jitterctl.c
        kalmanrls.c
        logging.c
@@ -50,6 +51,7 @@
        rtcp_fb.c
        rtcp_xr.c
        rtcpparse.c
+       rtpaudiolevel.c
        rtpparse.c
        rtpprofile.c
        rtpsession.c
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/fecstream.c 
new/ortp-5.1.3/src/fecstream.c
--- old/ortp-5.0.67/src/fecstream.c     1970-01-01 01:00:00.000000000 +0100
+++ new/ortp-5.1.3/src/fecstream.c      2022-02-04 11:58:14.000000000 +0100
@@ -0,0 +1,289 @@
+#include "ortp/str_utils.h"
+#include "ortp/rtp.h"
+#include "ortp/rtpsession.h"
+#include "ortp/fecstream.h"
+#include "ortp/port.h"
+#include "ortp/logging.h"
+
+#ifndef MIN
+#define MIN(a,b) (a < b ? a : b)
+#endif
+
+FecParameters *fec_params_new(int L, int D, int jitter){
+    FecParameters *fec_params = (FecParameters *) 
ortp_malloc0(sizeof(FecParameters));
+    fec_params->L = L;
+    fec_params->D = D;
+    fec_params->source_queue_size = L*jitter;
+    fec_params->repair_queue_size = (10-L)*5;
+    return fec_params;
+}
+
+FecStream *fec_stream_new(struct _RtpSession *source, struct _RtpSession *fec, 
const FecParameters *params){
+    FecStream *fec_stream = (FecStream *) ortp_malloc0(sizeof(FecStream));
+    fec_stream->source_session = source;
+    fec_stream->fec_session = fec;
+    rtp_session_enable_jitter_buffer(fec_stream->fec_session, FALSE);
+    qinit(&fec_stream->source_packets_recvd);
+    qinit(&fec_stream->repair_packets_recvd);
+    fec_stream->params = *params;
+    fec_stream->seqnumlist = (uint16_t *) ortp_malloc(fec_stream->params.L * 
sizeof(uint16_t));
+    fec_stream->bitstring = (uint8_t *) ortp_malloc(UDP_MAX_SIZE * 
sizeof(uint8_t));
+    fec_stream->header_bitstring = (uint8_t *) ortp_malloc(10 * 
sizeof(uint8_t));
+    fec_stream->payload_bitstring = (uint8_t *) ortp_malloc(UDP_MAX_SIZE * 
sizeof(uint8_t));
+    fec_stream->prec = (uint16_t *) ortp_malloc(fec_stream->params.L * 
sizeof(uint16_t));
+    return fec_stream;
+}
+
+void fec_stream_destroy(FecStream *fec_stream){
+    if(fec_stream->bitstring != NULL) ortp_free(fec_stream->bitstring);
+    if(fec_stream->seqnumlist != NULL) ortp_free(fec_stream->seqnumlist);
+    if(fec_stream->header_bitstring != NULL) 
ortp_free(fec_stream->header_bitstring);
+    if(fec_stream->payload_bitstring != NULL) 
ortp_free(fec_stream->payload_bitstring);
+    if(fec_stream->prec != NULL) ortp_free(fec_stream->prec);
+    flushq(&fec_stream->source_packets_recvd, 0);
+    flushq(&fec_stream->repair_packets_recvd, 0);
+}
+
+void fec_stream_on_new_source_packet_sent(FecStream *fec_stream, mblk_t 
*source_packet){
+    msgpullup(source_packet, -1);
+
+    ortp_message("Source packet size (SeqNum : %d) : %d", (int) 
rtp_get_seqnumber(source_packet), (int) 
(msgdsize(source_packet)-RTP_FIXED_HEADER_SIZE));
+
+    if(fec_stream->cpt == 0){
+        fec_stream->SSRC = rtp_get_ssrc(source_packet);
+        memset(fec_stream->bitstring, 0, UDP_MAX_SIZE * sizeof(uint8_t));
+        fec_stream->bitstring[0] = 1 << 6;
+    }
+
+    if(fec_stream->max_size < (msgdsize(source_packet) - 
RTP_FIXED_HEADER_SIZE)) fec_stream->max_size = msgdsize(source_packet) - 
RTP_FIXED_HEADER_SIZE;
+
+    fec_stream->bitstring[0] ^= rtp_get_padbit(source_packet) << 5;
+    fec_stream->bitstring[0] ^= rtp_get_extbit(source_packet) << 4;
+    fec_stream->bitstring[0] ^= rtp_get_cc(source_packet);
+    fec_stream->bitstring[1] ^= rtp_get_markbit(source_packet) << 7;
+    fec_stream->bitstring[1] ^= rtp_get_payload_type(source_packet);
+
+    //Length
+    *(uint16_t *) &fec_stream->bitstring[2] ^= 
htons((uint16_t)(msgdsize(source_packet) - RTP_FIXED_HEADER_SIZE));
+
+    //Timestamp
+    *(uint32_t *) &fec_stream->bitstring[4] ^= 
rtp_get_timestamp(source_packet);
+
+    //All octets after the fixed 12-bytes RTPheader
+    for(size_t i = 0 ; i < (msgdsize(source_packet) - RTP_FIXED_HEADER_SIZE) ; 
i++){
+        fec_stream->bitstring[8 + i] ^= *(uint8_t *) 
(source_packet->b_rptr+RTP_FIXED_HEADER_SIZE+i);
+    }
+
+    fec_stream->seqnumlist[fec_stream->cpt] = rtp_get_seqnumber(source_packet);
+
+    fec_stream->cpt++;
+
+    if(fec_stream->cpt == fec_stream->params.L){
+        uint16_t *p16 = NULL;
+        uint8_t *p8 = NULL;
+        mblk_t *repair_packet = 
rtp_session_create_packet(fec_stream->fec_session, RTP_FIXED_HEADER_SIZE, NULL, 
0);
+
+        rtp_set_version(repair_packet, 2);
+        rtp_set_padbit(repair_packet, 0);
+        rtp_set_extbit(repair_packet, 0);
+        rtp_set_markbit(repair_packet, 0);
+
+        msgpullup(repair_packet, msgdsize(repair_packet) + 4 + 8 + 
fec_stream->params.L*4 + fec_stream->max_size);
+
+        rtp_add_csrc(repair_packet, fec_stream->SSRC);
+        repair_packet->b_wptr += sizeof(uint32_t);
+
+        memcpy(repair_packet->b_wptr, &fec_stream->bitstring[0], 
8*sizeof(uint8_t));
+        repair_packet->b_wptr += 8*sizeof(uint8_t);
+
+        for (int i = 0 ; i < fec_stream->params.L ; i++){
+            p16 = (uint16_t *) (repair_packet->b_wptr);
+            *p16 = fec_stream->seqnumlist[i];
+            repair_packet->b_wptr += sizeof(uint16_t);
+            p8 = repair_packet->b_wptr;
+            *p8 = fec_stream->params.L;
+            repair_packet->b_wptr++;
+            p8 = repair_packet->b_wptr;
+            *p8 = fec_stream->params.D;
+            repair_packet->b_wptr++;
+        }
+
+        memcpy(repair_packet->b_wptr, &fec_stream->bitstring[8], 
fec_stream->max_size);
+        repair_packet->b_wptr += fec_stream->max_size;
+
+        fec_stream->cpt = 0;
+        fec_stream->max_size = 0;
+
+        ortp_message("Repair packet size before sending (SeqNum : %d) : %d", 
(int) rtp_get_seqnumber(repair_packet), (int) (msgdsize(repair_packet) - 
(RTP_FIXED_HEADER_SIZE + 12 + 4*(fec_stream->params.L))));
+
+        rtp_session_sendm_with_ts(fec_stream->fec_session, repair_packet, 
rtp_get_timestamp(repair_packet));
+    }
+}
+
+void fec_stream_on_new_source_packet_received(FecStream *fec_stream, mblk_t 
*source_packet){
+    mblk_t *repair_packet = NULL;
+    putq(&fec_stream->source_packets_recvd, dupmsg(source_packet));
+    if(fec_stream->source_packets_recvd.q_mcount > 
fec_stream->params.source_queue_size){
+        mblk_t *mp = qbegin(&fec_stream->source_packets_recvd);
+        remq(&fec_stream->source_packets_recvd, mp);
+        freemsg(mp);
+    }
+    repair_packet = rtp_session_recvm_with_ts(fec_stream->fec_session, 
rtp_get_timestamp(source_packet));
+    if(repair_packet != NULL){
+        putq(&fec_stream->repair_packets_recvd, dupmsg(repair_packet));
+        if(fec_stream->repair_packets_recvd.q_mcount > 
fec_stream->params.repair_queue_size){
+            mblk_t *rp = qbegin(&fec_stream->repair_packets_recvd);
+            remq(&fec_stream->repair_packets_recvd, rp);
+            freemsg(rp);
+        }
+    }
+}
+
+mblk_t *fec_stream_reconstruct_missing_packet(FecStream *fec_stream, uint16_t 
seqnum){
+    mblk_t *packet = NULL;
+    mblk_t *repair_packet = fec_stream_find_repair_packet(fec_stream, seqnum);
+    if(repair_packet != NULL){
+        bool_t find_all;
+        queue_t packets_for_reconstruction;
+        qinit(&packets_for_reconstruction);
+        find_all = fec_stream_find_source_packets(fec_stream, repair_packet, 
&packets_for_reconstruction);
+        if(find_all){
+            packet = fec_stream_reconstruct_packet(fec_stream, 
&packets_for_reconstruction, repair_packet, seqnum);
+        } else {
+            fec_stream->source_packets_not_found++;
+        }
+        flushq(&packets_for_reconstruction, 0);
+    } else {
+        fec_stream->repair_packet_not_found++;
+    }
+    return packet;
+}
+
+mblk_t *fec_stream_reconstruct_packet(FecStream *fec_stream, queue_t 
*source_packets_set, mblk_t *repair_packet, uint16_t seqnum){
+    mblk_t *packet = NULL;
+    uint16_t packet_size;
+    uint8_t *p = NULL;
+
+    for(mblk_t *tmp = qbegin(source_packets_set) ; !qend(source_packets_set, 
tmp) ; tmp = qnext(source_packets_set, tmp)){
+        ortp_message("Source packet for reconstruction (Seq Num : %d) : %d", 
rtp_get_seqnumber(tmp), (int) (msgdsize(tmp) - RTP_FIXED_HEADER_SIZE));
+    }
+
+    /* RTP HEADER RECONSTRUCTION */
+
+    //Creation of the bitstring
+    memset(fec_stream->header_bitstring, 0, 10);
+
+    for(mblk_t *tmp = qbegin(source_packets_set) ; !qend(source_packets_set, 
tmp) ; tmp = qnext(source_packets_set, tmp)){
+        for(size_t i = 0 ; i < 8 ; i++){
+            fec_stream->header_bitstring[i] ^= *(uint8_t *) (tmp->b_rptr+i);
+        }
+        *(uint16_t *) &(fec_stream->header_bitstring[8]) ^= 
htons((uint16_t)(msgdsize(tmp) - RTP_FIXED_HEADER_SIZE));
+    }
+
+    //XOR with FEC header
+    for(size_t j = 0 ; j < 2 ; j++){
+        fec_stream->header_bitstring[j] ^= *(uint8_t *) 
(repair_packet->b_rptr+RTP_FIXED_HEADER_SIZE+sizeof(uint32_t)+j);
+    }
+    *(uint32_t *) &fec_stream->header_bitstring[4] ^= *(uint32_t *) 
(repair_packet->b_rptr+RTP_FIXED_HEADER_SIZE+sizeof(uint32_t)+4*sizeof(uint8_t));
+    *(uint16_t *) &fec_stream->header_bitstring[8] ^= *(uint16_t *) 
(repair_packet->b_rptr+RTP_FIXED_HEADER_SIZE+sizeof(uint32_t)+2*sizeof(uint8_t));
+
+    //Recreation of the lost packet
+    packet = rtp_session_create_packet(fec_stream->source_session, 
RTP_FIXED_HEADER_SIZE, NULL, 0);
+
+    rtp_set_version(packet, 2);
+    rtp_set_padbit(packet, (fec_stream->header_bitstring[0] >> 5) & 0x1);
+    rtp_set_extbit(packet, (fec_stream->header_bitstring[0] >> 4) & 0x1);
+    rtp_set_cc(packet, fec_stream->header_bitstring[0] & 0xF);
+    rtp_set_markbit(packet, (fec_stream->header_bitstring[1] >> 7) & 0x1);
+    rtp_set_payload_type(packet, fec_stream->header_bitstring[1] & 0x7F);
+    rtp_set_seqnumber(packet, seqnum);
+    rtp_set_timestamp(packet, *(uint32_t *) &fec_stream->header_bitstring[4]);
+    rtp_set_ssrc(packet, rtp_get_ssrc(qbegin(source_packets_set)));
+    packet_size = ntohs(*(uint16_t *) &(fec_stream->header_bitstring[8]));
+
+    /* PAYLOAD RECONSTRUCTION */
+
+    memset(fec_stream->payload_bitstring, 0, packet_size);
+    for(mblk_t *tmp = qbegin(source_packets_set) ; !qend(source_packets_set, 
tmp) ; tmp = qnext(source_packets_set, tmp)){
+        for(size_t i = 0 ; i < MIN((msgdsize(tmp) - RTP_FIXED_HEADER_SIZE), 
(size_t) packet_size) ; i++){
+            fec_stream->payload_bitstring[i] ^= *(uint8_t *) 
(tmp->b_rptr+RTP_FIXED_HEADER_SIZE+i);
+        }
+    }
+    if((int)(msgdsize(repair_packet) - (RTP_FIXED_HEADER_SIZE + 12 + 
4*(fec_stream->params.L))) < packet_size){
+        ortp_message("Size of repair payload (Seq Num : %d) : %d | Size of 
source payload (Seq Num : %d) : %d", rtp_get_seqnumber(repair_packet), 
(int)(msgdsize(repair_packet) - (RTP_FIXED_HEADER_SIZE + 12 + 
4*(fec_stream->params.L))), seqnum, packet_size);
+        abort();
+    }
+    for(size_t i = 0 ; i < packet_size ; i++){
+        fec_stream->payload_bitstring[i] ^= *(uint8_t *) 
(repair_packet->b_rptr + RTP_FIXED_HEADER_SIZE + 12 + 4*(fec_stream->params.L) 
+ i); //Erreur potentielle : Buffer overflow - READ 1 byte
+    }
+
+    msgpullup(packet, msgdsize(packet) + packet_size);
+    for(size_t i = 0 ; i < packet_size ; i++){
+        p = (packet->b_wptr+i);
+        *p = fec_stream->payload_bitstring[i];
+    }
+    packet->b_wptr += packet_size;
+
+    return packet;
+}
+
+uint16_t *fec_stream_create_sequence_numbers_set(FecStream *fec_stream, mblk_t 
*repair_packet){
+    uint16_t *seqnum = (uint16_t *) malloc(fec_stream->params.L * 
sizeof(uint16_t));
+    int list_size = 0;
+    bool_t seq_num_ok = TRUE;
+    for(int i = 0 ; i < fec_stream->params.L ; i++){
+        for(int j = 0 ; j < list_size ; j++){
+            if(seqnum[j] == *(uint16_t *) (repair_packet->b_rptr + 
RTP_FIXED_HEADER_SIZE + 4 + 8 + 4*i)){
+                seq_num_ok = FALSE;
+            }
+        }
+        if(seq_num_ok){
+            seqnum[i] = *(uint16_t *) (repair_packet->b_rptr + 
RTP_FIXED_HEADER_SIZE + 4 + 8 + 4*i);
+            list_size++;
+        }
+        seq_num_ok = TRUE;
+    }
+    return seqnum;
+}
+
+mblk_t *fec_stream_find_repair_packet(FecStream *fec_stream, uint16_t seqnum){
+    mblk_t *tmp = qbegin(&fec_stream->repair_packets_recvd);
+    while(!qend(&fec_stream->repair_packets_recvd, tmp)){
+        uint16_t *seqnum_list = 
fec_stream_create_sequence_numbers_set(fec_stream, tmp);
+        for(int i = 0 ; i < fec_stream->params.L ; i++){
+            if(seqnum_list[i] == seqnum){
+                return tmp;
+            }
+        }
+        tmp = qnext(&fec_stream->repair_packets_recvd, tmp);
+    }
+    return NULL;
+}
+
+bool_t fec_stream_find_source_packets(FecStream *fec_stream, mblk_t 
*repair_packet, queue_t *source_packets){
+    uint16_t *seqnum_list = fec_stream_create_sequence_numbers_set(fec_stream, 
repair_packet);
+    for(int i = 0 ; i < fec_stream->params.L ; i++){
+        for(mblk_t *tmp = qbegin(&fec_stream->source_packets_recvd) ; 
!qend(&fec_stream->source_packets_recvd, tmp) ; tmp = 
qnext(&fec_stream->source_packets_recvd, tmp)){
+            if(rtp_get_seqnumber(tmp) == seqnum_list[i]){
+                putq(source_packets, dupmsg(tmp));
+            }
+        }
+    }
+    return (source_packets->q_mcount != fec_stream->params.L-1) ? FALSE : TRUE;
+}
+
+void fec_stream_reconstruction_error(FecStream *fec_stream, uint16_t seqnum){
+    if(fec_stream->size_prec == 0){
+        fec_stream->prec[0] = seqnum;
+        fec_stream->size_prec++;
+    } else if(((seqnum - fec_stream->prec[0]) < fec_stream->params.L) && 
(((fec_stream->prec[0]+1)%fec_stream->params.L) < 
((seqnum+1)%fec_stream->params.L))){
+        fec_stream->prec[fec_stream->size_prec] = seqnum;
+        fec_stream->size_prec++;
+    } else if(fec_stream->size_prec == 1){
+        fec_stream->error++;
+        fec_stream->prec[0] = seqnum;
+    } else {
+        fec_stream->size_prec = 1;
+        fec_stream->prec[0] = seqnum;
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/rtpaudiolevel.c 
new/ortp-5.1.3/src/rtpaudiolevel.c
--- old/ortp-5.0.67/src/rtpaudiolevel.c 1970-01-01 01:00:00.000000000 +0100
+++ new/ortp-5.1.3/src/rtpaudiolevel.c  2022-02-04 11:58:14.000000000 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010-2021 Belledonne Communications SARL.
+ *
+ * This file is part of oRTP.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have dispatchd a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ortp/logging.h"
+#include "ortp/rtp.h"
+
+/**
+ * Add the client to mixer audio level header extension.
+ * See https://tools.ietf.org/html/rfc6464
+ * @param packet the RTP packet.
+ * @param id the identifier of the client to mixer audio level extension.
+ * @param voice_activity TRUE if there is voice activity, FALSE otherwise.
+ * @param audio_level the audio level to set expressed in dBov.
+**/
+void rtp_add_client_to_mixer_audio_level(mblk_t *packet, int id, bool_t 
voice_activity, int audio_level) {
+       uint8_t data = (voice_activity ? 0x1 : 0x0) << 7 | (audio_level * -1);
+       rtp_add_extension_header(packet, id, sizeof(data), &data);
+}
+
+/**
+ * Obtain the client to mixer audio level through the header extension.
+ * See https://tools.ietf.org/html/rfc6464
+ * @param packet the RTP packet.
+ * @param id the identifier of the client to mixer audio level extension.
+ * @param voice_activity set to TRUE if there is voice activity, FALSE 
otherwise
+ * @return the client to mixer audio level in dBov, -1 if there is no 
extension header or the extension was not found.
+**/
+int rtp_get_client_to_mixer_audio_level(mblk_t *packet, int id, bool_t 
*voice_activity) {
+       uint8_t *data;
+       int ret;
+
+       ret = rtp_get_extension_header(packet, id, &data);
+       if (ret != -1) {
+               *voice_activity = (int)(*data) >> 7 & 0x1 ? TRUE : FALSE;
+
+               return (int)(*data & 0x7F) * -1; // Audio level is stored as a 
7-bit number expressed in -dBov
+       }
+
+       return -1;
+}
+
+/**
+ * Add the mixer to client audio level header extension.
+ * See https://tools.ietf.org/html/rfc6465
+ * @param packet the RTP packet.
+ * @param id the identifier of the client to mixer audio level extension.
+ * @param size the size of the audio_levels list.
+ * @param audio_levels the list if audio levels to set.
+**/
+void rtp_add_mixer_to_client_audio_level(mblk_t *packet, int id, size_t size, 
rtp_audio_level_t *audio_levels) {
+       uint8_t *data;
+       int i;
+
+       if (audio_levels == NULL || size <= 0) return;
+
+       // Increase packet size to have enough space to add csrc
+       msgpullup(packet, msgdsize(packet) + size * sizeof(uint32_t));
+       packet->b_wptr += size * sizeof(uint32_t);
+
+       data = ortp_new0(uint8_t, size);
+       for (i = 0; i < (int)size; i++) {
+               rtp_add_csrc(packet, audio_levels[i].csrc);
+               data[i] = 0x0 << 7 | (audio_levels[i].dbov * -1);
+       }
+       rtp_add_extension_header(packet, id, size, data);
+
+       ortp_free(data);
+}
+
+/**
+ * Obtain the mixer to client audio level through the header extension.
+ * See https://tools.ietf.org/html/rfc6465
+ * @param packet the RTP packet.
+ * @param id the identifier of the mixer to client audio level extension.
+ * @param audio_levels the list of mixer to client audio levels, this array 
must be allocated before calling this function.
+ * @return the size of the mixer to client audio levels list, -1 in case of 
error.
+**/
+int rtp_get_mixer_to_client_audio_level(mblk_t *packet, int id, 
rtp_audio_level_t* audio_levels) {
+       int ret, i;
+       uint8_t *data;
+
+       ret = rtp_get_extension_header(packet, id, &data);
+       if (ret != -1) {
+               rtp_header_t *header = (rtp_header_t*) packet->b_rptr;
+
+               if (ret != header->cc) {
+                       ortp_error("Error while retrieving mixer to client 
audio levels [%p]: number of audio level and csrc do not match", packet);
+                       return -1;
+               }
+
+               for (i = 0; i < ret; i++) {
+                       audio_levels[i].csrc = header->csrc[i];
+                       audio_levels[i].dbov = (int)(data[i] & 0x7F) * -1;
+               }
+       }
+
+       return ret;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/rtpbundle.cc 
new/ortp-5.1.3/src/rtpbundle.cc
--- old/ortp-5.0.67/src/rtpbundle.cc    2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/src/rtpbundle.cc     2022-02-04 11:58:14.000000000 +0100
@@ -224,27 +224,25 @@
                if (entry == ssrcToMid.end()) {
                        Mid value = {mid, isRtp ? sequenceNumber : (uint16_t)0};
                        ssrcToMid[ssrc] = value;
-
+                       ortp_message("Rtp Bundle [%p] SSRC [%u] paired with mid 
[%s]", this, ssrc, mid.c_str());
                        return true;
-               } else {
+               } else if ((*entry).second.mid != mid) {
                        if (isRtp) {
+                               ortp_message("Rtp Bundle [%p]: received a mid 
update via RTP.", this);
                                if (entry->second.sequenceNumber < 
sequenceNumber) {
                                        Mid value = {mid, sequenceNumber};
                                        ssrcToMid[ssrc] = value;
-
-                                       return true;
                                }
                        } else {
                                // We should normally update the mid but we 
chose not to for simplicity
                                // since RTCP does not have a sequence number.
                                // 
https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54#page-24
                                ortp_warning("Rtp Bundle [%p]: received a mid 
update via RTCP, ignoring it.", this);
-
-                               return true;
                        }
                }
+               return true;
        }
-
+       /* The mid is totally unknown, this is an error. */
        return false;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/rtpparse.c 
new/ortp-5.1.3/src/rtpparse.c
--- old/ortp-5.0.67/src/rtpparse.c      2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/src/rtpparse.c       2022-02-04 11:58:14.000000000 +0100
@@ -393,5 +393,7 @@
        if ((discarded == 0) && (duplicate == 0)) {
                session->rtcp_xr_stats.rcv_count++;
        }
+       if(session->fec_stream != NULL)
+               fec_stream_on_new_source_packet_received(session->fec_stream, 
mp);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/rtpsession.c 
new/ortp-5.1.3/src/rtpsession.c
--- old/ortp-5.0.67/src/rtpsession.c    2022-01-06 16:42:33.000000000 +0100
+++ new/ortp-5.1.3/src/rtpsession.c     2022-02-04 11:58:14.000000000 +0100
@@ -151,7 +151,7 @@
 }
 
 
-mblk_t *rtp_getq(queue_t *q,uint32_t timestamp, int *rejected)
+mblk_t *rtp_peekq(queue_t *q,uint32_t timestamp, int *rejected)
 {
        mblk_t *tmp,*ret=NULL,*old=NULL;
        rtp_header_t *tmprtp;
@@ -182,7 +182,7 @@
                                (*rejected)++;
                                freemsg(old);
                        }
-                       ret=getq(q); /* dequeue the packet, since it has an 
interesting timestamp*/
+            ret=peekq(q); /* dequeue the packet, since it has an interesting 
timestamp*/
                        ts_found=tmprtp->timestamp;
                        ortp_debug("rtp_getq: Found packet with 
ts=%u",tmprtp->timestamp);
 
@@ -196,7 +196,7 @@
        return ret;
 }
 
-mblk_t *rtp_getq_permissive(queue_t *q,uint32_t timestamp, int *rejected)
+mblk_t *rtp_peekq_permissive(queue_t *q,uint32_t timestamp, int *rejected)
 {
        mblk_t *tmp,*ret=NULL;
        rtp_header_t *tmprtp;
@@ -216,7 +216,7 @@
        ortp_debug("rtp_getq_permissive: Seeing packet with 
ts=%i",tmprtp->timestamp);
        if ( RTP_TIMESTAMP_IS_NEWER_THAN(timestamp,tmprtp->timestamp) )
        {
-               ret=getq(q); /* dequeue the packet, since it has an interesting 
timestamp*/
+        ret=peekq(q); /* dequeue the packet, since it has an interesting 
timestamp*/
                ortp_debug("rtp_getq_permissive: Found packet with 
ts=%i",tmprtp->timestamp);
        }
        return ret;
@@ -890,7 +890,8 @@
                const char *mid = rtp_bundle_get_session_mid(session->bundle, 
session);
 
                if (mid != NULL) {
-                       rtp_add_extension_header(mp, RTP_EXTENSION_MID, 
strlen(mid), (uint8_t *)mid);
+                       int midId = 
rtp_bundle_get_mid_extension_id(session->bundle);
+                       rtp_add_extension_header(mp, midId != -1 ? midId : 
RTP_EXTENSION_MID, strlen(mid), (uint8_t *)mid);
                }
        }
 
@@ -902,6 +903,43 @@
        return mp;
 }
 
+/**
+ *     This will do the same as rtp_session_create_packet() without payload 
data but it will also add 
+ *     mixer to client audio level indication through header extensions.
+ *
+ *@param session a rtp session.
+ *@param header_size the rtp header size. For standart size (without 
extensions), it is RTP_FIXED_HEADER_SIZE
+ *@param mtc_extension_id id of the mixer to client extension id.
+ *@param audio_levels_size size of audio levels contained in audio_levels 
parameter.
+ *@param audio_levels list of rtp_audio_level_t to add in this packet.
+ *@return a rtp packet in a mblk_t (message block) structure.
+**/
+mblk_t * rtp_session_create_packet_with_mixer_to_client_audio_level(RtpSession 
*session, size_t header_size, int mtc_extension_id, size_t audio_levels_size, 
rtp_audio_level_t *audio_levels)
+{
+       mblk_t *mp;
+       rtp_header_t *rtp;
+
+       mp=allocb(header_size,BPRI_MED);
+       rtp=(rtp_header_t*)mp->b_rptr;
+       rtp_header_init_from_session(rtp,session);
+       mp->b_wptr+=header_size;
+
+       /*this has to be called before adding any other extensions since it 
changes the header size to add the csrcs*/
+       rtp_add_mixer_to_client_audio_level(mp, mtc_extension_id, 
audio_levels_size, audio_levels);
+
+       /*add the mid from the bundle if any*/
+       if (session->bundle) {
+               const char *mid = rtp_bundle_get_session_mid(session->bundle, 
session);
+
+               if (mid != NULL) {
+                       int midId = 
rtp_bundle_get_mid_extension_id(session->bundle);
+                       rtp_add_extension_header(mp, midId != -1 ? midId : 
RTP_EXTENSION_MID, strlen(mid), (uint8_t *)mid);
+               }
+       }
+
+       return mp;
+}
+
 
 /**
  * Create a packet already including headers
@@ -950,7 +988,8 @@
                        const char *mid = 
rtp_bundle_get_session_mid(session->bundle, session);
 
                        if (mid != NULL) {
-                               rtp_add_extension_header(mp, RTP_EXTENSION_MID, 
strlen(mid), (uint8_t *)mid);
+                               int midId = 
rtp_bundle_get_mid_extension_id(session->bundle);
+                               rtp_add_extension_header(mp, midId != -1 ? 
midId : RTP_EXTENSION_MID, strlen(mid), (uint8_t *)mid);
                        }
                }
        }
@@ -1074,6 +1113,10 @@
                error = rtp_session_rtp_send (session, copymsg(mp));
                session->duplication_left -= 1.f;
        }
+       if((session->fec_stream != NULL) && (mp != NULL)){
+               fec_stream_on_new_source_packet_sent(session->fec_stream, mp);
+       }
+
        error = rtp_session_rtp_send (session, mp);
 
        /*send RTCP packet if needed */
@@ -1081,6 +1124,7 @@
        /* receives rtcp packet if session is send-only*/
        /*otherwise it is done in rtp_session_recvm_with_ts */
        if (session->mode==RTP_SESSION_SENDONLY) rtp_session_rtcp_recv(session);
+
        return error;
 }
 
@@ -1247,13 +1291,13 @@
                if (user_ts==session->rtp.rcv_last_app_ts)
                        read_socket=FALSE;
        }
-       session->rtp.rcv_last_app_ts = user_ts;
+    session->rtp.rcv_last_app_ts = user_ts;
        if (read_socket){
                rtp_session_rtp_recv (session, user_ts);
                rtp_session_rtcp_recv(session);
        }
        /* check for telephone event first */
-       mp=getq(&session->rtp.tev_rq);
+    mp=getq(&session->rtp.tev_rq);
        if (mp!=NULL){
                size_t msgsize=msgdsize(mp);
                ortp_global_stats.recv += msgsize;
@@ -1282,23 +1326,50 @@
                session->rcv.ssrc = rtp->ssrc;
                /* delete the recv synchronisation flag */
                rtp_session_unset_flag (session, RTP_SESSION_RECV_SYNC);
-       }
+    }
 
        /*calculate the stream timestamp from the user timestamp */
        ts = 
jitter_control_get_compensated_timestamp(&session->rtp.jittctl,user_ts);
        if (session->rtp.jittctl.params.enabled==TRUE){
                if (session->permissive)
-                       mp = rtp_getq_permissive(&session->rtp.rq, 
ts,&rejected);
+            mp = rtp_peekq_permissive(&session->rtp.rq, ts,&rejected);
                else{
-                       mp = rtp_getq(&session->rtp.rq, ts,&rejected);
+            mp = rtp_peekq(&session->rtp.rq, ts,&rejected);
                }
-       }else mp=getq(&session->rtp.rq);/*no jitter buffer at all*/
+    }else mp=peekq(&session->rtp.rq);/*no jitter buffer at all*/
 
        session->stats.outoftime+=rejected;
        ortp_global_stats.outoftime+=rejected;
        session->rtcp_xr_stats.discarded_count += rejected;
 
-       end:
+    end:
+    if(session->fec_stream != NULL && mp != NULL){
+        if(session->rtp.rcv_last_seq + 1 != rtp_get_seqnumber(mp)){
+            mblk_t *fec_mp = 
fec_stream_reconstruct_missing_packet(session->fec_stream, 
session->rtp.rcv_last_seq + 1);
+            session->fec_stream->total_lost_packets++;
+            if (fec_mp != NULL){
+                OrtpEvent *ev;
+                OrtpEventData *evdata;
+
+                mp = fec_mp;
+                ortp_message("Source packet reconstructed : SeqNum = %d ; 
TimeStamp = %u", (int)rtp_get_seqnumber(mp), (unsigned 
int)rtp_get_timestamp(mp));
+                ev = ortp_event_new(ORTP_EVENT_SOURCE_PACKET_RECONSTRUCTED);
+                evdata = ortp_event_get_data(ev);
+                evdata->info.reconstructed_packet_seq_number = 
rtp_get_seqnumber(mp);
+                rtp_session_dispatch_event(session, ev);
+            } else {
+                ortp_message("Unable to reconstuct source packet : SeqNum = 
%d", (int)(session->rtp.rcv_last_seq + 1));
+                fec_stream_reconstruction_error(session->fec_stream, 
rtp_get_seqnumber(mp));
+                session->fec_stream->reconstruction_fail++;
+                if(!qempty(&session->rtp.rq) && mp != NULL) 
remq(&session->rtp.rq, mp);
+            }
+        } else {
+            if(!qempty(&session->rtp.rq) && mp != NULL) remq(&session->rtp.rq, 
mp);
+        }
+    } else {
+        if(!qempty(&session->rtp.rq) && mp != NULL) remq(&session->rtp.rq, mp);
+    }
+
        if (mp != NULL)
        {
                size_t msgsize = msgdsize(mp);  /* evaluate how much bytes 
(including header) is received by app */
@@ -1337,7 +1408,7 @@
                        /*ortp_debug("Returned packet has timestamp %u, with 
clock slide compensated it is %u",packet_ts,rtp->timestamp);*/
                }
                session->rtp.rcv_last_ts = packet_ts;
-               session->rtp.rcv_last_seq = rtp->seq_number;
+        session->rtp.rcv_last_seq = rtp->seq_number;
                if (!(session->flags & RTP_SESSION_FIRST_PACKET_DELIVERED)){
                        
rtp_session_set_flag(session,RTP_SESSION_FIRST_PACKET_DELIVERED);
                }
@@ -1369,7 +1440,8 @@
                }
                else session_set_set(&sched->r_sessions,session);       /*to 
unblock _select() immediately */
                wait_point_unlock(&session->rcv.wp);
-       }
+    }
+
        return mp;
 }
 
@@ -2016,6 +2088,14 @@
 **/
 void rtp_session_destroy (RtpSession * session)
 {
+    if(session->fec_stream != NULL){
+        if(session->fec_stream->fec_session != NULL){
+            rtp_session_destroy(session->fec_stream->fec_session);
+            session->fec_stream->fec_session = NULL;
+        }
+        fec_stream_destroy(session->fec_stream);
+        session->fec_stream = NULL;
+    }
        rtp_session_uninit (session);
        ortp_free (session);
 }
@@ -2104,7 +2184,7 @@
  * @param size the size in bytes of the extension to add.
  * @param data the buffer to the extension data.
 **/
-ORTP_PUBLIC void rtp_add_extension_header(mblk_t *packet, int id, size_t size, 
uint8_t *data) {
+void rtp_add_extension_header(mblk_t *packet, int id, size_t size, uint8_t 
*data) {
        if (size <= 0 || data == NULL) {
                ortp_warning("Cannot add an extension with empty data");
                return;
@@ -2194,7 +2274,7 @@
  * @param data pointer that will be set to the beginning of the extension data.
  * @return the size of the wanted extension in bytes, -1 if there is no 
extension header or the wanted extension was not found.
 **/
-ORTP_PUBLIC int rtp_get_extension_header(mblk_t *packet, int id, uint8_t 
**data) {
+int rtp_get_extension_header(mblk_t *packet, int id, uint8_t **data) {
        uint8_t *ext_header, *tmp;
        uint16_t profile;
        size_t ext_header_size, size;
@@ -2204,7 +2284,6 @@
        ext_header_size = rtp_get_extheader(packet, &profile, &ext_header);
 
        if (ext_header_size == (size_t)-1) {
-               ortp_warning("Extension header is empty!");
                return -1;
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/rtpsession_priv.h 
new/ortp-5.1.3/src/rtpsession_priv.h
--- old/ortp-5.0.67/src/rtpsession_priv.h       2022-01-06 16:42:33.000000000 
+0100
+++ new/ortp-5.1.3/src/rtpsession_priv.h        2022-02-04 11:58:14.000000000 
+0100
@@ -53,7 +53,7 @@
 
 void rtp_session_update_payload_type(RtpSession * session, int pt);
 int rtp_putq(queue_t *q, mblk_t *mp);
-mblk_t * rtp_getq(queue_t *q, uint32_t ts, int *rejected);
+mblk_t * rtp_peekq(queue_t *q, uint32_t ts, int *rejected);
 int rtp_session_rtp_recv(RtpSession * session, uint32_t ts);
 int rtp_session_rtcp_recv(RtpSession * session);
 int rtp_session_rtp_send (RtpSession * session, mblk_t * m);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/tests/CMakeLists.txt 
new/ortp-5.1.3/src/tests/CMakeLists.txt
--- old/ortp-5.0.67/src/tests/CMakeLists.txt    2022-01-06 16:42:33.000000000 
+0100
+++ new/ortp-5.1.3/src/tests/CMakeLists.txt     2022-02-04 11:58:14.000000000 
+0100
@@ -21,7 +21,7 @@
 ############################################################################
 
 if (NOT IOS)
-       set(EXECUTABLES rtpsend rtprecv mrtpsend mrtprecv test_timer tevrtpsend 
tevrtprecv rtpsend_stupid rtpextensionheader)
+        set(EXECUTABLES rtpsend rtprecv mrtpsend mrtprecv test_timer 
tevrtpsend tevrtprecv rtpsend_stupid rtpextensionheader fectest)
        foreach(executable ${EXECUTABLES})
                bc_apply_compile_flags(${executable}.c STRICT_OPTIONS_CPP 
STRICT_OPTIONS_C)
                add_executable(${executable} ${executable}.c)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ortp-5.0.67/src/tests/rtpextensionheader.c 
new/ortp-5.1.3/src/tests/rtpextensionheader.c
--- old/ortp-5.0.67/src/tests/rtpextensionheader.c      2022-01-06 
16:42:33.000000000 +0100
+++ new/ortp-5.1.3/src/tests/rtpextensionheader.c       2022-02-04 
11:58:14.000000000 +0100
@@ -29,6 +29,9 @@
        char *foo = "foo";
        char *bar = "bar123";
        char *data;
+       rtp_audio_level_t audio_levels[15] = {0};
+       int audio_size, result;
+       bool_t voice_activity;
 
        srand(time(NULL));
 
@@ -103,6 +106,38 @@
        }
 
        freemsg(packet);
+
+       // Test client to mixer audio level api
+       packet = rtp_session_create_packet(session, RTP_FIXED_HEADER_SIZE, 
NULL, 0);
+
+       rtp_add_client_to_mixer_audio_level(packet, 2, TRUE, -64);
+       result = rtp_get_client_to_mixer_audio_level(packet, 2, 
&voice_activity);
+       if (result != -64) {
+               ortp_error("Client to mixer wrong value! %d", result);
+       } else {
+               ortp_message("Audio level for -64 with voice activity, value 
returned: %d, voice activity: %d", result, voice_activity ? 1 : 0);
+       }
+
+       freemsg(packet);
+
+       // Test mixer to client audio level api
+       packet = rtp_session_create_packet(session, RTP_FIXED_HEADER_SIZE, 
NULL, 0);
+       rtp_audio_level_t values[5] = {{1, -127}, {2, -115}, {0, -53}, {4, 
-28}, {5, 0}};
+
+       rtp_add_mixer_to_client_audio_level(packet, 2, 5, values);
+       audio_size = rtp_get_mixer_to_client_audio_level(packet, 2, 
audio_levels);
+
+       ortp_message("Audio levels' expected values: [1, -127], [2, -115], [0, 
-53], [4, -28], [5, 0]");
+       ortp_message("Results (%d):", audio_size);
+       if (audio_size != -1) {
+               for (i = 0; i < audio_size; i++) {
+                       ortp_message("\tcsrc: %d, level: %d", 
audio_levels[i].csrc, audio_levels[i].dbov);
+               }
+       } else {
+               ortp_error("Mixer to client has no values!");
+       }
+
+       freemsg(packet);
 
        rtp_session_destroy(session);
        ortp_exit();

Reply via email to