⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audiosource.cxx

📁 rtp在linux下的实现
💻 CXX
字号:
// AudioSource.cpp: implementation of the AudioSource class.
//
//////////////////////////////////////////////////////////////////////

#include <algorithm>
#include <iostream>

#include "AudioSource.h"
#include "AudioSink.h"
#include "AudioSample.h"

using namespace std;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

AudioSource::AudioSource()
{
	bSourceRunning = false;
	bSourceThreadRunning = false;
	bSourceThreadShouldStop = true;
#ifdef WIN32
	sourceThreadHandle = NULL;
	sourceThreadID = 0;
	sourceThreadStartEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	sourceThreadStopEvent  = CreateEvent(NULL, FALSE, FALSE, NULL);
	InitializeCriticalSection(&audioSinksMutex);
	InitializeCriticalSection(&sourceThreadMutex);
	InitializeCriticalSection(&sourceStateMutex);
#endif
}

AudioSource::~AudioSource()
{
#ifdef WIN32
	CloseHandle(sourceThreadStartEvent);
	CloseHandle(sourceThreadStopEvent);
	DeleteCriticalSection(&audioSinksMutex);
	DeleteCriticalSection(&sourceThreadMutex);
	DeleteCriticalSection(&sourceStateMutex);
#endif
}

int 
AudioSource::SubscribeAudioSink(AudioSink *audioSink)
{
	EnterCriticalSection(&audioSinksMutex);
	if (find(audioSinks.begin(), audioSinks.end(), audioSink) == audioSinks.end())
	{
		audioSinks.push_back(audioSink);
	}
	LeaveCriticalSection(&audioSinksMutex);
	return 0;
}

int
AudioSource::UnsubscribeAudioSink(AudioSink *audioSink)
{
	EnterCriticalSection(&audioSinksMutex);
	vector<AudioSink *>::iterator position = NULL;
	position = find(audioSinks.begin(), audioSinks.end(), audioSink);
	if (position != audioSinks.end())
	{
		audioSinks.erase(position);
	}
	LeaveCriticalSection(&audioSinksMutex);
	return 0;
}

int
AudioSource::StartSource()
{
	int result(0);
	EnterCriticalSection(&sourceStateMutex);
	if (bSourceThreadRunning || bSourceRunning)
	{
		result = -10;
	}
	else
	{
		bSourceRunning = true;
	}
	LeaveCriticalSection(&sourceStateMutex);
	return result;
}

int
AudioSource::StopSource()
{
	int result(0);
	EnterCriticalSection(&sourceStateMutex);
	if (bSourceThreadRunning)
	{
		result = -10;
	}
	else
	{
		bSourceRunning = false;
	}
	LeaveCriticalSection(&sourceStateMutex);
	return result;
}

