Opus mono/stereo on the same payloadtype, and fix of memory bug
During call setup Opus should always be signaled as a 48000 Hz stereo codec, not depending on what we plan to send, or how we plan to decode received packets. The previous implementation had different payload types for mono and stereo, which breaks the proposed standard. While working on this CL I ran in to the problem reported earlier, that we could get a crash related to deleting decoder memory. This should now be solved in Patch Set 3. BUG=issue1013, issue1112 Review URL: https://webrtc-codereview.appspot.com/933022 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3177 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -190,10 +190,8 @@ const CodecInst ACMCodecDB::database_[] = {
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
// Opus internally supports 48, 24, 16, 12, 8 kHz.
|
||||
// Mono
|
||||
{120, "opus", 48000, 960, 1, 32000},
|
||||
// Stereo
|
||||
{121, "opus", 48000, 960, 2, 32000},
|
||||
// Mono and stereo.
|
||||
{120, "opus", 48000, 960, 2, 32000},
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_SPEEX
|
||||
{kDynamicPayloadtypes[count_database++], "speex", 8000, 160, 1, 11000},
|
||||
@ -285,9 +283,7 @@ const ACMCodecDB::CodecSettings ACMCodecDB::codec_settings_[] = {
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
// Opus supports frames shorter than 10ms,
|
||||
// but it doesn't help us to use them.
|
||||
// Mono
|
||||
{1, {960}, 0, 2},
|
||||
// Stereo
|
||||
// Mono and stereo.
|
||||
{1, {960}, 0, 2},
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_SPEEX
|
||||
@ -375,10 +371,8 @@ const WebRtcNetEQDecoder ACMCodecDB::neteq_decoders_[] = {
|
||||
kDecoderGSMFR,
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
// Mono
|
||||
// Mono and stereo.
|
||||
kDecoderOpus,
|
||||
// Stereo
|
||||
kDecoderOpus_2ch,
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_SPEEX
|
||||
kDecoderSPEEX_8,
|
||||
@ -571,7 +565,13 @@ int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) {
|
||||
// always treated as true, like for RED.
|
||||
name_match = (STR_CASE_CMP(database_[id].plname, payload_name) == 0);
|
||||
frequency_match = (frequency == database_[id].plfreq) || (frequency == -1);
|
||||
channels_match = (channels == database_[id].channels);
|
||||
// The number of channels must match for all codecs but Opus.
|
||||
if (STR_CASE_CMP(payload_name, "opus") != 0) {
|
||||
channels_match = (channels == database_[id].channels);
|
||||
} else {
|
||||
// For opus we just check that number of channels is valid.
|
||||
channels_match = (channels == 1 || channels == 2);
|
||||
}
|
||||
|
||||
if (name_match && frequency_match && channels_match) {
|
||||
// We have found a matching codec in the list.
|
||||
@ -767,11 +767,7 @@ ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst* codec_inst) {
|
||||
#endif
|
||||
} else if (!STR_CASE_CMP(codec_inst->plname, "opus")) {
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
if (codec_inst->channels == 1) {
|
||||
return new ACMOpus(kOpus);
|
||||
} else {
|
||||
return new ACMOpus(kOpus_2ch);
|
||||
}
|
||||
return new ACMOpus(kOpus);
|
||||
#endif
|
||||
} else if (!STR_CASE_CMP(codec_inst->plname, "speex")) {
|
||||
#ifdef WEBRTC_CODEC_SPEEX
|
||||
|
||||
@ -92,10 +92,8 @@ class ACMCodecDB {
|
||||
, kGSMFR
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_OPUS
|
||||
// Mono
|
||||
// Mono and stereo
|
||||
, kOpus
|
||||
// Stereo
|
||||
, kOpus_2ch
|
||||
#endif
|
||||
#ifdef WEBRTC_CODEC_SPEEX
|
||||
, kSPEEX8
|
||||
@ -178,10 +176,8 @@ class ACMCodecDB {
|
||||
enum {kSPEEX16 = -1};
|
||||
#endif
|
||||
#ifndef WEBRTC_CODEC_OPUS
|
||||
// Mono
|
||||
// Mono and stereo
|
||||
enum {kOpus = -1};
|
||||
// Stereo
|
||||
enum {kOpus_2ch = -1};
|
||||
#endif
|
||||
#ifndef WEBRTC_CODEC_AVT
|
||||
enum {kAVT = -1};
|
||||
|
||||
@ -111,7 +111,7 @@ ACMOpus::ACMOpus(int16_t codecID)
|
||||
// Opus has internal DTX, but we dont use it for now.
|
||||
_hasInternalDTX = false;
|
||||
|
||||
if ((_codecID != ACMCodecDB::kOpus) && (_codecID != ACMCodecDB::kOpus_2ch)) {
|
||||
if (_codecID != ACMCodecDB::kOpus) {
|
||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
|
||||
"Wrong codec id for Opus.");
|
||||
_sampleFreq = -1;
|
||||
@ -190,15 +190,17 @@ int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codecParams) {
|
||||
}
|
||||
|
||||
int16_t ACMOpus::InternalInitDecoder(WebRtcACMCodecParams* codecParams) {
|
||||
if (_decoderInstPtr != NULL) {
|
||||
WebRtcOpus_DecoderFree(_decoderInstPtr);
|
||||
_decoderInstPtr = NULL;
|
||||
}
|
||||
if (WebRtcOpus_DecoderCreate(&_decoderInstPtr,
|
||||
codecParams->codecInstant.channels) < 0) {
|
||||
return -1;
|
||||
if(_decoderInstPtr == NULL) {
|
||||
if (WebRtcOpus_DecoderCreate(&_decoderInstPtr,
|
||||
codecParams->codecInstant.channels) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Number of channels in decoder should match the number in |codecParams|.
|
||||
assert(codecParams->codecInstant.channels ==
|
||||
WebRtcOpus_DecoderChannels(_decoderInstPtr));
|
||||
|
||||
if (WebRtcOpus_DecoderInit(_decoderInstPtr) < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -221,13 +223,8 @@ int32_t ACMOpus::CodecDef(WebRtcNetEQ_CodecDef& codecDef,
|
||||
// TODO(tlegrand): Decoder is registered in NetEQ as a 32 kHz decoder, which
|
||||
// is true until we have a full 48 kHz system, and remove the downsampling
|
||||
// in the Opus decoder wrapper.
|
||||
if (codecInst.channels == 1) {
|
||||
SET_CODEC_PAR(codecDef, kDecoderOpus, codecInst.pltype, _decoderInstPtr,
|
||||
32000);
|
||||
} else {
|
||||
SET_CODEC_PAR(codecDef, kDecoderOpus_2ch, codecInst.pltype,
|
||||
_decoderInstPtr, 32000);
|
||||
}
|
||||
SET_CODEC_PAR(codecDef, kDecoderOpus, codecInst.pltype,
|
||||
_decoderInstPtr, 32000);
|
||||
|
||||
// If this is the master of NetEQ, regular decoder will be added, otherwise
|
||||
// the slave decoder will be used.
|
||||
|
||||
@ -59,6 +59,10 @@ WebRtc_Word32 AudioCodingModule::Codec(const char* payload_name,
|
||||
// Get default codec settings.
|
||||
ACMCodecDB::Codec(codec_id, &codec);
|
||||
|
||||
// Keep the number of channels from the function call. For most codecs it
|
||||
// will be the same value as in defaul codec settings, but not for all.
|
||||
codec.channels = channels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1285,7 +1285,7 @@ WebRtc_Word32 AudioCodingModuleImpl::PlayoutFrequency() const {
|
||||
return _netEq.CurrentSampFreqHz();
|
||||
}
|
||||
|
||||
// Register possible reveive codecs, can be called multiple times,
|
||||
// Register possible receive codecs, can be called multiple times,
|
||||
// for codecs, CNG (NB, WB and SWB), DTMF, RED.
|
||||
WebRtc_Word32 AudioCodingModuleImpl::RegisterReceiveCodec(
|
||||
const CodecInst& receive_codec) {
|
||||
@ -1394,14 +1394,30 @@ WebRtc_Word32 AudioCodingModuleImpl::RegisterReceiveCodec(
|
||||
|
||||
if (!_stereoReceive[codec_id]
|
||||
&& (_lastRecvAudioCodecPlType == receive_codec.pltype)) {
|
||||
// The last received payload type is the same as the current one, but
|
||||
// was marked as mono. Reset to avoid problems.
|
||||
// The last received payload type is the same as the one we are
|
||||
// registering. Expected number of channels to receive is one (mono),
|
||||
// but we are now registering the receiving codec as stereo (number of
|
||||
// channels is 2).
|
||||
// Set |_lastRecvAudioCodedPlType| to invalid value to trigger a flush in
|
||||
// NetEq, and a reset of expected number of channels next time a packet is
|
||||
// received in AudioCodingModuleImpl::IncomingPacket().
|
||||
_lastRecvAudioCodecPlType = -1;
|
||||
}
|
||||
|
||||
_stereoReceive[codec_id] = true;
|
||||
_stereoReceiveRegistered = true;
|
||||
} else {
|
||||
if (_lastRecvAudioCodecPlType == receive_codec.pltype &&
|
||||
_expected_channels == 2) {
|
||||
// The last received payload type is the same as the one we are
|
||||
// registering. Expected number of channels to receive is two (stereo),
|
||||
// but we are now registering the receiving codec as mono (number of
|
||||
// channels is 1).
|
||||
// Set |_lastRecvAudioCodedPlType| to invalid value to trigger a flush in
|
||||
// NetEq, and a reset of expected number of channels next time a packet is
|
||||
// received in AudioCodingModuleImpl::IncomingPacket().
|
||||
_lastRecvAudioCodecPlType = -1;
|
||||
}
|
||||
_stereoReceive[codec_id] = false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user