diff --git a/src/modules/audio_coding/main/interface/audio_coding_module.h b/src/modules/audio_coding/main/interface/audio_coding_module.h index ed13689a7..7c0ba4e10 100644 --- a/src/modules/audio_coding/main/interface/audio_coding_module.h +++ b/src/modules/audio_coding/main/interface/audio_coding_module.h @@ -546,7 +546,7 @@ class AudioCodingModule: public Module { // -1 if failed to push in the payload // 0 if payload is successfully pushed in. // - virtual WebRtc_Word32 IncomingPacket(const WebRtc_Word8* incomingPayload, + virtual WebRtc_Word32 IncomingPacket(const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLengthByte, const WebRtcRTPHeader& rtpInfo) = 0; @@ -574,7 +574,7 @@ class AudioCodingModule: public Module { // -1 if failed to push in the payload // 0 if payload is successfully pushed in. // - virtual WebRtc_Word32 IncomingPayload(const WebRtc_Word8* incomingPayload, + virtual WebRtc_Word32 IncomingPayload(const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLengthByte, const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timestamp = 0) = 0; diff --git a/src/modules/audio_coding/main/source/acm_celt.cc b/src/modules/audio_coding/main/source/acm_celt.cc index a1462ecd6..1c505ad93 100644 --- a/src/modules/audio_coding/main/source/acm_celt.cc +++ b/src/modules/audio_coding/main/source/acm_celt.cc @@ -103,6 +103,9 @@ int16_t ACMCELT::SetBitRateSafe(const int32_t /*rate*/) { return -1; } +void ACMCELT::SplitStereoPacket(uint8_t* /*payload*/, + int32_t* /*payload_length*/) {} + #else //===================== Actual Implementation ======================= ACMCELT::ACMCELT(int16_t codecID) @@ -327,6 +330,19 @@ int16_t ACMCELT::SetBitRateSafe(const int32_t rate) { } } +// Copy the stereo packet so that NetEq will insert into both master and slave. +void ACMCELT::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 } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_celt.h b/src/modules/audio_coding/main/source/acm_celt.h index 776bd7fc5..f6fd0e460 100644 --- a/src/modules/audio_coding/main/source/acm_celt.h +++ b/src/modules/audio_coding/main/source/acm_celt.h @@ -61,6 +61,8 @@ class ACMCELT : public ACMGenericCodec { int16_t SetBitRateSafe(const int32_t rate); + void SplitStereoPacket(uint8_t* payload, int32_t* payload_length); + CELT_encinst_t_* enc_inst_ptr_; CELT_decinst_t_* dec_inst_ptr_; uint16_t sampling_freq_; diff --git a/src/modules/audio_coding/main/source/acm_g722.cc b/src/modules/audio_coding/main/source/acm_g722.cc index 40e431cf6..c13a59e5f 100644 --- a/src/modules/audio_coding/main/source/acm_g722.cc +++ b/src/modules/audio_coding/main/source/acm_g722.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -99,6 +99,9 @@ WebRtc_Word16 ACMG722::UnregisterFromNetEqSafe( return -1; } +void ACMG722::SplitStereoPacket(uint8_t* /*payload*/, + int32_t* /*payload_length*/) {} + #else //===================== Actual Implementation ======================= // Encoder and decoder memory @@ -332,6 +335,35 @@ WebRtc_Word16 ACMG722::UnregisterFromNetEqSafe(ACMNetEQ* netEq, return netEq->RemoveCodec(kDecoderG722); } +// Split the stereo packet and place left and right channel after each other +// in the payload vector. +void ACMG722::SplitStereoPacket(uint8_t* payload, int32_t* payload_length) { + uint8_t right_byte; + + // Check for valid inputs. + assert(payload != NULL); + assert(*payload_length > 0); + + // Regroup the 4 bits/sample so to |l1 l2| |r1 r2| |l3 l4| |r3 r4| ..., + // where "lx" is 4 bits representing left sample number x, and "rx" right + // sample. Two samples fits in one byte, represented with |...|. + for (int i = 0; i < *payload_length; i += 2) { + right_byte = ((payload[i] & 0x0F) << 4) + (payload[i + 1] & 0x0F); + payload[i] = (payload[i] & 0xF0) + (payload[i + 1] >> 4); + payload[i + 1] = right_byte; + } + + // Move one byte representing right channel each loop, and place it at the + // end of the bytestream vector. After looping the data is reordered to: + // |l1 l2| |l3 l4| ... |l(N-1) lN| |r1 r2| |r3 r4| ... |r(N-1) r(N)|, + // where N is the total number of samples. + for (int i = 0; i < *payload_length / 2; i++) { + right_byte = payload[i + 1]; + memmove(&payload[i + 1], &payload[i + 2], *payload_length - i - 2); + payload[*payload_length - 1] = right_byte; + } +} + #endif } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_g722.h b/src/modules/audio_coding/main/source/acm_g722.h index 776d18870..122ccf3ac 100644 --- a/src/modules/audio_coding/main/source/acm_g722.h +++ b/src/modules/audio_coding/main/source/acm_g722.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -63,6 +63,8 @@ class ACMG722: public ACMGenericCodec { WebRtc_Word16 UnregisterFromNetEqSafe(ACMNetEQ* netEq, WebRtc_Word16 payloadType); + void SplitStereoPacket(uint8_t* payload, int32_t* payload_length); + ACMG722EncStr* _ptrEncStr; ACMG722DecStr* _ptrDecStr; diff --git a/src/modules/audio_coding/main/source/acm_generic_codec.h b/src/modules/audio_coding/main/source/acm_generic_codec.h index 7f8ef8c47..36edbcb1d 100644 --- a/src/modules/audio_coding/main/source/acm_generic_codec.h +++ b/src/modules/audio_coding/main/source/acm_generic_codec.h @@ -141,6 +141,23 @@ public: WebRtc_Word16* audioSamples, WebRtc_Word8* speechType); + /////////////////////////////////////////////////////////////////////////// + // void SplitStereoPacket() + // This function is used to split stereo payloads in left and right channel. + // Codecs which has stereo support has there own implementation of the + // function. + // + // Input/Output: + // -payload : a vector with the received payload data. + // The function will reorder the data so that + // first half holds the left channel data, and the + // second half the right channel data. + // -payload_length : length of payload in bytes. Will be changed to + // twice the input in case of true stereo, where + // we simply copy the data and return it both for + // left channel and right channel decoding. + virtual void SplitStereoPacket(WebRtc_UWord8* /* payload */, + WebRtc_Word32* /* payload_length */) {} /////////////////////////////////////////////////////////////////////////// // bool EncoderInitialized(); diff --git a/src/modules/audio_coding/main/source/acm_neteq.cc b/src/modules/audio_coding/main/source/acm_neteq.cc index 69942bda1..e44f5a285 100644 --- a/src/modules/audio_coding/main/source/acm_neteq.cc +++ b/src/modules/audio_coding/main/source/acm_neteq.cc @@ -513,10 +513,12 @@ ACMNetEQ::NetworkStatistics( WebRtc_Word32 ACMNetEQ::RecIn( - const WebRtc_Word8* incomingPayload, + const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLength, const WebRtcRTPHeader& rtpInfo) { + WebRtc_Word16 payload_length = static_cast(payloadLength); + // translate to NetEq struct WebRtcNetEQ_RTPInfo netEqRTPInfo; netEqRTPInfo.payloadType = rtpInfo.header.payloadType; @@ -536,28 +538,32 @@ ACMNetEQ::RecIn( (_currentSampFreqKHz * nowInMs); int status; - - if(rtpInfo.type.Audio.channel == 1) - { - if(!_isInitialized[0]) - { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, - "RecIn: NetEq is not initialized."); - return -1; - } - // PUSH into Master - status = WebRtcNetEQ_RecInRTPStruct(_inst[0], &netEqRTPInfo, - (WebRtc_UWord8 *)incomingPayload, (WebRtc_Word16)payloadLength, - recvTimestamp); - if(status < 0) - { - LogError("RecInRTPStruct", 0); - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, - "RecIn: NetEq, error in pushing in Master"); - return -1; - } + // In case of stereo payload, first half of the data should be pushed into + // master, and the second half into slave. + if (rtpInfo.type.Audio.channel == 2) { + payload_length = payload_length / 2; } - else if(rtpInfo.type.Audio.channel == 2) + + // Check that master is initialized. + if(!_isInitialized[0]) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, + "RecIn: NetEq is not initialized."); + return -1; + } + // PUSH into Master + status = WebRtcNetEQ_RecInRTPStruct(_inst[0], &netEqRTPInfo, + incomingPayload, payload_length, recvTimestamp); + if(status < 0) + { + LogError("RecInRTPStruct", 0); + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, + "RecIn: NetEq, error in pushing in Master"); + return -1; + } + + // If the received stream is stereo, insert second half of paket into slave. + if(rtpInfo.type.Audio.channel == 2) { if(!_isInitialized[1]) { @@ -567,8 +573,9 @@ ACMNetEQ::RecIn( } // PUSH into Slave status = WebRtcNetEQ_RecInRTPStruct(_inst[1], &netEqRTPInfo, - (WebRtc_UWord8 *)incomingPayload, (WebRtc_Word16)payloadLength, - recvTimestamp); + &incomingPayload[payload_length], + payload_length, + recvTimestamp); if(status < 0) { LogError("RecInRTPStruct", 1); @@ -577,14 +584,6 @@ ACMNetEQ::RecIn( return -1; } } - else - { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, - "RecIn: NetEq, error invalid numbe of channels %d \ -(1, for Master stream, and 2, for slave stream, are valid values)", - rtpInfo.type.Audio.channel); - return -1; - } return 0; } @@ -677,6 +676,7 @@ ACMNetEQ::RecOut( } } } + if(payloadLenSample != payloadLenSampleSlave) { WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, _id, diff --git a/src/modules/audio_coding/main/source/acm_neteq.h b/src/modules/audio_coding/main/source/acm_neteq.h index 677c6222a..7db66cab4 100644 --- a/src/modules/audio_coding/main/source/acm_neteq.h +++ b/src/modules/audio_coding/main/source/acm_neteq.h @@ -85,7 +85,7 @@ public: // <0 if NetEQ returned an error. // WebRtc_Word32 RecIn( - const WebRtc_Word8* incomingPayload, + const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLength, const WebRtcRTPHeader& rtpInfo); diff --git a/src/modules/audio_coding/main/source/acm_neteq_unittest.cc b/src/modules/audio_coding/main/source/acm_neteq_unittest.cc index 7feb2e078..c0df2c571 100644 --- a/src/modules/audio_coding/main/source/acm_neteq_unittest.cc +++ b/src/modules/audio_coding/main/source/acm_neteq_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -67,7 +67,7 @@ void AcmNetEqTest::InsertZeroPacket(uint16_t sequence_number, rtp_header.header.payloadType = payload_type; rtp_header.header.markerBit = marker_bit; rtp_header.type.Audio.channel = 1; - ASSERT_EQ(0, neteq_.RecIn(reinterpret_cast(payload), + ASSERT_EQ(0, neteq_.RecIn(reinterpret_cast(payload), len_payload_bytes, rtp_header)); } diff --git a/src/modules/audio_coding/main/source/acm_pcm16b.cc b/src/modules/audio_coding/main/source/acm_pcm16b.cc index 5c93e9058..78c71780c 100644 --- a/src/modules/audio_coding/main/source/acm_pcm16b.cc +++ b/src/modules/audio_coding/main/source/acm_pcm16b.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -135,6 +135,8 @@ ACMPCM16B::UnregisterFromNetEqSafe( } +void ACMPCM16B::SplitStereoPacket(uint8_t* /*payload*/, + int32_t* /*payload_length*/) {} #else //===================== Actual Implementation ======================= @@ -329,6 +331,29 @@ the stored payload type", } } +// Split the stereo packet and place left and right channel after each other +// in the payload vector. +void ACMPCM16B::SplitStereoPacket(uint8_t* payload, int32_t* payload_length) { + uint8_t right_byte_msb; + uint8_t right_byte_lsb; + + // Check for valid inputs. + assert(payload != NULL); + assert(*payload_length > 0); + + // Move two bytes representing right channel each loop, and place it at the + // end of the bytestream vector. After looping the data is reordered to: + // l1 l2 l3 l4 ... l(N-1) lN r1 r2 r3 r4 ... r(N-1) r(N), + // where N is the total number of samples. + + for (int i = 0; i < *payload_length / 2; i += 2) { + right_byte_msb = payload[i + 2]; + right_byte_lsb = payload[i + 3]; + memmove(&payload[i + 2], &payload[i + 4], *payload_length - i - 4); + payload[*payload_length - 2] = right_byte_msb; + payload[*payload_length - 1] = right_byte_lsb; + } +} #endif } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_pcm16b.h b/src/modules/audio_coding/main/source/acm_pcm16b.h index a81d8fed1..495934beb 100644 --- a/src/modules/audio_coding/main/source/acm_pcm16b.h +++ b/src/modules/audio_coding/main/source/acm_pcm16b.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -61,6 +61,8 @@ protected: void InternalDestructEncoderInst( void* ptrInst); + void SplitStereoPacket(uint8_t* payload, int32_t* payload_length); + WebRtc_Word32 _samplingFreqHz; }; diff --git a/src/modules/audio_coding/main/source/acm_pcma.cc b/src/modules/audio_coding/main/source/acm_pcma.cc index c86bd1c66..9d2de204c 100644 --- a/src/modules/audio_coding/main/source/acm_pcma.cc +++ b/src/modules/audio_coding/main/source/acm_pcma.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -162,4 +162,24 @@ the stored payload type", return netEq->RemoveCodec(kDecoderPCMa); } +// Split the stereo packet and place left and right channel after each other +// in the payload vector. +void ACMPCMA::SplitStereoPacket(uint8_t* payload, int32_t* payload_length) { + uint8_t right_byte; + + // Check for valid inputs. + assert(payload != NULL); + assert(*payload_length > 0); + + // Move one bytes representing right channel each loop, and place it at the + // end of the bytestream vector. After looping the data is reordered to: + // l1 l2 l3 l4 ... l(N-1) lN r1 r2 r3 r4 ... r(N-1) r(N), + // where N is the total number of samples. + for (int i = 0; i < *payload_length / 2; i ++) { + right_byte = payload[i + 1]; + memmove(&payload[i + 1], &payload[i + 2], *payload_length - i - 2); + payload[*payload_length - 1] = right_byte; + } +} + } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_pcma.h b/src/modules/audio_coding/main/source/acm_pcma.h index db25798bd..1a970c740 100644 --- a/src/modules/audio_coding/main/source/acm_pcma.h +++ b/src/modules/audio_coding/main/source/acm_pcma.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -60,6 +60,8 @@ protected: void InternalDestructEncoderInst( void* ptrInst); + + void SplitStereoPacket(uint8_t* payload, int32_t* payload_length); }; } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_pcmu.cc b/src/modules/audio_coding/main/source/acm_pcmu.cc index 320ba5b47..332888d1e 100644 --- a/src/modules/audio_coding/main/source/acm_pcmu.cc +++ b/src/modules/audio_coding/main/source/acm_pcmu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -164,4 +164,24 @@ the stored payload type", return netEq->RemoveCodec(kDecoderPCMu); } +// Split the stereo packet and place left and right channel after each other +// in the payload vector. +void ACMPCMU::SplitStereoPacket(uint8_t* payload, int32_t* payload_length) { + uint8_t right_byte; + + // Check for valid inputs. + assert(payload != NULL); + assert(*payload_length > 0); + + // Move one bytes representing right channel each loop, and place it at the + // end of the bytestream vector. After looping the data is reordered to: + // l1 l2 l3 l4 ... l(N-1) lN r1 r2 r3 r4 ... r(N-1) r(N), + // where N is the total number of samples. + for (int i = 0; i < *payload_length / 2; i ++) { + right_byte = payload[i + 1]; + memmove(&payload[i + 1], &payload[i + 2], *payload_length - i - 2); + payload[*payload_length - 1] = right_byte; + } +} + } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_pcmu.h b/src/modules/audio_coding/main/source/acm_pcmu.h index 2fc4223f7..751be86bd 100644 --- a/src/modules/audio_coding/main/source/acm_pcmu.h +++ b/src/modules/audio_coding/main/source/acm_pcmu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -60,6 +60,8 @@ protected: void InternalDestructEncoderInst( void* ptrInst); + + void SplitStereoPacket(uint8_t* payload, int32_t* payload_length); }; } // namespace webrtc diff --git a/src/modules/audio_coding/main/source/audio_coding_module_impl.cc b/src/modules/audio_coding/main/source/audio_coding_module_impl.cc index 85950c860..9ecb23db6 100644 --- a/src/modules/audio_coding/main/source/audio_coding_module_impl.cc +++ b/src/modules/audio_coding/main/source/audio_coding_module_impl.cc @@ -44,6 +44,11 @@ enum { kACMToneEnd = 999 }; +// Maximum number of bytes in one packet (PCM16B, 20 ms packets, stereo) +enum { + kMaxPacketSize = 2560 +}; + AudioCodingModuleImpl::AudioCodingModuleImpl( const WebRtc_Word32 id): _packetizationCallback(NULL), @@ -62,7 +67,8 @@ AudioCodingModuleImpl::AudioCodingModuleImpl( _stereoSend(false), _prev_received_channel(0), _expected_channels(1), - _currentSendCodecIdx(-1), // invalid value + _currentSendCodecIdx(-1), // invalid value + _current_receive_codec_idx(-1), // invalid value _sendCodecRegistered(false), _acmCritSect(CriticalSectionWrapper::CreateCriticalSection()), _vadCallback(NULL), @@ -1777,10 +1783,14 @@ AudioCodingModuleImpl::ReceiveCodec( // Incoming packet from network parsed and ready for decode WebRtc_Word32 AudioCodingModuleImpl::IncomingPacket( - const WebRtc_Word8* incomingPayload, + const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLength, const WebRtcRTPHeader& rtpInfo) { + WebRtcRTPHeader rtp_header; + + memcpy(&rtp_header, &rtpInfo, sizeof(WebRtcRTPHeader)); + if (payloadLength < 0) { // Log error @@ -1807,7 +1817,7 @@ AudioCodingModuleImpl::IncomingPacket( if(rtpInfo.header.payloadType == _receiveREDPayloadType) { // get the primary payload-type. - myPayloadType = (WebRtc_UWord8)(incomingPayload[0] & 0x7F); + myPayloadType = incomingPayload[0] & 0x7F; } else { @@ -1841,12 +1851,14 @@ AudioCodingModuleImpl::IncomingPacket( } _codecs[i]->UpdateDecoderSampFreq(i); _netEq.SetReceivedStereo(_stereoReceive[i]); + _current_receive_codec_idx = i; // If we have a change in expected number of channels, // flush packet buffers in NetEQ. if ((_stereoReceive[i] && (_expected_channels == 1)) || (!_stereoReceive[i] && (_expected_channels == 2))) { _netEq.FlushBuffers(); + _codecs[i]->ResetDecoder(myPayloadType); } // Store number of channels we expect to receive for the @@ -1868,28 +1880,21 @@ AudioCodingModuleImpl::IncomingPacket( } } - // Check that number of received channels match the setup for the - // received codec. + // Split the payload for stereo packets, so that first half of payload + // vector holds left channel, and second half holds right channel. if (_expected_channels == 2) { - if ((_prev_received_channel == 1) && (rtpInfo.type.Audio.channel == 1)) { - // We expect every second call to this function to be for channel 2, - // since we are in stereo-receive mode. - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, - "IncomingPacket() Error, payload is" - "mono, but codec registered as stereo."); - return -1; - } - _prev_received_channel = rtpInfo.type.Audio.channel; - } else if (rtpInfo.type.Audio.channel == 2) { - // Codec is registered as mono, but we receive a stereo packet. - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id, - "IncomingPacket() Error, payload is" - "stereo, but codec registered as mono."); - return -1; + // Create a new vector for the payload, maximum payload size. + WebRtc_Word32 length = payloadLength; + WebRtc_UWord8 payload[kMaxPacketSize]; + assert(payloadLength <= kMaxPacketSize); + memcpy(payload, incomingPayload, payloadLength); + _codecs[_current_receive_codec_idx]->SplitStereoPacket(payload, &length); + rtp_header.type.Audio.channel = 2; + // Insert packet into NetEQ. + return _netEq.RecIn(payload, length, rtp_header); + } else { + return _netEq.RecIn(incomingPayload, payloadLength, rtp_header); } - - // Insert packet into NetEQ. - return _netEq.RecIn(incomingPayload, payloadLength, rtpInfo); } // Minimum playout delay (Used for lip-sync) @@ -2263,9 +2268,10 @@ AudioCodingModuleImpl::RegisterVADCallback( return 0; } +// TODO(tlegrand): Modify this function to work for stereo, and add tests. WebRtc_Word32 AudioCodingModuleImpl::IncomingPayload( - const WebRtc_Word8* incomingPayload, + const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLength, const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timestamp) diff --git a/src/modules/audio_coding/main/source/audio_coding_module_impl.h b/src/modules/audio_coding/main/source/audio_coding_module_impl.h index 788dd9482..27dc8ed88 100644 --- a/src/modules/audio_coding/main/source/audio_coding_module_impl.h +++ b/src/modules/audio_coding/main/source/audio_coding_module_impl.h @@ -187,14 +187,14 @@ public: // incoming packet from network parsed and ready for decode WebRtc_Word32 IncomingPacket( - const WebRtc_Word8* incomingPayload, + const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLength, const WebRtcRTPHeader& rtpInfo); // Incoming payloads, without rtp-info, the rtp-info will be created in ACM. // One usage for this API is when pre-encoded files are pushed in ACM. WebRtc_Word32 IncomingPayload( - const WebRtc_Word8* incomingPayload, + const WebRtc_UWord8* incomingPayload, const WebRtc_Word32 payloadLength, const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timestamp = 0); @@ -328,6 +328,7 @@ private: int _prev_received_channel; int _expected_channels; WebRtc_Word32 _currentSendCodecIdx; + int _current_receive_codec_idx; bool _sendCodecRegistered; ACMResampler _inputResampler; ACMResampler _outputResampler; diff --git a/src/modules/audio_coding/main/test/Channel.cc b/src/modules/audio_coding/main/test/Channel.cc index 363b10607..4b0f7d009 100644 --- a/src/modules/audio_coding/main/test/Channel.cc +++ b/src/modules/audio_coding/main/test/Channel.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -129,13 +129,8 @@ Channel::SendData( } } - - //status = _receiverACM->IncomingPayload((WebRtc_Word8*)_payloadData, payloadSize, payloadType, timeStamp); - status = _receiverACM->IncomingPacket((WebRtc_Word8*)_payloadData, payloadDataSize, rtpInfo); - - //delete [] payloadData; - - + status = _receiverACM->IncomingPacket(_payloadData, payloadDataSize, + rtpInfo); return status; } diff --git a/src/modules/audio_coding/main/test/EncodeDecodeTest.h b/src/modules/audio_coding/main/test/EncodeDecodeTest.h index a730fea5d..4b4dba8fc 100644 --- a/src/modules/audio_coding/main/test/EncodeDecodeTest.h +++ b/src/modules/audio_coding/main/test/EncodeDecodeTest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -86,7 +86,7 @@ class Receiver { PCMFile _pcmFile; WebRtc_Word16* _playoutBuffer; WebRtc_UWord16 _playoutLengthSmpls; - WebRtc_Word8 _incomingPayload[MAX_INCOMING_PAYLOAD]; + WebRtc_UWord8 _incomingPayload[MAX_INCOMING_PAYLOAD]; WebRtc_UWord16 _payloadSizeBytes; WebRtc_UWord16 _realPayloadSizeBytes; WebRtc_Word32 _frequency; diff --git a/src/modules/audio_coding/main/test/RTPFile.cc b/src/modules/audio_coding/main/test/RTPFile.cc index 29d6a1d53..91ba94695 100644 --- a/src/modules/audio_coding/main/test/RTPFile.cc +++ b/src/modules/audio_coding/main/test/RTPFile.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -106,7 +106,7 @@ RTPBuffer::Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp WebRtc_UWord16 RTPBuffer::Read(WebRtcRTPHeader* rtpInfo, - WebRtc_Word8* payloadData, + WebRtc_UWord8* payloadData, WebRtc_UWord16 payloadSize, WebRtc_UWord32* offset) { @@ -213,7 +213,7 @@ void RTPFile::Write(const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeSt } WebRtc_UWord16 RTPFile::Read(WebRtcRTPHeader* rtpInfo, - WebRtc_Word8* payloadData, + WebRtc_UWord8* payloadData, WebRtc_UWord16 payloadSize, WebRtc_UWord32* offset) { diff --git a/src/modules/audio_coding/main/test/RTPFile.h b/src/modules/audio_coding/main/test/RTPFile.h index e11b16061..b5f52990b 100644 --- a/src/modules/audio_coding/main/test/RTPFile.h +++ b/src/modules/audio_coding/main/test/RTPFile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -32,7 +32,7 @@ public: // Returns the packet's payload size. Zero should be treated as an // end-of-stream (in the case that EndOfFile() is true) or an error. virtual WebRtc_UWord16 Read(WebRtcRTPHeader* rtpInfo, - WebRtc_Word8* payloadData, + WebRtc_UWord8* payloadData, WebRtc_UWord16 payloadSize, WebRtc_UWord32* offset) = 0; virtual bool EndOfFile() const = 0; @@ -68,7 +68,7 @@ public: const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData, const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency); WebRtc_UWord16 Read(WebRtcRTPHeader* rtpInfo, - WebRtc_Word8* payloadData, + WebRtc_UWord8* payloadData, WebRtc_UWord16 payloadSize, WebRtc_UWord32* offset); virtual bool EndOfFile() const; @@ -90,7 +90,7 @@ public: const WebRtc_Word16 seqNo, const WebRtc_UWord8* payloadData, const WebRtc_UWord16 payloadSize, WebRtc_UWord32 frequency); WebRtc_UWord16 Read(WebRtcRTPHeader* rtpInfo, - WebRtc_Word8* payloadData, + WebRtc_UWord8* payloadData, WebRtc_UWord16 payloadSize, WebRtc_UWord32* offset); bool EndOfFile() const { return _rtpEOF; } diff --git a/src/modules/audio_coding/main/test/TestAllCodecs.cc b/src/modules/audio_coding/main/test/TestAllCodecs.cc index 9d7f1e32f..3b79b7810 100644 --- a/src/modules/audio_coding/main/test/TestAllCodecs.cc +++ b/src/modules/audio_coding/main/test/TestAllCodecs.cc @@ -77,7 +77,8 @@ TestPack::SendData( rtpInfo.type.Audio.channel = 1; memcpy(_payloadData, payloadData, payloadDataSize); - status = _receiverACM->IncomingPacket((WebRtc_Word8*)_payloadData, payloadDataSize, rtpInfo); + status = _receiverACM->IncomingPacket(_payloadData, payloadDataSize, + rtpInfo); _payloadSize = payloadDataSize; _timeStampDiff = timeStamp - _lastInTimestamp; diff --git a/src/modules/audio_coding/main/test/TestStereo.cc b/src/modules/audio_coding/main/test/TestStereo.cc index 4b1f107f0..bd07fca28 100644 --- a/src/modules/audio_coding/main/test/TestStereo.cc +++ b/src/modules/audio_coding/main/test/TestStereo.cc @@ -30,8 +30,8 @@ _timeStampDiff(0), _lastInTimestamp(0), _totalBytes(0), _payloadSize(0), -_noChannels(1), -_codecType(0) +_codec_mode(kNotSet), +_lost_packet(false) { } TestPackStereo::~TestPackStereo() @@ -46,101 +46,48 @@ TestPackStereo::RegisterReceiverACM(AudioCodingModule* acm) } -WebRtc_Word32 -TestPackStereo::SendData( - const FrameType frameType, - const WebRtc_UWord8 payloadType, - const WebRtc_UWord32 timeStamp, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadSize, - const RTPFragmentationHeader* fragmentation) -{ - WebRtcRTPHeader rtpInfo; - WebRtc_Word32 status; - WebRtc_UWord16 payloadDataSize = payloadSize; - WebRtc_UWord8 payloadDataMaster[60 * 32 * 2 * 2]; - WebRtc_UWord8 payloadDataSlave[60 * 32 * 2 * 2]; +WebRtc_Word32 TestPackStereo::SendData( + const FrameType frameType, + const WebRtc_UWord8 payloadType, + const WebRtc_UWord32 timeStamp, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadSize, + const RTPFragmentationHeader* fragmentation) { + WebRtcRTPHeader rtpInfo; + WebRtc_Word32 status = 0; - rtpInfo.header.markerBit = false; - rtpInfo.header.ssrc = 0; - rtpInfo.header.sequenceNumber = _seqNo++; - rtpInfo.header.payloadType = payloadType; - rtpInfo.header.timestamp = timeStamp; - if(frameType == kFrameEmpty) - { - // Skip this frame - return 0; - } - if(frameType != kAudioFrameCN) - { - rtpInfo.type.Audio.isCNG = false; + rtpInfo.header.markerBit = false; + rtpInfo.header.ssrc = 0; + rtpInfo.header.sequenceNumber = _seqNo++; + rtpInfo.header.payloadType = payloadType; + rtpInfo.header.timestamp = timeStamp; + if (frameType == kFrameEmpty) { + // Skip this frame + return 0; + } - // For stereo we need to call ACM with two incoming packets, one for each channel. - // Different packet-splitting depending on codec. - if (_codecType == 0) { - // one byte per sample - for (int i=0, j=0; i> 4); - payloadDataSlave[j] = ((payloadData[i] & 0x0F) << 4) + (payloadData[i+1] & 0x0F); - } - } else if (_codecType == 4) { - // True stereo, call both master and slave with whole stream. - memcpy(payloadDataMaster, payloadData, payloadSize); - memcpy(payloadDataSlave, payloadData, payloadSize); - payloadDataSize = payloadSize*2; - } - } - else - { - // If CNG packet, send the same packet to both master and slave. - rtpInfo.type.Audio.isCNG = true; - memcpy(payloadDataMaster, payloadData, payloadSize); - memcpy(payloadDataSlave, payloadData, payloadSize); - payloadDataSize = payloadSize*2; - } - - if (_codecType != 5) { - // Call ACM with two packets, one for each channel - rtpInfo.type.Audio.channel = 1; - status = _receiverACM->IncomingPacket((WebRtc_Word8*)payloadDataMaster, payloadDataSize/2, rtpInfo); - rtpInfo.type.Audio.channel = 2; - status = _receiverACM->IncomingPacket((WebRtc_Word8*)payloadDataSlave, payloadDataSize/2, rtpInfo); + if (_lost_packet == false) { + if (frameType != kAudioFrameCN) { + rtpInfo.type.Audio.isCNG = false; + rtpInfo.type.Audio.channel = (int) _codec_mode; } else { - // Mono case, call ACM with one packet. - rtpInfo.type.Audio.channel = 1; - status = _receiverACM->IncomingPacket((WebRtc_Word8*)payloadData, payloadDataSize, rtpInfo); + rtpInfo.type.Audio.isCNG = true; + rtpInfo.type.Audio.channel = (int) kMono; } + status = _receiverACM->IncomingPacket(payloadData, payloadSize, + rtpInfo); if (frameType != kAudioFrameCN) { - _payloadSize = payloadDataSize; + _payloadSize = payloadSize; } else { - _payloadSize = -1; + _payloadSize = -1; } + _timeStampDiff = timeStamp - _lastInTimestamp; _lastInTimestamp = timeStamp; - _totalBytes += payloadDataSize; - return status; + _totalBytes += payloadSize; + } + return status; } WebRtc_UWord16 @@ -162,10 +109,12 @@ TestPackStereo::ResetPayloadSize() _payloadSize = 0; } -void -TestPackStereo::SetCodecType(int codecType) -{ - _codecType = codecType; +void TestPackStereo::set_codec_mode(enum StereoMonoMode mode) { + _codec_mode = mode; +} + +void TestPackStereo::set_lost_packet(bool lost) { + _lost_packet = lost; } TestStereo::TestStereo(int testMode): @@ -388,16 +337,17 @@ void TestStereo::Perform() audio_channels = 2; codec_channels = 2; - // All codecs are tested for all allowed sampling frequencies, rates and packet sizes + // All codecs are tested for all allowed sampling frequencies, rates and + // packet sizes. #ifdef WEBRTC_CODEC_G722 if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { printf("."); } - _channelA2B->SetCodecType(3); + _channelA2B->set_codec_mode(kStereo); _testCntr++; OpenOutFile(_testCntr); char codecG722[] = "G722"; @@ -428,13 +378,13 @@ void TestStereo::Perform() #endif #ifdef WEBRTC_CODEC_PCM16 if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { printf("."); } - _channelA2B->SetCodecType(1); + _channelA2B->set_codec_mode(kStereo); _testCntr++; OpenOutFile(_testCntr); char codecL16[] = "L16"; @@ -458,7 +408,7 @@ void TestStereo::Perform() _outFileB.Close(); if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { @@ -486,7 +436,7 @@ void TestStereo::Perform() _outFileB.Close(); if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { @@ -510,13 +460,13 @@ void TestStereo::Perform() #define PCMA_AND_PCMU #ifdef PCMA_AND_PCMU if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { printf("."); } - _channelA2B->SetCodecType(0); + _channelA2B->set_codec_mode(kStereo); audio_channels = 2; codec_channels = 2; _testCntr++; @@ -547,7 +497,7 @@ void TestStereo::Perform() _acmA->SetVAD(false, false, VADNormal); _outFileB.Close(); if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { @@ -583,13 +533,13 @@ void TestStereo::Perform() #endif #ifdef WEBRTC_CODEC_CELT if(_testMode != 0) { - printf("=======================================================================\n"); + printf("===========================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-stereo\n"); } else { printf("."); } - _channelA2B->SetCodecType(4); + _channelA2B->set_codec_mode(kStereo); audio_channels = 2; codec_channels = 2; _testCntr++; @@ -624,7 +574,7 @@ void TestStereo::Perform() printf("Test type: Mono-to-stereo\n"); } _testCntr++; - _channelA2B->SetCodecType(3); + _channelA2B->set_codec_mode(kStereo); OpenOutFile(_testCntr); RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels, g722_pltype_); @@ -638,7 +588,7 @@ void TestStereo::Perform() printf("Test type: Mono-to-stereo\n"); } _testCntr++; - _channelA2B->SetCodecType(1); + _channelA2B->set_codec_mode(kStereo); OpenOutFile(_testCntr); RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels, l16_8khz_pltype_); @@ -674,7 +624,7 @@ void TestStereo::Perform() printf("Test type: Mono-to-stereo\n"); } _testCntr++; - _channelA2B->SetCodecType(0); + _channelA2B->set_codec_mode(kStereo); OpenOutFile(_testCntr); RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels, pcmu_pltype_); @@ -691,7 +641,7 @@ void TestStereo::Perform() printf("Test type: Mono-to-stereo\n"); } _testCntr++; - _channelA2B->SetCodecType(4); + _channelA2B->set_codec_mode(kStereo); OpenOutFile(_testCntr); RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels, celt_pltype_); @@ -704,7 +654,7 @@ void TestStereo::Perform() // audio_channels = 2; codec_channels = 1; - _channelA2B->SetCodecType(5); + _channelA2B->set_codec_mode(kMono); // Register receivers as mono. for(WebRtc_UWord8 n = 0; n < numEncoders; n++) { @@ -767,7 +717,7 @@ void TestStereo::Perform() Run(_channelA2B, audio_channels, codec_channels); _outFileB.Close(); if(_testMode != 0) { - printf("===============================================================\n"); + printf("==============================================================\n"); printf("Test number: %d\n",_testCntr + 1); printf("Test type: Stereo-to-mono\n"); } @@ -819,7 +769,8 @@ void TestStereo::Perform() #endif printf(" G.711\n"); - printf("\nTo complete the test, listen to the %d number of output files.\n", _testCntr); + printf("\nTo complete the test, listen to the %d number of output " + "files.\n", _testCntr); } else { printf("Done!\n"); } @@ -845,15 +796,23 @@ WebRtc_Word16 TestStereo::RegisterSendCodec(char side, { if(_testMode != 0) { // Print out codec and settings - printf("Codec: %s Freq: %d Rate: %d PackSize: %d", codecName, samplingFreqHz, rate, packSize); + printf("Codec: %s Freq: %d Rate: %d PackSize: %d", codecName, + samplingFreqHz, rate, packSize); } - // Store packetsize in samples, used to validate the recieved packet + // Store packetsize in samples, used to validate the received packet _packSizeSamp = packSize; - // Store the expected packet size in bytes, used to validate the recieved packet - // Add 0.875 to always round up to a whole byte - _packSizeBytes = (WebRtc_UWord16)((float)(packSize*rate)/(float)(samplingFreqHz*8)+0.875); + // Store the expected packet size in bytes, used to validate the received + // packet. Add 0.875 to always round up to a whole byte. + // For Celt the packet size in bytes is already counting the stereo part. + if (!strcmp(codecName, "CELT")) { + _packSizeBytes = (WebRtc_UWord16)((float)(packSize*rate)/ + (float)(samplingFreqHz*8)+0.875) / channels; + } else { + _packSizeBytes = (WebRtc_UWord16)((float)(packSize*rate)/ + (float)(samplingFreqHz*8)+0.875); + } // Set pointer to the ACM where to register the codec AudioCodingModule* myACM; @@ -881,7 +840,8 @@ WebRtc_Word16 TestStereo::RegisterSendCodec(char side, CodecInst myCodecParam; // Get all codec parameters before registering - CHECK_ERROR(AudioCodingModule::Codec(codecName, myCodecParam, samplingFreqHz)); + CHECK_ERROR(AudioCodingModule::Codec(codecName, myCodecParam, + samplingFreqHz)); myCodecParam.rate = rate; myCodecParam.pacsize = packSize; myCodecParam.pltype = payload_type; @@ -892,8 +852,8 @@ WebRtc_Word16 TestStereo::RegisterSendCodec(char side, return 0; } -void TestStereo::Run(TestPackStereo* channel, int in_channels, int out_channels) -{ +void TestStereo::Run(TestPackStereo* channel, int in_channels, int out_channels, + int percent_loss) { AudioFrame audioFrame; WebRtc_Word32 outFreqHzB = _outFileB.SamplingFrequency(); @@ -905,8 +865,20 @@ void TestStereo::Run(TestPackStereo* channel, int in_channels, int out_channels) // Only run 1 second for each test case // TODO(tlegrand): either remove |_counter| or start using it as the comment // above says. Now |_counter| is always 0. - while(_counter<1000) + while(1) { + // Simulate packet loss by setting |packet_loss_| to "true" in + // |percent_loss| percent of the loops. + if (percent_loss > 0) { + if (_counter == floor((100 / percent_loss) + 0.5)) { + _counter = 0; + channel->set_lost_packet(true); + } else { + channel->set_lost_packet(false); + } + _counter++; + } + // Add 10 msec to ACM if (in_channels == 1) { if (_in_file_mono.EndOfFile()) { @@ -967,6 +939,8 @@ void TestStereo::Run(TestPackStereo* channel, int in_channels, int out_channels) if (_in_file_stereo.EndOfFile()) { _in_file_stereo.Rewind(); } + // Reset in case we ended with a lost packet + channel->set_lost_packet(false); } void TestStereo::OpenOutFile(WebRtc_Word16 testNumber) diff --git a/src/modules/audio_coding/main/test/TestStereo.h b/src/modules/audio_coding/main/test/TestStereo.h index 0172c28f4..44ec198a7 100644 --- a/src/modules/audio_coding/main/test/TestStereo.h +++ b/src/modules/audio_coding/main/test/TestStereo.h @@ -11,12 +11,20 @@ #ifndef TEST_STEREO_H #define TEST_STEREO_H +#include + #include "ACMTest.h" #include "Channel.h" #include "PCMFile.h" namespace webrtc { +enum StereoMonoMode { + kNotSet, + kMono, + kStereo +}; + class TestPackStereo : public AudioPacketizationCallback { public: @@ -35,8 +43,8 @@ public: WebRtc_UWord16 GetPayloadSize(); WebRtc_UWord32 GetTimeStampDiff(); void ResetPayloadSize(); - void SetCodecType(int codecType); - + void set_codec_mode(StereoMonoMode mode); + void set_lost_packet(bool lost); private: AudioCodingModule* _receiverACM; @@ -46,8 +54,9 @@ private: WebRtc_UWord32 _lastInTimestamp; WebRtc_UWord64 _totalBytes; WebRtc_UWord16 _payloadSize; - WebRtc_UWord16 _noChannels; - int _codecType; + StereoMonoMode _codec_mode; + // Simulate packet losses + bool _lost_packet; }; class TestStereo : public ACMTest @@ -69,7 +78,8 @@ private: int channels, int payload_type); - void Run(TestPackStereo* channel, int in_channels, int out_channels); + void Run(TestPackStereo* channel, int in_channels, int out_channels, + int percent_loss = 0); void OpenOutFile(WebRtc_Word16 testNumber); void DisplaySendReceiveCodec(); @@ -95,7 +105,6 @@ private: WebRtc_UWord16 _packSizeSamp; WebRtc_UWord16 _packSizeBytes; int _counter; - int _codecType; // Payload types for stereo codecs and CNG int g722_pltype_; diff --git a/src/modules/audio_coding/main/test/Tester.cc b/src/modules/audio_coding/main/test/Tester.cc index e35a0ecaa..836216416 100644 --- a/src/modules/audio_coding/main/test/Tester.cc +++ b/src/modules/audio_coding/main/test/Tester.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -61,7 +61,7 @@ void PopulateTests(std::vector* tests) tests->push_back(new webrtc::TwoWayCommunication(0)); tests->push_back(new webrtc::TestAllCodecs(0)); tests->push_back(new webrtc::TestStereo(0)); - tests->push_back(new webrtc::SpatialAudio(0)); +// tests->push_back(new webrtc::SpatialAudio(0)); tests->push_back(new webrtc::TestVADDTX(0)); tests->push_back(new webrtc::TestFEC(0)); tests->push_back(new webrtc::ISACTest(0)); @@ -81,7 +81,7 @@ void PopulateTests(std::vector* tests) #ifdef ACM_TEST_STEREO printf(" ACM stereo test\n"); tests->push_back(new webrtc::TestStereo(1)); - tests->push_back(new webrtc::SpatialAudio(2)); + //tests->push_back(new webrtc::SpatialAudio(2)); #endif #ifdef ACM_TEST_VAD_DTX printf(" ACM VAD-DTX test\n"); diff --git a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc index 64bf508f3..dc0939699 100644 --- a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc +++ b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc @@ -586,7 +586,7 @@ decoder_CELT::decoder_CELT(WebRtc_UWord8 pt, WebRtc_UWord16 fs) : NETEQTEST_Decoder(kDecoderCELT_32, fs, "CELT", pt) { - if (WebRtcCelt_CreateDec((CELT_decinst_t **) &_decoder, 1)) + if (WebRtcCelt_CreateDec((CELT_decinst_t **) &_decoder, 2)) exit(EXIT_FAILURE); } @@ -603,6 +603,27 @@ int decoder_CELT::loadToNetEQ(NETEQTEST_NetEQClass & neteq) return(NETEQTEST_Decoder::loadToNetEQ(neteq, codecInst)); } + +decoder_CELTslave::decoder_CELTslave(WebRtc_UWord8 pt, WebRtc_UWord16 fs) +: +NETEQTEST_Decoder(kDecoderCELT_32, fs, "CELT", pt) +{ + if (WebRtcCelt_CreateDec((CELT_decinst_t **) &_decoder, 2)) + exit(EXIT_FAILURE); +} + +decoder_CELTslave::~decoder_CELTslave() +{ + WebRtcCelt_FreeDec((CELT_decinst_t *) _decoder); +} + +int decoder_CELTslave::loadToNetEQ(NETEQTEST_NetEQClass & neteq) +{ + WebRtcNetEQ_CodecDef codecInst; + + SET_CELTSLAVE_FUNCTIONS(codecInst); + return(NETEQTEST_Decoder::loadToNetEQ(neteq, codecInst)); +} #endif #ifdef CODEC_RED diff --git a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h index ff4904929..699079429 100644 --- a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h +++ b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h @@ -272,6 +272,13 @@ public: virtual ~decoder_CELT(); int loadToNetEQ(NETEQTEST_NetEQClass & neteq); }; +class decoder_CELTslave : public NETEQTEST_Decoder +{ +public: + decoder_CELTslave(WebRtc_UWord8 pt = 0, WebRtc_UWord16 fs = 32000); + virtual ~decoder_CELTslave(); + int loadToNetEQ(NETEQTEST_NetEQClass & neteq); +}; class decoder_RED : public NETEQTEST_Decoder { diff --git a/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc b/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc index ed26e9e6e..fdc966248 100644 --- a/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc +++ b/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.cc @@ -598,6 +598,12 @@ int NETEQTEST_RTPpacket::splitStereo(NETEQTEST_RTPpacket* slaveRtp, splitStereoFrame(slaveRtp); break; } + case stereoModeDuplicate: + { + // frame based codec, send the whole packet to both master and slave + splitStereoDouble(slaveRtp); + break; + } case stereoModeMono: { assert(false); @@ -780,6 +786,17 @@ void NETEQTEST_RTPpacket::splitStereoFrame(NETEQTEST_RTPpacket* slaveRtp) _payloadLen /= 2; slaveRtp->_payloadLen = _payloadLen; } +void NETEQTEST_RTPpacket::splitStereoDouble(NETEQTEST_RTPpacket* slaveRtp) +{ + if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr + || _payloadLen <= 0 || slaveRtp->_memSize < _memSize) + { + return; + } + + memcpy(slaveRtp->_payloadPtr, _payloadPtr, _payloadLen); + slaveRtp->_payloadLen = _payloadLen; +} // Get the RTP header for the RED payload indicated by argument index. // The first RED payload is index = 0. diff --git a/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h b/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h index 16beb95dd..a6d32dcca 100644 --- a/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h +++ b/src/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h @@ -20,7 +20,8 @@ enum stereoModes { stereoModeMono, stereoModeSample1, stereoModeSample2, - stereoModeFrame + stereoModeFrame, + stereoModeDuplicate }; class NETEQTEST_RTPpacket @@ -98,6 +99,7 @@ private: int calcPadLength(int i_P) const; void splitStereoSample(NETEQTEST_RTPpacket* slaveRtp, int stride); void splitStereoFrame(NETEQTEST_RTPpacket* slaveRtp); + void splitStereoDouble(NETEQTEST_RTPpacket* slaveRtp); }; #endif //NETEQTEST_RTPPACKET_H diff --git a/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc b/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc index bb2d895aa..cfcbaefce 100644 --- a/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc +++ b/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc @@ -695,9 +695,6 @@ int main(int argc, char* argv[]) printf(" RecIn complexity : %.2f MCPS\n", NetEQvector[0]->getRecInTime() / ((float) 1000*(simClock-start_clock))); printf(" RecOut complexity : %.2f MCPS\n", NetEQvector[0]->getRecOutTime() / ((float) 1000*(simClock-start_clock))); - delete rtp; - delete slaveRtp; - free_coders(decoders); //free_coders(0 /* first channel */); // if (stereoMode > stereoModeMono) { @@ -1196,6 +1193,11 @@ void parsePtypeFile(FILE *ptypeFile, std::map* dec break; } + case kDecoderCELT_32: + { + tempDecoder.stereo = stereoModeDuplicate; + break; + } // fixed-rate frame codecs // case kDecoderG729: // case NETEQ_CODEC_G729D: @@ -1462,7 +1464,10 @@ void createAndInsertDecoders (NETEQTEST_NetEQClass *neteq, std::mapname[RTP_PAYLOAD_NAME_SIZE - 1] = 0; strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); payload->typeSpecific.Audio.frequency = frequency; payload->typeSpecific.Audio.channels = channels; - payload->typeSpecific.Audio.bitsPerSample = bitsPerSample; payload->typeSpecific.Audio.rate = rate; - payload->typeSpecific.Audio.trueStereoCodec = isTrueStereo; payload->audio = true; return payload; } @@ -404,187 +372,8 @@ RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader, payloadLength-1, rtpHeader); } - if(audioSpecific.channels > 1) - { - WebRtc_Word32 retVal = 0; - WebRtc_UWord16 channelLength = payloadLength/audioSpecific.channels; - if(audioSpecific.bitsPerSample > 0) - { - // sanity - assert((payloadLength*8)%audioSpecific.bitsPerSample == 0); - - // sample based codec - - // build matrix - WebRtc_UWord8 matrix[IP_PACKET_SIZE]; - WebRtc_UWord32 offsetBytes = 0; - WebRtc_UWord32 offsetBytesInsert = 0; - // initialize matrix to 0 - memset(matrix, 0, audioSpecific.channels*channelLength); - - switch(audioSpecific.bitsPerSample) - { - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - { - WebRtc_UWord32 offsetSamples = 0; - WebRtc_UWord32 offsetSamplesInsert = 0; - WebRtc_UWord16 bitMask = (WebRtc_UWord16)ModuleRTPUtility::pow2(audioSpecific.bitsPerSample)-1; - WebRtc_UWord16 samplesPerChannel =payloadLength*8/audioSpecific.bitsPerSample/audioSpecific.channels; - - for(WebRtc_UWord32 i = 0; i < samplesPerChannel; i++) - { - WebRtc_UWord8 insertShift = (WebRtc_UWord8)((offsetSamplesInsert+audioSpecific.bitsPerSample)%16); - insertShift = 16 - insertShift; // inverse the calculation - - for(WebRtc_UWord32 j = 0; j < audioSpecific.channels; j++) - { - // get sample - WebRtc_UWord16 s = payloadData[offsetBytes] << 8; - - // check that we don't read outside the memory - if(offsetBytes < (WebRtc_UWord32)payloadLength - 1) - { - s += payloadData[offsetBytes+1]; - } - - WebRtc_UWord8 readShift = (WebRtc_UWord8)((offsetSamples+audioSpecific.bitsPerSample)%16); - readShift = 16 - readShift; // inverse the calculation - s >>= readShift; - s &= bitMask; - - // prepare for reading next sample - offsetSamples += audioSpecific.bitsPerSample; - if(readShift <= audioSpecific.bitsPerSample) - { - // next does not fit - // or fit exactly - offsetSamples -= 8; - offsetBytes++; - } - - // insert sample into matrix - WebRtc_UWord32 columOffset = j*channelLength; - - WebRtc_UWord16 insert = s << insertShift; -#if defined(WEBRTC_LITTLE_ENDIAN) - matrix[columOffset+offsetBytesInsert] |= static_cast(insert>>8); - matrix[columOffset+offsetBytesInsert+1] |= static_cast(insert); -#else - WebRtc_UWord16* matrixU16 = (WebRtc_UWord16*)&(matrix[columOffset+offsetBytesInsert]); - matrixU16[0] |= (s << insertShift); -#endif - } - // prepare for writing next sample - offsetSamplesInsert += audioSpecific.bitsPerSample; - if(insertShift <= audioSpecific.bitsPerSample) - { - // next does not fit - // or fit exactly - offsetSamplesInsert -= 8; - offsetBytesInsert++; - } - } - } - break; - case 8: - { - WebRtc_UWord32 sample = 0; - for(WebRtc_UWord32 i = 0; i < channelLength; i++) - { - for(WebRtc_UWord32 j = 0; j < audioSpecific.channels; j++) - { - WebRtc_UWord32 columOffset = j*channelLength; - matrix[columOffset + i] = payloadData[sample++]; - } - } - } - break; - case 16: - { - WebRtc_UWord32 sample = 0; - for(WebRtc_UWord32 i = 0; i < channelLength; i +=2) - { - for(WebRtc_UWord32 j = 0; j < audioSpecific.channels; j++) - { - WebRtc_UWord32 columOffset = j*channelLength; - matrix[columOffset + i] = payloadData[sample++]; - matrix[columOffset + i + 1] = payloadData[sample++]; - } - } - } - break; - default: - assert(false); - return -1; - } - // we support 16 bits sample - // callback for all channels - for(int channel = 0; channel < audioSpecific.channels && retVal == 0; channel++) - { - // one callback per channel - rtpHeader->type.Audio.channel = channel+1; - - if(channel == 0) - { - // include the original packet only in the first callback - retVal = CallbackOfReceivedPayloadData(&matrix[channel*channelLength], - channelLength, - rtpHeader); - } else - { - retVal = CallbackOfReceivedPayloadData(&matrix[channel*channelLength], - channelLength, - rtpHeader); - } - } - } else if (audioSpecific.trueStereoCodec) - { - // One callback with the whole payload for each channel. - for(int channel = 1; (channel <= audioSpecific.channels) && - (retVal == 0); channel++) - { - // One callback per channel. - rtpHeader->type.Audio.channel = channel; - retVal = CallbackOfReceivedPayloadData(payloadData, - payloadLength, - rtpHeader); - } - } else - { - for(int channel = 1; channel <= audioSpecific.channels && retVal == 0; channel++) - { - // one callback per channel - rtpHeader->type.Audio.channel = channel; - - if(channel == 1) - { - // include the original packet only in the first callback - retVal = CallbackOfReceivedPayloadData(payloadData, - channelLength, - rtpHeader); - } else - { - retVal = CallbackOfReceivedPayloadData(payloadData, - channelLength, - rtpHeader); - } - payloadData += channelLength; - } - } - return retVal; - }else - { - rtpHeader->type.Audio.channel = 1; - return CallbackOfReceivedPayloadData(payloadData, - payloadLength, - rtpHeader); - } + rtpHeader->type.Audio.channel = audioSpecific.channels; + return CallbackOfReceivedPayloadData(payloadData, payloadLength, rtpHeader); } } // namespace webrtc diff --git a/src/modules/rtp_rtcp/source/rtp_utility.h b/src/modules/rtp_rtcp/source/rtp_utility.h index ad88f11f7..20e7af1fb 100644 --- a/src/modules/rtp_rtcp/source/rtp_utility.h +++ b/src/modules/rtp_rtcp/source/rtp_utility.h @@ -40,9 +40,7 @@ namespace ModuleRTPUtility { WebRtc_UWord32 frequency; WebRtc_UWord8 channels; - WebRtc_UWord8 bitsPerSample; WebRtc_UWord32 rate; - bool trueStereoCodec; }; struct VideoPayload { diff --git a/src/modules/utility/source/coder.cc b/src/modules/utility/source/coder.cc index b858da14e..f5401d830 100644 --- a/src/modules/utility/source/coder.cc +++ b/src/modules/utility/source/coder.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -69,7 +69,7 @@ WebRtc_Word32 AudioCoder::Decode(AudioFrame& decodedAudio, { const WebRtc_UWord8 payloadType = _receiveCodec.pltype; _decodeTimestamp += _receiveCodec.pacsize; - if(_acm->IncomingPayload(incomingPayload, + if(_acm->IncomingPayload((const WebRtc_UWord8*) incomingPayload, payloadLength, payloadType, _decodeTimestamp) == -1) diff --git a/src/voice_engine/main/source/channel.cc b/src/voice_engine/main/source/channel.cc index 94b6dd457..f2b6de110 100644 --- a/src/voice_engine/main/source/channel.cc +++ b/src/voice_engine/main/source/channel.cc @@ -805,7 +805,7 @@ Channel::OnReceivedPayloadData(const WebRtc_UWord8* payloadData, } // Push the incoming payload (parsed and ready for decoding) into the ACM - if (_audioCodingModule.IncomingPacket((const WebRtc_Word8*) payloadData, + if (_audioCodingModule.IncomingPacket(payloadData, payloadSize, *rtpHeader) != 0) {