Dual-stream implementation, not including VoE APIs.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3230 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
turaj@webrtc.org
2012-12-03 22:13:31 +00:00
parent 277ec8e3f5
commit 226db898f7
7 changed files with 1305 additions and 235 deletions

View File

@ -29,7 +29,7 @@ enum {
// Interval for sending new CNG parameters (SID frames) is 100 msec.
enum {
kAcmSidIntervalMsec = 100
kCngSidIntervalMsec = 100
};
// We set some of the variables to invalid values as a check point
@ -70,7 +70,6 @@ ACMGenericCodec::ACMGenericCodec()
for (int i = 0; i < MAX_FRAME_SIZE_10MSEC; i++) {
_vadLabel[i] = 0;
}
// Nullify memory for encoder and decoder, and set payload type to an
// invalid value.
memset(&_encoderParams, 0, sizeof(WebRtcACMCodecParams));
@ -143,7 +142,7 @@ int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp,
_lastTimestamp = timestamp;
// If the data exceeds the buffer size, we through away the oldest data and
// If the data exceeds the buffer size, we throw away the oldest data and
// add the newly received 10 msec at the end.
if ((_inAudioIxWrite + lengthSmpl * audioChannel) > AUDIO_BUFFER_SIZE_W16) {
// Get the number of samples to be overwritten.
@ -191,29 +190,27 @@ int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp,
return 0;
}
bool ACMGenericCodec::HasFrameToEncode() const {
ReadLockScoped lockCodec(_codecWrapperLock);
if (_inAudioIxWrite < _frameLenSmpl * _noChannels)
return false;
return true;
}
int16_t ACMGenericCodec::Encode(uint8_t* bitStream,
int16_t* bitStreamLenByte,
uint32_t* timeStamp,
WebRtcACMEncodingType* encodingType) {
WriteLockScoped lockCodec(_codecWrapperLock);
ReadLockScoped lockNetEq(*_netEqDecodeLock);
return EncodeSafe(bitStream, bitStreamLenByte, timeStamp, encodingType);
}
int16_t ACMGenericCodec::EncodeSafe(uint8_t* bitStream,
int16_t* bitStreamLenByte,
uint32_t* timeStamp,
WebRtcACMEncodingType* encodingType) {
// Only encode if we have enough data to encode. If not wait until we have a
// full frame to encode.
if (_inAudioIxWrite < _frameLenSmpl * _noChannels) {
// There is not enough audio.
if (!HasFrameToEncode()) {
// There is not enough audio
*timeStamp = 0;
*bitStreamLenByte = 0;
// Doesn't really matter what this parameter set to.
// Doesn't really matter what this parameter set to
*encodingType = kNoEncoding;
return 0;
}
WriteLockScoped lockCodec(_codecWrapperLock);
ReadLockScoped lockNetEq(*_netEqDecodeLock);
// Not all codecs accept the whole frame to be pushed into encoder at once.
// Some codecs needs to be feed with a specific number of samples different
@ -230,7 +227,6 @@ int16_t ACMGenericCodec::EncodeSafe(uint8_t* bitStream,
"EncodeSafe: error, basic coding sample block is negative");
return -1;
}
// This makes the internal encoder read from the beginning of the buffer.
_inAudioIxRead = 0;
*timeStamp = _inTimestamp[0];
@ -932,7 +928,7 @@ int16_t ACMGenericCodec::EnableDTX() {
}
uint16_t freqHz;
EncoderSampFreq(freqHz);
if (WebRtcCng_InitEnc(_ptrDTXInst, freqHz, kAcmSidIntervalMsec,
if (WebRtcCng_InitEnc(_ptrDTXInst, freqHz, kCngSidIntervalMsec,
_numLPCParams) < 0) {
// Couldn't initialize, has to return -1, and free the memory.
WebRtcCng_FreeEnc(_ptrDTXInst);

View File

@ -711,20 +711,20 @@ class ACMGenericCodec {
///////////////////////////////////////////////////////////////////////////
// REDPayloadISAC()
// This is an iSAC-specific function. The function is called to get RED
// paylaod from a default-encoder.
// payload from a default-encoder.
//
// Inputs:
// -isacRate : the target rate of the main payload. A RED
// paylaod is generated according to the rate of
// main paylaod. Note that we are not specifying the
// payload is generated according to the rate of
// main payload. Note that we are not specifying the
// rate of RED payload, but the main payload.
// -isacBwEstimate : bandwidth information should be inserted in
// RED payload.
//
// Output:
// -payload : pointer to a buffer where the RED paylaod will
// -payload : pointer to a buffer where the RED payload will
// written to.
// -paylaodLenBytes : a place-holder to write the length of the RED
// -payloadLenBytes : a place-holder to write the length of the RED
// payload in Bytes.
//
// Return value:
@ -749,6 +749,13 @@ class ACMGenericCodec {
return false;
}
///////////////////////////////////////////////////////////////////////////
// HasFrameToEncode()
// Returns true if there is enough audio buffered for encoding, such that
// calling Encode() will return a payload.
//
bool HasFrameToEncode() const;
protected:
///////////////////////////////////////////////////////////////////////////
// All the functions with FunctionNameSafe(...) contain the actual
@ -758,15 +765,6 @@ class ACMGenericCodec {
// and return value we refer to FunctionName()
//
///////////////////////////////////////////////////////////////////////////
// See Encode() for the description of function, input(s)/output(s) and
// return value.
//
WebRtc_Word16 EncodeSafe(WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte,
WebRtc_UWord32* timeStamp,
WebRtcACMEncodingType* encodingType);
///////////////////////////////////////////////////////////////////////////
// See Decode() for the description of function, input(s)/output(s) and
// return value.

View File

@ -119,6 +119,10 @@
'<(webrtc_root)/test/test.gyp:test_support_main',
'<(DEPTH)/testing/gtest.gyp:gtest',
'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
'<(webrtc_root)/modules/modules.gyp:webrtc_utility',
],
'include_dirs': [
'<(webrtc_root)/common_audio/resampler/include',
],
'defines': [
'<@(audio_coding_defines)',
@ -127,6 +131,7 @@
'../test/ACMTest.cc',
'../test/APITest.cc',
'../test/Channel.cc',
'../test/dual_stream_unittest.cc',
'../test/EncodeDecodeTest.cc',
'../test/iSACTest.cc',
'../test/PCMFile.cc',

View File

@ -16,6 +16,7 @@
#include "acm_resampler.h"
#include "common_types.h"
#include "engine_configurations.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
namespace webrtc {
@ -59,6 +60,17 @@ class AudioCodingModuleImpl : public AudioCodingModule {
// Can be called multiple times for Codec, CNG, RED.
WebRtc_Word32 RegisterSendCodec(const CodecInst& send_codec);
// Register Secondary codec for dual-streaming. Dual-streaming is activated
// right after the secondary codec is registered.
int RegisterSecondarySendCodec(const CodecInst& send_codec);
// Unregister the secondary codec. Dual-streaming is deactivated right after
// deregistering secondary codec.
void UnregisterSecondarySendCodec();
// Get the secondary codec.
int SecondarySendCodec(CodecInst* secondary_codec) const;
// Get current send codec.
WebRtc_Word32 SendCodec(CodecInst& current_codec) const;
@ -248,6 +260,35 @@ class AudioCodingModuleImpl : public AudioCodingModule {
WebRtc_Word16 mirror_id,
ACMNetEQ::JB jitter_buffer);
// Set VAD/DTX status. This function does not acquire a lock, and it is
// created to be called only from inside a critical section.
int SetVADSafe(bool enable_dtx, bool enable_vad, ACMVADMode mode);
// Process buffered audio when dual-streaming is not enabled (When RED is
// enabled still this function is used.)
int ProcessSingleStream();
// Process buffered audio when dual-streaming is enabled, i.e. secondary send
// codec is registered.
int ProcessDualStream();
// Preprocessing of input audio, including resampling and down-mixing if
// required, before pushing audio into encoder'r buffer.
//
// in_frame: input audio-frame
// out_frame: output audio_frame, the output is valid only if a preprocessing
// is required.
//
// Return value:
// -1: if encountering an error.
// kPreprocessingSuccessful: if a preprocessing successfully performed.
// kNoPreprocessingRequired: if there was no need for preprocessing. In
// this case |out_frame| is not updated and
// |in_frame| has to be used for further
// operations.
int PreprocessToAddData(const AudioFrame& in_frame,
const AudioFrame** ptr_out);
private:
// Change required states after starting to receive the codec corresponding
// to |index|.
@ -261,15 +302,12 @@ class AudioCodingModuleImpl : public AudioCodingModule {
// is a stereo codec, RED or CN.
bool IsCodecForSlave(int index) const;
// Returns true if the |codec| is RED.
bool IsCodecRED(const CodecInst* codec) const;
// ...or if its |index| is RED.
bool IsCodecRED(int index) const;
int EncodeFragmentation(int fragmentation_index, int payload_type,
uint32_t current_timestamp,
ACMGenericCodec* _secondary_encoder,
uint8_t* stream);
// Returns true if the |codec| is CN.
bool IsCodecCN(int index) const;
// ...or if its |index| is CN.
bool IsCodecCN(const CodecInst* codec) const;
void ResetFragmentation(int vector_size);
AudioPacketizationCallback* _packetizationCallback;
WebRtc_Word32 _id;
@ -305,8 +343,15 @@ class AudioCodingModuleImpl : public AudioCodingModule {
// RED/FEC.
bool _isFirstRED;
bool _fecEnabled;
// TODO(turajs): |_redBuffer| is allocated in constructor, why having them
// as pointers and not an array. If concerned about the memory, then make a
// set-up function to allocate them only when they are going to be used, i.e.
// FEC or Dual-streaming is enabled.
WebRtc_UWord8* _redBuffer;
RTPFragmentationHeader* _fragmentation;
// TODO(turajs): we actually don't need |_fragmentation| as a member variable.
// It is sufficient to keep the length & payload type of previous payload in
// member variables.
RTPFragmentationHeader _fragmentation;
WebRtc_UWord32 _lastFECTimestamp;
// If no RED is registered as receive codec this
// will have an invalid value.
@ -334,7 +379,9 @@ class AudioCodingModuleImpl : public AudioCodingModule {
CriticalSectionWrapper* _callbackCritSect;
AudioFrame _audioFrame;
AudioFrame _preprocess_frame;
CodecInst _secondarySendCodecInst;
scoped_ptr<ACMGenericCodec> _secondaryEncoder;
#ifdef ACM_QA_TEST
FILE* _outgoingPL;
FILE* _incomingPL;