| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 } // namespace | 63 } // namespace |
| 64 | 64 |
| 65 MixerParticipant::MixerParticipant() | 65 MixerParticipant::MixerParticipant() |
| 66 : _mixHistory(new MixHistory()) { | 66 : _mixHistory(new MixHistory()) { |
| 67 } | 67 } |
| 68 | 68 |
| 69 MixerParticipant::~MixerParticipant() { | 69 MixerParticipant::~MixerParticipant() { |
| 70 delete _mixHistory; | 70 delete _mixHistory; |
| 71 } | 71 } |
| 72 | 72 |
| 73 int32_t MixerParticipant::IsMixed(bool& mixed) const { | 73 bool MixerParticipant::IsMixed() const { |
| 74 return _mixHistory->IsMixed(mixed); | 74 return _mixHistory->IsMixed(); |
| 75 } | 75 } |
| 76 | 76 |
| 77 MixHistory::MixHistory() | 77 MixHistory::MixHistory() |
| 78 : _isMixed(0) { | 78 : _isMixed(0) { |
| 79 } | 79 } |
| 80 | 80 |
| 81 MixHistory::~MixHistory() { | 81 MixHistory::~MixHistory() { |
| 82 } | 82 } |
| 83 | 83 |
| 84 int32_t MixHistory::IsMixed(bool& mixed) const { | 84 bool MixHistory::IsMixed() const { |
| 85 mixed = _isMixed; | 85 return _isMixed; |
| 86 return 0; | |
| 87 } | 86 } |
| 88 | 87 |
| 89 int32_t MixHistory::WasMixed(bool& wasMixed) const { | 88 bool MixHistory::WasMixed() const { |
| 90 // Was mixed is the same as is mixed depending on perspective. This function | 89 // Was mixed is the same as is mixed depending on perspective. This function |
| 91 // is for the perspective of AudioConferenceMixerImpl. | 90 // is for the perspective of AudioConferenceMixerImpl. |
| 92 return IsMixed(wasMixed); | 91 return IsMixed(); |
| 93 } | 92 } |
| 94 | 93 |
| 95 int32_t MixHistory::SetIsMixed(const bool mixed) { | 94 int32_t MixHistory::SetIsMixed(const bool mixed) { |
| 96 _isMixed = mixed; | 95 _isMixed = mixed; |
| 97 return 0; | 96 return 0; |
| 98 } | 97 } |
| 99 | 98 |
| 100 void MixHistory::ResetMixedStatus() { | 99 void MixHistory::ResetMixedStatus() { |
| 101 _isMixed = false; | 100 _isMixed = false; |
| 102 } | 101 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 default: | 248 default: |
| 250 assert(false); | 249 assert(false); |
| 251 | 250 |
| 252 CriticalSectionScoped cs(_crit.get()); | 251 CriticalSectionScoped cs(_crit.get()); |
| 253 _processCalls--; | 252 _processCalls--; |
| 254 return -1; | 253 return -1; |
| 255 } | 254 } |
| 256 } | 255 } |
| 257 | 256 |
| 258 UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap, | 257 UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap, |
| 259 remainingParticipantsAllowedToMix); | 258 &remainingParticipantsAllowedToMix); |
| 260 | 259 |
| 261 GetAdditionalAudio(&additionalFramesList); | 260 GetAdditionalAudio(&additionalFramesList); |
| 262 UpdateMixedStatus(mixedParticipantsMap); | 261 UpdateMixedStatus(mixedParticipantsMap); |
| 263 } | 262 } |
| 264 | 263 |
| 265 // Get an AudioFrame for mixing from the memory pool. | 264 // Get an AudioFrame for mixing from the memory pool. |
| 266 AudioFrame* mixedAudio = NULL; | 265 AudioFrame* mixedAudio = NULL; |
| 267 if(_audioFramePool->PopMemory(mixedAudio) == -1) { | 266 if(_audioFramePool->PopMemory(mixedAudio) == -1) { |
| 268 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, | 267 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, |
| 269 "failed PopMemory() call"); | 268 "failed PopMemory() call"); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 287 AudioFrame::kNormalSpeech, | 286 AudioFrame::kNormalSpeech, |
| 288 AudioFrame::kVadPassive, num_mixed_channels); | 287 AudioFrame::kVadPassive, num_mixed_channels); |
| 289 | 288 |
| 290 _timeStamp += static_cast<uint32_t>(_sampleSize); | 289 _timeStamp += static_cast<uint32_t>(_sampleSize); |
| 291 | 290 |
| 292 // We only use the limiter if it supports the output sample rate and | 291 // We only use the limiter if it supports the output sample rate and |
| 293 // we're actually mixing multiple streams. | 292 // we're actually mixing multiple streams. |
| 294 use_limiter_ = _numMixedParticipants > 1 && | 293 use_limiter_ = _numMixedParticipants > 1 && |
| 295 _outputFrequency <= kAudioProcMaxNativeSampleRateHz; | 294 _outputFrequency <= kAudioProcMaxNativeSampleRateHz; |
| 296 | 295 |
| 297 MixFromList(*mixedAudio, &mixList); | 296 MixFromList(mixedAudio, mixList); |
| 298 MixAnonomouslyFromList(*mixedAudio, &additionalFramesList); | 297 MixAnonomouslyFromList(mixedAudio, additionalFramesList); |
| 299 MixAnonomouslyFromList(*mixedAudio, &rampOutList); | 298 MixAnonomouslyFromList(mixedAudio, rampOutList); |
| 300 | 299 |
| 301 if(mixedAudio->samples_per_channel_ == 0) { | 300 if(mixedAudio->samples_per_channel_ == 0) { |
| 302 // Nothing was mixed, set the audio samples to silence. | 301 // Nothing was mixed, set the audio samples to silence. |
| 303 mixedAudio->samples_per_channel_ = _sampleSize; | 302 mixedAudio->samples_per_channel_ = _sampleSize; |
| 304 mixedAudio->Mute(); | 303 mixedAudio->Mute(); |
| 305 } else { | 304 } else { |
| 306 // Only call the limiter if we have something to mix. | 305 // Only call the limiter if we have something to mix. |
| 307 if(!LimitMixedAudio(*mixedAudio)) | 306 if(!LimitMixedAudio(mixedAudio)) |
| 308 retval = -1; | 307 retval = -1; |
| 309 } | 308 } |
| 310 } | 309 } |
| 311 | 310 |
| 312 { | 311 { |
| 313 CriticalSectionScoped cs(_cbCrit.get()); | 312 CriticalSectionScoped cs(_cbCrit.get()); |
| 314 if(_mixReceiver != NULL) { | 313 if(_mixReceiver != NULL) { |
| 315 const AudioFrame** dummy = NULL; | 314 const AudioFrame** dummy = NULL; |
| 316 _mixReceiver->NewMixedAudio( | 315 _mixReceiver->NewMixedAudio( |
| 317 _id, | 316 _id, |
| 318 *mixedAudio, | 317 *mixedAudio, |
| 319 dummy, | 318 dummy, |
| 320 0); | 319 0); |
| 321 } | 320 } |
| 322 } | 321 } |
| 323 | 322 |
| 324 // Reclaim all outstanding memory. | 323 // Reclaim all outstanding memory. |
| 325 _audioFramePool->PushMemory(mixedAudio); | 324 _audioFramePool->PushMemory(mixedAudio); |
| 326 ClearAudioFrameList(&mixList); | 325 ClearAudioFrameList(&mixList); |
| 327 ClearAudioFrameList(&rampOutList); | 326 ClearAudioFrameList(&rampOutList); |
| 328 ClearAudioFrameList(&additionalFramesList); | 327 ClearAudioFrameList(&additionalFramesList); |
| 329 { | 328 { |
| 330 CriticalSectionScoped cs(_crit.get()); | 329 CriticalSectionScoped cs(_crit.get()); |
| 331 _processCalls--; | 330 _processCalls--; |
| 332 } | 331 } |
| 333 return retval; | 332 return retval; |
| 334 } | 333 } |
| 335 | 334 |
| 336 int32_t AudioConferenceMixerImpl::RegisterMixedStreamCallback( | 335 int32_t AudioConferenceMixerImpl::RegisterMixedStreamCallback( |
| 337 AudioMixerOutputReceiver& mixReceiver) { | 336 AudioMixerOutputReceiver* mixReceiver) { |
| 338 CriticalSectionScoped cs(_cbCrit.get()); | 337 CriticalSectionScoped cs(_cbCrit.get()); |
| 339 if(_mixReceiver != NULL) { | 338 if(_mixReceiver != NULL) { |
| 340 return -1; | 339 return -1; |
| 341 } | 340 } |
| 342 _mixReceiver = &mixReceiver; | 341 _mixReceiver = mixReceiver; |
| 343 return 0; | 342 return 0; |
| 344 } | 343 } |
| 345 | 344 |
| 346 int32_t AudioConferenceMixerImpl::UnRegisterMixedStreamCallback() { | 345 int32_t AudioConferenceMixerImpl::UnRegisterMixedStreamCallback() { |
| 347 CriticalSectionScoped cs(_cbCrit.get()); | 346 CriticalSectionScoped cs(_cbCrit.get()); |
| 348 if(_mixReceiver == NULL) { | 347 if(_mixReceiver == NULL) { |
| 349 return -1; | 348 return -1; |
| 350 } | 349 } |
| 351 _mixReceiver = NULL; | 350 _mixReceiver = NULL; |
| 352 return 0; | 351 return 0; |
| 353 } | 352 } |
| 354 | 353 |
| 355 int32_t AudioConferenceMixerImpl::SetOutputFrequency( | 354 int32_t AudioConferenceMixerImpl::SetOutputFrequency( |
| 356 const Frequency frequency) { | 355 const Frequency& frequency) { |
| 357 CriticalSectionScoped cs(_crit.get()); | 356 CriticalSectionScoped cs(_crit.get()); |
| 358 | 357 |
| 359 _outputFrequency = frequency; | 358 _outputFrequency = frequency; |
| 360 _sampleSize = | 359 _sampleSize = |
| 361 static_cast<size_t>((_outputFrequency*kProcessPeriodicityInMs) / 1000); | 360 static_cast<size_t>((_outputFrequency*kProcessPeriodicityInMs) / 1000); |
| 362 | 361 |
| 363 return 0; | 362 return 0; |
| 364 } | 363 } |
| 365 | 364 |
| 366 AudioConferenceMixer::Frequency | 365 AudioConferenceMixer::Frequency |
| 367 AudioConferenceMixerImpl::OutputFrequency() const { | 366 AudioConferenceMixerImpl::OutputFrequency() const { |
| 368 CriticalSectionScoped cs(_crit.get()); | 367 CriticalSectionScoped cs(_crit.get()); |
| 369 return _outputFrequency; | 368 return _outputFrequency; |
| 370 } | 369 } |
| 371 | 370 |
| 372 int32_t AudioConferenceMixerImpl::SetMixabilityStatus( | 371 int32_t AudioConferenceMixerImpl::SetMixabilityStatus( |
| 373 MixerParticipant& participant, | 372 MixerParticipant* participant, bool mixable) { |
| 374 bool mixable) { | |
| 375 if (!mixable) { | 373 if (!mixable) { |
| 376 // Anonymous participants are in a separate list. Make sure that the | 374 // Anonymous participants are in a separate list. Make sure that the |
| 377 // participant is in the _participantList if it is being mixed. | 375 // participant is in the _participantList if it is being mixed. |
| 378 SetAnonymousMixabilityStatus(participant, false); | 376 SetAnonymousMixabilityStatus(participant, false); |
| 379 } | 377 } |
| 380 size_t numMixedParticipants; | 378 size_t numMixedParticipants; |
| 381 { | 379 { |
| 382 CriticalSectionScoped cs(_cbCrit.get()); | 380 CriticalSectionScoped cs(_cbCrit.get()); |
| 383 const bool isMixed = | 381 const bool isMixed = |
| 384 IsParticipantInList(participant, &_participantList); | 382 IsParticipantInList(*participant, _participantList); |
| 385 // API must be called with a new state. | 383 // API must be called with a new state. |
| 386 if(!(mixable ^ isMixed)) { | 384 if(!(mixable ^ isMixed)) { |
| 387 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 385 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, |
| 388 "Mixable is aready %s", | 386 "Mixable is aready %s", |
| 389 isMixed ? "ON" : "off"); | 387 isMixed ? "ON" : "off"); |
| 390 return -1; | 388 return -1; |
| 391 } | 389 } |
| 392 bool success = false; | 390 bool success = false; |
| 393 if(mixable) { | 391 if(mixable) { |
| 394 success = AddParticipantToList(participant, &_participantList); | 392 success = AddParticipantToList(participant, &_participantList); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 411 numMixedNonAnonymous + _additionalParticipantList.size(); | 409 numMixedNonAnonymous + _additionalParticipantList.size(); |
| 412 } | 410 } |
| 413 // A MixerParticipant was added or removed. Make sure the scratch | 411 // A MixerParticipant was added or removed. Make sure the scratch |
| 414 // buffer is updated if necessary. | 412 // buffer is updated if necessary. |
| 415 // Note: The scratch buffer may only be updated in Process(). | 413 // Note: The scratch buffer may only be updated in Process(). |
| 416 CriticalSectionScoped cs(_crit.get()); | 414 CriticalSectionScoped cs(_crit.get()); |
| 417 _numMixedParticipants = numMixedParticipants; | 415 _numMixedParticipants = numMixedParticipants; |
| 418 return 0; | 416 return 0; |
| 419 } | 417 } |
| 420 | 418 |
| 421 int32_t AudioConferenceMixerImpl::MixabilityStatus( | 419 bool AudioConferenceMixerImpl::MixabilityStatus( |
| 422 MixerParticipant& participant, | 420 const MixerParticipant& participant) const { |
| 423 bool& mixable) { | |
| 424 CriticalSectionScoped cs(_cbCrit.get()); | 421 CriticalSectionScoped cs(_cbCrit.get()); |
| 425 mixable = IsParticipantInList(participant, &_participantList); | 422 return IsParticipantInList(participant, _participantList); |
| 426 return 0; | |
| 427 } | 423 } |
| 428 | 424 |
| 429 int32_t AudioConferenceMixerImpl::SetAnonymousMixabilityStatus( | 425 int32_t AudioConferenceMixerImpl::SetAnonymousMixabilityStatus( |
| 430 MixerParticipant& participant, const bool anonymous) { | 426 MixerParticipant* participant, bool anonymous) { |
| 431 CriticalSectionScoped cs(_cbCrit.get()); | 427 CriticalSectionScoped cs(_cbCrit.get()); |
| 432 if(IsParticipantInList(participant, &_additionalParticipantList)) { | 428 if(IsParticipantInList(*participant, _additionalParticipantList)) { |
| 433 if(anonymous) { | 429 if(anonymous) { |
| 434 return 0; | 430 return 0; |
| 435 } | 431 } |
| 436 if(!RemoveParticipantFromList(participant, | 432 if(!RemoveParticipantFromList(participant, |
| 437 &_additionalParticipantList)) { | 433 &_additionalParticipantList)) { |
| 438 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 434 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, |
| 439 "unable to remove participant from anonymous list"); | 435 "unable to remove participant from anonymous list"); |
| 440 assert(false); | 436 assert(false); |
| 441 return -1; | 437 return -1; |
| 442 } | 438 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 454 _id, | 450 _id, |
| 455 "participant must be registered before turning it into anonymous"); | 451 "participant must be registered before turning it into anonymous"); |
| 456 // Setting anonymous status is only possible if MixerParticipant is | 452 // Setting anonymous status is only possible if MixerParticipant is |
| 457 // already registered. | 453 // already registered. |
| 458 return -1; | 454 return -1; |
| 459 } | 455 } |
| 460 return AddParticipantToList(participant, &_additionalParticipantList) ? | 456 return AddParticipantToList(participant, &_additionalParticipantList) ? |
| 461 0 : -1; | 457 0 : -1; |
| 462 } | 458 } |
| 463 | 459 |
| 464 int32_t AudioConferenceMixerImpl::AnonymousMixabilityStatus( | 460 bool AudioConferenceMixerImpl::AnonymousMixabilityStatus( |
| 465 MixerParticipant& participant, bool& mixable) { | 461 const MixerParticipant& participant) const { |
| 466 CriticalSectionScoped cs(_cbCrit.get()); | 462 CriticalSectionScoped cs(_cbCrit.get()); |
| 467 mixable = IsParticipantInList(participant, | 463 return IsParticipantInList(participant, _additionalParticipantList); |
| 468 &_additionalParticipantList); | |
| 469 return 0; | |
| 470 } | 464 } |
| 471 | 465 |
| 472 int32_t AudioConferenceMixerImpl::SetMinimumMixingFrequency( | 466 int32_t AudioConferenceMixerImpl::SetMinimumMixingFrequency( |
| 473 Frequency freq) { | 467 Frequency freq) { |
| 474 // Make sure that only allowed sampling frequencies are used. Use closest | 468 // Make sure that only allowed sampling frequencies are used. Use closest |
| 475 // higher sampling frequency to avoid losing information. | 469 // higher sampling frequency to avoid losing information. |
| 476 if (static_cast<int>(freq) == 12000) { | 470 if (static_cast<int>(freq) == 12000) { |
| 477 freq = kWbInHz; | 471 freq = kWbInHz; |
| 478 } else if (static_cast<int>(freq) == 24000) { | 472 } else if (static_cast<int>(freq) == 24000) { |
| 479 freq = kSwbInHz; | 473 freq = kSwbInHz; |
| 480 } | 474 } |
| 481 | 475 |
| 482 if((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) || | 476 if((freq == kNbInHz) || (freq == kWbInHz) || (freq == kSwbInHz) || |
| 483 (freq == kLowestPossible)) { | 477 (freq == kLowestPossible)) { |
| 484 _minimumMixingFreq=freq; | 478 _minimumMixingFreq=freq; |
| 485 return 0; | 479 return 0; |
| 486 } else { | 480 } else { |
| 487 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 481 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, |
| 488 "SetMinimumMixingFrequency incorrect frequency: %i",freq); | 482 "SetMinimumMixingFrequency incorrect frequency: %i",freq); |
| 489 assert(false); | 483 assert(false); |
| 490 return -1; | 484 return -1; |
| 491 } | 485 } |
| 492 } | 486 } |
| 493 | 487 |
| 494 // Check all AudioFrames that are to be mixed. The highest sampling frequency | 488 // Check all AudioFrames that are to be mixed. The highest sampling frequency |
| 495 // found is the lowest that can be used without losing information. | 489 // found is the lowest that can be used without losing information. |
| 496 int32_t AudioConferenceMixerImpl::GetLowestMixingFrequency() { | 490 int32_t AudioConferenceMixerImpl::GetLowestMixingFrequency() const { |
| 497 const int participantListFrequency = | 491 const int participantListFrequency = |
| 498 GetLowestMixingFrequencyFromList(&_participantList); | 492 GetLowestMixingFrequencyFromList(_participantList); |
| 499 const int anonymousListFrequency = | 493 const int anonymousListFrequency = |
| 500 GetLowestMixingFrequencyFromList(&_additionalParticipantList); | 494 GetLowestMixingFrequencyFromList(_additionalParticipantList); |
| 501 const int highestFreq = | 495 const int highestFreq = |
| 502 (participantListFrequency > anonymousListFrequency) ? | 496 (participantListFrequency > anonymousListFrequency) ? |
| 503 participantListFrequency : anonymousListFrequency; | 497 participantListFrequency : anonymousListFrequency; |
| 504 // Check if the user specified a lowest mixing frequency. | 498 // Check if the user specified a lowest mixing frequency. |
| 505 if(_minimumMixingFreq != kLowestPossible) { | 499 if(_minimumMixingFreq != kLowestPossible) { |
| 506 if(_minimumMixingFreq > highestFreq) { | 500 if(_minimumMixingFreq > highestFreq) { |
| 507 return _minimumMixingFreq; | 501 return _minimumMixingFreq; |
| 508 } | 502 } |
| 509 } | 503 } |
| 510 return highestFreq; | 504 return highestFreq; |
| 511 } | 505 } |
| 512 | 506 |
| 513 int32_t AudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( | 507 int32_t AudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( |
| 514 MixerParticipantList* mixList) { | 508 const MixerParticipantList& mixList) const { |
| 515 int32_t highestFreq = 8000; | 509 int32_t highestFreq = 8000; |
| 516 for (MixerParticipantList::iterator iter = mixList->begin(); | 510 for (MixerParticipantList::const_iterator iter = mixList.begin(); |
| 517 iter != mixList->end(); | 511 iter != mixList.end(); |
| 518 ++iter) { | 512 ++iter) { |
| 519 const int32_t neededFrequency = (*iter)->NeededFrequency(_id); | 513 const int32_t neededFrequency = (*iter)->NeededFrequency(_id); |
| 520 if(neededFrequency > highestFreq) { | 514 if(neededFrequency > highestFreq) { |
| 521 highestFreq = neededFrequency; | 515 highestFreq = neededFrequency; |
| 522 } | 516 } |
| 523 } | 517 } |
| 524 return highestFreq; | 518 return highestFreq; |
| 525 } | 519 } |
| 526 | 520 |
| 527 void AudioConferenceMixerImpl::UpdateToMix( | 521 void AudioConferenceMixerImpl::UpdateToMix( |
| 528 AudioFrameList* mixList, | 522 AudioFrameList* mixList, |
| 529 AudioFrameList* rampOutList, | 523 AudioFrameList* rampOutList, |
| 530 std::map<int, MixerParticipant*>* mixParticipantList, | 524 std::map<int, MixerParticipant*>* mixParticipantList, |
| 531 size_t& maxAudioFrameCounter) { | 525 size_t* maxAudioFrameCounter) const { |
| 532 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 526 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 533 "UpdateToMix(mixList,rampOutList,mixParticipantList,%d)", | 527 "UpdateToMix(mixList,rampOutList,mixParticipantList,%d)", |
| 534 maxAudioFrameCounter); | 528 *maxAudioFrameCounter); |
| 535 const size_t mixListStartSize = mixList->size(); | 529 const size_t mixListStartSize = mixList->size(); |
| 536 AudioFrameList activeList; | 530 AudioFrameList activeList; |
| 537 // Struct needed by the passive lists to keep track of which AudioFrame | 531 // Struct needed by the passive lists to keep track of which AudioFrame |
| 538 // belongs to which MixerParticipant. | 532 // belongs to which MixerParticipant. |
| 539 ParticipantFramePairList passiveWasNotMixedList; | 533 ParticipantFramePairList passiveWasNotMixedList; |
| 540 ParticipantFramePairList passiveWasMixedList; | 534 ParticipantFramePairList passiveWasMixedList; |
| 541 for (MixerParticipantList::iterator participant = _participantList.begin(); | 535 for (MixerParticipantList::const_iterator participant = |
| 542 participant != _participantList.end(); | 536 _participantList.begin(); participant != _participantList.end(); |
| 543 ++participant) { | 537 ++participant) { |
| 544 // Stop keeping track of passive participants if there are already | 538 // Stop keeping track of passive participants if there are already |
| 545 // enough participants available (they wont be mixed anyway). | 539 // enough participants available (they wont be mixed anyway). |
| 546 bool mustAddToPassiveList = (maxAudioFrameCounter > | 540 bool mustAddToPassiveList = (*maxAudioFrameCounter > |
| 547 (activeList.size() + | 541 (activeList.size() + |
| 548 passiveWasMixedList.size() + | 542 passiveWasMixedList.size() + |
| 549 passiveWasNotMixedList.size())); | 543 passiveWasNotMixedList.size())); |
| 550 | 544 |
| 551 bool wasMixed = false; | 545 bool wasMixed = false; |
| 552 (*participant)->_mixHistory->WasMixed(wasMixed); | 546 wasMixed = (*participant)->_mixHistory->WasMixed(); |
| 553 AudioFrame* audioFrame = NULL; | 547 AudioFrame* audioFrame = NULL; |
| 554 if(_audioFramePool->PopMemory(audioFrame) == -1) { | 548 if(_audioFramePool->PopMemory(audioFrame) == -1) { |
| 555 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, | 549 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, |
| 556 "failed PopMemory() call"); | 550 "failed PopMemory() call"); |
| 557 assert(false); | 551 assert(false); |
| 558 return; | 552 return; |
| 559 } | 553 } |
| 560 audioFrame->sample_rate_hz_ = _outputFrequency; | 554 audioFrame->sample_rate_hz_ = _outputFrequency; |
| 561 | 555 |
| 562 if((*participant)->GetAudioFrame(_id,*audioFrame) != 0) { | 556 if((*participant)->GetAudioFrame(_id, audioFrame) != 0) { |
| 563 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 557 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, |
| 564 "failed to GetAudioFrame() from participant"); | 558 "failed to GetAudioFrame() from participant"); |
| 565 _audioFramePool->PushMemory(audioFrame); | 559 _audioFramePool->PushMemory(audioFrame); |
| 566 continue; | 560 continue; |
| 567 } | 561 } |
| 568 if (_participantList.size() != 1) { | 562 if (_participantList.size() != 1) { |
| 569 // TODO(wu): Issue 3390, add support for multiple participants case. | 563 // TODO(wu): Issue 3390, add support for multiple participants case. |
| 570 audioFrame->ntp_time_ms_ = -1; | 564 audioFrame->ntp_time_ms_ = -1; |
| 571 } | 565 } |
| 572 | 566 |
| 573 // TODO(henrike): this assert triggers in some test cases where SRTP is | 567 // TODO(henrike): this assert triggers in some test cases where SRTP is |
| 574 // used which prevents NetEQ from making a VAD. Temporarily disable this | 568 // used which prevents NetEQ from making a VAD. Temporarily disable this |
| 575 // assert until the problem is fixed on a higher level. | 569 // assert until the problem is fixed on a higher level. |
| 576 // assert(audioFrame->vad_activity_ != AudioFrame::kVadUnknown); | 570 // assert(audioFrame->vad_activity_ != AudioFrame::kVadUnknown); |
| 577 if (audioFrame->vad_activity_ == AudioFrame::kVadUnknown) { | 571 if (audioFrame->vad_activity_ == AudioFrame::kVadUnknown) { |
| 578 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 572 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, |
| 579 "invalid VAD state from participant"); | 573 "invalid VAD state from participant"); |
| 580 } | 574 } |
| 581 | 575 |
| 582 if(audioFrame->vad_activity_ == AudioFrame::kVadActive) { | 576 if(audioFrame->vad_activity_ == AudioFrame::kVadActive) { |
| 583 if(!wasMixed) { | 577 if(!wasMixed) { |
| 584 RampIn(*audioFrame); | 578 RampIn(*audioFrame); |
| 585 } | 579 } |
| 586 | 580 |
| 587 if(activeList.size() >= maxAudioFrameCounter) { | 581 if(activeList.size() >= *maxAudioFrameCounter) { |
| 588 // There are already more active participants than should be | 582 // There are already more active participants than should be |
| 589 // mixed. Only keep the ones with the highest energy. | 583 // mixed. Only keep the ones with the highest energy. |
| 590 AudioFrameList::iterator replaceItem; | 584 AudioFrameList::iterator replaceItem; |
| 591 CalculateEnergy(*audioFrame); | 585 CalculateEnergy(*audioFrame); |
| 592 uint32_t lowestEnergy = audioFrame->energy_; | 586 uint32_t lowestEnergy = audioFrame->energy_; |
| 593 | 587 |
| 594 bool found_replace_item = false; | 588 bool found_replace_item = false; |
| 595 for (AudioFrameList::iterator iter = activeList.begin(); | 589 for (AudioFrameList::iterator iter = activeList.begin(); |
| 596 iter != activeList.end(); | 590 iter != activeList.end(); |
| 597 ++iter) { | 591 ++iter) { |
| 598 CalculateEnergy(**iter); | 592 CalculateEnergy(**iter); |
| 599 if((*iter)->energy_ < lowestEnergy) { | 593 if((*iter)->energy_ < lowestEnergy) { |
| 600 replaceItem = iter; | 594 replaceItem = iter; |
| 601 lowestEnergy = (*iter)->energy_; | 595 lowestEnergy = (*iter)->energy_; |
| 602 found_replace_item = true; | 596 found_replace_item = true; |
| 603 } | 597 } |
| 604 } | 598 } |
| 605 if(found_replace_item) { | 599 if(found_replace_item) { |
| 606 AudioFrame* replaceFrame = *replaceItem; | 600 AudioFrame* replaceFrame = *replaceItem; |
| 607 | 601 |
| 608 bool replaceWasMixed = false; | 602 bool replaceWasMixed = false; |
| 609 std::map<int, MixerParticipant*>::iterator it = | 603 std::map<int, MixerParticipant*>::const_iterator it = |
| 610 mixParticipantList->find(replaceFrame->id_); | 604 mixParticipantList->find(replaceFrame->id_); |
| 611 | 605 |
| 612 // When a frame is pushed to |activeList| it is also pushed | 606 // When a frame is pushed to |activeList| it is also pushed |
| 613 // to mixParticipantList with the frame's id. This means | 607 // to mixParticipantList with the frame's id. This means |
| 614 // that the Find call above should never fail. | 608 // that the Find call above should never fail. |
| 615 assert(it != mixParticipantList->end()); | 609 assert(it != mixParticipantList->end()); |
| 616 it->second->_mixHistory->WasMixed(replaceWasMixed); | 610 replaceWasMixed = it->second->_mixHistory->WasMixed(); |
| 617 | 611 |
| 618 mixParticipantList->erase(replaceFrame->id_); | 612 mixParticipantList->erase(replaceFrame->id_); |
| 619 activeList.erase(replaceItem); | 613 activeList.erase(replaceItem); |
| 620 | 614 |
| 621 activeList.push_front(audioFrame); | 615 activeList.push_front(audioFrame); |
| 622 (*mixParticipantList)[audioFrame->id_] = *participant; | 616 (*mixParticipantList)[audioFrame->id_] = *participant; |
| 623 assert(mixParticipantList->size() <= | 617 assert(mixParticipantList->size() <= |
| 624 kMaximumAmountOfMixedParticipants); | 618 kMaximumAmountOfMixedParticipants); |
| 625 | 619 |
| 626 if (replaceWasMixed) { | 620 if (replaceWasMixed) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 657 RampIn(*audioFrame); | 651 RampIn(*audioFrame); |
| 658 ParticipantFramePair* pair = new ParticipantFramePair; | 652 ParticipantFramePair* pair = new ParticipantFramePair; |
| 659 pair->audioFrame = audioFrame; | 653 pair->audioFrame = audioFrame; |
| 660 pair->participant = *participant; | 654 pair->participant = *participant; |
| 661 passiveWasNotMixedList.push_back(pair); | 655 passiveWasNotMixedList.push_back(pair); |
| 662 } else { | 656 } else { |
| 663 _audioFramePool->PushMemory(audioFrame); | 657 _audioFramePool->PushMemory(audioFrame); |
| 664 } | 658 } |
| 665 } | 659 } |
| 666 } | 660 } |
| 667 assert(activeList.size() <= maxAudioFrameCounter); | 661 assert(activeList.size() <= *maxAudioFrameCounter); |
| 668 // At this point it is known which participants should be mixed. Transfer | 662 // At this point it is known which participants should be mixed. Transfer |
| 669 // this information to this functions output parameters. | 663 // this information to this functions output parameters. |
| 670 for (AudioFrameList::iterator iter = activeList.begin(); | 664 for (AudioFrameList::const_iterator iter = activeList.begin(); |
| 671 iter != activeList.end(); | 665 iter != activeList.end(); |
| 672 ++iter) { | 666 ++iter) { |
| 673 mixList->push_back(*iter); | 667 mixList->push_back(*iter); |
| 674 } | 668 } |
| 675 activeList.clear(); | 669 activeList.clear(); |
| 676 // Always mix a constant number of AudioFrames. If there aren't enough | 670 // Always mix a constant number of AudioFrames. If there aren't enough |
| 677 // active participants mix passive ones. Starting with those that was mixed | 671 // active participants mix passive ones. Starting with those that was mixed |
| 678 // last iteration. | 672 // last iteration. |
| 679 for (ParticipantFramePairList::iterator iter = passiveWasMixedList.begin(); | 673 for (ParticipantFramePairList::const_iterator |
| 680 iter != passiveWasMixedList.end(); | 674 iter = passiveWasMixedList.begin(); iter != passiveWasMixedList.end(); |
| 681 ++iter) { | 675 ++iter) { |
| 682 if(mixList->size() < maxAudioFrameCounter + mixListStartSize) { | 676 if(mixList->size() < *maxAudioFrameCounter + mixListStartSize) { |
| 683 mixList->push_back((*iter)->audioFrame); | 677 mixList->push_back((*iter)->audioFrame); |
| 684 (*mixParticipantList)[(*iter)->audioFrame->id_] = | 678 (*mixParticipantList)[(*iter)->audioFrame->id_] = |
| 685 (*iter)->participant; | 679 (*iter)->participant; |
| 686 assert(mixParticipantList->size() <= | 680 assert(mixParticipantList->size() <= |
| 687 kMaximumAmountOfMixedParticipants); | 681 kMaximumAmountOfMixedParticipants); |
| 688 } else { | 682 } else { |
| 689 _audioFramePool->PushMemory((*iter)->audioFrame); | 683 _audioFramePool->PushMemory((*iter)->audioFrame); |
| 690 } | 684 } |
| 691 delete *iter; | 685 delete *iter; |
| 692 } | 686 } |
| 693 // And finally the ones that have not been mixed for a while. | 687 // And finally the ones that have not been mixed for a while. |
| 694 for (ParticipantFramePairList::iterator iter = | 688 for (ParticipantFramePairList::const_iterator iter = |
| 695 passiveWasNotMixedList.begin(); | 689 passiveWasNotMixedList.begin(); |
| 696 iter != passiveWasNotMixedList.end(); | 690 iter != passiveWasNotMixedList.end(); |
| 697 ++iter) { | 691 ++iter) { |
| 698 if(mixList->size() < maxAudioFrameCounter + mixListStartSize) { | 692 if(mixList->size() < *maxAudioFrameCounter + mixListStartSize) { |
| 699 mixList->push_back((*iter)->audioFrame); | 693 mixList->push_back((*iter)->audioFrame); |
| 700 (*mixParticipantList)[(*iter)->audioFrame->id_] = | 694 (*mixParticipantList)[(*iter)->audioFrame->id_] = |
| 701 (*iter)->participant; | 695 (*iter)->participant; |
| 702 assert(mixParticipantList->size() <= | 696 assert(mixParticipantList->size() <= |
| 703 kMaximumAmountOfMixedParticipants); | 697 kMaximumAmountOfMixedParticipants); |
| 704 } else { | 698 } else { |
| 705 _audioFramePool->PushMemory((*iter)->audioFrame); | 699 _audioFramePool->PushMemory((*iter)->audioFrame); |
| 706 } | 700 } |
| 707 delete *iter; | 701 delete *iter; |
| 708 } | 702 } |
| 709 assert(maxAudioFrameCounter + mixListStartSize >= mixList->size()); | 703 assert(*maxAudioFrameCounter + mixListStartSize >= mixList->size()); |
| 710 maxAudioFrameCounter += mixListStartSize - mixList->size(); | 704 *maxAudioFrameCounter += mixListStartSize - mixList->size(); |
| 711 } | 705 } |
| 712 | 706 |
| 713 void AudioConferenceMixerImpl::GetAdditionalAudio( | 707 void AudioConferenceMixerImpl::GetAdditionalAudio( |
| 714 AudioFrameList* additionalFramesList) { | 708 AudioFrameList* additionalFramesList) const { |
| 715 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 709 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 716 "GetAdditionalAudio(additionalFramesList)"); | 710 "GetAdditionalAudio(additionalFramesList)"); |
| 717 // The GetAudioFrame() callback may result in the participant being removed | 711 // The GetAudioFrame() callback may result in the participant being removed |
| 718 // from additionalParticipantList_. If that happens it will invalidate any | 712 // from additionalParticipantList_. If that happens it will invalidate any |
| 719 // iterators. Create a copy of the participants list such that the list of | 713 // iterators. Create a copy of the participants list such that the list of |
| 720 // participants can be traversed safely. | 714 // participants can be traversed safely. |
| 721 MixerParticipantList additionalParticipantList; | 715 MixerParticipantList additionalParticipantList; |
| 722 additionalParticipantList.insert(additionalParticipantList.begin(), | 716 additionalParticipantList.insert(additionalParticipantList.begin(), |
| 723 _additionalParticipantList.begin(), | 717 _additionalParticipantList.begin(), |
| 724 _additionalParticipantList.end()); | 718 _additionalParticipantList.end()); |
| 725 | 719 |
| 726 for (MixerParticipantList::iterator participant = | 720 for (MixerParticipantList::const_iterator participant = |
| 727 additionalParticipantList.begin(); | 721 additionalParticipantList.begin(); |
| 728 participant != additionalParticipantList.end(); | 722 participant != additionalParticipantList.end(); |
| 729 ++participant) { | 723 ++participant) { |
| 730 AudioFrame* audioFrame = NULL; | 724 AudioFrame* audioFrame = NULL; |
| 731 if(_audioFramePool->PopMemory(audioFrame) == -1) { | 725 if(_audioFramePool->PopMemory(audioFrame) == -1) { |
| 732 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, | 726 WEBRTC_TRACE(kTraceMemory, kTraceAudioMixerServer, _id, |
| 733 "failed PopMemory() call"); | 727 "failed PopMemory() call"); |
| 734 assert(false); | 728 assert(false); |
| 735 return; | 729 return; |
| 736 } | 730 } |
| 737 audioFrame->sample_rate_hz_ = _outputFrequency; | 731 audioFrame->sample_rate_hz_ = _outputFrequency; |
| 738 if((*participant)->GetAudioFrame(_id, *audioFrame) != 0) { | 732 if((*participant)->GetAudioFrame(_id, audioFrame) != 0) { |
| 739 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 733 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, |
| 740 "failed to GetAudioFrame() from participant"); | 734 "failed to GetAudioFrame() from participant"); |
| 741 _audioFramePool->PushMemory(audioFrame); | 735 _audioFramePool->PushMemory(audioFrame); |
| 742 continue; | 736 continue; |
| 743 } | 737 } |
| 744 if(audioFrame->samples_per_channel_ == 0) { | 738 if(audioFrame->samples_per_channel_ == 0) { |
| 745 // Empty frame. Don't use it. | 739 // Empty frame. Don't use it. |
| 746 _audioFramePool->PushMemory(audioFrame); | 740 _audioFramePool->PushMemory(audioFrame); |
| 747 continue; | 741 continue; |
| 748 } | 742 } |
| 749 additionalFramesList->push_back(audioFrame); | 743 additionalFramesList->push_back(audioFrame); |
| 750 } | 744 } |
| 751 } | 745 } |
| 752 | 746 |
| 753 void AudioConferenceMixerImpl::UpdateMixedStatus( | 747 void AudioConferenceMixerImpl::UpdateMixedStatus( |
| 754 std::map<int, MixerParticipant*>& mixedParticipantsMap) { | 748 const std::map<int, MixerParticipant*>& mixedParticipantsMap) const { |
| 755 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 749 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 756 "UpdateMixedStatus(mixedParticipantsMap)"); | 750 "UpdateMixedStatus(mixedParticipantsMap)"); |
| 757 assert(mixedParticipantsMap.size() <= kMaximumAmountOfMixedParticipants); | 751 assert(mixedParticipantsMap.size() <= kMaximumAmountOfMixedParticipants); |
| 758 | 752 |
| 759 // Loop through all participants. If they are in the mix map they | 753 // Loop through all participants. If they are in the mix map they |
| 760 // were mixed. | 754 // were mixed. |
| 761 for (MixerParticipantList::iterator participant = _participantList.begin(); | 755 for (MixerParticipantList::const_iterator |
| 762 participant != _participantList.end(); | 756 participant =_participantList.begin(); |
| 757 participant != _participantList.end(); |
| 763 ++participant) { | 758 ++participant) { |
| 764 bool isMixed = false; | 759 bool isMixed = false; |
| 765 for (std::map<int, MixerParticipant*>::iterator it = | 760 for (std::map<int, MixerParticipant*>::const_iterator it = |
| 766 mixedParticipantsMap.begin(); | 761 mixedParticipantsMap.begin(); |
| 767 it != mixedParticipantsMap.end(); | 762 it != mixedParticipantsMap.end(); |
| 768 ++it) { | 763 ++it) { |
| 769 if (it->second == *participant) { | 764 if (it->second == *participant) { |
| 770 isMixed = true; | 765 isMixed = true; |
| 771 break; | 766 break; |
| 772 } | 767 } |
| 773 } | 768 } |
| 774 (*participant)->_mixHistory->SetIsMixed(isMixed); | 769 (*participant)->_mixHistory->SetIsMixed(isMixed); |
| 775 } | 770 } |
| 776 } | 771 } |
| 777 | 772 |
| 778 void AudioConferenceMixerImpl::ClearAudioFrameList( | 773 void AudioConferenceMixerImpl::ClearAudioFrameList( |
| 779 AudioFrameList* audioFrameList) { | 774 AudioFrameList* audioFrameList) const { |
| 780 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 775 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 781 "ClearAudioFrameList(audioFrameList)"); | 776 "ClearAudioFrameList(audioFrameList)"); |
| 782 for (AudioFrameList::iterator iter = audioFrameList->begin(); | 777 for (AudioFrameList::iterator iter = audioFrameList->begin(); |
| 783 iter != audioFrameList->end(); | 778 iter != audioFrameList->end(); |
| 784 ++iter) { | 779 ++iter) { |
| 785 _audioFramePool->PushMemory(*iter); | 780 _audioFramePool->PushMemory(*iter); |
| 786 } | 781 } |
| 787 audioFrameList->clear(); | 782 audioFrameList->clear(); |
| 788 } | 783 } |
| 789 | 784 |
| 790 void AudioConferenceMixerImpl::UpdateVADPositiveParticipants( | 785 void AudioConferenceMixerImpl::UpdateVADPositiveParticipants( |
| 791 AudioFrameList* mixList) { | 786 AudioFrameList* mixList) const { |
| 792 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 787 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 793 "UpdateVADPositiveParticipants(mixList)"); | 788 "UpdateVADPositiveParticipants(mixList)"); |
| 794 | 789 |
| 795 for (AudioFrameList::iterator iter = mixList->begin(); | 790 for (AudioFrameList::const_iterator iter = mixList->begin(); |
| 796 iter != mixList->end(); | 791 iter != mixList->end(); |
| 797 ++iter) { | 792 ++iter) { |
| 798 CalculateEnergy(**iter); | 793 CalculateEnergy(**iter); |
| 799 } | 794 } |
| 800 } | 795 } |
| 801 | 796 |
| 802 bool AudioConferenceMixerImpl::IsParticipantInList( | 797 bool AudioConferenceMixerImpl::IsParticipantInList( |
| 803 MixerParticipant& participant, | 798 const MixerParticipant& participant, |
| 804 MixerParticipantList* participantList) const { | 799 const MixerParticipantList& participantList) const { |
| 805 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 800 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 806 "IsParticipantInList(participant,participantList)"); | 801 "IsParticipantInList(participant,participantList)"); |
| 807 for (MixerParticipantList::const_iterator iter = participantList->begin(); | 802 for (MixerParticipantList::const_iterator iter = participantList.begin(); |
| 808 iter != participantList->end(); | 803 iter != participantList.end(); |
| 809 ++iter) { | 804 ++iter) { |
| 810 if(&participant == *iter) { | 805 if(&participant == *iter) { |
| 811 return true; | 806 return true; |
| 812 } | 807 } |
| 813 } | 808 } |
| 814 return false; | 809 return false; |
| 815 } | 810 } |
| 816 | 811 |
| 817 bool AudioConferenceMixerImpl::AddParticipantToList( | 812 bool AudioConferenceMixerImpl::AddParticipantToList( |
| 818 MixerParticipant& participant, | 813 MixerParticipant* participant, |
| 819 MixerParticipantList* participantList) { | 814 MixerParticipantList* participantList) const { |
| 820 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 815 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 821 "AddParticipantToList(participant, participantList)"); | 816 "AddParticipantToList(participant, participantList)"); |
| 822 participantList->push_back(&participant); | 817 participantList->push_back(participant); |
| 823 // Make sure that the mixed status is correct for new MixerParticipant. | 818 // Make sure that the mixed status is correct for new MixerParticipant. |
| 824 participant._mixHistory->ResetMixedStatus(); | 819 participant->_mixHistory->ResetMixedStatus(); |
| 825 return true; | 820 return true; |
| 826 } | 821 } |
| 827 | 822 |
| 828 bool AudioConferenceMixerImpl::RemoveParticipantFromList( | 823 bool AudioConferenceMixerImpl::RemoveParticipantFromList( |
| 829 MixerParticipant& participant, | 824 MixerParticipant* participant, |
| 830 MixerParticipantList* participantList) { | 825 MixerParticipantList* participantList) const { |
| 831 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 826 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 832 "RemoveParticipantFromList(participant, participantList)"); | 827 "RemoveParticipantFromList(participant, participantList)"); |
| 833 for (MixerParticipantList::iterator iter = participantList->begin(); | 828 for (MixerParticipantList::iterator iter = participantList->begin(); |
| 834 iter != participantList->end(); | 829 iter != participantList->end(); |
| 835 ++iter) { | 830 ++iter) { |
| 836 if(*iter == &participant) { | 831 if(*iter == participant) { |
| 837 participantList->erase(iter); | 832 participantList->erase(iter); |
| 838 // Participant is no longer mixed, reset to default. | 833 // Participant is no longer mixed, reset to default. |
| 839 participant._mixHistory->ResetMixedStatus(); | 834 participant->_mixHistory->ResetMixedStatus(); |
| 840 return true; | 835 return true; |
| 841 } | 836 } |
| 842 } | 837 } |
| 843 return false; | 838 return false; |
| 844 } | 839 } |
| 845 | 840 |
| 846 int32_t AudioConferenceMixerImpl::MixFromList( | 841 int32_t AudioConferenceMixerImpl::MixFromList( |
| 847 AudioFrame& mixedAudio, | 842 AudioFrame* mixedAudio, |
| 848 const AudioFrameList* audioFrameList) { | 843 const AudioFrameList& audioFrameList) const { |
| 849 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 844 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 850 "MixFromList(mixedAudio, audioFrameList)"); | 845 "MixFromList(mixedAudio, audioFrameList)"); |
| 851 if(audioFrameList->empty()) return 0; | 846 if(audioFrameList.empty()) return 0; |
| 852 | 847 |
| 853 uint32_t position = 0; | 848 uint32_t position = 0; |
| 854 | 849 |
| 855 if (_numMixedParticipants == 1) { | 850 if (_numMixedParticipants == 1) { |
| 856 mixedAudio.timestamp_ = audioFrameList->front()->timestamp_; | 851 mixedAudio->timestamp_ = audioFrameList.front()->timestamp_; |
| 857 mixedAudio.elapsed_time_ms_ = audioFrameList->front()->elapsed_time_ms_; | 852 mixedAudio->elapsed_time_ms_ = audioFrameList.front()->elapsed_time_ms_; |
| 858 } else { | 853 } else { |
| 859 // TODO(wu): Issue 3390. | 854 // TODO(wu): Issue 3390. |
| 860 // Audio frame timestamp is only supported in one channel case. | 855 // Audio frame timestamp is only supported in one channel case. |
| 861 mixedAudio.timestamp_ = 0; | 856 mixedAudio->timestamp_ = 0; |
| 862 mixedAudio.elapsed_time_ms_ = -1; | 857 mixedAudio->elapsed_time_ms_ = -1; |
| 863 } | 858 } |
| 864 | 859 |
| 865 for (AudioFrameList::const_iterator iter = audioFrameList->begin(); | 860 for (AudioFrameList::const_iterator iter = audioFrameList.begin(); |
| 866 iter != audioFrameList->end(); | 861 iter != audioFrameList.end(); |
| 867 ++iter) { | 862 ++iter) { |
| 868 if(position >= kMaximumAmountOfMixedParticipants) { | 863 if(position >= kMaximumAmountOfMixedParticipants) { |
| 869 WEBRTC_TRACE( | 864 WEBRTC_TRACE( |
| 870 kTraceMemory, | 865 kTraceMemory, |
| 871 kTraceAudioMixerServer, | 866 kTraceAudioMixerServer, |
| 872 _id, | 867 _id, |
| 873 "Trying to mix more than max amount of mixed participants:%d!", | 868 "Trying to mix more than max amount of mixed participants:%d!", |
| 874 kMaximumAmountOfMixedParticipants); | 869 kMaximumAmountOfMixedParticipants); |
| 875 // Assert and avoid crash | 870 // Assert and avoid crash |
| 876 assert(false); | 871 assert(false); |
| 877 position = 0; | 872 position = 0; |
| 878 } | 873 } |
| 879 MixFrames(&mixedAudio, (*iter), use_limiter_); | 874 MixFrames(mixedAudio, (*iter), use_limiter_); |
| 880 | 875 |
| 881 position++; | 876 position++; |
| 882 } | 877 } |
| 883 | 878 |
| 884 return 0; | 879 return 0; |
| 885 } | 880 } |
| 886 | 881 |
| 887 // TODO(andrew): consolidate this function with MixFromList. | 882 // TODO(andrew): consolidate this function with MixFromList. |
| 888 int32_t AudioConferenceMixerImpl::MixAnonomouslyFromList( | 883 int32_t AudioConferenceMixerImpl::MixAnonomouslyFromList( |
| 889 AudioFrame& mixedAudio, | 884 AudioFrame* mixedAudio, |
| 890 const AudioFrameList* audioFrameList) { | 885 const AudioFrameList& audioFrameList) const { |
| 891 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 886 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
| 892 "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); | 887 "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); |
| 893 | 888 |
| 894 if(audioFrameList->empty()) return 0; | 889 if(audioFrameList.empty()) return 0; |
| 895 | 890 |
| 896 for (AudioFrameList::const_iterator iter = audioFrameList->begin(); | 891 for (AudioFrameList::const_iterator iter = audioFrameList.begin(); |
| 897 iter != audioFrameList->end(); | 892 iter != audioFrameList.end(); |
| 898 ++iter) { | 893 ++iter) { |
| 899 MixFrames(&mixedAudio, *iter, use_limiter_); | 894 MixFrames(mixedAudio, *iter, use_limiter_); |
| 900 } | 895 } |
| 901 return 0; | 896 return 0; |
| 902 } | 897 } |
| 903 | 898 |
| 904 bool AudioConferenceMixerImpl::LimitMixedAudio(AudioFrame& mixedAudio) { | 899 bool AudioConferenceMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const { |
| 905 if (!use_limiter_) { | 900 if (!use_limiter_) { |
| 906 return true; | 901 return true; |
| 907 } | 902 } |
| 908 | 903 |
| 909 // Smoothly limit the mixed frame. | 904 // Smoothly limit the mixed frame. |
| 910 const int error = _limiter->ProcessStream(&mixedAudio); | 905 const int error = _limiter->ProcessStream(mixedAudio); |
| 911 | 906 |
| 912 // And now we can safely restore the level. This procedure results in | 907 // And now we can safely restore the level. This procedure results in |
| 913 // some loss of resolution, deemed acceptable. | 908 // some loss of resolution, deemed acceptable. |
| 914 // | 909 // |
| 915 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS | 910 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS |
| 916 // and compression gain of 6 dB). However, in the transition frame when this | 911 // and compression gain of 6 dB). However, in the transition frame when this |
| 917 // is enabled (moving from one to two participants) it has the potential to | 912 // is enabled (moving from one to two participants) it has the potential to |
| 918 // create discontinuities in the mixed frame. | 913 // create discontinuities in the mixed frame. |
| 919 // | 914 // |
| 920 // Instead we double the frame (with addition since left-shifting a | 915 // Instead we double the frame (with addition since left-shifting a |
| 921 // negative value is undefined). | 916 // negative value is undefined). |
| 922 mixedAudio += mixedAudio; | 917 *mixedAudio += *mixedAudio; |
| 923 | 918 |
| 924 if(error != _limiter->kNoError) { | 919 if(error != _limiter->kNoError) { |
| 925 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 920 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, |
| 926 "Error from AudioProcessing: %d", error); | 921 "Error from AudioProcessing: %d", error); |
| 927 assert(false); | 922 assert(false); |
| 928 return false; | 923 return false; |
| 929 } | 924 } |
| 930 return true; | 925 return true; |
| 931 } | 926 } |
| 932 } // namespace webrtc | 927 } // namespace webrtc |
| OLD | NEW |