int
AudioSource::StartSourceThread()
{
	tracer.tracef(EE, "StartSourceThread\n");
	int result(0);
	
	tracer.tracef(ARB, "StartSourceThread : entering  sourceStateMutex\n");
	EnterCriticalSection(&sourceStateMutex);
	do
	{
		if (bSourceRunning || bSourceThreadRunning)
		{
			tracer.tracef(ERR, "StartSourceThread : e-error : bSourceRunning = %d, bSourceThreadRunning = %d\n", bSourceRunning, bSourceThreadRunning);
			result = -10;
			break;
		}
#ifdef WIN32
		if (sourceThreadHandle != NULL || sourceThreadID != 0)
		{
			tracer.tracef(ERR, "StartSourceThread : e-error : sourceThreadHandle = 0x%x, sourceThreadID = 0x%x\n", sourceThreadHandle, sourceThreadID);
			result = -20;
			break;
		}
		BOOL resetResult;
		tracer.tracef(ARB, "StartSourceThread : resetting sourceThreadStartEvent and sourceThreadStopEvent\n");
		resetResult = ResetEvent(sourceThreadStartEvent);
		if (resetResult == 0)
		{
			tracer.tracef(ERR, "StartSourceThread : e-ResetEvent(sourceThreadStartedEvent) : 0x%x\n", GetLastError());
		}
		resetResult = ResetEvent(sourceThreadStopEvent);
		if (resetResult == 0)
		{
			tracer.tracef(ERR, "StartSourceThread : e-ResetEvent(sourceThreadStopEvent) : 0x%x\n", GetLastError());
		}
#endif
		bSourceThreadShouldStop = true;		// we make it false only if everything else succeeds
#ifdef WIN32
		sourceThreadHandle = CreateThread(NULL, 0, SourceThreadProc, (void *)this, CREATE_SUSPENDED, &sourceThreadID);
		if (sourceThreadHandle == NULL)
		{
			result = -20;
			break;
		}
		result = SourceThreadStarted(sourceThreadHandle, sourceThreadID);
		if (result != 0)
		{
			result = -30;
			break;
		}
		bSourceThreadShouldStop = false;
		DWORD result = ResumeThread(sourceThreadHandle);
		if (result == -1)
		{
			result = -40;
			break;
		}
		tracer.tracef(ARB, "StartSourceThread : before WaitForSingleObject(sourceThreadStartEvent, INFINITE)\n");
		DWORD waitResult = WaitForSingleObject(sourceThreadStartEvent, INFINITE);
		tracer.tracef(ARB, "StartSourceThread : waitResult = 0x%x\n", waitResult);
		if (waitResult == WAIT_FAILED)
		{
			waitResult = GetLastError();
			tracer.tracef(ERR, "StartSourceThread : e-WaitForSingleObject : %d 0x%x\n", waitResult, waitResult);
		}
#else
		bSourceThreadShouldStop = false;
                sourceThreadHandle.spawn(SourceThreadProc, (void *)this);
                sourceThreadStartEvent.wait(&sourceStateMutex, -1);
		SourceThreadStarted(*sourceThreadHandle.getId(), *sourceThreadHandle.getId());
#endif
	} while (false);
	LeaveCriticalSection(&sourceStateMutex);
	tracer.tracef(ARB, "StartSourceThread : left  sourceStateMutex\n");
	tracer.tracef(EE, "~StartSourceThread : returning %d\n", result);
	return result;
}

int
AudioSource::StopSourceThread()
{
	int result(0);
	bool waitForThread = true;
	tracer.tracef(EE, "StopSourceThread\n");
	tracer.tracef(ARB, "StopSourceThread : entering  sourceStateMutex\n");
	EnterCriticalSection(&sourceStateMutex);
	do
	{
		if (!bSourceThreadRunning)
		{
			tracer.tracef(EE, "StopSourceThread : bSourceThreadRunning = false\n");
			result =  -10;
			waitForThread = false;
			break;
		}
		bSourceThreadShouldStop = true;
	} while (false);

	LeaveCriticalSection(&sourceStateMutex);
	tracer.tracef(ARB, "StopSourceThread : left  sourceStateMutex\n");
	if (waitForThread)
	{
		tracer.tracef(ARB, "StopSourceThread : before WaitForSingleObject(sourceThreadStopEvent, INFINITE)\n");
#ifdef WIN32
		DWORD waitResult = WaitForSingleObject(sourceThreadStopEvent, INFINITE);
		tracer.tracef(ARB, "StopSourceThread : waitResult = 0x%x\n", waitResult);
		if (waitResult == WAIT_FAILED)
		{
			waitResult = GetLastError();
			tracer.tracef(ERR, "StopSourceThread : e-WaitForSingleObject : %d 0x%x\n", waitResult, waitResult);
		}
#else
		sourceThreadStopEvent.wait(&sourceStateMutex, -1);
#endif
	}
	tracer.tracef(EE, "~StopSourceThread : returning %d\n", result);
	return result;
}

#ifdef WIN32

