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 + -
显示快捷键?