[Pkg-voip-commits] [ortp] 01/06: New upstream version 1.0.2

Bernhard Schmidt berni at moszumanska.debian.org
Mon Oct 16 22:44:01 UTC 2017


This is an automated email from the git hooks/post-receive script.

berni pushed a commit to branch master
in repository ortp.

commit 90fd024508112e1e5aac249b4c53c4eac73265ff
Author: Bernhard Schmidt <berni at debian.org>
Date:   Thu Aug 31 08:30:54 2017 +0200

    New upstream version 1.0.2
---
 .gitignore                    |   1 +
 CMakeLists.txt                |  38 +++++------
 NEWS                          |   3 +
 ORTPConfig.cmake.in           |  28 ++++++--
 README.md                     |   8 +++
 build/CMakeLists.txt          |  50 ++++++++++++++
 build/osx/Info.plist.in       |  43 ++++++++++++
 build/rpm/ortp.spec.cmake     | 116 ++++++++++++++++++++++++++++++++
 include/ortp/event.h          |  11 ++-
 include/ortp/payloadtype.h    |   6 +-
 include/ortp/port.h           |   5 +-
 include/ortp/rtpsession.h     |  15 +++++
 include/ortp/str_utils.h      |   2 -
 include/ortp/utils.h          |  20 ++++++
 ortp-config.h.cmake           |   1 -
 src/CMakeLists.txt            |  28 ++++++--
 src/Makefile.am               |   1 +
 src/b64.c                     |  80 +++++++++++-----------
 src/congestiondetector.c      |  87 ++++++++++++++++++------
 src/congestiondetector.h      |   5 +-
 src/jitterctl.c               |   4 +-
 src/netsim.c                  |  13 ----
 src/payloadtype.c             |   5 ++
 src/posixtimer.c              |   4 +-
 src/rtcp.c                    |  15 ++++-
 src/rtpparse.c                |  11 ++-
 src/rtpsession.c              |  37 ++++++++--
 src/rtpsession_inet.c         |  36 +++++++---
 src/tests/CMakeLists.txt      |   2 +-
 src/utils.c                   |  33 +++++++++
 src/videobandwidthestimator.c | 153 ++++++++++++++++++++++++++++++++++++++++++
 src/videobandwidthestimator.h |  96 ++++++++++++++++++++++++++
 32 files changed, 814 insertions(+), 143 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6a0ce76..231df4f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,4 @@ stamp-h1
 *.vcxproj.*
 compile
 git-clang-format.diff
+*.DS_Store
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eccb8db..ab746ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,7 +21,7 @@
 ############################################################################
 
 cmake_minimum_required(VERSION 3.0)
-project(oRTP VERSION 1.0.1)
+project(oRTP VERSION 1.0.2)
 
 
 set(ORTP_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})
@@ -42,26 +42,11 @@ option(ENABLE_DEBUG_LOGS "Turn on or off debug level logs." NO)
 set(WITH_THREAD_STACK_SIZE "0" CACHE STRING "Set thread stack size (0 is the OS default).")
 
 
-macro(apply_compile_flags SOURCE_FILES)
-	if(${SOURCE_FILES})
-		set(options "")
-		foreach(a ${ARGV})
-			if(STRICT_OPTIONS_${a})
-				string(REPLACE ";" " " options_${a} "${STRICT_OPTIONS_${a}}")
-				set(options "${options} ${options_${a}}")
-			endif()
-		endforeach()
-		if(options)
-			set_source_files_properties(${${SOURCE_FILES}} PROPERTIES COMPILE_FLAGS "${options}")
-		endif()
-	endif()
-endmacro()
-
-
 include(CheckIncludeFile)
 include(CheckFunctionExists)
 include(GNUInstallDirs)
 
+
 if(NOT CMAKE_INSTALL_RPATH AND CMAKE_INSTALL_PREFIX)
 	set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR})
 	message(STATUS "Setting install rpath to ${CMAKE_INSTALL_RPATH}")
@@ -81,6 +66,8 @@ else()
 	find_package(BcToolbox 0.2.0 REQUIRED)
 endif()
 
+add_subdirectory(build)
+
 check_include_file(sys/uio.h HAVE_SYS_UIO_H)
 check_include_file(sys/audio.h HAVE_SYS_AUDIO_H)
 if(NOT ANDROID)
@@ -100,16 +87,14 @@ include_directories(
 	include/
 	src/
 	${CMAKE_CURRENT_BINARY_DIR}
-	${BCTOOLBOX_CORE_INCLUDE_DIRS}
 )
 if(MSVC)
 	include_directories(${MSVC_INCLUDE_DIR})
 endif()
 
 
-set(ORTP_CPPFLAGS )
+set(ORTP_CPPFLAGS ${BCTOOLBOX_CPPFLAGS})
 if(ENABLE_STATIC)
-	set(ORTP_STATIC 1)
 	list(APPEND ORTP_CPPFLAGS "-DORTP_STATIC")
 endif()
 if(ENABLE_PERF)
@@ -128,6 +113,9 @@ endif()
 if(APPLE)
 	set(__APPLE_USE_RFC_3542 1)
 endif()
+if(ORTP_CPPFLAGS)
+	add_definitions(${ORTP_CPPFLAGS})
+endif()
 set(POSIXTIMER_INTERVAL 10000)
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ortp-config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/ortp-config.h)
 set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/ortp-config.h PROPERTIES GENERATED ON)
