Fixed #1904: Support for Opus codec
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5239 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
f748884498
commit
d3ece1d774
110
aconfigure
110
aconfigure
|
@ -623,6 +623,9 @@ LIBOBJS
|
|||
ac_main_obj
|
||||
ac_host
|
||||
ac_linux_poll
|
||||
opus_present
|
||||
opus_h_present
|
||||
ac_no_opus
|
||||
silk_present
|
||||
silk_h_present
|
||||
ac_no_silk
|
||||
|
@ -816,6 +819,8 @@ with_opencore_amrwbenc
|
|||
enable_opencore_amr
|
||||
with_silk
|
||||
enable_silk
|
||||
with_opus
|
||||
enable_opus
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
host_alias
|
||||
|
@ -1482,6 +1487,9 @@ Optional Features:
|
|||
--disable-silk Exclude SILK support from the build (default:
|
||||
autodetect)
|
||||
|
||||
--disable-opus Exclude OPUS support from the build (default:
|
||||
autodetect)
|
||||
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
|
@ -1523,6 +1531,7 @@ Optional Packages:
|
|||
--with-opencore-amrwbenc=DIR
|
||||
Specify alternate libvo-amrwbenc prefix
|
||||
--with-silk=DIR Specify alternate SILK prefix
|
||||
--with-opus=DIR Specify alternate OPUS prefix
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
|
@ -8226,6 +8235,107 @@ $as_echo "SILK library found, SILK support enabled" >&6; }
|
|||
fi
|
||||
|
||||
|
||||
if test "x$ac_cross_compile" != "x" -a "x$with_opus" = "xno"; then
|
||||
enable_opus=no
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-opus was given.
|
||||
if test "${with_opus+set}" = set; then :
|
||||
withval=$with_opus;
|
||||
else
|
||||
with_opus=no
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-opus was given.
|
||||
if test "${enable_opus+set}" = set; then :
|
||||
enableval=$enable_opus;
|
||||
if test "$enable_opus" = "no"; then
|
||||
ac_no_opus=1
|
||||
$as_echo "#define PJMEDIA_HAS_OPUS_CODEC 0" >>confdefs.h
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OPUS support is disabled... yes" >&5
|
||||
$as_echo "Checking if OPUS support is disabled... yes" >&6; }
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for OPUS installations.." >&5
|
||||
$as_echo "checking for OPUS installations.." >&6; }
|
||||
if test "x$with_opus" != "xno" -a "x$with_opus" != "x"; then
|
||||
CFLAGS="$CFLAGS -I$with_opus/include"
|
||||
CPPFLAGS="$CPPFLAGS -I$with_opus/include"
|
||||
LDFLAGS="$LDFLAGS -L$with_opus/lib"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OPUS prefix... $with_opus" >&5
|
||||
$as_echo "Using OPUS prefix... $with_opus" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "opus/opus.h" "ac_cv_header_opus_opus_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_opus_opus_h" = xyes; then :
|
||||
opus_h_present=1
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for opus_repacketizer_get_size in -lopus" >&5
|
||||
$as_echo_n "checking for opus_repacketizer_get_size in -lopus... " >&6; }
|
||||
if ${ac_cv_lib_opus_opus_repacketizer_get_size+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lopus $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char opus_repacketizer_get_size ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return opus_repacketizer_get_size ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_opus_opus_repacketizer_get_size=yes
|
||||
else
|
||||
ac_cv_lib_opus_opus_repacketizer_get_size=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opus_opus_repacketizer_get_size" >&5
|
||||
$as_echo "$ac_cv_lib_opus_opus_repacketizer_get_size" >&6; }
|
||||
if test "x$ac_cv_lib_opus_opus_repacketizer_get_size" = xyes; then :
|
||||
opus_present=1 && LIBS="$LIBS -lopus"
|
||||
fi
|
||||
|
||||
if test "x$opus_h_present" = "x1" -a "x$opus_present" = "x1"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: OPUS library found, OPUS support enabled" >&5
|
||||
$as_echo "OPUS library found, OPUS support enabled" >&6; }
|
||||
$as_echo "#define PJMEDIA_HAS_OPUS_CODEC 1" >>confdefs.h
|
||||
|
||||
else
|
||||
ac_no_opus=1
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: OPUS library not found, OPUS support disabled" >&5
|
||||
$as_echo "OPUS library not found, OPUS support disabled" >&6; }
|
||||
$as_echo "#define PJMEDIA_HAS_OPUS_CODEC 0" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1761,6 +1761,54 @@ AC_ARG_ENABLE(silk,
|
|||
fi
|
||||
])
|
||||
|
||||
dnl # Do not use default OPUS installation if we are cross-compiling
|
||||
if test "x$ac_cross_compile" != "x" -a "x$with_opus" = "xno"; then
|
||||
enable_opus=no
|
||||
fi
|
||||
|
||||
dnl # OPUS prefix
|
||||
AC_ARG_WITH(opus,
|
||||
AC_HELP_STRING([--with-opus=DIR],
|
||||
[Specify alternate OPUS prefix]),
|
||||
[],
|
||||
[with_opus=no]
|
||||
)
|
||||
|
||||
dnl # Include OPUS support
|
||||
AC_SUBST(ac_no_opus)
|
||||
AC_ARG_ENABLE(opus,
|
||||
AC_HELP_STRING([--disable-opus],
|
||||
[Exclude OPUS support from the build (default: autodetect)])
|
||||
,
|
||||
[
|
||||
if test "$enable_opus" = "no"; then
|
||||
[ac_no_opus=1]
|
||||
AC_DEFINE(PJMEDIA_HAS_OPUS_CODEC,0)
|
||||
AC_MSG_RESULT([Checking if OPUS support is disabled... yes])
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([checking for OPUS installations..])
|
||||
if test "x$with_opus" != "xno" -a "x$with_opus" != "x"; then
|
||||
CFLAGS="$CFLAGS -I$with_opus/include"
|
||||
CPPFLAGS="$CPPFLAGS -I$with_opus/include"
|
||||
LDFLAGS="$LDFLAGS -L$with_opus/lib"
|
||||
AC_MSG_RESULT([Using OPUS prefix... $with_opus])
|
||||
fi
|
||||
AC_SUBST(opus_h_present)
|
||||
AC_SUBST(opus_present)
|
||||
AC_CHECK_HEADER(opus/opus.h,[opus_h_present=1])
|
||||
AC_CHECK_LIB(opus,opus_repacketizer_get_size,[opus_present=1 && LIBS="$LIBS -lopus"])
|
||||
if test "x$opus_h_present" = "x1" -a "x$opus_present" = "x1"; then
|
||||
AC_MSG_RESULT([OPUS library found, OPUS support enabled])
|
||||
AC_DEFINE(PJMEDIA_HAS_OPUS_CODEC,1)
|
||||
else
|
||||
[ac_no_opus=1]
|
||||
AC_MSG_RESULT([OPUS library not found, OPUS support disabled])
|
||||
AC_DEFINE(PJMEDIA_HAS_OPUS_CODEC,0)
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl ##########################################
|
||||
dnl #
|
||||
|
|
|
@ -138,7 +138,7 @@ export PJMEDIA_CODEC_SRCDIR = ../src/pjmedia-codec
|
|||
export PJMEDIA_CODEC_OBJS += audio_codecs.o ffmpeg_vid_codecs.o openh264.o \
|
||||
h263_packetizer.o h264_packetizer.o \
|
||||
$(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
|
||||
ipp_codecs.o silk.o $(CODEC_OBJS) \
|
||||
ipp_codecs.o silk.o opus.o $(CODEC_OBJS) \
|
||||
g7221_sdp_match.o amr_sdp_match.o
|
||||
export PJMEDIA_CODEC_CFLAGS += $(_CFLAGS) $(GSM_CFLAGS) $(SPEEX_CFLAGS) \
|
||||
$(ILBC_CFLAGS) $(IPP_CFLAGS) $(G7221_CFLAGS)
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <pjmedia-codec/openh264.h>
|
||||
#include <pjmedia-codec/passthrough.h>
|
||||
#include <pjmedia-codec/silk.h>
|
||||
#include <pjmedia-codec/opus.h>
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_CODEC_PJMEDIA_CODEC_H__ */
|
||||
|
|
|
@ -419,6 +419,56 @@
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Enable OPUS codec.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
#ifndef PJMEDIA_HAS_OPUS_CODEC
|
||||
# define PJMEDIA_HAS_OPUS_CODEC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* OPUS codec sample rate.
|
||||
*
|
||||
* Default: 48000
|
||||
*/
|
||||
#ifndef PJMEDIA_CODEC_OPUS_DEFAULT_SAMPLE_RATE
|
||||
# define PJMEDIA_CODEC_OPUS_DEFAULT_SAMPLE_RATE 48000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* OPUS codec default maximum average bit rate.
|
||||
*
|
||||
* Default: 0 (leave it to default value specified by Opus, which will
|
||||
* take into account factors such as media content (speech/music), sample
|
||||
* rate, channel count, etc).
|
||||
*/
|
||||
#ifndef PJMEDIA_CODEC_OPUS_DEFAULT_BIT_RATE
|
||||
# define PJMEDIA_CODEC_OPUS_DEFAULT_BIT_RATE 0
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* OPUS default encoding complexity, which is an integer from
|
||||
* 0 to 10, where 0 is the lowest complexity and 10 is the highest.
|
||||
*
|
||||
* Default: 5
|
||||
*/
|
||||
#ifndef PJMEDIA_CODEC_OPUS_DEFAULT_COMPLEXITY
|
||||
# define PJMEDIA_CODEC_OPUS_DEFAULT_COMPLEXITY 5
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* OPUS default CBR (constant bit rate) setting
|
||||
*
|
||||
* Default: PJ_FALSE (which means Opus will use VBR (variable bit rate))
|
||||
*/
|
||||
#ifndef PJMEDIA_CODEC_OPUS_DEFAULT_CBR
|
||||
# define PJMEDIA_CODEC_OPUS_DEFAULT_CBR PJ_FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Specify if FFMPEG codecs are available.
|
||||
*
|
||||
|
|
|
@ -84,6 +84,11 @@
|
|||
#undef PJMEDIA_HAS_SILK_CODEC
|
||||
#endif
|
||||
|
||||
/* OPUS codec */
|
||||
#ifndef PJMEDIA_HAS_OPUS_CODEC
|
||||
#undef PJMEDIA_HAS_OPUS_CODEC
|
||||
#endif
|
||||
|
||||
#endif /* __PJMEDIA_CODEC_CONFIG_AUTO_H_ */
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Teluu Inc. (http://www.teluu.com)
|
||||
* Copyright (C) 2012-2015 Zaark Technology AB
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
/* This file is the header of Opus codec wrapper and was contributed by
|
||||
* Zaark Technology AB
|
||||
*/
|
||||
|
||||
#ifndef __PJMEDIA_CODEC_OPUS_H__
|
||||
#define __PJMEDIA_CODEC_OPUS_H__
|
||||
|
||||
/**
|
||||
* @file opus.h
|
||||
* @brief Opus codec.
|
||||
*/
|
||||
|
||||
#include <pjmedia-codec/types.h>
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_OPUS Opus Codec Family
|
||||
* @ingroup PJMEDIA_CODEC_CODECS
|
||||
* @brief Opus codec wrapper
|
||||
* @{
|
||||
*
|
||||
* This section describes functions to initialize and register Opus codec
|
||||
* factory to the codec manager. After the codec factory has been registered,
|
||||
* application can use @ref PJMEDIA_CODEC API to manipulate the codec.
|
||||
*
|
||||
* Opus codec uses multiple bit rates, and supports fullband (48 kHz
|
||||
* sampling rate), super wideband (24 kHz sampling rate), wideband (16 kHz
|
||||
* sampling rate), medium band (12kHz sampling rate), and narrowband
|
||||
* (8 kHz sampling rate).
|
||||
*
|
||||
*
|
||||
* \section codec_setting Codec Settings
|
||||
*
|
||||
* General codec settings for this codec such as VAD and PLC can be
|
||||
* manipulated through the <tt>setting</tt> field in #pjmedia_codec_param
|
||||
* (see the documentation of #pjmedia_codec_param for more info).
|
||||
*
|
||||
* For Opus codec specific settings, such as sample rate,
|
||||
* channel count, bit rate, complexity, and CBR, can be configured
|
||||
* in #pjmedia_codec_opus_config.
|
||||
* The default setting of sample rate is specified in
|
||||
* #PJMEDIA_CODEC_OPUS_DEFAULT_SAMPLE_RATE. The default setting of
|
||||
* bitrate is specified in #PJMEDIA_CODEC_OPUS_DEFAULT_BIT_RATE.
|
||||
* And the default setting of complexity is specified in
|
||||
* #PJMEDIA_CODEC_OPUS_DEFAULT_COMPLEXITY.
|
||||
*
|
||||
* After modifying any of these settings, application needs to call
|
||||
* #pjmedia_codec_opus_set_default_param(), which will generate the
|
||||
* appropriate decoding fmtp attributes.
|
||||
*
|
||||
* Here is an example of modifying the codec settings:
|
||||
\code
|
||||
pjmedia_codec_param param;
|
||||
pjmedia_codec_opus_config opus_cfg;
|
||||
|
||||
pjmedia_codec_mgr_get_default_param(.., ¶m);
|
||||
pjmedia_codec_opus_get_config(&opus_cfg);
|
||||
...
|
||||
// Set VAD
|
||||
param.setting.vad = 1;
|
||||
// Set PLC
|
||||
param.setting.vad = 1;
|
||||
// Set sample rate
|
||||
opus_cfg.sample_rate = 16000;
|
||||
// Set channel count
|
||||
opus_cfg.channel_cnt = 2;
|
||||
// Set bit rate
|
||||
opus_cfg.bit_rate = 20000;
|
||||
...
|
||||
pjmedia_codec_opus_set_default_param(&opus_cfg, ¶m);
|
||||
\endcode
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Opus codec configuration.
|
||||
*/
|
||||
typedef struct pjmedia_codec_opus_config
|
||||
{
|
||||
unsigned sample_rate; /**< Sample rate in Hz. */
|
||||
unsigned channel_cnt; /**< Number of channels. */
|
||||
unsigned bit_rate; /**< Encoder bit rate in bps. */
|
||||
unsigned packet_loss; /**< Encoder's expected packet loss pct. */
|
||||
unsigned complexity; /**< Encoder complexity, 0-10(10 is highest)*/
|
||||
pj_bool_t cbr; /**< Constant bit rate? */
|
||||
} pjmedia_codec_opus_config;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize and register Opus codec factory to pjmedia endpoint.
|
||||
*
|
||||
* @param endpt The pjmedia endpoint.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_codec_opus_init( pjmedia_endpt *endpt );
|
||||
|
||||
/**
|
||||
* Unregister Opus codec factory from pjmedia endpoint and deinitialize
|
||||
* the Opus codec library.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_codec_opus_deinit( void );
|
||||
|
||||
/**
|
||||
* Get the default Opus configuration.
|
||||
*
|
||||
* @param cfg Opus codec configuration.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t)
|
||||
pjmedia_codec_opus_get_config( pjmedia_codec_opus_config *cfg );
|
||||
|
||||
/**
|
||||
* Set the default Opus configuration and set the default Opus codec param.
|
||||
* Note that the function will call #pjmedia_codec_mgr_set_default_param().
|
||||
*
|
||||
* @param cfg Opus codec configuration.
|
||||
* @param param The new default Opus codec parameter.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t)
|
||||
pjmedia_codec_opus_set_default_param(const pjmedia_codec_opus_config *cfg,
|
||||
pjmedia_codec_param *param );
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __PJMEDIA_CODEC_OPUS_H__ */
|
|
@ -83,6 +83,7 @@ enum pjmedia_audio_pt
|
|||
PJMEDIA_RTP_PT_G7221C_48, /**< G722.1 Annex C (48Kbps)*/
|
||||
PJMEDIA_RTP_PT_G7221_RSV1, /**< G722.1 reserve */
|
||||
PJMEDIA_RTP_PT_G7221_RSV2, /**< G722.1 reserve */
|
||||
PJMEDIA_RTP_PT_OPUS, /**< OPUS */
|
||||
PJMEDIA_RTP_PT_L16_8KHZ_MONO, /**< L16 @ 8KHz, mono */
|
||||
PJMEDIA_RTP_PT_L16_8KHZ_STEREO, /**< L16 @ 8KHz, stereo */
|
||||
//PJMEDIA_RTP_PT_L16_11KHZ_MONO, /**< L16 @ 11KHz, mono */
|
||||
|
|
|
@ -972,6 +972,7 @@
|
|||
* See:
|
||||
* - G.722 : RFC 3551 4.5.2
|
||||
* - MPEG audio : RFC 3551 4.5.13 & RFC 3119
|
||||
* - OPUS : RFC 7587
|
||||
*
|
||||
* Also when this feature is enabled, some handling will be performed
|
||||
* to deal with clock rate incompatibilities of some phones.
|
||||
|
|
|
@ -121,6 +121,13 @@ pjmedia_codec_register_audio_codecs(pjmedia_endpt *endpt,
|
|||
return status;
|
||||
#endif
|
||||
|
||||
#if PJMEDIA_HAS_OPUS_CODEC
|
||||
/* Register OPUS */
|
||||
status = pjmedia_codec_opus_init(endpt);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
#endif
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2109,6 +2109,15 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
|
|||
goto err_cleanup;
|
||||
|
||||
/* Open the codec. */
|
||||
|
||||
/* The clock rate for Opus codec is not static,
|
||||
* it's negotiated in the SDP.
|
||||
*/
|
||||
if (!pj_stricmp2(&info->fmt.encoding_name, "opus")) {
|
||||
stream->codec_param.info.clock_rate = info->fmt.clock_rate;
|
||||
stream->codec_param.info.channel_cnt = info->fmt.channel_cnt;
|
||||
}
|
||||
|
||||
status = pjmedia_codec_open(stream->codec, &stream->codec_param);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto err_cleanup;
|
||||
|
@ -2223,6 +2232,12 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
|
|||
stream->has_g722_mpeg_bug = PJ_TRUE;
|
||||
/* RTP clock rate = 1/2 real clock rate */
|
||||
stream->rtp_tx_ts_len_per_pkt >>= 1;
|
||||
} else if (!pj_stricmp2(&info->fmt.encoding_name, "opus")) {
|
||||
unsigned opus_ts_modifier = 48000 / afd->clock_rate;
|
||||
stream->rtp_rx_check_cnt = 0;
|
||||
stream->has_g722_mpeg_bug = PJ_TRUE;
|
||||
stream->rtp_tx_ts_len_per_pkt *= opus_ts_modifier;
|
||||
stream->rtp_rx_ts_len_per_frame *= opus_ts_modifier;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,6 +33,47 @@ static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 };
|
|||
static const pj_str_t ID_RTPMAP = { "rtpmap", 6 };
|
||||
static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 };
|
||||
|
||||
static void get_opus_channels_and_clock_rate(const pjmedia_codec_fmtp *enc_fmtp,
|
||||
const pjmedia_codec_fmtp *dec_fmtp,
|
||||
unsigned *channel_cnt,
|
||||
unsigned *clock_rate)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned enc_channel_cnt = 0, local_channel_cnt = 0;
|
||||
unsigned enc_clock_rate = 0, local_clock_rate = 0;
|
||||
|
||||
for (i = 0; i < dec_fmtp->cnt; ++i) {
|
||||
if (!pj_stricmp2(&dec_fmtp->param[i].name, "sprop-maxcapturerate")) {
|
||||
local_clock_rate = (unsigned)pj_strtoul(&dec_fmtp->param[i].val);
|
||||
} else if (!pj_stricmp2(&dec_fmtp->param[i].name, "sprop-stereo")) {
|
||||
local_channel_cnt = (unsigned)pj_strtoul(&dec_fmtp->param[i].val);
|
||||
local_channel_cnt = (local_channel_cnt > 0) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
if (!local_clock_rate) local_clock_rate = *clock_rate;
|
||||
if (!local_channel_cnt) local_channel_cnt = *channel_cnt;
|
||||
|
||||
for (i = 0; i < enc_fmtp->cnt; ++i) {
|
||||
if (!pj_stricmp2(&enc_fmtp->param[i].name, "maxplaybackrate")) {
|
||||
enc_clock_rate = (unsigned)pj_strtoul(&enc_fmtp->param[i].val);
|
||||
} else if (!pj_stricmp2(&enc_fmtp->param[i].name, "stereo")) {
|
||||
enc_channel_cnt = (unsigned)pj_strtoul(&enc_fmtp->param[i].val);
|
||||
enc_channel_cnt = (enc_channel_cnt > 0) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
/* The default is a standard mono session with 48000 Hz clock rate
|
||||
* (RFC 7587, section 7)
|
||||
*/
|
||||
if (!enc_clock_rate) enc_clock_rate = 48000;
|
||||
if (!enc_channel_cnt) enc_channel_cnt = 1;
|
||||
|
||||
*clock_rate = (enc_clock_rate < local_clock_rate) ? enc_clock_rate :
|
||||
local_clock_rate;
|
||||
|
||||
*channel_cnt = (enc_channel_cnt < local_channel_cnt) ? enc_channel_cnt :
|
||||
local_channel_cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function for collecting codec info and param from the SDP media.
|
||||
*/
|
||||
|
@ -218,6 +259,14 @@ static pj_status_t get_audio_codec_info_param(pjmedia_stream_info *si,
|
|||
pjmedia_stream_info_parse_fmtp(pool, local_m, si->rx_pt,
|
||||
&si->param->setting.dec_fmtp);
|
||||
|
||||
if (!pj_stricmp2(&si->fmt.encoding_name, "opus")) {
|
||||
get_opus_channels_and_clock_rate(&si->param->setting.enc_fmtp,
|
||||
&si->param->setting.dec_fmtp,
|
||||
&si->fmt.channel_cnt,
|
||||
&si->fmt.clock_rate);
|
||||
}
|
||||
|
||||
|
||||
/* Get the remote ptime for our encoder. */
|
||||
attr = pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr,
|
||||
"ptime", NULL);
|
||||
|
|
Loading…
Reference in New Issue