Adding Opus stereo support to WebRTC

This CL adds support for sending and receiving stereo using the Opus codec.

BUG=issue1013

Review URL: https://webrtc-codereview.appspot.com/930008

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3050 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
tina.legrand@webrtc.org
2012-11-07 08:07:29 +00:00
parent 6dddfe9c35
commit 0ad3c1af0a
14 changed files with 276 additions and 36 deletions

View File

@ -29,7 +29,8 @@ ACMOpus::ACMOpus(int16_t /* codecID */)
: _encoderInstPtr(NULL),
_decoderInstPtr(NULL),
_sampleFreq(0),
_bitrate(0) {
_bitrate(0),
_channels(1) {
return;
}
@ -91,18 +92,26 @@ int16_t ACMOpus::SetBitRateSafe(const int32_t /*rate*/) {
return -1;
}
bool ACMOpus::IsTrueStereoCodec() {
return true;
}
void ACMOpus::SplitStereoPacket(uint8_t* /*payload*/,
int32_t* /*payload_length*/) {}
#else //===================== Actual Implementation =======================
ACMOpus::ACMOpus(int16_t codecID)
: _encoderInstPtr(NULL),
_decoderInstPtr(NULL),
_sampleFreq(32000), // Default sampling frequency.
_bitrate(20000) { // Default bit-rate.
_bitrate(20000), // Default bit-rate.
_channels(1) { // Default mono
_codecID = codecID;
// Opus has internal DTX, but we dont use it for now.
_hasInternalDTX = false;
if (_codecID != ACMCodecDB::kOpus) {
if ((_codecID != ACMCodecDB::kOpus) && (_codecID != ACMCodecDB::kOpus_2ch)) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Wrong codec id for Opus.");
_sampleFreq = -1;
@ -140,7 +149,7 @@ int16_t ACMOpus::InternalEncode(uint8_t* bitStream, int16_t* bitStreamLenByte) {
// Increment the read index. This tells the caller how far
// we have gone forward in reading the audio buffer.
_inAudioIxRead += _frameLenSmpl;
_inAudioIxRead += _frameLenSmpl * _channels;
return *bitStreamLenByte;
}
@ -159,6 +168,9 @@ int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codecParams) {
}
ret = WebRtcOpus_EncoderCreate(&_encoderInstPtr,
codecParams->codecInstant.channels);
// Store number of channels.
_channels = codecParams->codecInstant.channels;
if (ret < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"Encoder creation failed for Opus");
@ -170,6 +182,10 @@ int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codecParams) {
"Setting initial bitrate failed for Opus");
return ret;
}
// Store bitrate.
_bitrate = codecParams->codecInstant.rate;
return 0;
}
@ -182,7 +198,14 @@ int16_t ACMOpus::InternalInitDecoder(WebRtcACMCodecParams* codecParams) {
codecParams->codecInstant.channels) < 0) {
return -1;
}
return WebRtcOpus_DecoderInit(_decoderInstPtr);
if (WebRtcOpus_DecoderInit(_decoderInstPtr) < 0) {
return -1;
}
if (WebRtcOpus_DecoderInitSlave(_decoderInstPtr) < 0) {
return -1;
}
return 0;
}
int32_t ACMOpus::CodecDef(WebRtcNetEQ_CodecDef& codecDef,
@ -198,12 +221,26 @@ 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.
SET_CODEC_PAR((codecDef), kDecoderOpus, codecInst.pltype, _decoderInstPtr,
32000);
SET_OPUS_FUNCTIONS((codecDef));
if (codecInst.channels == 1) {
SET_CODEC_PAR(codecDef, kDecoderOpus, codecInst.pltype, _decoderInstPtr,
32000);
} else {
SET_CODEC_PAR(codecDef, kDecoderOpus_2ch, codecInst.pltype,
_decoderInstPtr, 32000);
}
// If this is the master of NetEQ, regular decoder will be added, otherwise
// the slave decoder will be used.
if (_isMaster) {
SET_OPUS_FUNCTIONS(codecDef);
} else {
SET_OPUSSLAVE_FUNCTIONS(codecDef);
}
return 0;
}
ACMGenericCodec* ACMOpus::CreateInstance(void) {
return NULL;
}
@ -258,6 +295,23 @@ int16_t ACMOpus::SetBitRateSafe(const int32_t rate) {
return -1;
}
bool ACMOpus::IsTrueStereoCodec() {
return true;
}
// Copy the stereo packet so that NetEq will insert into both master and slave.
void ACMOpus::SplitStereoPacket(uint8_t* payload, int32_t* payload_length) {
// Check for valid inputs.
assert(payload != NULL);
assert(*payload_length > 0);
// Duplicate the payload.
memcpy(&payload[*payload_length], &payload[0],
sizeof(uint8_t) * (*payload_length));
// Double the size of the packet.
*payload_length *= 2;
}
#endif // WEBRTC_CODEC_OPUS
} // namespace webrtc