waveaudiosource.cxx
来自「rtp在linux下的实现」· CXX 代码 · 共 861 行 · 第 1/2 页
CXX
861 行
{
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "BeginAudioCapture\n");
HRESULT result = NOERROR;
tracer.tracef(SDI_LEVEL_DETAILED, "BeginAudioCapture : Entering bufferListMutex\n");
EnterCriticalSection(&bufferListMutex);
buffersToAdd.clear();
LeaveCriticalSection(&bufferListMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "BeginAudioCapture : Left bufferListMutex\n");
audioSampleManager = AudioSampleManager::GetInstance();
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : waveInOpen\n");
MMRESULT mr = waveInOpen(&hWaveIn, waveinDeviceID, &format, (DWORD)WaveInCallback, DWORD(this), CALLBACK_FUNCTION);
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : ~waveInOpen\n");
if (mr != NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "BeginAudioCapture : e-waveInOpen : 0x%x\n", mr);
result = mr;
}
else {
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : Entering waveInMutex\n");
EnterCriticalSection(&waveInMutex);
bEnableAddBuffer = true;
for (int i=0; i<numBuffers; i++) {
waveHdr[i].lpData = dataBuffer[i];
waveHdr[i].dwBufferLength = bufferSize;
waveHdr[i].dwFlags = 0;
waveHdr[i].dwUser = i;
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : waveInPrepareHeader\n");
result = waveInPrepareHeader(hWaveIn, &(waveHdr[i]), sizeof(waveHdr[i]));
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : ~waveInPrepareHeader\n");
if (result == MMSYSERR_NOERROR)
{
AddBuffer(i);
}
else
{
tracer.tracef(SDI_LEVEL_ERROR, "BeginAudioCapture : e-waveInPrepareHeader : 0x%x\n", result);
}
}
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : waveInStart\n");
result = waveInStart(hWaveIn);
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : ~waveInStart\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "BeginAudioCapture : e-waveInStart : 0x%x\n", result);
}
LeaveCriticalSection(&waveInMutex);
tracer.tracef(SDI_LEVEL_ARBITRARY, "BeginAudioCapture : Left waveInMutex\n");
}
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~BeginAudioCapture\n");
return result;
}
int
WaveAudioSource::EndAudioCapture()
{
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "EndAudioCapture\n");
tracer.tracef(SDI_LEVEL_DETAILED, "EndAudioCapture : entering waveInMutex\n");
EnterCriticalSection(&waveInMutex);
bEnableAddBuffer = false;
HRESULT result = NOERROR;
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioCapture : waveInReset\n");
result = waveInReset(hWaveIn);
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioCapture : ~waveInReset\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "EndAudioCapture : e-waveInReset : 0x%x\n", result);
}
else
{
LeaveCriticalSection(&waveInMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "EndAudioCapture : left waveInMutex\n");
while(true)
{
tracer.tracef(DET, "EndAudioCapture : entering bufferListMutex\n");
EnterCriticalSection(&bufferListMutex);
tracer.tracef(DET, "EndAudioCapture : buffersToAdd.size = %d, numBuffers = %d\n", buffersToAdd.size(), numBuffers);
if (buffersToAdd.size() < numBuffers)
{
LeaveCriticalSection(&bufferListMutex);
tracer.tracef(DET, "EndAudioCapture : left bufferListMutex. Waiting for dataEvent\n");
WaitForSingleObject(dataEvent, INFINITE);
tracer.tracef(DET, "EndAudioCapture : got dataEvent\n");
continue;
}
else
{
LeaveCriticalSection(&bufferListMutex);
tracer.tracef(DET, "EndAudioCapture : left bufferListMutex\n");
break;
}
}
tracer.tracef(DET, "EndAudioCapture : entering waveInMutex\n");
EnterCriticalSection(&waveInMutex);
for (int i=0; i<numBuffers; i++) {
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioCapture : waveInUnprepareHeader\n");
result = waveInUnprepareHeader(hWaveIn, &(waveHdr[i]), sizeof(waveHdr[i]));
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioCapture : ~waveInUnprepareHeader\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "EndAudioCapture : e-waveInUnprepareHeader : 0x%x\n", result);
}
}
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioCapture : waveInClose\n");
result = waveInClose(hWaveIn);
tracer.tracef(SDI_LEVEL_ARBITRARY, "EndAudioCapture : ~waveInClose\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "EndAudioCapture : e-waveInClose : 0x%x\n", result);
}
hWaveIn = NULL;
}
LeaveCriticalSection(&waveInMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "EndAudioCapture : Left waveInMutex\n");
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~EndAudioCapture\n");
return result;
}
int
WaveAudioSource::ResetAudioCapture()
{
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "ResetAudioCapture\n");
HRESULT result = NOERROR;
result = EndAudioCapture();
if (result == MMSYSERR_NOERROR)
{
result = BeginAudioCapture();
}
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~ResetAudioCapture\n");
return result;
}
int
WaveAudioSource::AddBuffer(int i)
{
tracer.tracef(SDI_LEVEL_DETAILED, "AddBuffer %d\n", i);
HRESULT result = NOERROR;
tracer.tracef(SDI_LEVEL_DETAILED, "AddBuffer : Entering waveInMutex\n");
EnterCriticalSection(&waveInMutex);
bool bEnabled = bEnableAddBuffer;
if (bEnabled)
{
tracer.tracef(SDI_LEVEL_ARBITRARY, "AddBuffer : waveInAddBuffer\n");
result = waveInAddBuffer(hWaveIn, &(waveHdr[i]), sizeof(waveHdr[i]));
tracer.tracef(SDI_LEVEL_ARBITRARY, "AddBuffer : ~waveInAddBuffer\n");
LeaveCriticalSection(&waveInMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "AddBuffer : Left waveInMutex\n");
if (result != MMSYSERR_NOERROR)
{
tracer.tracef(SDI_LEVEL_ERROR, "AddBuffer : e-waveInAddBuffer : 0x%x\n", result);
result = -10;
}
}
else
{
LeaveCriticalSection(&waveInMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "AddBuffer : !bEnabled. Left waveInMutex. Putting buffer back in buffersToAdd\n");
tracer.tracef(SDI_LEVEL_DETAILED, "AddBuffer : Entering bufferListMutex\n");
EnterCriticalSection(&bufferListMutex);
buffersToAdd.push_back(&(waveHdr[i]));
LeaveCriticalSection(&bufferListMutex);
SetEvent(dataEvent);
tracer.tracef(SDI_LEVEL_DETAILED, "AddBuffer : Left bufferListMutex\n");
}
tracer.tracef(SDI_LEVEL_DETAILED, "~AddBuffer\n");
return result;
}
// TO avoid problems with wave calls not returning, one has to GUARANTEE that the callback function
// will return regardless of the state of any other function. if this function grabs a mutex that is
// also entered by other functions, one has to ensure that in no circumstance does the other function
// hold in while making a system call (like a wave api call) since those calls may freeze until this
// callback function returns. that's the potential deadlock
void CALLBACK
WaveAudioSource::WaveInCallback(HWAVEIN hWaveIn, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) {
WAVEHDR *wHdr;
WaveAudioSource *waveAudioSource;
waveAudioSource = (WaveAudioSource *)dwInstance;
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "WaveInCallback\n");
switch(uMsg) {
case WIM_OPEN:
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "WaveInCallback : WIM_OPEN\n");
break;
case WIM_CLOSE:
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "WaveInCallback : WIM_CLOSE\n");
SetEvent(waveAudioSource->dataEvent);
break;
case WIM_DATA:
wHdr = (WAVEHDR *)dwParam1;
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "WaveInCallback : WIM_DATA %d\n", wHdr->dwUser);
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "WaveInCallback : Entering bufferListMutex\n");
EnterCriticalSection(&(waveAudioSource->bufferListMutex));
(waveAudioSource->buffersToAdd).push_back(wHdr);
LeaveCriticalSection(&(waveAudioSource->bufferListMutex));
SetEvent(waveAudioSource->dataEvent); // we do this within the critical section because fillbuffer resets this within the same critical section - ??? so i go it out
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "WaveInCallback : Left bufferListMutex\n");
break;
default:
break;
}
(waveAudioSource->tracer).tracef(SDI_LEVEL_DETAILED, "~WaveInCallback\n");
}
int
WaveAudioSource::GenerateData(AudioSample **ppAudioSample)
{
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData\n");
HRESULT result = NOERROR;
*ppAudioSample = NULL;
bool fireDataEvent = false;
while (true)
{
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : Entering waveInMutex\n");
EnterCriticalSection(&waveInMutex);
bool bEnabled = bEnableAddBuffer;
LeaveCriticalSection(&waveInMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : Left waveInMutex\n");
if (!bEnabled)
{
if (fireDataEvent)
{
SetEvent(dataEvent);
}
break;
}
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : Entering bufferListMutex\n");
EnterCriticalSection(&bufferListMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : buffersToAdd.size = %d\n", buffersToAdd.size());
if (buffersToAdd.size() <= 0)
{
LeaveCriticalSection(&bufferListMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : Left bufferListMutex. Waiting for dataEvent\n");
WaitForSingleObject(dataEvent, INFINITE);
tracer.tracef(DET, "GenerateData : Got dataEvent\n");
fireDataEvent = true;
continue;
}
else
{
WAVEHDR *wHdr = buffersToAdd.front();
buffersToAdd.pop_front();
LeaveCriticalSection(&bufferListMutex);
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : Left bufferListMutex\n");
AudioSample *audioSample;
audioSampleManager->GetAudioSample(&audioSample);
*ppAudioSample = audioSample;
audioSample->SetFormat(format);
int bytesToFill = min(wHdr->dwBytesRecorded, audioSample->BufferSize());
audioSample->SetDataSize(bytesToFill);
if (micVolume > 0)
{
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : memcpy(0x%x, 0x%x, %d)\n", audioSample->Data(), wHdr->lpData, bytesToFill);
memcpy(audioSample->Data(), wHdr->lpData, bytesToFill);
}
else
{
tracer.tracef(SDI_LEVEL_DETAILED, "GenerateData : memset(0x%x, 0, %d)\n", audioSample->Data(), bytesToFill);
memset(audioSample->Data(), 0, bytesToFill);
}
AddBuffer(wHdr->dwUser);
break;
}
}
tracer.tracef(SDI_LEVEL_DETAILED, "~GenerateData\n");
return 0;
}
int
WaveAudioSource::StartSource()
{
int result(0);
int returnCode(0);
SetTraceLevel();
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "StartSource\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "StartSource : entered filterMutex\n");
do
{
if (bRunning)
{
tracer.tracef(ERR, "StartSource : e-error : already running\n");
result = -10;
break;
}
returnCode = BeginAudioCapture();
if (returnCode != 0)
{
tracer.tracef(ERR, "StartSource : e-BeginAudioCapture : %d 0x%x\n", returnCode, returnCode);
result = -20;
break;
}
returnCode = AudioSource::StartSource();
if (returnCode != 0)
{
tracer.tracef(ERR, "StartSource : e-AudioSource::StartSource : %d 0x%x\n", returnCode, returnCode);
result = -30;
break;
}
if (needToSetVolume)
{
SetVolume(micVolume);
needToSetVolume = false;
}
bRunning = true;
}
while (false);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "StartSource : left filterMutex\n");
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~StartSource : returning %d\n", result);
return result;
}
int
WaveAudioSource::StopSource()
{
int result(0);
int returnCode(0);
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "StopSource\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "StopSource : entered filterMutex\n");
do
{
if (!bRunning)
{
tracer.tracef(ERR, "StopSource : e-error : not running\n");
result = -10;
break;
}
returnCode = EndAudioCapture();
if (returnCode != 0)
{
tracer.tracef(ERR, "StopSource : e-EndAudioCapture : %d 0x%x\n", returnCode, returnCode);
result = -20;
break;
}
returnCode = AudioSource::StopSource();
if (returnCode != 0)
{
tracer.tracef(ERR, "StopSource : e-AudioSource::StopSource : %d 0x%x\n", returnCode, returnCode);
result = -30;
break;
}
needToSetVolume = false;
bRunning = false;
}
while (false);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "StopSource : left filterMutex\n");
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~StopSource : returning %d\n", result);
return result;
}
int
WaveAudioSource::SourceThreadStarted(HANDLE sourceThreadHandle, DWORD sourceThreadID)
{
int result(0);
int returnCode(0);
SetTraceLevel();
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "SourceThreadStarted\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStarted : entered filterMutex\n");
do
{
returnCode = SetThreadPriority(sourceThreadHandle, THREAD_PRIORITY_TIME_CRITICAL);
if (returnCode == 0)
{
returnCode = GetLastError();
tracer.tracef(ERR, "SourceThreadStarted : e-SetThreadPriority : %d 0x%x\n", returnCode, returnCode);
}
returnCode = BeginAudioCapture();
if (returnCode != 0)
{
tracer.tracef(ERR, "SourceThreadStarted : e-BeginAudioCapture : %d 0x%x\n", returnCode, returnCode);
result = -10;
break;
}
if (needToSetVolume)
{
SetVolume(micVolume);
needToSetVolume = false;
}
bRunning = true;
}
while (false);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStarted : left filterMutex\n");
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~SourceThreadStarted : returning %d\n", result);
return result;
}
int
WaveAudioSource::SourceThreadStopped(HANDLE sourceThreadHandle, DWORD sourceThreadID)
{
int result(0);
int returnCode(0);
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "SourceThreadStopped\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStopped : entered filterMutex\n");
do
{
returnCode = EndAudioCapture();
if (returnCode != 0)
{
tracer.tracef(ERR, "SourceThreadStopped : e-BeginAudioCapture : %d 0x%x\n", returnCode, returnCode);
result = -10;
break;
}
needToSetVolume = false;
bRunning = true;
}
while (false);
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "SourceThreadStopped : left filterMutex\n");
tracer.tracef(SDI_LEVEL_ENTRY_EXIT, "~SourceThreadStopped : returning %d\n", result);
return result;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?