Ray, please verify that this cl fixes the issue. Once the verification has been made, please review:
Henrik A: VoE Andrew: audio_conference_mixer Thanks! Review URL: http://webrtc-codereview.appspot.com/241010 git-svn-id: http://webrtc.googlecode.com/svn/trunk@841 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
731ecba47d
commit
066f9e5a2f
@ -73,6 +73,16 @@ public:
|
||||
virtual WebRtc_Word32 AmountOfMixables(
|
||||
WebRtc_UWord32& amountOfMixableParticipants) = 0;
|
||||
|
||||
// Inform the mixer that the participant should always be mixed and not
|
||||
// count toward the number of mixed participants. Note that a participant
|
||||
// must have been added to the mixer (by calling SetMixabilityStatus())
|
||||
// before this function can be successfully called.
|
||||
virtual WebRtc_Word32 SetAnonymousMixabilityStatus(
|
||||
MixerParticipant& participant, const bool mixable) = 0;
|
||||
// mixable is set to true if the participant is mixed anonymously.
|
||||
virtual WebRtc_Word32 AnonymousMixabilityStatus(
|
||||
MixerParticipant& participant, bool& mixable) = 0;
|
||||
|
||||
// Set the minimum sampling frequency at which to mix. The mixing algorithm
|
||||
// may still choose to mix at a higher samling frequency to avoid
|
||||
// downsampling of audio contributing to the mixed audio.
|
||||
|
@ -89,6 +89,7 @@ AudioConferenceMixerImpl::AudioConferenceMixerImpl(const WebRtc_Word32 id)
|
||||
_outputFrequency(kDefaultFrequency),
|
||||
_sampleSize((_outputFrequency*kProcessPeriodicityInMs)/1000),
|
||||
_participantList(),
|
||||
_additionalParticipantList(),
|
||||
_amountOfMixableParticipants(0),
|
||||
_timeStamp(0),
|
||||
_timeScheduler(kProcessPeriodicityInMs),
|
||||
@ -200,6 +201,7 @@ WebRtc_Word32 AudioConferenceMixerImpl::Process()
|
||||
|
||||
ListWrapper mixList;
|
||||
ListWrapper rampOutList;
|
||||
ListWrapper additionalFramesList;
|
||||
MapWrapper mixedParticipantsMap;
|
||||
{
|
||||
CriticalSectionScoped cs(*_cbCrit);
|
||||
@ -253,6 +255,7 @@ WebRtc_Word32 AudioConferenceMixerImpl::Process()
|
||||
UpdateToMix(mixList, rampOutList, mixedParticipantsMap,
|
||||
remainingParticipantsAllowedToMix);
|
||||
|
||||
GetAdditionalAudio(additionalFramesList);
|
||||
UpdateMixedStatus(mixedParticipantsMap);
|
||||
_scratchParticipantsToMixAmount = mixedParticipantsMap.Size();
|
||||
}
|
||||
@ -297,6 +300,7 @@ WebRtc_Word32 AudioConferenceMixerImpl::Process()
|
||||
_timeStamp += _sampleSize;
|
||||
|
||||
MixFromList(*mixedAudio,mixList);
|
||||
MixAnonomouslyFromList(*mixedAudio, additionalFramesList);
|
||||
|
||||
MixAnonomouslyFromList(*mixedAudio, rampOutList);
|
||||
if(mixedAudio->_payloadDataLengthInSamples == 0)
|
||||
@ -353,6 +357,7 @@ WebRtc_Word32 AudioConferenceMixerImpl::Process()
|
||||
_audioFramePool->PushMemory(mixedAudio);
|
||||
ClearAudioFrameList(mixList);
|
||||
ClearAudioFrameList(rampOutList);
|
||||
ClearAudioFrameList(additionalFramesList);
|
||||
{
|
||||
CriticalSectionScoped cs(*_crit);
|
||||
_processCalls--;
|
||||
@ -530,6 +535,60 @@ WebRtc_Word32 AudioConferenceMixerImpl::AmountOfMixables(
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 AudioConferenceMixerImpl::SetAnonymousMixabilityStatus(
|
||||
MixerParticipant& participant, const bool anonymous)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceModuleCall, kTraceAudioMixerServer, _id,
|
||||
"SetAnonymousMixabilityStatus(participant,anonymous:%s)",
|
||||
anonymous ? "true" : "false");
|
||||
CriticalSectionScoped cs(*_cbCrit);
|
||||
if(IsParticipantInList(participant, _additionalParticipantList))
|
||||
{
|
||||
if(anonymous)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(!RemoveParticipantFromList(participant, _additionalParticipantList))
|
||||
{
|
||||
WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id,
|
||||
"unable to remove participant from anonymous list");
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
return AddParticipantToList(participant, _participantList) ? 0 : -1;
|
||||
}
|
||||
if(!anonymous)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const bool mixable = RemoveParticipantFromList(participant,
|
||||
_participantList);
|
||||
if(!mixable)
|
||||
{
|
||||
WEBRTC_TRACE(
|
||||
kTraceWarning,
|
||||
kTraceAudioMixerServer,
|
||||
_id,
|
||||
"participant must be registered before turning it into anonymous");
|
||||
// Setting anonymous status is only possible if MixerParticipant is
|
||||
// already registered.
|
||||
return -1;
|
||||
}
|
||||
return AddParticipantToList(participant, _additionalParticipantList) ?
|
||||
0 : -1;
|
||||
}
|
||||
|
||||
WebRtc_Word32 AudioConferenceMixerImpl::AnonymousMixabilityStatus(
|
||||
MixerParticipant& participant, bool& mixable)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceModuleCall, kTraceAudioMixerServer, _id,
|
||||
"AnonymousMixabilityStatus(participant,mixable)");
|
||||
CriticalSectionScoped cs(*_cbCrit);
|
||||
mixable = IsParticipantInList(participant,
|
||||
_additionalParticipantList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 AudioConferenceMixerImpl::SetMinimumMixingFrequency(
|
||||
Frequency freq)
|
||||
{
|
||||
@ -593,7 +652,7 @@ void AudioConferenceMixerImpl::UpdateToMix(
|
||||
WebRtc_UWord32& maxAudioFrameCounter)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id,
|
||||
"GetVIPAudio(mixList,rampOutList,mixParticipantList,%d)",
|
||||
"UpdateToMix(mixList,rampOutList,mixParticipantList,%d)",
|
||||
maxAudioFrameCounter);
|
||||
const WebRtc_UWord32 mixListStartSize = mixList.GetSize();
|
||||
ListWrapper activeList; // Elements are AudioFrames
|
||||
@ -800,6 +859,49 @@ void AudioConferenceMixerImpl::UpdateToMix(
|
||||
maxAudioFrameCounter += mixListStartSize - mixList.GetSize();
|
||||
}
|
||||
|
||||
void AudioConferenceMixerImpl::GetAdditionalAudio(
|
||||
ListWrapper& additionalFramesList)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id,
|
||||
"GetAdditionalAudio(additionalFramesList)");
|
||||
ListItem* item = _additionalParticipantList.First();
|
||||
while(item)
|
||||
{
|
||||
// The GetAudioFrame() callback may remove the current item. Store the
|
||||
// next item just in case that happens.
|
||||
ListItem* nextItem = _additionalParticipantList.Next(item);
|
||||
|
||||
MixerParticipant* participant = static_cast<MixerParticipant*>(
|
||||
item->GetItem());
|
||||
AudioFrame* audioFrame = NULL;
|
||||
if(_audioFramePool->PopMemory(audioFrame) == -1)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id,
|
||||
"failed PopMemory() call");
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
audioFrame->_frequencyInHz = _outputFrequency;
|
||||
if(participant->GetAudioFrame(_id, *audioFrame) != 0)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id,
|
||||
"failed to GetAudioFrame() from participant");
|
||||
_audioFramePool->PushMemory(audioFrame);
|
||||
item = nextItem;
|
||||
continue;
|
||||
}
|
||||
if(audioFrame->_payloadDataLengthInSamples == 0)
|
||||
{
|
||||
// Empty frame. Don't use it.
|
||||
_audioFramePool->PushMemory(audioFrame);
|
||||
item = nextItem;
|
||||
continue;
|
||||
}
|
||||
additionalFramesList.PushBack(static_cast<void*>(audioFrame));
|
||||
item = nextItem;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioConferenceMixerImpl::UpdateMixedStatus(
|
||||
MapWrapper& mixedParticipantsMap)
|
||||
{
|
||||
@ -807,7 +909,7 @@ void AudioConferenceMixerImpl::UpdateMixedStatus(
|
||||
"UpdateMixedStatus(mixedParticipantsMap)");
|
||||
assert(mixedParticipantsMap.Size() <= kMaximumAmountOfMixedParticipants);
|
||||
|
||||
// Loop through all non-VIP participants. If they are in the mix map they
|
||||
// Loop through all participants. If they are in the mix map they
|
||||
// were mixed.
|
||||
ListItem* participantItem = _participantList.First();
|
||||
while(participantItem != NULL)
|
||||
|
@ -78,6 +78,10 @@ public:
|
||||
virtual WebRtc_Word32 SetMinimumMixingFrequency(Frequency freq);
|
||||
virtual WebRtc_Word32 AmountOfMixables(
|
||||
WebRtc_UWord32& amountOfMixableParticipants);
|
||||
virtual WebRtc_Word32 SetAnonymousMixabilityStatus(
|
||||
MixerParticipant& participant, const bool mixable);
|
||||
virtual WebRtc_Word32 AnonymousMixabilityStatus(
|
||||
MixerParticipant& participant, bool& mixable);
|
||||
private:
|
||||
enum{DEFAULT_AUDIO_FRAME_POOLSIZE = 50};
|
||||
|
||||
@ -101,6 +105,9 @@ private:
|
||||
// downsample any audio.
|
||||
WebRtc_Word32 GetLowestMixingFrequency();
|
||||
|
||||
// Return the AudioFrames that should be mixed anonymously.
|
||||
void GetAdditionalAudio(ListWrapper& additionalFramesList);
|
||||
|
||||
// Update the MixHistory of all MixerParticipants. mixedParticipantsList
|
||||
// should contain a map of MixerParticipants that have been mixed.
|
||||
void UpdateMixedStatus(MapWrapper& mixedParticipantsList);
|
||||
@ -172,6 +179,7 @@ private:
|
||||
|
||||
// List of all participants. Note all lists are disjunct
|
||||
ListWrapper _participantList; // May be mixed.
|
||||
ListWrapper _additionalParticipantList; // Always mixed, anonomously.
|
||||
|
||||
WebRtc_UWord32 _amountOfMixableParticipants;
|
||||
|
||||
|
@ -3501,6 +3501,16 @@ int Channel::StartPlayingFileLocally(const char* fileName,
|
||||
_outputFilePlayerPtr = NULL;
|
||||
return -1;
|
||||
}
|
||||
if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StartPlayingFile() failed to add participant as file to mixer");
|
||||
_outputFilePlayerPtr->StopPlayingFile();
|
||||
FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
|
||||
_outputFilePlayerPtr = NULL;
|
||||
return -1;
|
||||
}
|
||||
_outputFilePlayerPtr->RegisterModuleFileCallback(this);
|
||||
_outputFilePlaying = true;
|
||||
|
||||
@ -3573,6 +3583,16 @@ int Channel::StartPlayingFileLocally(InStream* stream,
|
||||
_outputFilePlayerPtr = NULL;
|
||||
return -1;
|
||||
}
|
||||
if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StartPlayingFile() failed to add participant as file to mixer");
|
||||
_outputFilePlayerPtr->StopPlayingFile();
|
||||
FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
|
||||
_outputFilePlayerPtr = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_outputFilePlayerPtr->RegisterModuleFileCallback(this);
|
||||
_outputFilePlaying = true;
|
||||
@ -3602,6 +3622,14 @@ int Channel::StopPlayingFileLocally()
|
||||
"StopPlayingFile() could not stop playing");
|
||||
return -1;
|
||||
}
|
||||
if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0)
|
||||
{
|
||||
_engineStatisticsPtr->SetLastError(
|
||||
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
|
||||
"StopPlayingFile() failed to stop participant from playing as file"
|
||||
"in the mixer");
|
||||
return -1;
|
||||
}
|
||||
_outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
|
||||
FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
|
||||
_outputFilePlayerPtr = NULL;
|
||||
|
@ -272,6 +272,13 @@ OutputMixer::SetMixabilityStatus(MixerParticipant& participant,
|
||||
return _mixerModule.SetMixabilityStatus(participant, mixable);
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
OutputMixer::SetAnonymousMixabilityStatus(MixerParticipant& participant,
|
||||
const bool mixable)
|
||||
{
|
||||
return _mixerModule.SetAnonymousMixabilityStatus(participant,mixable);
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
OutputMixer::MixActiveChannels()
|
||||
{
|
||||
|
@ -69,6 +69,9 @@ public:
|
||||
WebRtc_Word32 SetMixabilityStatus(MixerParticipant& participant,
|
||||
const bool mixable);
|
||||
|
||||
WebRtc_Word32 SetAnonymousMixabilityStatus(MixerParticipant& participant,
|
||||
const bool mixable);
|
||||
|
||||
WebRtc_Word32 GetMixedAudio(const WebRtc_Word32 desiredFreqHz,
|
||||
const WebRtc_UWord8 channels,
|
||||
AudioFrame& audioFrame);
|
||||
|
Loading…
x
Reference in New Issue
Block a user