Commit 351bb970 authored by François Grisez's avatar François Grisez
Browse files

Reworking of Liblinphone's API around payload types

parent 5e02b53e
......@@ -102,6 +102,7 @@ set(LINPHONE_SOURCE_FILES_C
misc.c
nat_policy.c
offeranswer.c
payload_type.c
player.c
presence.c
proxy.c
......
......@@ -213,15 +213,27 @@ const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){
return cp->session_name;
}
const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
LinphonePayloadType *linphone_call_params_get_used_audio_payload_type(const LinphoneCallParams *cp) {
return cp->audio_codec ? linphone_payload_type_new(NULL, cp->audio_codec) : NULL;
}
LinphonePayloadType *linphone_call_params_get_used_video_payload_type(const LinphoneCallParams *cp) {
return cp->video_codec ? linphone_payload_type_new(NULL, cp->video_codec) : NULL;
}
LinphonePayloadType *linphone_call_params_get_used_text_payload_type(const LinphoneCallParams *cp) {
return cp->text_codec ? linphone_payload_type_new(NULL, cp->text_codec) : NULL;
}
const OrtpPayloadType *linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
return cp->audio_codec;
}
const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
const OrtpPayloadType *linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
return cp->video_codec;
}
const LinphonePayloadType* linphone_call_params_get_used_text_codec(const LinphoneCallParams *cp) {
const OrtpPayloadType *linphone_call_params_get_used_text_codec(const LinphoneCallParams *cp) {
return cp->text_codec;
}
......
......@@ -27,14 +27,14 @@ if (ENABLE_DOC OR CXX_WRAPPER)
set(top_srcdir "${CMAKE_CURRENT_LIST_DIR}/../../")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
${LINPHONE_HEADER_FILES}
${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox
${LINPHONE_HEADER_FILES}
)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html"
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml/index.xml"
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
DEPENDS ${DOC_INPUT_FILES}
)
add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html")
add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml/index.xml")
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml"
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/linphone-${LINPHONE_VERSION}")
else()
......
......@@ -513,7 +513,7 @@ static bctbx_list_t *make_codec_list(LinphoneCore *lc, CodecConstraints * hints,
pt->mime_type,pt->clock_rate,hints->bandwidth_limit);
continue;
}
if (!linphone_core_check_payload_type_usability(lc,pt)){
if (!_linphone_core_check_payload_type_usability(lc, pt)) {
continue;
}
pt=payload_type_clone(pt);
......
......@@ -2220,6 +2220,53 @@ void linphone_core_unref(LinphoneCore *lc) {
belle_sip_object_unref(BELLE_SIP_OBJECT(lc));
}
static bctbx_list_t *ortp_payloads_to_linphone_payloads(const bctbx_list_t *ortp_payloads, LinphoneCore *lc) {
bctbx_list_t *linphone_payloads = NULL;
for (; ortp_payloads!=NULL; ortp_payloads=bctbx_list_next(ortp_payloads)) {
LinphonePayloadType *pt = linphone_payload_type_new(lc, (OrtpPayloadType *)ortp_payloads->data);
linphone_payloads = bctbx_list_append(linphone_payloads, pt);
}
return linphone_payloads;
}
static void sort_ortp_pt_list(bctbx_list_t **ortp_pt_list, const bctbx_list_t *linphone_pt_list) {
bctbx_list_t *new_list = NULL;
const bctbx_list_t *it;
for (it=bctbx_list_first_elem(linphone_pt_list); it; it=bctbx_list_next(it)) {
OrtpPayloadType *ortp_pt = linphone_payload_type_get_ortp_pt((LinphonePayloadType *)it->data);
bctbx_list_t *elem = bctbx_list_find(*ortp_pt_list, ortp_pt);
if (elem) {
*ortp_pt_list = bctbx_list_unlink(*ortp_pt_list, elem);
new_list = bctbx_list_append_link(new_list, elem);
}
}
*ortp_pt_list = bctbx_list_prepend_link(*ortp_pt_list, new_list);
}
bctbx_list_t *linphone_core_get_audio_payload_types(LinphoneCore *lc) {
return ortp_payloads_to_linphone_payloads(lc->codecs_conf.audio_codecs, lc);
}
void linphone_core_set_audio_payload_types(LinphoneCore *lc, const bctbx_list_t *payload_types) {
sort_ortp_pt_list(&lc->codecs_conf.audio_codecs, payload_types);
}
bctbx_list_t *linphone_core_get_video_payload_types(LinphoneCore *lc) {
return ortp_payloads_to_linphone_payloads(lc->codecs_conf.video_codecs, lc);
}
void linphone_core_set_video_payload_types(LinphoneCore *lc, const bctbx_list_t *payload_types) {
sort_ortp_pt_list(&lc->codecs_conf.video_codecs, payload_types);
}
bctbx_list_t *linphone_core_get_text_payload_types(LinphoneCore *lc) {
return ortp_payloads_to_linphone_payloads(lc->codecs_conf.text_codecs, lc);
}
void linphone_core_set_text_payload_types(LinphoneCore *lc, const bctbx_list_t *payload_types) {
sort_ortp_pt_list(&lc->codecs_conf.text_codecs, payload_types);
}
const bctbx_list_t *linphone_core_get_audio_codecs(const LinphoneCore *lc) {
return lc->codecs_conf.audio_codecs;
}
......@@ -4193,7 +4240,7 @@ void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bool_t val){
lp_config_set_int(lc->config,"sound","echocancellation",val);
}
bool_t linphone_core_echo_cancellation_enabled(LinphoneCore *lc){
bool_t linphone_core_echo_cancellation_enabled(const LinphoneCore *lc){
return lc->sound_conf.ec;
}
......@@ -5616,7 +5663,7 @@ void _linphone_core_codec_config_write(LinphoneCore *lc){
lp_config_set_string(lc->config,key,"mime",pt->mime_type);
lp_config_set_int(lc->config,key,"rate",pt->clock_rate);
lp_config_set_int(lc->config,key,"channels",pt->channels);
lp_config_set_int(lc->config,key,"enabled",linphone_core_payload_type_enabled(lc,pt));
lp_config_set_int(lc->config,key,"enabled",payload_type_enabled(pt));
index++;
}
sprintf(key,"audio_codec_%i",index);
......@@ -5628,7 +5675,7 @@ void _linphone_core_codec_config_write(LinphoneCore *lc){
sprintf(key,"video_codec_%i",index);
lp_config_set_string(lc->config,key,"mime",pt->mime_type);
lp_config_set_int(lc->config,key,"rate",pt->clock_rate);
lp_config_set_int(lc->config,key,"enabled",linphone_core_payload_type_enabled(lc,pt));
lp_config_set_int(lc->config,key,"enabled",payload_type_enabled(pt));
lp_config_set_string(lc->config,key,"recv_fmtp",pt->recv_fmtp);
index++;
}
......@@ -6003,8 +6050,8 @@ bool_t linphone_core_get_ring_during_incoming_early_media(const LinphoneCore *lc
return (bool_t)lp_config_get_int(lc->config, "sound", "ring_during_incoming_early_media", 0);
}
LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
LinphonePayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
static OrtpPayloadType* _linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
OrtpPayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc));
if (result) {
return result;
} else {
......@@ -6022,6 +6069,15 @@ LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const cha
return NULL;
}
OrtpPayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) {
return _linphone_core_find_payload_type(lc, type, rate, channels);
}
LinphonePayloadType *linphone_core_get_payload_type(LinphoneCore *lc, const char *type, int rate, int channels) {
OrtpPayloadType *pt = _linphone_core_find_payload_type(lc, type, rate, channels);
return pt ? linphone_payload_type_new(lc, pt) : NULL;
}
const char* linphone_configuring_state_to_string(LinphoneConfiguringState cs){
switch(cs){
case LinphoneConfiguringSuccessful:
......@@ -6444,22 +6500,6 @@ void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval){
lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval);
}
int linphone_payload_type_get_type(const LinphonePayloadType *pt) {
return pt->type;
}
int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) {
return pt->normal_bitrate;
}
const char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) {
return pt->mime_type;
}
int linphone_payload_type_get_channels(const LinphonePayloadType *pt) {
return pt->channels;
}
int linphone_core_set_audio_multicast_addr(LinphoneCore *lc, const char* ip) {
char* new_value;
if (ip && !ms_is_multicast(ip)) {
......
......@@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mediastreamer2/mediastream.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SIGHANDLER_T
#include <signal.h>
#endif /*HAVE_SIGHANDLER_T*/
......@@ -62,78 +63,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
static void clear_ice_check_list(LinphoneCall *call, IceCheckList *removed);
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt){
if (bctbx_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || bctbx_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt) || bctbx_list_find(lc->codecs_conf.text_codecs, (PayloadType*)pt)){
return payload_type_enabled(pt);
}
ms_error("Getting enablement status of codec not in audio or video list of PayloadType !");
return FALSE;
}
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt) {
return linphone_payload_type_is_vbr(pt);
}
bool_t linphone_payload_type_is_vbr(const LinphonePayloadType *pt) {
if (pt->type == PAYLOAD_VIDEO) return TRUE;
return !!(pt->flags & PAYLOAD_TYPE_IS_VBR);
}
int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enabled){
if (bctbx_list_find(lc->codecs_conf.audio_codecs,pt) || bctbx_list_find(lc->codecs_conf.video_codecs,pt) || bctbx_list_find(lc->codecs_conf.text_codecs,pt)){
payload_type_set_enable(pt,enabled);
_linphone_core_codec_config_write(lc);
linphone_core_update_allocated_audio_bandwidth(lc);
return 0;
}
ms_error("Enabling codec not in audio or video list of PayloadType !");
return -1;
}
int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt) {
return linphone_payload_type_get_number(pt);
}
int linphone_payload_type_get_number(const LinphonePayloadType *pt) {
return payload_type_get_number(pt);
}
void linphone_core_set_payload_type_number(LinphoneCore *lc, PayloadType *pt, int number) {
linphone_payload_type_set_number(pt, number);
}
void linphone_payload_type_set_number(LinphonePayloadType *pt, int number) {
payload_type_set_number(pt, number);
}
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){
//if (ms_filter_codec_supported(pt->mime_type)){
if (ms_factory_codec_supported(lc->factory, pt->mime_type)){
MSFilterDesc *desc=ms_factory_get_encoder(lc->factory, pt->mime_type);
#ifdef ENABLE_NLS
return dgettext("mediastreamer",desc->text);
#else
return desc->text;
#endif
}
return NULL;
}
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate){
if (bctbx_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || bctbx_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt) || bctbx_list_find(lc->codecs_conf.text_codecs, (PayloadType*)pt)){
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
pt->normal_bitrate=bitrate*1000;
pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE;
linphone_core_update_allocated_audio_bandwidth(lc);
}else{
ms_error("Cannot set an explicit bitrate for codec %s/%i, because it is not VBR.",pt->mime_type,pt->clock_rate);
return;
}
} else {
ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !");
}
}
/*
*((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime;
......@@ -184,8 +113,8 @@ static int lookup_vbr_typical_bitrate(int maxbw, int clock_rate){
return 32;
}
static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt, int maxbw){
if (linphone_payload_type_is_vbr(pt)){
int get_audio_payload_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int maxbw) {
if (payload_type_is_vbr(pt)) {
if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){
ms_debug("PayloadType %s/%i has bitrate override",pt->mime_type,pt->clock_rate);
return pt->normal_bitrate/1000;
......@@ -194,23 +123,6 @@ static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt,
}else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/
}
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt){
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){
return get_audio_payload_bandwidth(lc,pt,maxbw);
}else if (pt->type==PAYLOAD_VIDEO){
int video_bw;
if (maxbw<=0) {
video_bw=1500; /*default bitrate for video stream when no bandwidth limit is set, around 1.5 Mbit/s*/
}else{
video_bw=get_remaining_bandwidth_for_video(maxbw,lc->audio_bw);
}
return video_bw;
}
return 0;
}
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw){
call->audio_bw=get_audio_payload_bandwidth(call->core,pt,maxbw);
ms_message("Audio bandwidth for this call is %i",call->audio_bw);
......@@ -238,7 +150,7 @@ void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){
}
}
bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit){
bool_t linphone_core_is_payload_type_usable_for_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit){
double codec_band;
const int video_enablement_limit = 99;
bool_t ret=FALSE;
......@@ -263,24 +175,6 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, cons
return ret;
}
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt){
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
bool_t ret=linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, maxbw);
if ((pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED)
&& lc->sound_conf.capt_sndcard
&& !(ms_snd_card_get_capabilities(lc->sound_conf.capt_sndcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER)
&& linphone_core_echo_cancellation_enabled(lc)
&& (pt->clock_rate!=16000 && pt->clock_rate!=8000)
&& strcasecmp(pt->mime_type,"opus")!=0
&& ms_factory_lookup_filter_by_name(lc->factory, "MSWebRTCAEC")!=NULL){
ms_warning("Payload type %s/%i cannot be used because software echo cancellation is required but is unable to operate at this rate.",
pt->mime_type,pt->clock_rate);
ret=FALSE;
}
return ret;
}
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){
#if !defined(_WIN32_WCE) && !defined(LINPHONE_WINDOWS_UNIVERSAL)
FILE *f=popen(command,"r");
......
/*
payload_type.c
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <ortp/payloadtype.h>
#include "linphone/payload_type.h"
#include "private.h"
struct _LinphonePayloadType {
belle_sip_object_t base;
OrtpPayloadType *pt;
LinphoneCore *lc;
};
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePayloadType);
BELLE_SIP_DECLARE_VPTR(LinphonePayloadType);
LinphonePayloadType *linphone_payload_type_new(LinphoneCore *lc, OrtpPayloadType *ortp_pt) {
LinphonePayloadType *pt;
if (ortp_pt == NULL) return NULL;
pt = belle_sip_object_new(LinphonePayloadType);
pt->pt = ortp_pt;
pt->lc = lc;
return pt;
}
LinphonePayloadType *linphone_payload_type_ref(LinphonePayloadType *pt) {
return (LinphonePayloadType *)belle_sip_object_ref(pt);
}
void linphone_payload_type_unref(LinphonePayloadType *pt) {
belle_sip_object_unref(pt);
}
int linphone_payload_type_get_type(const LinphonePayloadType *pt) {
return pt->pt->type;
}
static bool_t _payload_type_is_in_core(const OrtpPayloadType *pt, const LinphoneCore *lc) {
return (bctbx_list_find(lc->codecs_conf.audio_codecs, pt) != NULL)
|| (bctbx_list_find(lc->codecs_conf.video_codecs, pt) != NULL)
|| (bctbx_list_find(lc->codecs_conf.text_codecs, pt) != NULL);
}
static char *_payload_type_get_description(const OrtpPayloadType *pt) {
return bctbx_strdup_printf("%s/%d/%d", pt->mime_type, pt->clock_rate, pt->channels);
}
static int _linphone_core_enable_payload_type(LinphoneCore *lc, OrtpPayloadType *pt, bool_t enabled) {
payload_type_set_enable(pt,enabled);
_linphone_core_codec_config_write(lc);
linphone_core_update_allocated_audio_bandwidth(lc);
return 0;
}
int linphone_core_enable_payload_type(LinphoneCore *lc, OrtpPayloadType *pt, bool_t enabled){
if (!_payload_type_is_in_core(pt, lc)) {
char *desc = _payload_type_get_description(pt);
ms_error("cannot enable '%s' payload type: not in the core", desc);
bctbx_free(desc);
return -1;
}
return _linphone_core_enable_payload_type(lc, pt, enabled);
}
int linphone_payload_type_enable(LinphonePayloadType *pt, bool_t enabled) {
if (pt->lc == NULL) {
char *desc = linphone_payload_type_get_description(pt);
ms_error("cannot enable '%s' payload type: no core associated", desc);
bctbx_free(desc);
return -1;
}
return _linphone_core_enable_payload_type(pt->lc, pt->pt, enabled);
}
bool_t linphone_core_payload_type_enabled(const LinphoneCore *lc, const OrtpPayloadType *pt){
return payload_type_enabled(pt);
}
bool_t linphone_payload_type_enabled(const LinphonePayloadType *pt) {
return payload_type_enabled(pt->pt);
}
char *linphone_payload_type_get_description(const LinphonePayloadType *pt) {
return _payload_type_get_description(pt->pt);
}
static const char *_linphone_core_get_payload_type_codec_description(const LinphoneCore *lc, const OrtpPayloadType *pt) {
if (ms_factory_codec_supported(lc->factory, pt->mime_type)){
MSFilterDesc *desc=ms_factory_get_encoder(lc->factory, pt->mime_type);
#ifdef ENABLE_NLS
return dgettext("mediastreamer",desc->text);
#else
return desc->text;
#endif
}
return NULL;
}
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, const OrtpPayloadType *pt){
if (!_payload_type_is_in_core(pt, lc)) {
char *desc = _payload_type_get_description(pt);
ms_error("cannot get codec description for '%s' payload type: not in the core", desc);
bctbx_free(desc);
return NULL;
}
return _linphone_core_get_payload_type_codec_description(lc, pt);
}
const char *linphone_payload_type_get_encoder_description(const LinphonePayloadType *pt) {
if (pt->lc == NULL) {
char *desc = linphone_payload_type_get_description(pt);
ms_error("cannot get codec description for '%s' payload type: no associated core", desc);
bctbx_free(desc);
return NULL;
}
return _linphone_core_get_payload_type_codec_description(pt->lc, pt->pt);
}
static int _linphone_core_get_payload_type_normal_bitrate(const LinphoneCore *lc, const OrtpPayloadType *pt) {
int maxbw = get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){
return get_audio_payload_bandwidth(lc, pt, maxbw);
}else if (pt->type==PAYLOAD_VIDEO){
int video_bw;
if (maxbw<=0) {
video_bw=1500; /*default bitrate for video stream when no bandwidth limit is set, around 1.5 Mbit/s*/
}else{
video_bw=get_remaining_bandwidth_for_video(maxbw,lc->audio_bw);
}
return video_bw;
}
return 0;
}
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const OrtpPayloadType *pt){
if (_payload_type_is_in_core(pt, lc)) {
return _linphone_core_get_payload_type_normal_bitrate(lc, pt);
} else {
char *desc = _payload_type_get_description(pt);
ms_error("cannot get normal bitrate of payload type '%s': not in the core", desc);
bctbx_free(desc);
return -1;
}
}
int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) {
if (pt->lc == NULL) {
char *desc = linphone_payload_type_get_description(pt);
ms_error("cannot get normal bitrate of codec '%s': no associated core", desc);
bctbx_free(desc);
return -1;
}
return _linphone_core_get_payload_type_normal_bitrate(pt->lc, pt->pt);
}
static void _linphone_core_set_payload_type_normal_bitrate(LinphoneCore *lc, OrtpPayloadType *pt, int bitrate) {
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
pt->normal_bitrate=bitrate*1000;
pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE;
linphone_core_update_allocated_audio_bandwidth(lc);
}else{
char *desc = _payload_type_get_description(pt);
ms_error("Cannot set an explicit bitrate for codec '%s', because it is not VBR.",desc);
bctbx_free(desc);
}
}
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, OrtpPayloadType *pt, int bitrate) {
if (_payload_type_is_in_core(pt, lc)) {
_linphone_core_set_payload_type_normal_bitrate(lc, pt, bitrate);
} else {
char *desc = _payload_type_get_description(pt);
ms_error("cannot set normal bitrate of codec '%s': not in the core", desc);
bctbx_free(desc);
}
}
void linphone_payload_type_set_normal_bitrate(LinphonePayloadType *pt, int bitrate) {
if (pt->lc == NULL) {
ms_error("cannot set bitrate of codec %s/%d: no associated core", pt->pt->mime_type, pt->pt->clock_rate);
return;
}
_linphone_core_set_payload_type_normal_bitrate(pt->lc, pt->pt, bitrate);
}
const char *linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) {
return pt->pt->mime_type;
}
int linphone_payload_type_get_channels(const LinphonePayloadType *pt) {
return pt->pt->channels;
}
int linphone_core_get_payload_type_number(LinphoneCore *lc, const OrtpPayloadType *pt) {
return payload_type_get_number(pt);
}
int linphone_payload_type_get_number(const LinphonePayloadType *pt) {
return payload_type_get_number(pt->pt);
}
void linphone_core_set_payload_type_number(LinphoneCore *lc, OrtpPayloadType *pt, int number) {
payload_type_set_number(pt, number);
}
void linphone_payload_type_set_number(LinphonePayloadType *pt, int number) {
payload_type_set_number(pt->pt, number);
}
const char *linphone_payload_type_get_recv_fmtp(const LinphonePayloadType *pt) {
return pt->pt->recv_fmtp;
}
void linphone_payload_type_set_recv_fmtp(LinphonePayloadType *pt, const char *recv_fmtp) {
if (pt->pt->recv_fmtp != NULL) bctbx_free(pt->pt->recv_fmtp);
if (recv_fmtp != NULL) pt->pt->recv_fmtp = bctbx_strdup(recv_fmtp);
else recv_fmtp = NULL;
}
const char *linphone_payload_type_get_send_fmtp(const LinphonePayloadType *pt) {
return pt->pt->send_fmtp;
}
void linphone_payload_type_set_send_fmtp(LinphonePayloadType *pt, const char *send_fmtp) {
if (pt->pt->send_fmtp != NULL) bctbx_free(pt->pt->send_fmtp);
if (send_fmtp != NULL) pt->pt->recv_fmtp = bctbx_strdup(send_fmtp);
else send_fmtp = NULL;
}
int linphone_payload_type_get_clock_rate(const LinphonePayloadType *pt) {