@@ -187,7 +175,7 @@ if(ENABLE_DOC)
 		)
 		add_custom_target(ortp-html-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html")
 		install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html"
-			DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/oRTP-${ORTP_VERSION}")
+			DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/ortp-${ORTP_VERSION}")
 	endif()
 endif()
 
@@ -204,7 +192,6 @@ set(ORTPDEPS_LIBS )
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ortp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/ortp.pc)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ortp.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 
-
 include(CMakePackageConfigHelpers)
 write_basic_package_version_file(
 	"${CMAKE_CURRENT_BINARY_DIR}/ORTPConfigVersion.cmake"
@@ -229,3 +216,10 @@ install(FILES
 	"${CMAKE_CURRENT_BINARY_DIR}/ORTPConfigVersion.cmake"
 	DESTINATION ${CONFIG_PACKAGE_LOCATION}
 )
+install(FILES 	"${CMAKE_CURRENT_SOURCE_DIR}/README.md" 
+	"${CMAKE_CURRENT_SOURCE_DIR}/ChangeLog" 
+	"${CMAKE_CURRENT_SOURCE_DIR}/COPYING" 
+	"${CMAKE_CURRENT_SOURCE_DIR}/AUTHORS" 
+	DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/ortp-${ORTP_VERSION}")
+
+
diff --git a/NEWS b/NEWS
index 782c193..89f116d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+July 20, 2017: ortp-1.0.2
+	- Bug fixes
+
 February 23, 2017: ortp-1.0.1
 	- minor enhancements and bugfixes
 
diff --git a/ORTPConfig.cmake.in b/ORTPConfig.cmake.in
index a0b8324..2c03b56 100644
--- a/ORTPConfig.cmake.in
+++ b/ORTPConfig.cmake.in
@@ -32,16 +32,30 @@ if(NOT LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
 	include("${CMAKE_CURRENT_LIST_DIR}/ORTPTargets.cmake")
 endif()
 
-get_filename_component(ORTP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
-if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
-	set(ORTP_INCLUDE_DIRS "${EP_ortp_INCLUDE_DIR}")
+if(@ENABLE_SHARED@)
+	set(ORTP_TARGETNAME ortp)
+	set(ORTP_LIBRARIES ${ORTP_TARGETNAME})
 else()
-	set(ORTP_INCLUDE_DIRS "${ORTP_CMAKE_DIR}/../../../include")
+	set(ORTP_TARGETNAME ortp-static)
+	if(TARGET ${ORTP_TARGETNAME})
+		if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
+			set(ORTP_LIBRARIES ${ORTP_TARGETNAME})
+		else()
+			get_target_property(ORTP_LIBRARIES ${ORTP_TARGETNAME} LOCATION)
+		endif()
+		get_target_property(ORTP_LINK_LIBRARIES ${ORTP_TARGETNAME} INTERFACE_LINK_LIBRARIES)
+		if(ORTP_LINK_LIBRARIES)
+			list(APPEND ORTP_LIBRARIES ${ORTP_LINK_LIBRARIES})
+		endif()
+	endif()
 endif()
-if(@ENABLE_SHARED@)
-	set(ORTP_LIBRARIES ortp)
+get_target_property(ORTP_INCLUDE_DIRS ${ORTP_TARGETNAME} INTERFACE_INCLUDE_DIRECTORIES)
+if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS)
+	list(INSERT ORTP_INCLUDE_DIRS 0 "${EP_ortp_INCLUDE_DIR}")
 else()
-	set(ORTP_LIBRARIES ortp-static)
+	list(INSERT ORTP_INCLUDE_DIRS 0 "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
 endif()
+list(REMOVE_DUPLICATES ORTP_INCLUDE_DIRS)
+
 set(ORTP_CPPFLAGS @ORTP_CPPFLAGS@)
 set(ORTP_FOUND 1)
diff --git a/README.md b/README.md
index e765ab3..a1c385a 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,14 @@ Our CMake scripts may automatically add some paths into research paths of genera
 To ensure that the installed binaries are striped of any rpath, use `-DCMAKE_SKIP_INSTALL_RPATH=ON`
 while you invoke cmake.
 
+Rpm packaging
+ortp rpm can be generated with cmake3 using the following command:
+mkdir WORK
+cd WORK
+cmake3 ../
+make package_source
+rpmbuild -ta --clean --rmsource --rmspec ortp-<version>-<release>.tar.gz
+
 
 How do you I test ?
 -------------------
diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt
new file mode 100644
index 0000000..d7511b7
--- /dev/null
+++ b/build/CMakeLists.txt
@@ -0,0 +1,50 @@
+############################################################################
+# CMakeLists.txt
+# Copyright (C) 2017  Belledonne Communications, Grenoble France
+#
+############################################################################
+#
+# 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 2
+# 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 received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+############################################################################
+
+if (NOT CPACK_PACKAGE_NAME)
+	set(CPACK_PACKAGE_NAME "ortp")
+ENDIF()
+
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../COPYING")
+
+set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
+
+set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PROJECT_VERSION})
+
+set(CPACK_SOURCE_GENERATOR "TGZ")
+set(CPACK_SOURCE_IGNORE_FILES
+"${CMAKE_BINARY_DIR}"
+"^${PROJECT_SOURCE_DIR}/.git*"
+)
+bc_project_build_version(${PROJECT_VERSION} PROJECT_VERSION_BUILD)
+
+set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${PROJECT_VERSION_BUILD}")
+
+message("Package file name is ${CPACK_PACKAGE_FILE_NAME}" )
+
+set(CPACK_SOURCE_PACKAGE_FILE_NAME ${CPACK_PACKAGE_FILE_NAME})
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rpm/ortp.spec.cmake ${CMAKE_CURRENT_SOURCE_DIR}/../ortp.spec)
+
+include(CPack)
+
diff --git a/build/osx/Info.plist.in b/build/osx/Info.plist.in
new file mode 100644
index 0000000..9e3f26f
--- /dev/null
+++ b/build/osx/Info.plist.in
@@ -0,0 +1,43 @@
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>ortp</string>
+	<key>CFBundleGetInfoString</key>
+	<string>${MACOSX_BUNDLE_INFO_STRING}</string>
+	<key>CFBundleIconFile</key>
+	<string>${MACOSX_BUNDLE_ICON_FILE}</string>
+	<key>CFBundleIdentifier</key>
+	<string>${MACOSX_FRAMEWORK_IDENTIFIER}</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>${MIN_OS}</string>
+	<key>MinimumOSVersion</key>
+	<string>${MIN_OS}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleLongVersionString</key>
+	<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
+	<key>CFBundleName</key>
+	<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>${ORTP_VERSION}</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>${ORTP_VERSION}</string>
+	<key>CSResourcesFileMapped</key>
+	<true/>
+	<key>NSHumanReadableCopyright</key>
+	<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+	<key>NSHighResolutionCapable</key>
+	<string>True</string>
+</dict>
+</plist>
\ No newline at end of file
diff --git a/build/rpm/ortp.spec.cmake b/build/rpm/ortp.spec.cmake
new file mode 100644
index 0000000..7b15219
--- /dev/null
+++ b/build/rpm/ortp.spec.cmake
@@ -0,0 +1,116 @@
+# -*- rpm-spec -*-
+#
+# ortp -- Real-time Transport Protocol Stack
+#
+# Default is optimized for Pentium IV but will execute on Pentium II &
+# later (i686).
+
+# These 2 lines are here because we can build the RPM for flexisip, in which 
+# case we prefix the entire installation so that we don't break compatibility
+# with the user's libs.
+# To compile with bc prefix, use rpmbuild -ba --with bc [SPEC]
+%define 		pkg_name 	%{?_with_bc:bc-ortp}%{!?_with_bc:ortp}
+%{?_with_bc: %define 	_prefix		/opt/belledonne-communications}
+%define 		srtp 		%{?_without_srtp:0}%{?!_without_srtp:1}
+
+# re-define some directories for older RPMBuild versions which don't. This messes up the doc/ dir
+# taken from https://fedoraproject.org/wiki/Packaging:RPMMacros?rd=Packaging/RPMMacros
+%define _datarootdir       %{_prefix}/share
+%define _datadir           %{_datarootdir}
+%define _docdir            %{_datadir}/doc
+
+%ifarch %ix86
+%define		ortp_cpu	pentium4
+%endif
+%define build_number @PROJECT_VERSION_BUILD@
+Summary:	Real-time Transport Protocol Stack
+Name:		%pkg_name
+Version:	@PROJECT_VERSION@
+Release:	%build_number%{?dist}
+#to be alined with redhat which changed epoc to 1 for an unknown reason
+Epoch:		1
+License:	GPL
+Group:		Applications/Communications
+URL:		http://linphone.org/ortp/
+Source0:	%{name}-%{version}-%build_number.tar.gz
+BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-buildroot
+%ifarch %ix86
+BuildArch:	i686
+%endif
+
+%if 0%{?rhel} && 0%{?rhel} <= 7
+%global cmake_name cmake3
+%define ctest_name ctest3
+%else
+%global cmake_name cmake
+%define ctest_name ctest
+%endif
+
+%description
+oRTP is a GPL licensed C library implementing the RTP protocol
+(rfc3550). It is available for most unix clones (primilarly Linux and
+HP-UX), and Microsoft Windows.
+
+%package        devel
+Summary:        Headers, libraries and docs for the oRTP library
+Group:          Development/Libraries
+BuildRequires:	doxygen
+#to be alined with redhat which changed epoc to 1 for an unknown reason
+Epoch:		1
+Requires:      %{name} = %{epoch}:%{version}-%{release}
+
+%description    devel
+oRTP is a GPL licensed C library implementing the RTP protocol
+(rfc1889). It is available for most unix clones (primilarly Linux and
+HP-UX), and Microsoft Windows.
+
+This package contains header files and development libraries needed to
+develop programs using the oRTP library.
+
+%ifarch %ix86
+%define	ortp_arch_cflags -malign-double -march=i686 -mtune=%{ortp_cpu}
+%else
+# Must be non-empty
+%define ortp_arch_cflags -Wall
+%endif
+%define ortp_cflags %ortp_arch_cflags -Wall -g -pipe -pthread -O3 -fomit-frame-pointer -fno-schedule-insns -fschedule-insns2 -fno-strict-aliasing
+
+%prep
+%setup -n %{name}-%{version}-%build_number
+
+%build
+%{expand:%%%cmake_name} . -DCMAKE_INSTALL_LIBDIR:PATH=%{_libdir} -DCMAKE_PREFIX_PATH:PATH=%{_prefix}
+make %{?_smp_mflags}
+
+%install
+make install DESTDIR=%{buildroot}
+
+%check
+%{ctest_name} -V %{?_smp_mflags}
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root,-)
+%doc %{_docdir}/ortp-%{version}/README.md
+%doc %{_docdir}/ortp-%{version}/ChangeLog
+%doc %{_docdir}/ortp-%{version}/COPYING
+%doc %{_docdir}/ortp-%{version}/AUTHORS
+%{_libdir}/*.so.*
+
+%files devel
+%defattr(-,root,root,-)
+%doc %{_docdir}/ortp-%{version}/html/*
+%{_libdir}/*.a
+%{_libdir}/*.so
+%{_libdir}/pkgconfig/*.pc
+%{_includedir}/*
+%{_datadir}/oRTP/cmake/ORTPConfig.cmake 
+%{_datadir}/oRTP/cmake/ORTPConfigVersion.cmake
+%{_datadir}/oRTP/cmake/ORTPTargets-noconfig.cmake
+%{_datadir}/oRTP/cmake/ORTPTargets.cmake
+
+%changelog
+* Tue Oct 25 2005 Francois-Xavier Kowalski <fix at hp.com>
+- Add to oRTP distribution with "make rpm" target
diff --git a/include/ortp/event.h b/include/ortp/event.h
index efc63b1..017e562 100644
--- a/include/ortp/event.h
+++ b/include/ortp/event.h
@@ -44,14 +44,16 @@ struct _OrtpEventData{
 		bool_t dtls_stream_encrypted;
 		bool_t zrtp_stream_encrypted;
 		bool_t ice_processing_successful;
-		struct _ZrtpSas{
+		struct _ZrtpInfo{
 			char sas[32]; // up to 31 + null characters
 			bool_t verified;
-			bool_t pad[3];
-		} zrtp_sas;
+			bool_t cache_mismatch;
+			bool_t pad[2];
+		} zrtp_info;
 		OrtpSocketType socket_type;
 		uint32_t received_rtt_character;
 		bool_t congestion_detected;
+		float video_bandwidth_available;
 	} info;
 };
 
@@ -80,6 +82,9 @@ ORTP_PUBLIC OrtpEventType ortp_event_get_type(const OrtpEvent *ev);
 #define ORTP_EVENT_DTLS_ENCRYPTION_CHANGED		13
 #define ORTP_EVENT_RTT_CHARACTER_RECEIVED		15
 #define ORTP_EVENT_CONGESTION_STATE_CHANGED		16
+#define ORTP_EVENT_ZRTP_CACHE_MISMATCH			17
+#define ORTP_EVENT_ZRTP_PEER_VERSION_OBSOLETE		18
+#define ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE             19
 
 ORTP_PUBLIC OrtpEventData * ortp_event_get_data(OrtpEvent *ev);
 ORTP_PUBLIC void ortp_event_destroy(OrtpEvent *ev);
diff --git a/include/ortp/payloadtype.h b/include/ortp/payloadtype.h
index ff443f9..7085854 100644
--- a/include/ortp/payloadtype.h
+++ b/include/ortp/payloadtype.h
@@ -70,7 +70,7 @@ struct _PayloadTypeAvpfParams {
 	uint16_t trr_interval; /**< The interval in milliseconds between regular RTCP packets. */
 };
 