DWORD WINAPI
AudioSource::SourceThreadProc(LPVOID params)
#else
void* 
AudioSource::SourceThreadProc(void* params)
#endif
{
	int result(0);
	AudioSource *audioSource = (AudioSource *)params;
	audioSource->tracer.tracef(EE, "SourceThreadProc : begin\n");
	audioSource->bSourceThreadRunning = true;
#ifdef WIN32
	SetEvent(audioSource->sourceThreadStartEvent);
#else
	audioSource->sourceThreadStartEvent.signal();
#endif
	while (!audioSource->bSourceThreadShouldStop)
	{
		AudioSample *pAudioSample;
		pAudioSample = NULL;
		if ((result = audioSource->GenerateData(&pAudioSample)) < 0)
		{
			break;
		}
		if (pAudioSample)
		{
			EnterCriticalSection(&(audioSource->audioSinksMutex));
			vector<AudioSink *>::iterator iter = (audioSource->audioSinks).begin();
			for (iter = (audioSource->audioSinks).begin(); iter != (audioSource->audioSinks).end(); iter++)
			{
				int i = audioSource->SendAudioSample(pAudioSample, *iter);
			}
			LeaveCriticalSection(&(audioSource->audioSinksMutex));
			pAudioSample->Release();
		}
	}
	audioSource->tracer.tracef(ARB, "SourceThreadProc : broke out of while loop. bSourceThreadShouldStop = %d\n", audioSource->bSourceThreadShouldStop);

	audioSource->tracer.tracef(EE, "SourceThreadProc : entering sourceStateMutex\n");
	EnterCriticalSection(&(audioSource->sourceStateMutex));
	audioSource->bSourceThreadRunning = false;
	
	audioSource->tracer.tracef(ARB, "SourceThreadProc : calling SourceThreadStopped\n");
#ifdef WIN32
	audioSource->SourceThreadStopped(audioSource->sourceThreadHandle, audioSource->sourceThreadID);
	CloseHandle(audioSource->sourceThreadHandle);
	audioSource->sourceThreadHandle = NULL;
	audioSource->sourceThreadID = 0;
#else
        audioSource->sourceThreadHandle.exit();
#endif

	LeaveCriticalSection(&(audioSource->sourceStateMutex));
	audioSource->tracer.tracef(EE, "SourceThreadProc : left sourceStateMutex\n");

	audioSource->tracer.tracef(EE, "SourceThreadProc : setting sourceThreadStopEvent and exiting\n");
#ifdef WIN32
	BOOL setResult = SetEvent(audioSource->sourceThreadStopEvent);
#else
	audioSource->sourceThreadStopEvent.signal();
#endif
	return 0;
}

int
AudioSource::SendAudioSample(AudioSample *audioSample, AudioSink *audioSink)
{
	tracer.tracef(DET, "SendAudioSample : calling TakeNextAudioSample\n");
	return audioSink->TakeNextAudioSample(audioSample, this);
}

#ifdef WIN32
int
AudioSource::SourceThreadStarted(HANDLE sourceThreadHandle, DWORD sourceThreadID)
#else
int
AudioSource::SourceThreadStarted(vthread_t sourceThreadHandle, DWORD sourceThreadID)
#endif
{
	return 0;
}

#ifdef WIN32
int
AudioSource::SourceThreadStopped(HANDLE sourceThreadHandle, DWORD sourceThreadID)
#else
int
AudioSource::SourceThreadStopped(vthread_t sourceThreadHandle, DWORD sourceThreadID)
#endif
{
	return 0;
}

int
AudioSource::GiveNextAudioSample(AudioSample **ppAudioSample, AudioSink *audioSink)
{
	int result = GenerateData(ppAudioSample);
	EnterCriticalSection(&audioSinksMutex);
	vector<AudioSink *>::iterator iter = audioSinks.begin();
	for (iter = audioSinks.begin(); iter != audioSinks.end(); iter++)
	{
		if (*(iter) == audioSink)
		{
			continue;
		}
		SendAudioSample(*ppAudioSample, *iter);
	}
	LeaveCriticalSection(&audioSinksMutex);
	return 0;
}

int
AudioSource::GenerateData(AudioSample **audioSample)
{
	tracer.tracef(ERR, "GenerateData : ERROR : Pure Virtual Function Call !!!\n");
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -