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();