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 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 397 } |
398 | 398 |
399 // ============================================================================ | 399 // ============================================================================ |
400 // Construction & Destruction | 400 // Construction & Destruction |
401 // ============================================================================ | 401 // ============================================================================ |
402 | 402 |
403 // ---------------------------------------------------------------------------- | 403 // ---------------------------------------------------------------------------- |
404 // AudioDeviceWindowsCore() - ctor | 404 // AudioDeviceWindowsCore() - ctor |
405 // ---------------------------------------------------------------------------- | 405 // ---------------------------------------------------------------------------- |
406 | 406 |
407 AudioDeviceWindowsCore::AudioDeviceWindowsCore(const int32_t id) : | 407 AudioDeviceWindowsCore::AudioDeviceWindowsCore(const int32_t id) |
408 _comInit(ScopedCOMInitializer::kMTA), | 408 : _comInit(ScopedCOMInitializer::kMTA), |
409 _id(id), | 409 _id(id), |
410 _ptrAudioBuffer(NULL), | 410 _ptrAudioBuffer(NULL), |
411 _ptrEnumerator(NULL), | 411 _ptrEnumerator(NULL), |
412 _ptrRenderCollection(NULL), | 412 _ptrRenderCollection(NULL), |
413 _ptrCaptureCollection(NULL), | 413 _ptrCaptureCollection(NULL), |
414 _ptrDeviceOut(NULL), | 414 _ptrDeviceOut(NULL), |
415 _ptrDeviceIn(NULL), | 415 _ptrDeviceIn(NULL), |
416 _ptrClientOut(NULL), | 416 _ptrClientOut(NULL), |
417 _ptrClientIn(NULL), | 417 _ptrClientIn(NULL), |
418 _ptrRenderClient(NULL), | 418 _ptrRenderClient(NULL), |
419 _ptrCaptureClient(NULL), | 419 _ptrCaptureClient(NULL), |
420 _ptrCaptureVolume(NULL), | 420 _ptrCaptureVolume(NULL), |
421 _ptrRenderSimpleVolume(NULL), | 421 _ptrRenderSimpleVolume(NULL), |
422 _dmo(NULL), | 422 _dmo(NULL), |
423 _mediaBuffer(NULL), | 423 _mediaBuffer(NULL), |
424 _builtInAecEnabled(false), | 424 _builtInAecEnabled(false), |
425 _playAudioFrameSize(0), | 425 _playAudioFrameSize(0), |
426 _playSampleRate(0), | 426 _playSampleRate(0), |
427 _playBlockSizePerChannel(0), | 427 _playBlockSizeInFrames(0), |
428 _playBlockSize(0), | 428 _playBlockSizeInSamples(0), |
429 _playChannels(2), | 429 _playChannels(2), |
430 _sndCardPlayDelay(0), | 430 _sndCardPlayDelay(0), |
431 _sndCardRecDelay(0), | 431 _sndCardRecDelay(0), |
432 _writtenSamples(0), | 432 _writtenSamples(0), |
433 _readSamples(0), | 433 _readSamples(0), |
434 _playAcc(0), | 434 _playAcc(0), |
435 _recAudioFrameSize(0), | 435 _recAudioFrameSize(0), |
436 _recSampleRate(0), | 436 _recSampleRate(0), |
437 _recBlockSize(0), | 437 _recBlockSize(0), |
438 _recChannels(2), | 438 _recChannels(2), |
439 _avrtLibrary(NULL), | 439 _avrtLibrary(NULL), |
440 _winSupportAvrt(false), | 440 _winSupportAvrt(false), |
441 _hRenderSamplesReadyEvent(NULL), | 441 _hRenderSamplesReadyEvent(NULL), |
442 _hPlayThread(NULL), | 442 _hPlayThread(NULL), |
443 _hCaptureSamplesReadyEvent(NULL), | 443 _hCaptureSamplesReadyEvent(NULL), |
444 _hRecThread(NULL), | 444 _hRecThread(NULL), |
445 _hShutdownRenderEvent(NULL), | 445 _hShutdownRenderEvent(NULL), |
446 _hShutdownCaptureEvent(NULL), | 446 _hShutdownCaptureEvent(NULL), |
447 _hRenderStartedEvent(NULL), | 447 _hRenderStartedEvent(NULL), |
448 _hCaptureStartedEvent(NULL), | 448 _hCaptureStartedEvent(NULL), |
449 _hGetCaptureVolumeThread(NULL), | 449 _hGetCaptureVolumeThread(NULL), |
450 _hSetCaptureVolumeThread(NULL), | 450 _hSetCaptureVolumeThread(NULL), |
451 _hSetCaptureVolumeEvent(NULL), | 451 _hSetCaptureVolumeEvent(NULL), |
452 _hMmTask(NULL), | 452 _hMmTask(NULL), |
453 _initialized(false), | 453 _initialized(false), |
454 _recording(false), | 454 _recording(false), |
455 _playing(false), | 455 _playing(false), |
456 _recIsInitialized(false), | 456 _recIsInitialized(false), |
457 _playIsInitialized(false), | 457 _playIsInitialized(false), |
458 _speakerIsInitialized(false), | 458 _speakerIsInitialized(false), |
459 _microphoneIsInitialized(false), | 459 _microphoneIsInitialized(false), |
460 _AGC(false), | 460 _AGC(false), |
461 _playWarning(0), | 461 _playWarning(0), |
462 _playError(0), | 462 _playError(0), |
463 _recWarning(0), | 463 _recWarning(0), |
464 _recError(0), | 464 _recError(0), |
465 _playBufType(AudioDeviceModule::kAdaptiveBufferSize), | 465 _playBufType(AudioDeviceModule::kAdaptiveBufferSize), |
466 _playBufDelay(80), | 466 _playBufDelay(80), |
467 _playBufDelayFixed(80), | 467 _playBufDelayFixed(80), |
468 _usingInputDeviceIndex(false), | 468 _usingInputDeviceIndex(false), |
469 _usingOutputDeviceIndex(false), | 469 _usingOutputDeviceIndex(false), |
470 _inputDevice(AudioDeviceModule::kDefaultCommunicationDevice), | 470 _inputDevice(AudioDeviceModule::kDefaultCommunicationDevice), |
471 _outputDevice(AudioDeviceModule::kDefaultCommunicationDevice), | 471 _outputDevice(AudioDeviceModule::kDefaultCommunicationDevice), |
472 _inputDeviceIndex(0), | 472 _inputDeviceIndex(0), |
473 _outputDeviceIndex(0), | 473 _outputDeviceIndex(0), |
474 _newMicLevel(0) | 474 _newMicLevel(0) { |
475 { | 475 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); |
476 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__
); | 476 assert(_comInit.succeeded()); |
477 assert(_comInit.succeeded()); | |
478 | 477 |
479 // Try to load the Avrt DLL | 478 // Try to load the Avrt DLL |
480 if (!_avrtLibrary) | 479 if (!_avrtLibrary) { |
481 { | 480 // Get handle to the Avrt DLL module. |
482 // Get handle to the Avrt DLL module. | 481 _avrtLibrary = LoadLibrary(TEXT("Avrt.dll")); |
483 _avrtLibrary = LoadLibrary(TEXT("Avrt.dll")); | 482 if (_avrtLibrary) { |
484 if (_avrtLibrary) | 483 // Handle is valid (should only happen if OS larger than vista & win7). |
485 { | 484 // Try to get the function addresses. |
486 // Handle is valid (should only happen if OS larger than vista & win
7). | 485 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
487 // Try to get the function addresses. | 486 "AudioDeviceWindowsCore::AudioDeviceWindowsCore() The Avrt " |
488 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindows
Core::AudioDeviceWindowsCore() The Avrt DLL module is now loaded"); | 487 "DLL module is now loaded"); |
489 | 488 |
490 _PAvRevertMmThreadCharacteristics = (PAvRevertMmThreadCharacteristic
s)GetProcAddress(_avrtLibrary, "AvRevertMmThreadCharacteristics"); | 489 _PAvRevertMmThreadCharacteristics = |
491 _PAvSetMmThreadCharacteristicsA = (PAvSetMmThreadCharacteristicsA)Ge
tProcAddress(_avrtLibrary, "AvSetMmThreadCharacteristicsA"); | 490 (PAvRevertMmThreadCharacteristics)GetProcAddress( |
492 _PAvSetMmThreadPriority = (PAvSetMmThreadPriority)GetProcAddress(_av
rtLibrary, "AvSetMmThreadPriority"); | 491 _avrtLibrary, "AvRevertMmThreadCharacteristics"); |
| 492 _PAvSetMmThreadCharacteristicsA = |
| 493 (PAvSetMmThreadCharacteristicsA)GetProcAddress( |
| 494 _avrtLibrary, "AvSetMmThreadCharacteristicsA"); |
| 495 _PAvSetMmThreadPriority = (PAvSetMmThreadPriority)GetProcAddress( |
| 496 _avrtLibrary, "AvSetMmThreadPriority"); |
493 | 497 |
494 if ( _PAvRevertMmThreadCharacteristics && | 498 if (_PAvRevertMmThreadCharacteristics && |
495 _PAvSetMmThreadCharacteristicsA && | 499 _PAvSetMmThreadCharacteristicsA && _PAvSetMmThreadPriority) { |
496 _PAvSetMmThreadPriority) | 500 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
497 { | 501 "AudioDeviceWindowsCore::AudioDeviceWindowsCore() " |
498 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWin
dowsCore::AudioDeviceWindowsCore() AvRevertMmThreadCharacteristics() is OK"); | 502 "AvRevertMmThreadCharacteristics() is OK"); |
499 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWin
dowsCore::AudioDeviceWindowsCore() AvSetMmThreadCharacteristicsA() is OK"); | 503 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
500 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWin
dowsCore::AudioDeviceWindowsCore() AvSetMmThreadPriority() is OK"); | 504 "AudioDeviceWindowsCore::AudioDeviceWindowsCore() " |
501 _winSupportAvrt = true; | 505 "AvSetMmThreadCharacteristicsA() is OK"); |
502 } | 506 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
503 } | 507 "AudioDeviceWindowsCore::AudioDeviceWindowsCore() " |
| 508 "AvSetMmThreadPriority() is OK"); |
| 509 _winSupportAvrt = true; |
| 510 } |
504 } | 511 } |
| 512 } |
505 | 513 |
506 // Create our samples ready events - we want auto reset events that start in
the not-signaled state. | 514 // Create our samples ready events - we want auto reset events that start in |
507 // The state of an auto-reset event object remains signaled until a single w
aiting thread is released, | 515 // the not-signaled state. The state of an auto-reset event object remains |
508 // at which time the system automatically sets the state to nonsignaled. If
no threads are waiting, | 516 // signaled until a single waiting thread is released, at which time the |
509 // the event object's state remains signaled. | 517 // system automatically sets the state to nonsignaled. If no threads are |
510 // (Except for _hShutdownCaptureEvent, which is used to shutdown multiple th
reads). | 518 // waiting, the event object's state remains signaled. (Except for |
511 _hRenderSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 519 // _hShutdownCaptureEvent, which is used to shutdown multiple threads). |
512 _hCaptureSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 520 _hRenderSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
513 _hShutdownRenderEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 521 _hCaptureSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
514 _hShutdownCaptureEvent = CreateEvent(NULL, TRUE, FALSE, NULL); | 522 _hShutdownRenderEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
515 _hRenderStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 523 _hShutdownCaptureEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
516 _hCaptureStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 524 _hRenderStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
517 _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 525 _hCaptureStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
| 526 _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
518 | 527 |
519 _perfCounterFreq.QuadPart = 1; | 528 _perfCounterFreq.QuadPart = 1; |
520 _perfCounterFactor = 0.0; | 529 _perfCounterFactor = 0.0; |
521 _avgCPULoad = 0.0; | 530 _avgCPULoad = 0.0; |
522 | 531 |
523 // list of number of channels to use on recording side | 532 // list of number of channels to use on recording side |
524 _recChannelsPrioList[0] = 2; // stereo is prio 1 | 533 _recChannelsPrioList[0] = 2; // stereo is prio 1 |
525 _recChannelsPrioList[1] = 1; // mono is prio 2 | 534 _recChannelsPrioList[1] = 1; // mono is prio 2 |
526 _recChannelsPrioList[2] = 4; // quad is prio 3 | 535 _recChannelsPrioList[2] = 4; // quad is prio 3 |
527 | 536 |
528 // list of number of channels to use on playout side | 537 // list of number of channels to use on playout side |
529 _playChannelsPrioList[0] = 2; // stereo is prio 1 | 538 _playChannelsPrioList[0] = 2; // stereo is prio 1 |
530 _playChannelsPrioList[1] = 1; // mono is prio 2 | 539 _playChannelsPrioList[1] = 1; // mono is prio 2 |
531 | 540 |
532 HRESULT hr; | 541 HRESULT hr; |
533 | 542 |
534 // We know that this API will work since it has already been verified in | 543 // We know that this API will work since it has already been verified in |
535 // CoreAudioIsSupported, hence no need to check for errors here as well. | 544 // CoreAudioIsSupported, hence no need to check for errors here as well. |
536 | 545 |
537 // Retrive the IMMDeviceEnumerator API (should load the MMDevAPI.dll) | 546 // Retrive the IMMDeviceEnumerator API (should load the MMDevAPI.dll) |
538 // TODO(henrika): we should probably move this allocation to Init() instead | 547 // TODO(henrika): we should probably move this allocation to Init() instead |
539 // and deallocate in Terminate() to make the implementation more symmetric. | 548 // and deallocate in Terminate() to make the implementation more symmetric. |
540 CoCreateInstance( | 549 CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, |
541 __uuidof(MMDeviceEnumerator), | 550 __uuidof(IMMDeviceEnumerator), |
542 NULL, | 551 reinterpret_cast<void**>(&_ptrEnumerator)); |
543 CLSCTX_ALL, | 552 assert(NULL != _ptrEnumerator); |
544 __uuidof(IMMDeviceEnumerator), | |
545 reinterpret_cast<void**>(&_ptrEnumerator)); | |
546 assert(NULL != _ptrEnumerator); | |
547 | 553 |
548 // DMO initialization for built-in WASAPI AEC. | 554 // DMO initialization for built-in WASAPI AEC. |
549 { | 555 { |
550 IMediaObject* ptrDMO = NULL; | 556 IMediaObject* ptrDMO = NULL; |
551 hr = CoCreateInstance(CLSID_CWMAudioAEC, | 557 hr = CoCreateInstance(CLSID_CWMAudioAEC, NULL, CLSCTX_INPROC_SERVER, |
552 NULL, | 558 IID_IMediaObject, reinterpret_cast<void**>(&ptrDMO)); |
553 CLSCTX_INPROC_SERVER, | 559 if (FAILED(hr) || ptrDMO == NULL) { |
554 IID_IMediaObject, | 560 // Since we check that _dmo is non-NULL in EnableBuiltInAEC(), the |
555 reinterpret_cast<void**>(&ptrDMO)); | 561 // feature is prevented from being enabled. |
556 if (FAILED(hr) || ptrDMO == NULL) | 562 _builtInAecEnabled = false; |
557 { | 563 _TraceCOMError(hr); |
558 // Since we check that _dmo is non-NULL in EnableBuiltInAEC(), the | |
559 // feature is prevented from being enabled. | |
560 _builtInAecEnabled = false; | |
561 _TraceCOMError(hr); | |
562 } | |
563 _dmo = ptrDMO; | |
564 SAFE_RELEASE(ptrDMO); | |
565 } | 564 } |
| 565 _dmo = ptrDMO; |
| 566 SAFE_RELEASE(ptrDMO); |
| 567 } |
566 } | 568 } |
567 | 569 |
568 // ---------------------------------------------------------------------------- | 570 // ---------------------------------------------------------------------------- |
569 // AudioDeviceWindowsCore() - dtor | 571 // AudioDeviceWindowsCore() - dtor |
570 // ---------------------------------------------------------------------------- | 572 // ---------------------------------------------------------------------------- |
571 | 573 |
572 AudioDeviceWindowsCore::~AudioDeviceWindowsCore() | 574 AudioDeviceWindowsCore::~AudioDeviceWindowsCore() |
573 { | 575 { |
574 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTIO
N__); | 576 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTIO
N__); |
575 | 577 |
(...skipping 1700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2276 if (hr == S_OK) | 2278 if (hr == S_OK) |
2277 break; | 2279 break; |
2278 } | 2280 } |
2279 | 2281 |
2280 // TODO(andrew): what happens in the event of failure in the above loop? | 2282 // TODO(andrew): what happens in the event of failure in the above loop? |
2281 // Is _ptrClientOut->Initialize expected to fail? | 2283 // Is _ptrClientOut->Initialize expected to fail? |
2282 // Same in InitRecording(). | 2284 // Same in InitRecording(). |
2283 if (hr == S_OK) | 2285 if (hr == S_OK) |
2284 { | 2286 { |
2285 _playAudioFrameSize = Wfx.nBlockAlign; | 2287 _playAudioFrameSize = Wfx.nBlockAlign; |
2286 _playBlockSizePerChannel = Wfx.nSamplesPerSec/100; | 2288 // Block size in frames is the number of samples each channel in 10ms. |
2287 _playBlockSize = _playBlockSizePerChannel*Wfx.nChannels; | 2289 _playBlockSizeInFrames = Wfx.nSamplesPerSec / 100; |
| 2290 // Block size in samples is block size in frames times number of |
| 2291 // channels. |
| 2292 _playBlockSizeInSamples = _playBlockSizeInFrames * Wfx.nChannels; |
2288 _playSampleRate = Wfx.nSamplesPerSec; | 2293 _playSampleRate = Wfx.nSamplesPerSec; |
2289 _devicePlaySampleRate = Wfx.nSamplesPerSec; // The device itself continu
es to run at 44.1 kHz. | 2294 _devicePlaySampleRate = Wfx.nSamplesPerSec; // The device itself continu
es to run at 44.1 kHz. |
2290 _devicePlayBlockSize = Wfx.nSamplesPerSec/100; | 2295 _devicePlayBlockSize = Wfx.nSamplesPerSec/100; |
2291 _playChannels = Wfx.nChannels; | 2296 _playChannels = Wfx.nChannels; |
2292 | 2297 |
2293 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "VoE selected this rend
ering format:"); | 2298 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "VoE selected this rend
ering format:"); |
2294 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wFormatTag : 0
x%X (%u)", Wfx.wFormatTag, Wfx.wFormatTag); | 2299 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wFormatTag : 0
x%X (%u)", Wfx.wFormatTag, Wfx.wFormatTag); |
2295 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels : %
d", Wfx.nChannels); | 2300 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nChannels : %
d", Wfx.nChannels); |
2296 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nSamplesPerSec : %
d", Wfx.nSamplesPerSec); | 2301 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nSamplesPerSec : %
d", Wfx.nSamplesPerSec); |
2297 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nAvgBytesPerSec : %
d", Wfx.nAvgBytesPerSec); | 2302 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nAvgBytesPerSec : %
d", Wfx.nAvgBytesPerSec); |
2298 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nBlockAlign : %
d", Wfx.nBlockAlign); | 2303 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "nBlockAlign : %
d", Wfx.nBlockAlign); |
2299 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wBitsPerSample : %
d", Wfx.wBitsPerSample); | 2304 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wBitsPerSample : %
d", Wfx.wBitsPerSample); |
2300 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %
d", Wfx.cbSize); | 2305 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %
d", Wfx.cbSize); |
2301 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Additional settings:")
; | 2306 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Additional settings:")
; |
2302 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playAudioFrameSize: %
d", _playAudioFrameSize); | 2307 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playAudioFrameSize: %
d", _playAudioFrameSize); |
2303 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playBlockSize : %
d", _playBlockSize); | 2308 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
| 2309 "_playBlockSizeInFrames : %d", _playBlockSizeInFrames); |
2304 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playChannels : %
d", _playChannels); | 2310 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playChannels : %
d", _playChannels); |
2305 } | 2311 } |
2306 | 2312 |
2307 // Create a rendering stream. | 2313 // Create a rendering stream. |
2308 // | 2314 // |
2309 // *************************************************************************
*** | 2315 // *************************************************************************
*** |
2310 // For a shared-mode stream that uses event-driven buffering, the caller mus
t | 2316 // For a shared-mode stream that uses event-driven buffering, the caller mus
t |
2311 // set both hnsPeriodicity and hnsBufferDuration to 0. The Initialize method | 2317 // set both hnsPeriodicity and hnsBufferDuration to 0. The Initialize method |
2312 // determines how large a buffer to allocate based on the scheduling period | 2318 // determines how large a buffer to allocate based on the scheduling period |
2313 // of the audio engine. Although the client's buffer processing thread is | 2319 // of the audio engine. Although the client's buffer processing thread is |
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3456 // | 3462 // |
3457 REFERENCE_TIME devPeriod = 0; | 3463 REFERENCE_TIME devPeriod = 0; |
3458 REFERENCE_TIME devPeriodMin = 0; | 3464 REFERENCE_TIME devPeriodMin = 0; |
3459 _ptrClientOut->GetDevicePeriod(&devPeriod, &devPeriodMin); | 3465 _ptrClientOut->GetDevicePeriod(&devPeriod, &devPeriodMin); |
3460 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] device period
: %u (%3.2f ms)", | 3466 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] device period
: %u (%3.2f ms)", |
3461 (DWORD)devPeriod, (double)(devPeriod/10000.0)); | 3467 (DWORD)devPeriod, (double)(devPeriod/10000.0)); |
3462 | 3468 |
3463 // Derive initial rendering delay. | 3469 // Derive initial rendering delay. |
3464 // Example: 10*(960/480) + 15 = 20 + 15 = 35ms | 3470 // Example: 10*(960/480) + 15 = 20 + 15 = 35ms |
3465 // | 3471 // |
3466 int playout_delay = 10 * (bufferLength / _playBlockSize) + | 3472 int playout_delay = 10 * (bufferLength / _playBlockSizeInFrames) + |
3467 (int)((latency + devPeriod) / 10000); | 3473 (int)((latency + devPeriod) / 10000); |
3468 _sndCardPlayDelay = playout_delay; | 3474 _sndCardPlayDelay = playout_delay; |
3469 _writtenSamples = 0; | 3475 _writtenSamples = 0; |
3470 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 3476 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
3471 "[REND] initial delay : %u", playout_delay); | 3477 "[REND] initial delay : %u", playout_delay); |
3472 | 3478 |
3473 double endpointBufferSizeMS = 10.0 * ((double)bufferLength / (double)_device
PlayBlockSize); | 3479 double endpointBufferSizeMS = 10.0 * ((double)bufferLength / (double)_device
PlayBlockSize); |
3474 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] endpointBufferSizeM
S : %3.2f", endpointBufferSizeMS); | 3480 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] endpointBufferSizeM
S : %3.2f", endpointBufferSizeMS); |
3475 | 3481 |
3476 // Before starting the stream, fill the rendering buffer with silence. | 3482 // Before starting the stream, fill the rendering buffer with silence. |
3477 // | 3483 // |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3538 // Get the number of frames of padding (queued up to play) in the en
dpoint buffer. | 3544 // Get the number of frames of padding (queued up to play) in the en
dpoint buffer. |
3539 UINT32 padding = 0; | 3545 UINT32 padding = 0; |
3540 hr = _ptrClientOut->GetCurrentPadding(&padding); | 3546 hr = _ptrClientOut->GetCurrentPadding(&padding); |
3541 EXIT_ON_ERROR(hr); | 3547 EXIT_ON_ERROR(hr); |
3542 | 3548 |
3543 // Derive the amount of available space in the output buffer | 3549 // Derive the amount of available space in the output buffer |
3544 uint32_t framesAvailable = bufferLength - padding; | 3550 uint32_t framesAvailable = bufferLength - padding; |
3545 // WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "#avaliable au
dio frames = %u", framesAvailable); | 3551 // WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "#avaliable au
dio frames = %u", framesAvailable); |
3546 | 3552 |
3547 // Do we have 10 ms available in the render buffer? | 3553 // Do we have 10 ms available in the render buffer? |
3548 if (framesAvailable < _playBlockSize) | 3554 if (framesAvailable < _playBlockSizeInFrames) { |
3549 { | 3555 // Not enough space in render buffer to store next render packet. |
3550 // Not enough space in render buffer to store next render packet
. | 3556 _UnLock(); |
3551 _UnLock(); | 3557 break; |
3552 break; | |
3553 } | 3558 } |
3554 | 3559 |
3555 // Write n*10ms buffers to the render buffer | 3560 // Write n*10ms buffers to the render buffer |
3556 const uint32_t n10msBuffers = (framesAvailable / _playBlockSize); | 3561 const uint32_t n10msBuffers = |
| 3562 (framesAvailable / _playBlockSizeInFrames); |
3557 for (uint32_t n = 0; n < n10msBuffers; n++) | 3563 for (uint32_t n = 0; n < n10msBuffers; n++) |
3558 { | 3564 { |
3559 // Get pointer (i.e., grab the buffer) to next space in the shar
ed render buffer. | 3565 // Get pointer (i.e., grab the buffer) to next space in the shar
ed render buffer. |
3560 hr = _ptrRenderClient->GetBuffer(_playBlockSize, &pData); | 3566 hr = |
| 3567 _ptrRenderClient->GetBuffer(_playBlockSizeInFrames, &pData); |
3561 EXIT_ON_ERROR(hr); | 3568 EXIT_ON_ERROR(hr); |
3562 | 3569 |
3563 QueryPerformanceCounter(&t1); // measure time: START | 3570 QueryPerformanceCounter(&t1); // measure time: START |
3564 | 3571 |
3565 if (_ptrAudioBuffer) | 3572 if (_ptrAudioBuffer) |
3566 { | 3573 { |
3567 // Request data to be played out (#bytes = _playBlockSize*_a
udioFrameSize) | 3574 // Request data to be played out (#bytes = |
| 3575 // _playBlockSizeInFrames*_audioFrameSize) |
| 3576 _UnLock(); |
| 3577 int32_t nSamples = _ptrAudioBuffer->RequestPlayoutData( |
| 3578 _playBlockSizeInFrames); |
| 3579 _Lock(); |
| 3580 |
| 3581 if (nSamples == -1) { |
3568 _UnLock(); | 3582 _UnLock(); |
3569 int32_t nSamples = | 3583 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, |
3570 _ptrAudioBuffer->RequestPlayoutData( | 3584 "failed to read data from render client"); |
3571 _playBlockSizePerChannel); | 3585 goto Exit; |
3572 _Lock(); | |
3573 | |
3574 if (nSamples == -1) | |
3575 { | |
3576 _UnLock(); | |
3577 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, | |
3578 "failed to read data from render client"); | |
3579 goto Exit; | |
3580 } | 3586 } |
3581 | 3587 |
3582 // Sanity check to ensure that essential states are not modi
fied during the unlocked period | 3588 // Sanity check to ensure that essential states are not modi
fied during the unlocked period |
3583 if (_ptrRenderClient == NULL || _ptrClientOut == NULL) | 3589 if (_ptrRenderClient == NULL || _ptrClientOut == NULL) |
3584 { | 3590 { |
3585 _UnLock(); | 3591 _UnLock(); |
3586 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, "ou
tput state has been modified during unlocked period"); | 3592 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, "ou
tput state has been modified during unlocked period"); |
3587 goto Exit; | 3593 goto Exit; |
3588 } | 3594 } |
3589 if (nSamples != static_cast<int32_t>(_playBlockSize)) | 3595 if (nSamples != |
3590 { | 3596 static_cast<int32_t>(_playBlockSizeInSamples)) { |
3591 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "nSa
mples(%d) != _playBlockSize(%d)", nSamples, _playBlockSize); | 3597 WEBRTC_TRACE( |
| 3598 kTraceWarning, kTraceAudioDevice, _id, |
| 3599 "nSamples(%d) != _playBlockSizeInSamples(%d)", |
| 3600 nSamples, _playBlockSizeInSamples); |
3592 } | 3601 } |
3593 | 3602 |
3594 // Get the actual (stored) data | 3603 // Get the actual (stored) data |
3595 nSamples = _ptrAudioBuffer->GetPlayoutData((int8_t*)pData); | 3604 nSamples = _ptrAudioBuffer->GetPlayoutData((int8_t*)pData); |
3596 } | 3605 } |
3597 | 3606 |
3598 QueryPerformanceCounter(&t2); // measure time: STOP | 3607 QueryPerformanceCounter(&t2); // measure time: STOP |
3599 time = (int)(t2.QuadPart-t1.QuadPart); | 3608 time = (int)(t2.QuadPart-t1.QuadPart); |
3600 _playAcc += time; | 3609 _playAcc += time; |
3601 | 3610 |
3602 DWORD dwFlags(0); | 3611 DWORD dwFlags(0); |
3603 hr = _ptrRenderClient->ReleaseBuffer(_playBlockSize, dwFlags); | 3612 hr = _ptrRenderClient->ReleaseBuffer(_playBlockSizeInFrames, |
| 3613 dwFlags); |
3604 // See http://msdn.microsoft.com/en-us/library/dd316605(VS.85).a
spx | 3614 // See http://msdn.microsoft.com/en-us/library/dd316605(VS.85).a
spx |
3605 // for more details regarding AUDCLNT_E_DEVICE_INVALIDATED. | 3615 // for more details regarding AUDCLNT_E_DEVICE_INVALIDATED. |
3606 EXIT_ON_ERROR(hr); | 3616 EXIT_ON_ERROR(hr); |
3607 | 3617 |
3608 _writtenSamples += _playBlockSize; | 3618 _writtenSamples += _playBlockSizeInFrames; |
3609 } | 3619 } |
3610 | 3620 |
3611 // Check the current delay on the playout side. | 3621 // Check the current delay on the playout side. |
3612 if (clock) { | 3622 if (clock) { |
3613 UINT64 pos = 0; | 3623 UINT64 pos = 0; |
3614 UINT64 freq = 1; | 3624 UINT64 freq = 1; |
3615 clock->GetPosition(&pos, NULL); | 3625 clock->GetPosition(&pos, NULL); |
3616 clock->GetFrequency(&freq); | 3626 clock->GetFrequency(&freq); |
3617 playout_delay = ROUND((double(_writtenSamples) / | 3627 playout_delay = ROUND((double(_writtenSamples) / |
3618 _devicePlaySampleRate - double(pos) / freq) * 1000.0); | 3628 _devicePlaySampleRate - double(pos) / freq) * 1000.0); |
(...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5107 int key_down = 0; | 5117 int key_down = 0; |
5108 for (int key = VK_SPACE; key < VK_NUMLOCK; key++) { | 5118 for (int key = VK_SPACE; key < VK_NUMLOCK; key++) { |
5109 short res = GetAsyncKeyState(key); | 5119 short res = GetAsyncKeyState(key); |
5110 key_down |= res & 0x1; // Get the LSB | 5120 key_down |= res & 0x1; // Get the LSB |
5111 } | 5121 } |
5112 return (key_down > 0); | 5122 return (key_down > 0); |
5113 } | 5123 } |
5114 } // namespace webrtc | 5124 } // namespace webrtc |
5115 | 5125 |
5116 #endif // WEBRTC_WINDOWS_CORE_AUDIO_BUILD | 5126 #endif // WEBRTC_WINDOWS_CORE_AUDIO_BUILD |
OLD | NEW |