分析承接<7-13 打开播放设备>

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\audio_device\win\audio_device_core_win.cc

AudioDeviceWindowsCore::InitPlayout

  1. int32_t AudioDeviceWindowsCore::InitPlayout() {
  2. MutexLock lock(&mutex_);
  3. if (_playing) {
  4. return -1;
  5. }
  6. if (_playIsInitialized) {
  7. return 0;
  8. }
  9. if (_ptrDeviceOut == NULL) {
  10. return -1;
  11. }
  12. // Initialize the speaker (devices might have been added or removed)
  13. if (InitSpeakerLocked() == -1) {
  14. RTC_LOG(LS_WARNING) << "InitSpeaker() failed";
  15. }
  16. // Ensure that the updated rendering endpoint device is valid
  17. if (_ptrDeviceOut == NULL) {
  18. return -1;
  19. }
  20. if (_builtInAecEnabled && _recIsInitialized) {
  21. // Ensure the correct render device is configured in case
  22. // InitRecording() was called before InitPlayout().
  23. if (SetDMOProperties() == -1) {
  24. return -1;
  25. }
  26. }
  27. HRESULT hr = S_OK;
  28. WAVEFORMATEX* pWfxOut = NULL;
  29. WAVEFORMATEX Wfx = WAVEFORMATEX();
  30. WAVEFORMATEX* pWfxClosestMatch = NULL;
  31. // Create COM object with IAudioClient interface.
  32. SAFE_RELEASE(_ptrClientOut);
  33. hr = _ptrDeviceOut->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL,
  34. (void**)&_ptrClientOut);
  35. EXIT_ON_ERROR(hr);
  36. // 获取扬声器支持的参数
  37. // Retrieve the stream format that the audio engine uses for its internal
  38. // processing (mixing) of shared-mode streams.
  39. hr = _ptrClientOut->GetMixFormat(&pWfxOut);
  40. if (SUCCEEDED(hr)) {
  41. ***
  42. }
  43. // 构造我们想输出的参数
  44. // Set wave format
  45. Wfx.wFormatTag = WAVE_FORMAT_PCM;
  46. Wfx.wBitsPerSample = 16;
  47. Wfx.cbSize = 0;
  48. const int freqs[] = {48000, 44100, 16000, 96000, 32000, 8000};
  49. hr = S_FALSE;
  50. // 获取一个支持共享模式下的freqs值
  51. // Iterate over frequencies and channels, in order of priority
  52. for (unsigned int freq = 0; freq < sizeof(freqs) / sizeof(freqs[0]); freq++) {
  53. // _playChannelsPrioList两个成员,一个单声道,一个双声道
  54. for (unsigned int chan = 0; chan < sizeof(_playChannelsPrioList) /
  55. sizeof(_playChannelsPrioList[0]);
  56. chan++) {
  57. Wfx.nChannels = _playChannelsPrioList[chan];
  58. Wfx.nSamplesPerSec = freqs[freq];
  59. Wfx.nBlockAlign = Wfx.nChannels * Wfx.wBitsPerSample / 8;
  60. Wfx.nAvgBytesPerSec = Wfx.nSamplesPerSec * Wfx.nBlockAlign;
  61. // If the method succeeds and the audio endpoint device supports the
  62. // specified stream format, it returns S_OK. If the method succeeds and
  63. // provides a closest match to the specified format, it returns S_FALSE.
  64. // 判断该系统是否在该采样率下支持共享模式
  65. hr = _ptrClientOut->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &Wfx,
  66. &pWfxClosestMatch);
  67. if (hr == S_OK) {
  68. break;
  69. } else {
  70. ****
  71. }
  72. }
  73. if (hr == S_OK)
  74. break;
  75. }
  76. // TODO(andrew): what happens in the event of failure in the above loop?
  77. // Is _ptrClientOut->Initialize expected to fail?
  78. // Same in InitRecording().
  79. if (hr == S_OK) {
  80. _playAudioFrameSize = Wfx.nBlockAlign;
  81. // Block size is the number of samples each channel in 10ms.
  82. _playBlockSize = Wfx.nSamplesPerSec / 100;
  83. _playSampleRate = Wfx.nSamplesPerSec;
  84. _devicePlaySampleRate =
  85. Wfx.nSamplesPerSec; // The device itself continues to run at 44.1 kHz.
  86. _devicePlayBlockSize = Wfx.nSamplesPerSec / 100;
  87. _playChannels = Wfx.nChannels;
  88. ***
  89. }
  90. // Create a rendering stream.
  91. //
  92. // ****************************************************************************
  93. // For a shared-mode stream that uses event-driven buffering, the caller must
  94. // set both hnsPeriodicity and hnsBufferDuration to 0. The Initialize method
  95. // determines how large a buffer to allocate based on the scheduling period
  96. // of the audio engine. Although the client's buffer processing thread is
  97. // event driven, the basic buffer management process, as described previously,
  98. // is unaltered.
  99. // Each time the thread awakens, it should call
  100. // IAudioClient::GetCurrentPadding to determine how much data to write to a
  101. // rendering buffer or read from a capture buffer. In contrast to the two
  102. // buffers that the Initialize method allocates for an exclusive-mode stream
  103. // that uses event-driven buffering, a shared-mode stream requires a single
  104. // buffer.
  105. // ****************************************************************************
  106. // 指明扬声器的buffer的最小值
  107. REFERENCE_TIME hnsBufferDuration =
  108. 0; // ask for minimum buffer size (default)
  109. if (_devicePlaySampleRate == 44100) {
  110. // Ask for a larger buffer size (30ms) when using 44.1kHz as render rate.
  111. // There seems to be a larger risk of underruns for 44.1 compared
  112. // with the default rate (48kHz). When using default, we set the requested
  113. // buffer duration to 0, which sets the buffer to the minimum size
  114. // required by the engine thread. The actual buffer size can then be
  115. // read by GetBufferSize() and it is 20ms on most machines.
  116. hnsBufferDuration = 30 * 10000;
  117. }
  118. hr = _ptrClientOut->Initialize(
  119. AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications
  120. AUDCLNT_STREAMFLAGS_EVENTCALLBACK, // processing of the audio buffer by
  121. // the client will be event driven
  122. hnsBufferDuration, // requested buffer capacity as a time value (in
  123. // 100-nanosecond units)
  124. 0, // periodicity
  125. &Wfx, // selected wave format
  126. NULL); // session GUID
  127. if (FAILED(hr)) {
  128. RTC_LOG(LS_ERROR) << "IAudioClient::Initialize() failed:";
  129. }
  130. EXIT_ON_ERROR(hr);
  131. // 扬声器播放的声音放到_ptrAudioBuffer
  132. if (_ptrAudioBuffer) {
  133. // Update the audio buffer with the selected parameters
  134. _ptrAudioBuffer->SetPlayoutSampleRate(_playSampleRate);
  135. _ptrAudioBuffer->SetPlayoutChannels((uint8_t)_playChannels);
  136. } else {
  137. ***
  138. }
  139. // Get the actual size of the shared (endpoint buffer).
  140. // Typical value is 960 audio frames <=> 20ms @ 48kHz sample rate.
  141. UINT bufferFrameCount(0);
  142. hr = _ptrClientOut->GetBufferSize(&bufferFrameCount);
  143. if (SUCCEEDED(hr)) {
  144. RTC_LOG(LS_VERBOSE) << "IAudioClient::GetBufferSize() => "
  145. << bufferFrameCount << " (<=> "
  146. << bufferFrameCount * _playAudioFrameSize << " bytes)";
  147. }
  148. // Set the event handle that the system signals when an audio buffer is ready
  149. // to be processed by the client.
  150. hr = _ptrClientOut->SetEventHandle(_hRenderSamplesReadyEvent);
  151. EXIT_ON_ERROR(hr);
  152. // Get an IAudioRenderClient interface.
  153. SAFE_RELEASE(_ptrRenderClient);
  154. hr = _ptrClientOut->GetService(__uuidof(IAudioRenderClient),
  155. (void**)&_ptrRenderClient);
  156. EXIT_ON_ERROR(hr);
  157. // Mark playout side as initialized
  158. _playIsInitialized = true;
  159. *****
  160. }

7-15 InitPlayout源码分析 - 图1