-struct _PayloadType
+struct _OrtpPayloadType
 {
 	int type; /**< one of PAYLOAD_* macros*/
 	int clock_rate; /**< rtp clock rate*/
@@ -90,7 +90,8 @@ struct _PayloadType
 
 #ifndef PayloadType_defined
 #define PayloadType_defined
-typedef struct _PayloadType PayloadType;
+typedef struct _OrtpPayloadType OrtpPayloadType;
+typedef OrtpPayloadType PayloadType;
 typedef struct _PayloadTypeAvpfParams PayloadTypeAvpfParams;
 #endif
 
@@ -109,6 +110,7 @@ ORTP_PUBLIC void payload_type_append_recv_fmtp(PayloadType *pt, const char *fmtp
 ORTP_PUBLIC void payload_type_append_send_fmtp(PayloadType *pt, const char *fmtp);
 #define payload_type_get_avpf_params(pt)	((pt)->avpf)
 ORTP_PUBLIC void payload_type_set_avpf_params(PayloadType *pt, PayloadTypeAvpfParams params);
+ORTP_PUBLIC bool_t payload_type_is_vbr(const PayloadType *pt);
 
 #define payload_type_get_bitrate(pt)	((pt)->normal_bitrate)
 #define payload_type_get_rate(pt)		((pt)->clock_rate)
diff --git a/include/ortp/port.h b/include/ortp/port.h
index bfe77b9..eb30ddf 100644
--- a/include/ortp/port.h
+++ b/include/ortp/port.h
@@ -21,6 +21,9 @@
 #ifndef ORTP_PORT_H
 #define ORTP_PORT_H
 
+#if __APPLE__
+#include "TargetConditionals.h"
+#endif
 
 #if !defined(_WIN32) && !defined(_WIN32_WCE)
 /********************************/
@@ -385,7 +388,7 @@ ORTP_PUBLIC	bool_t ortp_is_multicast_addr(const struct sockaddr *addr);
 /*define __ios when we are compiling for ios.
  The TARGET_OS_IPHONE macro is stupid, it is defined to 0 when compiling on mac os x.
 */
-#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE==1
+#if TARGET_OS_IPHONE
 #define __ios 1
 #endif
 
diff --git a/include/ortp/rtpsession.h b/include/ortp/rtpsession.h
index e39f46b..e10765c 100644
--- a/include/ortp/rtpsession.h
+++ b/include/ortp/rtpsession.h
@@ -302,6 +302,7 @@ typedef struct _OrtpStream {
 	socklen_t loc_addrlen;
 	struct sockaddr_storage loc_addr;
 	struct _RtpTransport *tr;
+	OrtpBwEstimator recv_bw_estimator;
 	struct timeval send_bw_start; /* used for bandwidth estimation */
 	struct timeval recv_bw_start; /* used for bandwidth estimation */
 	unsigned int sent_bytes; /* used for bandwidth estimation */
@@ -351,6 +352,7 @@ typedef struct _RtpStream
 	int ssrc_changed_thres;
 	jitter_stats_t jitter_stats;
 	struct _OrtpCongestionDetector *congdetect;
+	struct _OrtpVideoBandwidthEstimator *video_bw_estimator;
 }RtpStream;
 
 typedef struct _RtcpStream
@@ -443,8 +445,20 @@ struct _RtpSession
 	bool_t use_pktinfo;
 
 	bool_t is_spliced;
+	bool_t congestion_detector_enabled;
+	bool_t video_bandwidth_estimator_enabled;
 };
 
+/**
+ * Structure describing the video bandwidth estimator parameters
+**/
+typedef struct _OrtpVideoBandwidthEstimatorParams {
+	int enabled; /**<Whether estimator is enabled or off.*/
+	unsigned int packet_count_min; /** minimum number of packets with the same sent timestamp to be processed continuously before being used */
+	unsigned int packets_size_max; /** number of packets needed to compute the available video bandwidth */
+	unsigned int trust_percentage; /** percentage for which the chosen bandwidth value in all available will be inferior */
+} OrtpVideoBandwidthEstimatorParams;
+
 
 
 
@@ -681,6 +695,7 @@ ORTP_PUBLIC float rtp_session_get_round_trip_propagation(RtpSession *session);
 
 ORTP_PUBLIC void rtp_session_enable_network_simulation(RtpSession *session, const OrtpNetworkSimulatorParams *params);
 ORTP_PUBLIC void rtp_session_enable_congestion_detection(RtpSession *session, bool_t enabled);
+ORTP_PUBLIC void rtp_session_enable_video_bandwidth_estimator(RtpSession *session, const OrtpVideoBandwidthEstimatorParams *params);
 
 ORTP_PUBLIC void rtp_session_rtcp_set_lost_packet_value( RtpSession *session, const int value );
 ORTP_PUBLIC void rtp_session_rtcp_set_jitter_value(RtpSession *session, const unsigned int value );
diff --git a/include/ortp/str_utils.h b/include/ortp/str_utils.h
index 4bd0075..e696b1d 100644
--- a/include/ortp/str_utils.h
+++ b/include/ortp/str_utils.h
@@ -63,9 +63,7 @@ typedef struct msgb
 	unsigned char *b_wptr;
 	uint32_t reserved1;
 	uint32_t reserved2;
-#if defined(ORTP_TIMESTAMP)
 	struct timeval timestamp;
-#endif
 	ortp_recv_addr_t recv_addr; /*contains the destination address of incoming packets, used for ICE processing*/
 	struct sockaddr_storage net_addr; /*source address of incoming packet, or dest address of outgoing packet, used only by simulator and modifiers*/
 	socklen_t net_addrlen; /*source (dest) address of incoming (outgoing) packet length used by simulator and modifiers*/
diff --git a/include/ortp/utils.h b/include/ortp/utils.h
index 886cc72..3c43964 100644
--- a/include/ortp/utils.h
+++ b/include/ortp/utils.h
@@ -71,6 +71,26 @@ ORTP_PUBLIC void ortp_kalman_rls_init(OrtpKalmanRLS *obj, double m0, double b0);
 ORTP_PUBLIC void ortp_kalman_rls_record(OrtpKalmanRLS *obj, double xmes, double ymes);
 
 
+typedef struct _OrtpBwEstimator{
+	float one_minus_alpha;
+	float inv_step;
+	float exp_constant;
+	struct timeval last_packet_recv;
+	float value;
+}OrtpBwEstimator;
+
+/**
+ * Utility object to compute a sliding exponential mean bitrate.
+ * @param obj the estimator structure to initialize
+ * @param alpha the weight of previous estimation (between 0 and 1)
+ * @param step a time constant in seconds representing the sampling period
+**/ 
+ORTP_PUBLIC void ortp_bw_estimator_init(OrtpBwEstimator *obj, float alpha, float step);
+
+ORTP_PUBLIC void ortp_bw_estimator_packet_received (OrtpBwEstimator *obj, size_t bytes, const struct timeval *recv_time);
+
+ORTP_PUBLIC float ortp_bw_estimator_get_value(OrtpBwEstimator *obj);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ortp-config.h.cmake b/ortp-config.h.cmake
index 020c3d5..1a9c79d 100644
--- a/ortp-config.h.cmake
+++ b/ortp-config.h.cmake
@@ -34,7 +34,6 @@
 #cmakedefine ORTP_BIGENDIAN
 
 #cmakedefine PERF
-#cmakedefine ORTP_STATIC
 #cmakedefine ORTP_TIMESTAMP
 #cmakedefine ORTP_DEBUG_MODE
 #cmakedefine ORTP_DEFAULT_THREAD_STACK_SIZE ${ORTP_DEFAULT_THREAD_STACK_SIZE}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 480ca18..7a96dc6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -59,6 +59,7 @@ set(ORTP_SOURCE_FILES_C
 	sessionset.c
 	str_utils.c
 	telephonyevents.c
+	videobandwidthestimator.c
 	utils.c
 )
 set(ORTP_SOURCE_FILES_CXX )
@@ -81,14 +82,15 @@ if(WIN32)
 	endif()
 endif()
 
-apply_compile_flags(ORTP_SOURCE_FILES_C "CPP" "C")
-apply_compile_flags(ORTP_SOURCE_FILES_CXX "CPP" "CXX")
+bc_apply_compile_flags(ORTP_SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
+bc_apply_compile_flags(ORTP_SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX)
 
 if(ENABLE_STATIC)
 	add_library(ortp-static STATIC ${ORTP_HEADER_FILES} ${ORTP_SOURCE_FILES_C} ${ORTP_SOURCE_FILES_CXX})
 	set_target_properties(ortp-static PROPERTIES OUTPUT_NAME ortp)
 	target_compile_definitions(ortp-static PRIVATE "ORTP_EXPORTS")
-	target_link_libraries(ortp-static ${LIBS})
+	target_include_directories(ortp-static PUBLIC ${BCTOOLBOX_CORE_INCLUDE_DIRS})
+	target_link_libraries(ortp-static INTERFACE ${LIBS})
 	install(TARGETS ortp-static EXPORT ${EXPORT_TARGETS_NAME}Targets
 		ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
 		PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
@@ -96,9 +98,21 @@ if(ENABLE_STATIC)
 endif()
 if(ENABLE_SHARED)
 	add_library(ortp SHARED ${ORTP_HEADER_FILES} ${ORTP_SOURCE_FILES_C} ${ORTP_SOURCE_FILES_CXX})
-	if(ANDROID)
-		set_target_properties(ortp PROPERTIES OUTPUT_NAME "ortp-${NDK_ARCHITECTURE}")
-	else()
+	if(IOS)
+		if(IOS)
+			set(MIN_OS ${LINPHONE_IOS_DEPLOYMENT_TARGET})
+		else()
+			set(MIN_OS ${CMAKE_OSX_DEPLOYMENT_TARGET})
+		endif()
+		set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build/osx/")
+		set_target_properties(ortp PROPERTIES
+			FRAMEWORK TRUE
+			MACOSX_FRAMEWORK_IDENTIFIER org.linphone.ortp
+  			MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in
+			PUBLIC_HEADER "${ORTP_HEADER_FILES}"
+		)
+	endif()
+	if(NOT ANDROID)
 		# Do not version shared library on Android
 		set_target_properties(ortp PROPERTIES SOVERSION ${ORTP_SO_VERSION})
 	endif()
@@ -106,6 +120,7 @@ if(ENABLE_SHARED)
 		target_compile_options(ortp PRIVATE "/DELAYLOAD:Qwave.dll")
 	endif()
 	target_compile_definitions(ortp PRIVATE "ORTP_EXPORTS")
+	target_include_directories(ortp PUBLIC ${BCTOOLBOX_CORE_INCLUDE_DIRS})
 	target_link_libraries(ortp PRIVATE ${LIBS})
 	if(MSVC)
 		if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
@@ -119,6 +134,7 @@ if(ENABLE_SHARED)
 		RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
 		LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
 		ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+		FRAMEWORK DESTINATION Frameworks
 		PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
 	)
 endif()
diff --git a/src/Makefile.am b/src/Makefile.am
index 3398c7e..33cffe9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -47,6 +47,7 @@ libortp_la_SOURCES=	\
 			sessionset.c  \
 			str_utils.c 	\
 			telephonyevents.c  \
+			videobandwidthestimator.c videobandwidthestimator.h\
 			utils.c utils.h
 
 libortp_la_LIBADD= $(PTHREAD_LIBS) $(RT_LIBS) -lm $(BCTOOLBOX_LIBS)
diff --git a/src/b64.c b/src/b64.c
index 0b4282b..e7cec29 100644
--- a/src/b64.c
+++ b/src/b64.c
@@ -11,11 +11,11 @@
  * Copyright (c) 2004-2008, Matthew Wilson and Synesis Software
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without 
+ * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *
  * - Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer. 
+ *   list of conditions and the following disclaimer.
  * - Redistributions in binary form must reproduce the above copyright notice,
  *   this list of conditions and the following disclaimer in the documentation
  *   and/or other materials provided with the distribution.
@@ -59,6 +59,8 @@
 #include "ortp/port.h"
 #include "ortp/b64.h"
 
+#include <bctoolbox/defs.h>
+
 #include <assert.h>
 #include <string.h>
 /* /////////////////////////////////////////////////////////////////////////////
@@ -93,15 +95,15 @@
 
 static const char           b64_chars[] =   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-static const signed char    b64_indexes[]   =   
+static const signed char    b64_indexes[]   =
 {
     /* 0 - 31 / 0x00 - 0x1f */
-        -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
+        -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
     ,   -1, -1, -1, -1, -1, -1, -1, -1
     /* 32 - 63 / 0x20 - 0x3f */
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
     ,   -1, -1, -1, 62, -1, -1, -1, 63  /* ... , '+', ... '/' */
     ,   52, 53, 54, 55, 56, 57, 58, 59  /* '0' - '7' */
     ,   60, 61, -1, -1, -1, -1, -1, -1  /* '8', '9', ... */
@@ -116,25 +118,25 @@ static const signed char    b64_indexes[]   =
     ,   41, 42, 43, 44, 45, 46, 47, 48  /* 'p' - 'w' */
     ,   49, 50, 51, -1, -1, -1, -1, -1  /* 'x', 'y', 'z', ... */
 
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
-    ,   -1, -1, -1, -1, -1, -1, -1, -1  
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
+    ,   -1, -1, -1, -1, -1, -1, -1, -1
 };
 
 /* /////////////////////////////////////////////////////////////////////////////
@@ -183,17 +185,17 @@ static size_t b64_encode_(  unsigned char const *src
         {
             unsigned char    characters[NUM_ENCODED_DATA_BYTES];
 
-            /* 
-             * 
+            /*
+             *
              * |       0       |       1       |       2       |
              *
              * |               |               |               |
              * |       |       |       |       |       |       |
              * |   |   |   |   |   |   |   |   |   |   |   |   |
              * | | | | | | | | | | | | | | | | | | | | | | | | |
-             * 
+             *
              * |     0     |     1     |     2     |     3     |
-             * 
+             *
              */
 
             /* characters[0] is the 6 left-most bits of src[0] */
@@ -274,7 +276,7 @@ static size_t b64_encode_(  unsigned char const *src
     }
 }
 
-/** This function reads in a character string in 4-character chunks, and writes 
+/** This function reads in a character string in 4-character chunks, and writes
  * out the converted form in 3-byte chunks to the destination.
  */
 static size_t b64_decode_(  char const      *src
@@ -313,7 +315,7 @@ static size_t b64_decode_(  char const      *src
         /* Now we iterate through the src, collecting together four characters
          * at a time from the Base-64 alphabet, until the end-point is reached.
          *
-         * 
+         *
          */
 
         char const          *begin      =   src;
@@ -343,9 +345,9 @@ static size_t b64_decode_(  char const      *src
                 {
                     switch(ch)
                     {
-                        case    ' ':
-                        case    '\t':
-                        case    '\b':
+                        case    ' ':BCTBX_NO_BREAK; /*intentionally no break*/
+                        case    '\t':BCTBX_NO_BREAK; /*intentionally no break*/
+                        case    '\b':BCTBX_NO_BREAK; /*intentionally no break*/
                         case    '\v':
                             if(B64_F_STOP_ON_UNEXPECTED_WS & flags)
                             {
@@ -355,9 +357,9 @@ static size_t b64_decode_(  char const      *src
                             }
                             else
                             {
-                                /* Fall through */
+                                BCTBX_NO_BREAK; /* Fall through */
                             }
-                        case    '\r':
+                        case    '\r':BCTBX_NO_BREAK; /*intentionally no break*/
                         case    '\n':
                             continue;
                         default:
@@ -454,7 +456,7 @@ size_t b64_encode2( void const  *src
             {
                 break;
             }
-            /* Fall through to 64 */
+            BCTBX_NO_BREAK; /* Fall through to 64 */
         case    B64_F_LINE_LEN_64:
             lineLen = 64;
             break;
@@ -581,7 +583,7 @@ static char const *b64_LookupErrorStringA_(int error, size_t *len)
     SEVERITY_STR_DECL(B64_RC_TRUNCATED_INPUT        ,   "The input did not represent a fully formed stream of octet couplings"  );
     SEVERITY_STR_DECL(B64_RC_DATA_ERROR             ,   "Invalid data"                                                          );
 
-    static const b64ErrorString_t_    *s_strings[] = 
+    static const b64ErrorString_t_    *s_strings[] =
     {
         SEVERITY_STR_ENTRY(B64_RC_OK),
         SEVERITY_STR_ENTRY(B64_RC_INSUFFICIENT_BUFFER),
diff --git a/src/congestiondetector.c b/src/congestiondetector.c
index a4714b7..6ae8524 100644
--- a/src/congestiondetector.c
+++ b/src/congestiondetector.c
@@ -25,7 +25,10 @@
 #include <ortp/rtpsession.h>
 
 static const unsigned int congestion_pending_duration_ms = 5000;
-static const float congested_clock_ratio = 0.93f;
+static const float return_from_suspected_max_loss_rate = 5.0;
+static const float absolute_congested_clock_ratio = 0.93f;
+static const float relative_congested_clock_ratio = 0.96f;
+static const float rls_forgetting_factor = 0.97f;
 
 const char *ortp_congestion_detector_state_to_string(OrtpCongestionState state){
 	switch (state){
@@ -52,6 +55,7 @@ static bool_t ortp_congestion_detector_set_state(OrtpCongestionDetector *cd, Ort
 		     ortp_congestion_detector_state_to_string(cd->state),
 		     ortp_congestion_detector_state_to_string(state));
 	cd->state = state;
+	cd->too_much_loss = FALSE;
 	if (state == CongestionStateDetected){
 		if (!cd->is_in_congestion){
 			cd->is_in_congestion = TRUE;
@@ -86,6 +90,15 @@ static uint32_t local_ts_to_remote_ts_rls(double clock_ratio, double offset, uin
 }
 */
 
+static float ortp_congestion_detector_get_loss_rate(OrtpCongestionDetector *cd){
+	uint32_t cur_loss = (uint32_t)cd->session->stats.cum_packet_loss;
+	uint32_t cur_seq = rtp_session_get_rcv_ext_seq_number(cd->session);
+	uint32_t expected = cur_seq - cd->seq_begin;
+	
+	if (expected == 0) return 0;
+	return 100.0f*(float)(cur_loss - cd->loss_begin) / (float)expected;
+}
+
 bool_t ortp_congestion_detector_record(OrtpCongestionDetector *cd, uint32_t packet_ts, uint32_t cur_str_ts) {
 	bool_t binary_state_changed = FALSE;
 	bool_t clock_drift;
@@ -100,7 +113,7 @@ bool_t ortp_congestion_detector_record(OrtpCongestionDetector *cd, uint32_t pack
 	if (!cd->initialized) {
 		cd->initialized = TRUE;
 		ortp_kalman_rls_init(&cd->rls, 1, packet_ts - cur_str_ts);
-		cd->rls.lambda = 0.99f;
+		cd->rls.lambda = rls_forgetting_factor;
 		if (jitterctl->params.buffer_algorithm != OrtpJitterBufferRecursiveLeastSquare){
 			ortp_error("ortp congestion detection requires RLS jitter buffer algorithm.");
 			cd->skip = TRUE;
@@ -109,38 +122,75 @@ bool_t ortp_congestion_detector_record(OrtpCongestionDetector *cd, uint32_t pack
 
 	ortp_kalman_rls_record(&cd->rls, cur_str_ts, packet_ts);
 
-	clock_drift = cd->rls.m < congested_clock_ratio || cd->rls.m < congested_clock_ratio * jitterctl->capped_clock_ratio || jitterctl->capped_clock_ratio < congested_clock_ratio ;
+	if (cd->rls.m < 0) {
+		/*
+		 * This can arrive when packets arrive in a very chaotic way during the first seconds of a call.
+		 * There is no usable information as long as the rls hasn't yet converged.
+		 */
+		return binary_state_changed;
+	}
+	
+	clock_drift = cd->rls.m < absolute_congested_clock_ratio || jitterctl->capped_clock_ratio < absolute_congested_clock_ratio
+		|| cd->rls.m < relative_congested_clock_ratio * jitterctl->capped_clock_ratio ;
 	//deviation = ((int32_t)(packet_ts - local_ts_to_remote_ts_rls(cd->rls.m, cd->rls.b, cur_str_ts))) / (float)jitterctl->clock_rate;
 	//deviation = ortp_extremum_get_current(&jitterctl->max_ts_deviation)/(float)jitterctl->clock_rate;
 	//has_jitter = deviation > acceptable_deviation;
 
-	ortp_debug(
-		"OrtpCongestionDetector state=%s clock=%f"
-		", jb->capped_clock_ratio=%f"
-		", down_bw=%0.f, up_bw=%0.f kbits/s"
-		, ortp_congestion_detector_state_to_string(cd->state)
-		, cd->rls.m
-		, jitterctl->capped_clock_ratio
-		, rtp_session_get_recv_bandwidth_smooth(cd->session)*1e-3, rtp_session_get_send_bandwidth_smooth(cd->session)*1e-3
-	);
+	/*
+	if (jitterctl->clock_rate == 90000){
+		ortp_message(
+			"OrtpCongestionDetector state=%s clock=%f"
+			", jb->capped_clock_ratio=%f"
+			", down_bw=%0.f, up_bw=%0.f kbits/s"
+			, ortp_congestion_detector_state_to_string(cd->state)
+			, cd->rls.m
+			, jitterctl->capped_clock_ratio
+			, rtp_session_get_recv_bandwidth_smooth(cd->session)*1e-3, rtp_session_get_send_bandwidth_smooth(cd->session)*1e-3
+		);
+	}
+	*/
 
 	switch (cd->state) {
 		case CongestionStateNormal:
 			if (clock_drift) {
 				cd->start_ms = ortp_get_cur_time_ms();
+				cd->loss_begin = (uint32_t)cd->session->stats.cum_packet_loss;
+				cd->seq_begin = rtp_session_get_rcv_ext_seq_number(cd->session);
+				cd->last_packet_recv = cd->start_ms;
 				binary_state_changed = ortp_congestion_detector_set_state(cd, CongestionStateSuspected);
 			}
 		break;
 		case CongestionStateSuspected:
+		{
+			uint64_t curtime = ortp_get_cur_time_ms();
 			if (!clock_drift) {
-				// congestion has maybe stopped 
-				binary_state_changed = ortp_congestion_detector_set_state(cd, CongestionStateNormal);
+				float loss_rate = ortp_congestion_detector_get_loss_rate(cd);
+				if (loss_rate >= return_from_suspected_max_loss_rate){
+					if (!cd->too_much_loss){
+						ortp_message("OrtpCongestionDetector: loss rate is [%f], too much for returning to CongestionStateNormal state.", loss_rate);
+						cd->too_much_loss = TRUE;
+					}
+				}else{
+					// congestion has maybe stopped 
+					binary_state_changed = ortp_congestion_detector_set_state(cd, CongestionStateNormal);
+				}
 			} else {
-				// congestion continues - if it has been for longer enough, trigger congestion flag
-				if (ortp_get_cur_time_ms() - cd->start_ms > congestion_pending_duration_ms) {
-					binary_state_changed = ortp_congestion_detector_set_state(cd, CongestionStateDetected);
+				
+				if (curtime - cd->last_packet_recv >= 1000){
+					/*no packet received during last second ! 
+					 It means that the drift measure is not very significant, and futhermore the banwdith computation will be 
+					 near to zero. It makes no sense to trigger a congestion detection in this case; the network is simply not working.
+					 */
+					binary_state_changed = ortp_congestion_detector_set_state(cd, CongestionStateNormal);
+				}else{
+					// congestion continues - if it has been for longer enough, trigger congestion flag
+					if (curtime - cd->start_ms > congestion_pending_duration_ms) {
+						binary_state_changed = ortp_congestion_detector_set_state(cd, CongestionStateDetected);
+					}
 				}
 			}
+			cd->last_packet_recv = curtime;
+		}
 		break;
 		case CongestionStateDetected:
 			if (!clock_drift) {
@@ -164,5 +214,4 @@ bool_t ortp_congestion_detector_record(OrtpCongestionDetector *cd, uint32_t pack
 
 void ortp_congestion_detector_destroy(OrtpCongestionDetector *obj){
 	ortp_free(obj);
-}
-
+}
\ No newline at end of file
diff --git a/src/congestiondetector.h b/src/congestiondetector.h
index 8a451bf..c2ecfcd 100644
--- a/src/congestiondetector.h
+++ b/src/congestiondetector.h
@@ -23,6 +23,7 @@
 
 #include <ortp/port.h>
 #include <ortp/utils.h>
+#include <bctoolbox/list.h>
 struct _JitterControl;
 
 typedef enum _OrtpCongestionState {
@@ -35,10 +36,12 @@ typedef enum _OrtpCongestionState {
 typedef struct _OrtpCongestionDetector{
 	OrtpKalmanRLS rls;
 	uint64_t start_ms;
+	uint64_t last_packet_recv;
+	uint32_t loss_begin, seq_begin;
 	bool_t initialized;
 	bool_t is_in_congestion;
 	bool_t skip;
-	bool_t pad[1];
+	bool_t too_much_loss;
 	OrtpCongestionState state;
 	struct _RtpSession *session;
 }OrtpCongestionDetector;
diff --git a/src/jitterctl.c b/src/jitterctl.c
index 9904d74..bd964bf 100644
--- a/src/jitterctl.c
+++ b/src/jitterctl.c
@@ -311,13 +311,13 @@ void jitter_control_new_packet_rls(JitterControl *ctl, uint32_t packet_ts, uint3
 			((float)ctl->adapt_jitt_comp_ts/(float)ctl->clock_rate)*1000.0,
 			ctl->jitter_buffer_mean_size,
 			ctl->params.min_size, ctl->params.nom_size, ctl->params.max_size);
-		ortp_message("jitter buffer rls stats: count=%d"
+		ortp_message("jitter buffer rls stats: count=%d, clockrate=%i"
 			", offset=%g clock_ratio=%g"
 			", capped_offset=%i capped_clock_ratio=%f"
 			", max_ts_deviation=%f prev_max_ts_deviation=%f"
 			", deviation=%i"
 			", RLS VARIABLES: P[0][0]=%f, P[1][0]=%f, P[0][1]=%f, P[1][1]=%f"
-			, ctl->count
+			, ctl->count, ctl->clock_rate
 			, ctl->kalman_rls.b, ctl->kalman_rls.m
 			, (int) ctl->clock_offset_ts, (float)ctl->capped_clock_ratio
 			, ortp_extremum_get_current(&ctl->max_ts_deviation), ortp_extremum_get_previous(&ctl->max_ts_deviation)
diff --git a/src/netsim.c b/src/netsim.c
index b5b8f25..509db7e 100644
--- a/src/netsim.c
+++ b/src/netsim.c
@@ -399,7 +399,6 @@ int ortp_timespec_compare(const ortpTimeSpec *s1, const ortpTimeSpec *s2){
 		return 1;
 }
 
-#if defined(ORTP_TIMESTAMP)
 static mblk_t * rtp_session_netsim_find_next_packet_to_send(RtpSession *session){
 	mblk_t *om;
 	ortpTimeSpec min_packet_time = { 0, 0};
@@ -420,7 +419,6 @@ static mblk_t * rtp_session_netsim_find_next_packet_to_send(RtpSession *session)
 	}
 	return next_packet;
 }
-#endif
 
 static void rtp_session_schedule_outbound_network_simulator(RtpSession *session, ortpTimeSpec *sleep_until){
 	mblk_t *om;
@@ -459,7 +457,6 @@ static void rtp_session_schedule_outbound_network_simulator(RtpSession *session,
 			}
 		}
 	}else if (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutboundControlled){
-#if defined(ORTP_TIMESTAMP)
 		ortpTimeSpec current={0};
 		ortpTimeSpec packet_time;
 		mblk_t *todrop=NULL;
@@ -499,16 +496,6 @@ static void rtp_session_schedule_outbound_network_simulator(RtpSession *session,
 			sleep_until->tv_sec=current.tv_sec;
 			sleep_until->tv_nsec=current.tv_nsec+1000000LL; /*in 1 ms*/
 		}
-#else
-		ortp_mutex_lock(&session->net_sim_ctx->mutex);
-		while((om=getq(&session->net_sim_ctx->send_q))!=NULL){
-			ortp_mutex_unlock(&session->net_sim_ctx->mutex);
-			freemsg(om);
-			ortp_error("Network simulator is in mode OrtpNetworkSimulatorOutboundControlled but oRTP wasn't compiled with --enable-ntp-timestamp.");
-			ortp_mutex_lock(&session->net_sim_ctx->mutex);
-		}
-		ortp_mutex_unlock(&session->net_sim_ctx->mutex);
-#endif
 	}
 }
 
diff --git a/src/payloadtype.c b/src/payloadtype.c
index e585a1c..b12b561 100644
--- a/src/payloadtype.c
+++ b/src/payloadtype.c
@@ -128,6 +128,11 @@ void payload_type_set_avpf_params(PayloadType *pt, PayloadTypeAvpfParams params)
 	}
 }
 
+bool_t payload_type_is_vbr(const PayloadType *pt) {
+	if (pt->type == PAYLOAD_VIDEO) return TRUE;
+	return !!(pt->flags & PAYLOAD_TYPE_IS_VBR);
+}
+
 
 /**
  * Frees a PayloadType.
diff --git a/src/posixtimer.c b/src/posixtimer.c
index 5767102..13c46a1 100644
--- a/src/posixtimer.c
+++ b/src/posixtimer.c
@@ -109,7 +109,7 @@ static DWORD offset_time;
 
 
 
-void CALLBACK timerCb(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
+void CALLBACK timerCb(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
 {
         // Check timerId
         if (timerId == uID)
@@ -122,7 +122,7 @@ void CALLBACK timerCb(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
 
 void win_timer_init(void)
 {
-        timerId = timeSetEvent(TIME_INTERVAL,10,timerCb,0,TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
+	timerId = timeSetEvent(TIME_INTERVAL, 10, timerCb, (DWORD)0, (UINT)(TIME_PERIODIC | TIME_CALLBACK_FUNCTION));
         TimeEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
 
         late_ticks = 0;
diff --git a/src/rtcp.c b/src/rtcp.c
index bd9b6b7..0575a3d 100644
--- a/src/rtcp.c
+++ b/src/rtcp.c
@@ -687,8 +687,8 @@ void ortp_loss_rate_estimator_init(OrtpLossRateEstimator *obj, int min_packet_co
 bool_t ortp_loss_rate_estimator_process_report_block(OrtpLossRateEstimator *obj, const RtpSession *session, const report_block_t *rb){
 	int32_t cum_loss=report_block_get_cum_packet_lost(rb);
 	int32_t extseq=report_block_get_high_ext_seq(rb);
-	int32_t diff_unique_outgoing=(int32_t)(session->stats.packet_sent-obj->last_packet_sent_count);
-	int32_t diff_total_outgoing=diff_unique_outgoing+(int32_t)(session->stats.packet_dup_sent-obj->last_dup_packet_sent_count);
+	//int32_t diff_unique_outgoing=(int32_t)(session->stats.packet_sent-obj->last_packet_sent_count);
+	//int32_t diff_total_outgoing=diff_unique_outgoing+(int32_t)(session->stats.packet_dup_sent-obj->last_dup_packet_sent_count);
 	int32_t diff;
 	uint64_t curtime;
 	bool_t got_value=FALSE;
@@ -718,17 +718,28 @@ bool_t ortp_loss_rate_estimator_process_report_block(OrtpLossRateEstimator *obj,
 	}else if (diff>obj->min_packet_count_interval && curtime-obj->last_estimate_time_ms>=obj->min_time_ms_interval){
 		/*we have sufficient interval*/
 		int32_t new_losses=cum_loss-obj->last_cum_loss;
+		
+#if 0 /*SM: the following code try to takes into account sent duplicates - however by doing this it creates a bias in the loss rate computation
+		that can sometimes result in a negative loss rate, even if there is no duplicate.
+		Since the rate control doesn't use duplicates anymore, there is no good reason to take this into account.
+		*/
 		/*if we are using duplicates, they will not be visible in 'diff' variable.
 		But since we are the emitter, we can retrieve the total count of packet we
 		sent and use this value to compute the loss rate instead.*/
 		obj->loss_rate = 100.f * (1.f - MAX(0, (diff_unique_outgoing - new_losses) * 1.f / diff_total_outgoing));
+#endif
+		obj->loss_rate = 100.f * (float) new_losses / (float)( extseq - obj->last_ext_seq);
 
 		/*update last values with current*/
 		got_value=TRUE;
 		obj->last_estimate_time_ms=curtime;
 
 		if (obj->loss_rate>100.f){
+			obj->loss_rate = 100.f;
 			ortp_error("ortp_loss_rate_estimator_process %p: Loss rate MUST NOT be greater than 100%%", obj);
+		}else if(obj->loss_rate < 0){
+			obj->loss_rate = 0;
+			ortp_error("ortp_loss_rate_estimator_process %p: Loss rate MUST NOT be negative", obj);
 		}
 		obj->last_ext_seq=extseq;
 		obj->last_cum_loss=cum_loss;
diff --git a/src/rtpparse.c b/src/rtpparse.c
index 2f639c5..729146c 100644
--- a/src/rtpparse.c
+++ b/src/rtpparse.c
@@ -27,6 +27,7 @@
 #include "utils.h"
 #include "rtpsession_priv.h"
 #include "congestiondetector.h"
+#include "videobandwidthestimator.h"
 
 static bool_t queue_packet(queue_t *q, int maxrqsz, mblk_t *mp, rtp_header_t *rtp, int *discarded, int *duplicate)
 {
@@ -284,7 +285,12 @@ void rtp_session_rtp_parse(RtpSession *session, mblk_t *mp, uint32_t local_str_t
 
 	jitter_control_new_packet(&session->rtp.jittctl,rtp->timestamp,local_str_ts);
 
-	if (session->rtp.congdetect){
+	if (session->video_bandwidth_estimator_enabled && session->rtp.video_bw_estimator) {
+		int overhead = ortp_stream_is_ipv6(&session->rtp.gs) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
+		ortp_video_bandwidth_estimator_process_packet(session->rtp.video_bw_estimator, rtp->timestamp, &mp->timestamp, msgsize + overhead, rtp->markbit == 1);
+	}
+
+	if (session->congestion_detector_enabled && session->rtp.congdetect){
 		if (ortp_congestion_detector_record(session->rtp.congdetect,rtp->timestamp,local_str_ts)) {
 			OrtpEvent *ev=ortp_event_new(ORTP_EVENT_CONGESTION_STATE_CHANGED);
 			OrtpEventData *ed=ortp_event_get_data(ev);
@@ -313,7 +319,8 @@ void rtp_session_rtp_parse(RtpSession *session, mblk_t *mp, uint32_t local_str_t
 				ortp_warning("rtp_parse: negative timestamp jump detected");
 				rtp_signal_table_emit2(&session->on_timestamp_jump, &rtp->timestamp);
 			}
-			ortp_error("rtp_parse: discarding too old packet (seq_num=%i, ts=%u)",rtp->seq_number, rtp->timestamp);
+			ortp_error("rtp_parse: discarding too old packet (seq=%i, ts=%u, last_delivered was seq=%i, ts=%u)",rtp->seq_number, rtp->timestamp,
+				(int)session->rtp.rcv_last_seq, session->rtp.rcv_last_ts);
 			freemsg(mp);
 			stats->outoftime++;
 			ortp_global_stats.outoftime++;
diff --git a/src/rtpsession.c b/src/rtpsession.c
index 537ff74..c8d16dd 100644
--- a/src/rtpsession.c
+++ b/src/rtpsession.c
@@ -30,6 +30,7 @@
 #include "utils.h"
 #include "rtpsession_priv.h"
 #include "congestiondetector.h"
+#include "videobandwidthestimator.h"
 
 #if (_WIN32_WINNT >= 0x0600)
 #include <delayimp.h>
@@ -306,6 +307,9 @@ rtp_session_init (RtpSession * session, int mode)
 		rtp_session_set_transports(session, rtp_tr, rtcp_tr);
 	}
 	session->tev_send_pt = -1; /*check in rtp profile when needed*/
+	
+	ortp_bw_estimator_init(&session->rtp.gs.recv_bw_estimator, 0.95f, 0.01f);
+	ortp_bw_estimator_init(&session->rtcp.gs.recv_bw_estimator, 0.95f, 0.01f);
 }
 
 void rtp_session_enable_congestion_detection(RtpSession *session, bool_t enabled){
@@ -316,13 +320,24 @@ void rtp_session_enable_congestion_detection(RtpSession *session, bool_t enabled
 		}
 		if (!session->rtp.congdetect){
 			session->rtp.congdetect = ortp_congestion_detector_new(session);
+		}else{
+			if (!session->congestion_detector_enabled) ortp_congestion_detector_reset(session->rtp.congdetect); 
 		}
-	}else{
-		if (session->rtp.congdetect){
-			ortp_congestion_detector_destroy(session->rtp.congdetect);
-			session->rtp.congdetect = NULL;
+	}
+	session->congestion_detector_enabled = enabled;
+}
+
+void rtp_session_enable_video_bandwidth_estimator(RtpSession *session, const OrtpVideoBandwidthEstimatorParams *params) {
+	if (params->enabled) {
+		if (!session->rtp.video_bw_estimator) {
+			session->rtp.video_bw_estimator = ortp_video_bandwidth_estimator_new(session);
 		}
+		if (params->packet_count_min > 0) session->rtp.video_bw_estimator->packet_count_min = params->packet_count_min;
+		if (params->packets_size_max > 0) session->rtp.video_bw_estimator->packets_size_max = params->packets_size_max;
+		if (params->trust_percentage > 0) session->rtp.video_bw_estimator->trust_percentage = params->trust_percentage;
+		if (!session->video_bandwidth_estimator_enabled) ortp_video_bandwidth_estimator_reset(session->rtp.video_bw_estimator);
 	}
+	session->video_bandwidth_estimator_enabled = params->enabled;
 }
 
 void jb_parameters_init(JBParameters *jbp) {
@@ -1579,6 +1594,10 @@ void rtp_session_uninit (RtpSession * session)
 		ortp_congestion_detector_destroy(session->rtp.congdetect);
 	}
 
+	if (session->rtp.video_bw_estimator){
+		ortp_video_bandwidth_estimator_destroy(session->rtp.video_bw_estimator);
+	}
+
 	rtp_session_get_transports(session,&rtp_meta_transport,&rtcp_meta_transport);
 	if (rtp_meta_transport)
 		meta_rtp_transport_destroy(rtp_meta_transport);
@@ -1627,6 +1646,7 @@ void rtp_session_resync(RtpSession *session){
 	rtp_session_unset_flag(session,RTP_SESSION_FIRST_PACKET_DELIVERED);
 	rtp_session_init_jitter_buffer(session);
 	if (session->rtp.congdetect) ortp_congestion_detector_reset(session->rtp.congdetect);
+	if (session->rtp.video_bw_estimator) ortp_video_bandwidth_estimator_reset(session->rtp.video_bw_estimator);
 
 	/* Since multiple streams might share the same session (fixed RTCP port for example),
 	RTCP values might be erroneous (number of packets received is computed
@@ -1848,7 +1868,8 @@ float rtp_session_compute_send_bandwidth(RtpSession *session) {
  * Computation must have been done with rtp_session_compute_recv_bandwidth()
 **/
 float rtp_session_get_recv_bandwidth(RtpSession *session){
-	return session->rtp.gs.download_bw + session->rtcp.gs.download_bw;
+	//return session->rtp.gs.download_bw + session->rtcp.gs.download_bw;
+	return ortp_bw_estimator_get_value(&session->rtp.gs.recv_bw_estimator) + ortp_bw_estimator_get_value(&session->rtcp.gs.recv_bw_estimator);
 }
 
 float rtp_session_get_recv_bandwidth_smooth(RtpSession *session){
@@ -1868,7 +1889,8 @@ float rtp_session_get_send_bandwidth_smooth(RtpSession *session){
 }
 
 float rtp_session_get_rtp_recv_bandwidth(RtpSession *session) {
-	return session->rtp.gs.download_bw;
+	//return session->rtp.gs.download_bw;
+	return ortp_bw_estimator_get_value(&session->rtp.gs.recv_bw_estimator);
 }
 
 float rtp_session_get_rtp_send_bandwidth(RtpSession *session) {
@@ -1876,7 +1898,8 @@ float rtp_session_get_rtp_send_bandwidth(RtpSession *session) {
 }
 
 float rtp_session_get_rtcp_recv_bandwidth(RtpSession *session) {
-	return session->rtcp.gs.download_bw;
+	//return session->rtcp.gs.download_bw;
+	return ortp_bw_estimator_get_value(&session->rtcp.gs.recv_bw_estimator);
 }
 
 float rtp_session_get_rtcp_send_bandwidth(RtpSession *session) {
diff --git a/src/rtpsession_inet.c b/src/rtpsession_inet.c
index 9280984..001d855 100644
--- a/src/rtpsession_inet.c
+++ b/src/rtpsession_inet.c
@@ -22,6 +22,10 @@
 #define _GNU_SOURCE
 #endif
 
+#if __APPLE__
+#include "TargetConditionals.h"
+#endif
+
 #ifdef HAVE_CONFIG_H
 #include "ortp-config.h" /*needed for HAVE_SYS_UIO_H and HAVE_ARC4RANDOM */
 #endif
@@ -205,7 +209,7 @@ static ortp_socket_t create_and_bind(const char *addr, int *port, int *sock_fami
 			}
 		}
 
-#if defined(ORTP_TIMESTAMP)
+#ifdef SO_TIMESTAMP
 		optval=1;
 		err = setsockopt (sock, SOL_SOCKET, SO_TIMESTAMP,
 			(SOCKET_OPTION_VALUE)&optval, sizeof (optval));
@@ -220,12 +224,12 @@ static ortp_socket_t create_and_bind(const char *addr, int *port, int *sock_fami
 			default:
 			case AF_INET:
 #ifdef IP_RECVTTL
-				err = setsockopt(sock, IPPROTO_IP, IP_RECVTTL, &optval, sizeof(optval));
+				err = setsockopt(sock, IPPROTO_IP, IP_RECVTTL, (SOCKET_OPTION_VALUE)&optval, sizeof(optval));
 #endif
 				break;
 			case AF_INET6:
 #ifdef IPV6_RECVHOPLIMIT
-				err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval, sizeof(optval));
+				err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, (SOCKET_OPTION_VALUE)&optval, sizeof(optval));
 #endif
 				break;
 		}
@@ -1139,12 +1143,13 @@ void update_sent_bytes(OrtpStream *os, int nbytes) {
 	os->sent_bytes += nbytes + overhead;
 }
 
-static void update_recv_bytes(OrtpStream *os, int nbytes) {
+static void update_recv_bytes(OrtpStream *os, size_t nbytes, const struct timeval *recv_time) {
 	int overhead = ortp_stream_is_ipv6(os) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
 	if ((os->recv_bytes == 0) && (os->recv_bw_start.tv_sec == 0) && (os->recv_bw_start.tv_usec == 0)) {
 		ortp_gettimeofday(&os->recv_bw_start, NULL);
 	}
-	os->recv_bytes += nbytes + overhead;
+	os->recv_bytes += (unsigned int)(nbytes + overhead);
+	ortp_bw_estimator_packet_received(&os->recv_bw_estimator, nbytes + overhead, recv_time);
 }
 
 static void log_send_error(RtpSession *session, const char *type, mblk_t *m, struct sockaddr *destaddr, socklen_t destlen){
@@ -1331,8 +1336,8 @@ int rtp_session_rtp_recv_abstract(ortp_socket_t socket, mblk_t *msg, int flags,
 		ret = bytes_received;
 #endif
 		for (cmsghdr = CMSG_FIRSTHDR(&msghdr); cmsghdr != NULL ; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
-#if defined(ORTP_TIMESTAMP)
-			if (cmsghdr->cmsg_level == SOL_SOCKET && cmsghdr->cmsg_type == SO_TIMESTAMP) {
+#ifdef SO_TIMESTAMP
+			if (cmsghdr->cmsg_level == SOL_SOCKET && cmsghdr->cmsg_type == SCM_TIMESTAMP) {
 				memcpy(&msg->timestamp, (struct timeval *)CMSG_DATA(cmsghdr), sizeof(struct timeval));
 			}
 #endif
@@ -1377,6 +1382,15 @@ int rtp_session_rtp_recv_abstract(ortp_socket_t socket, mblk_t *msg, int flags,
 			}
 #endif
 		}
+
+		if (msg->timestamp.tv_sec == 0){
+			static int warn_once = 1; /*VERY BAD to use a static but there is no context in this function to hold this variable*/
+			if (warn_once){
+				ortp_warning("This platform doesn't implement SO_TIMESTAMP, will use gettimeofday() instead.");
+				warn_once = 0;
+			}
+			ortp_gettimeofday(&msg->timestamp, NULL);
+		}
 		/*store recv addr for use by modifiers*/
 		if (from && fromlen) {
 			memcpy(&msg->net_addr,from,*fromlen);
@@ -1507,7 +1521,7 @@ static int process_rtcp_packet( RtpSession *session, mblk_t *block, struct socka
 		return -1;
 	}
 
-	update_recv_bytes(&session->rtcp.gs, (int)(block->b_wptr - block->b_rptr));
+	update_recv_bytes(&session->rtcp.gs, (int)(block->b_wptr - block->b_rptr), &block->timestamp);
 
 	/* compound rtcp packet can be composed by more than one rtcp message */
 	do{
@@ -1595,7 +1609,7 @@ static void rtp_process_incoming_packet(RtpSession * session, mblk_t * mp, bool_
 			}
 		}
 		/* then parse the message and put on jitter buffer queue */
-		update_recv_bytes(&session->rtp.gs, (int)(mp->b_wptr - mp->b_rptr));
+		update_recv_bytes(&session->rtp.gs, (size_t)(mp->b_wptr - mp->b_rptr), &mp->timestamp);
 		rtp_session_rtp_parse(session, mp, user_ts, remaddr,addrlen);
 		/*for bandwidth measurements:*/
 	}else {
@@ -1665,7 +1679,7 @@ int rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts) {
 				if (session->on_network_error.count>0){
 					rtp_signal_table_emit3(&session->on_network_error,"Error receiving RTP packet",ORTP_INT_TO_POINTER(getSocketErrorCode()));
 				}else ortp_warning("Error receiving RTP packet: %s, err num  [%i],error [%i]",getSocketError(),errnum,error);
-#ifdef __ios
+#if TARGET_OS_IPHONE
 				/*hack for iOS and non-working socket because of background mode*/
 				if (errnum==ENOTCONN){
 					/*re-create new sockets */
@@ -1728,7 +1742,7 @@ int rtp_session_rtcp_recv (RtpSession * session) {
 				if (session->on_network_error.count>0){
 					rtp_signal_table_emit3(&session->on_network_error,"Error receiving RTCP packet",ORTP_INT_TO_POINTER(getSocketErrorCode()));
 				}else ortp_warning("Error receiving RTCP packet: %s, err num  [%i],error [%i]",getSocketError(),errnum,error);
-#ifdef __ios
+#if TARGET_OS_IPHONE
 				/*hack for iOS and non-working socket because of background mode*/
 				if (errnum==ENOTCONN){
 					/*re-create new sockets */
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 811d070..eb7a4cb 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -23,7 +23,7 @@
 if (NOT IOS)
 	set(EXECUTABLES rtpsend rtprecv mrtpsend mrtprecv test_timer tevrtpsend tevrtprecv rtpsend_stupid)
 	foreach(executable ${EXECUTABLES})
-		apply_compile_flags(${executable}.c "CPP" "C")
+		bc_apply_compile_flags(${executable}.c STRICT_OPTIONS_CPP STRICT_OPTIONS_C)
 		add_executable(${executable} ${executable}.c)
 		target_link_libraries(${executable} ortp)
 	endforeach()
diff --git a/src/utils.c b/src/utils.c
index a314d5e..5cb831e 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -18,7 +18,9 @@
  */
 
 #include "ortp/port.h"
+#include "ortp/logging.h"
 #include "utils.h"
+#include "math.h"
 
 
 uint64_t ortp_timeval_to_ntp(const struct timeval *tv){
@@ -28,3 +30,34 @@ uint64_t ortp_timeval_to_ntp(const struct timeval *tv){
 	lsw=(uint32_t)((double)tv->tv_usec*(double)(((uint64_t)1)<<32)*1.0e-6);
 	return msw<<32 | lsw;
 }
+
+
+void ortp_bw_estimator_init(OrtpBwEstimator *obj, float alpha, float step){
+	obj->one_minus_alpha = 1.0f - alpha;
+	obj->inv_step = 1.0f/step;
+	obj->exp_constant = logf(alpha) * obj->inv_step;
+	obj->last_packet_recv.tv_sec = 0;
+	obj->last_packet_recv.tv_usec = 0;
+	obj->value = 0;
+}
+
+void ortp_bw_estimator_packet_received (OrtpBwEstimator *obj, size_t bytes, const struct timeval *recv_time){
+	float diff_time;
+	
+	if (obj->last_packet_recv.tv_sec == 0){
+		diff_time = 1.0f/obj->inv_step;
+		ortp_message("First estimation");
+	}else{
+		diff_time = (float)(recv_time->tv_sec - obj->last_packet_recv.tv_sec) + 1e-6f*(recv_time->tv_usec - obj->last_packet_recv.tv_usec);
+	}
+	obj->value = ((float)bytes * obj->one_minus_alpha) + expf(diff_time * obj->exp_constant)*obj->value;
+	obj->last_packet_recv = *recv_time;
+}
+
+float ortp_bw_estimator_get_value(OrtpBwEstimator *obj){
+	struct timeval current;
+	bctbx_gettimeofday(&current, NULL);
+	ortp_bw_estimator_packet_received(obj, 0, &current);
+	return obj->value * 8.0f * obj->inv_step;
+}
+
diff --git a/src/videobandwidthestimator.c b/src/videobandwidthestimator.c
new file mode 100644
index 0000000..053b284
--- /dev/null
+++ b/src/videobandwidthestimator.c
@@ -0,0 +1,153 @@
+/*
+ * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
+ * Copyright (C) 2017 Belledonne Communications SARL
+ *
+ *  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 2 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 received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "videobandwidthestimator.h"
+#include <ortp/logging.h>
+#include <math.h>
+#include <ortp/rtpsession.h>
+
+OrtpVideoBandwidthEstimator * ortp_video_bandwidth_estimator_new(RtpSession *session) {
+	OrtpVideoBandwidthEstimator *vbe = (OrtpVideoBandwidthEstimator*)ortp_malloc0(sizeof(OrtpVideoBandwidthEstimator));
+	vbe->session = session;
+	vbe->packet_count_min = 5;
+	vbe->packets_size_max = 30;
+	vbe->trust_percentage = 90;
+    vbe->nb_packets_computed = 0;
+    vbe->packets = NULL;
+    vbe->last_packet = NULL;
+	return vbe;
+}
+
+void ortp_video_bandwidth_estimator_destroy(OrtpVideoBandwidthEstimator *vbe){
+    ortp_video_bandwidth_estimator_reset(vbe);
+    ortp_free(vbe);
+}
+
+void ortp_video_bandwidth_estimator_reset(OrtpVideoBandwidthEstimator *vbe) {
+	ortp_free(vbe->last_packet);
+    vbe->last_packet = NULL;
+    vbe->nb_packets_computed = 0;
+	vbe->packets = bctbx_list_free_with_data(vbe->packets, ortp_free);
+}
+
+void ortp_video_bandwidth_estimator_set_packets_count_min(OrtpVideoBandwidthEstimator *vbe, unsigned int value) {
+    vbe->packet_count_min = value;
+}
+
+void ortp_video_bandwidth_estimator_set_history_max_size(OrtpVideoBandwidthEstimator *vbe, unsigned int value) {
+    vbe->packets_size_max = value;
+}
+
+void ortp_video_bandwidth_estimator_set_trust(OrtpVideoBandwidthEstimator *vbe, unsigned int value) {
+    vbe->trust_percentage = value;
+}
+
+unsigned int ortp_video_bandwidth_estimator_get_packets_count_min(OrtpVideoBandwidthEstimator *vbe) {
+    return vbe->packet_count_min;
+}
+
+unsigned int ortp_video_bandwidth_estimator_get_history_max_size(OrtpVideoBandwidthEstimator *vbe) {
+    return vbe->packets_size_max;
+}
+
+unsigned int ortp_video_bandwidth_estimator_get_trust(OrtpVideoBandwidthEstimator *vbe) {
+    return vbe->trust_percentage;
+}
+
+static int compare_float(const float *v1, const float *v2) {
+	if (*v1 == *v2) return 0;
+	if (*v1 < *v2) return 1;
+	return -1;
+}
+
+float ortp_video_bandwidth_estimator_get_estimated_available_bandwidth(OrtpVideoBandwidthEstimator *vbe) {
+    bctbx_list_t *bitrate_sorted = NULL;
+    bctbx_list_t *elem;
+    float *result = NULL;
+    int index = (int)(vbe->trust_percentage * vbe->packets_size_max / 100);
+    for(elem = vbe->packets; elem != NULL; elem = bctbx_list_next(elem)) {
+        OrtpVideoBandwidthEstimatorPacket *packet = (OrtpVideoBandwidthEstimatorPacket *)bctbx_list_get_data(elem);
+        bitrate_sorted = bctbx_list_insert_sorted(bitrate_sorted, &packet->bitrate, (bctbx_compare_func)compare_float);
+    }
+    result = (float *)bctbx_list_nth_data(bitrate_sorted, index);
+    bctbx_list_free(bitrate_sorted);
+    return (float)*result;
+}
+
+static void compute_bitrate_add_to_list_and_remove_oldest_value(OrtpVideoBandwidthEstimator *vbe, OrtpVideoBandwidthEstimatorPacket *packet) {
+	float difftime = (float)(packet->recv_last_timestamp.tv_sec - packet->recv_first_timestamp.tv_sec) 
+		+ 1e-6f*(packet->recv_last_timestamp.tv_usec - packet->recv_first_timestamp.tv_usec);
+	packet->bitrate = (packet->bytes * 8 / difftime);
+	ortp_debug("[VBE] Bitrate is %f kbits/s computed using %f timedif and %u size", packet->bitrate / 1000, difftime, packet->bytes);
+
+    vbe->nb_packets_computed += 1;
+	vbe->packets = bctbx_list_prepend(vbe->packets, packet);
+
+	if (bctbx_list_size(vbe->packets) > vbe->packets_size_max) {
+		void *old_data = bctbx_list_nth_data(vbe->packets, vbe->packets_size_max);
+		vbe->packets = bctbx_list_remove(vbe->packets, old_data);
+	}
+
+    if (vbe->nb_packets_computed % vbe->packets_size_max == 0) {
+        OrtpEvent *ev = ortp_event_new(ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE);
+        OrtpEventData *ed = ortp_event_get_data(ev);
+        ed->info.video_bandwidth_available = ortp_video_bandwidth_estimator_get_estimated_available_bandwidth(vbe);
+        ortp_debug("[VBE] Dispatching event ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE with value %f kbits/s", ed->info.video_bandwidth_available / 1000);
+        rtp_session_dispatch_event(vbe->session, ev);
+    }
+}
+
+void ortp_video_bandwidth_estimator_process_packet(OrtpVideoBandwidthEstimator *vbe, uint32_t sent_timestamp, const struct timeval *recv_timestamp, int msgsize, bool_t is_last) {
+	OrtpVideoBandwidthEstimatorPacket *last_packet = vbe->last_packet;
+	OrtpVideoBandwidthEstimatorPacket *current_packet = NULL;
+
+	if (last_packet) {
+		if (last_packet->sent_timestamp == sent_timestamp) {
+			current_packet = last_packet;
+			current_packet->count += 1;
+			current_packet->bytes += msgsize;
+			current_packet->recv_last_timestamp.tv_sec = recv_timestamp->tv_sec;
+			current_packet->recv_last_timestamp.tv_usec = recv_timestamp->tv_usec;
+
+			if (is_last && current_packet->count >= vbe->packet_count_min) {
+				compute_bitrate_add_to_list_and_remove_oldest_value(vbe, current_packet);
+				vbe->last_packet = NULL;
+			}
+		} else {
+			// This can happen even if it's probability is quite low
+			if (last_packet->count >= vbe->packet_count_min) {
+				ortp_warning("[VBE] Last packet not complete but enough packet received (%u), add to packets list", last_packet->count);
+				compute_bitrate_add_to_list_and_remove_oldest_value(vbe, last_packet);
+			} else {
+				ortp_free(vbe->last_packet);
+			}
+			vbe->last_packet = NULL;
+		}
+	}
+
+	if (!current_packet) {
+		current_packet = (OrtpVideoBandwidthEstimatorPacket*)ortp_malloc0(sizeof(OrtpVideoBandwidthEstimatorPacket));
+		current_packet->count = 1;
+		current_packet->bytes = msgsize;
+		current_packet->sent_timestamp = sent_timestamp;
+		current_packet->recv_first_timestamp.tv_sec = recv_timestamp->tv_sec;
+		current_packet->recv_first_timestamp.tv_usec = recv_timestamp->tv_usec;
+		vbe->last_packet = current_packet;
+	}
+}
diff --git a/src/videobandwidthestimator.h b/src/videobandwidthestimator.h
new file mode 100644
index 0000000..4ed5654
--- /dev/null
+++ b/src/videobandwidthestimator.h
@@ -0,0 +1,96 @@
+/*
+ * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
+ * Copyright (C) 2017 Belledonne Communications SARL
+ *
+ *  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 2 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 received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef VIDEOBANDWIDTHESTIMATOR_H
+#define VIDEOBANDWIDTHESTIMATOR_H
+
+#include <ortp/port.h>
+#include <ortp/utils.h>
+#include <bctoolbox/list.h>
+
+typedef struct _OrtpVideoBandwidthEstimatorPacket{
+	uint32_t sent_timestamp;
+	struct timeval recv_first_timestamp;
+	struct timeval recv_last_timestamp;
+	unsigned int bytes;
+	unsigned int count;
+	float bitrate;
+}OrtpVideoBandwidthEstimatorPacket;
+
+typedef struct _OrtpVideoBandwidthEstimator{
+	struct _RtpSession *session;
+	unsigned int packet_count_min;
+	unsigned int packets_size_max;
+	unsigned int trust_percentage;
+	OrtpVideoBandwidthEstimatorPacket *last_packet;
+	bctbx_list_t *packets;
+	uint32_t last_computed;
+    int nb_packets_computed;
+}OrtpVideoBandwidthEstimator;
+
+OrtpVideoBandwidthEstimator * ortp_video_bandwidth_estimator_new(struct _RtpSession *session);
+
+void ortp_video_bandwidth_estimator_destroy(OrtpVideoBandwidthEstimator *vbe);
+
+void ortp_video_bandwidth_estimator_reset(OrtpVideoBandwidthEstimator *vbe);
+
+/**
+ * Sets the minimum number of packets with the same sent timestamp to be processed continuously before being used.
+ * Default value is 7.
+ */
+void ortp_video_bandwidth_estimator_set_packets_count_min(OrtpVideoBandwidthEstimator *vbe, unsigned int value);
+
+/**
+ * Sets the number of packets needed to compute the available video bandwidth.
+ * Default value is 30.
+ */
+void ortp_video_bandwidth_estimator_set_history_max_size(OrtpVideoBandwidthEstimator *vbe, unsigned int value);
+
+/**
+ * Sets the percentage for which the chosen bandwidth value in all available will be inferior.
+ * Example: for 100 packets with 90% trust, bandwidth value will be the 90th after sorted.
+ * Default value is 90.
+ */
+void ortp_video_bandwidth_estimator_set_trust(OrtpVideoBandwidthEstimator *vbe, unsigned int value);
+
+/**
+ * Gets the minimum number of packets with the same sent timestamp to be processed continuously before being used.
+ * Default value is 7.
+ */
+unsigned int ortp_video_bandwidth_estimator_get_packets_count_min(OrtpVideoBandwidthEstimator *vbe);
+
+/**
+ * Gets the number of packets needed to compute the available video bandwidth.
+ * Default value is 30.
+ */
+unsigned int ortp_video_bandwidth_estimator_get_history_max_size(OrtpVideoBandwidthEstimator *vbe);
+
+/**
+ * Gets the percentage for which the chosen bandwidth value in all available will be inferior.
+ * Example: for 100 packets with 90% trust, bandwidth value will be the 90th after sorted.
+ * Default value is 90.
+ */
+unsigned int ortp_video_bandwidth_estimator_get_trust(OrtpVideoBandwidthEstimator *vbe);
+
+void ortp_video_bandwidth_estimator_process_packet(OrtpVideoBandwidthEstimator *vbe, uint32_t sent_timestamp, const struct timeval *recv_timestamp, int msgsize, bool_t is_last);
+
+float ortp_video_bandwidth_estimator_get_estimated_available_bandwidth(OrtpVideoBandwidthEstimator *vbe);
+
+#endif
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/ortp.git



More information about the Pkg-voip-commits mailing list