DXGI高帧率屏幕录像软件源码解析(声音捕获,抓屏,ffmpeg录像,MP4录像,flv录像,麦克风采集)(第2篇声音采集部分)

本文资源下载:(91条消息) dxgi桌面屏幕录像(windows屏幕录像,硬件编码,声音捕获,音视频同步)-编解码文档类资源-CSDN文库https://download.csdn.net/download/xjb2006/85109025

(91条消息) DXGI抓屏优化扩展:GPU硬件编码保存文件即录像为MP4和FLV,外加麦克风+计算机声音_周星星的星的博客-CSDN博客_dxgi 录屏https://blog.csdn.net/xjb2006/article/details/117849944由于篇幅有限,分为4篇发表:

1、SDK接口一览:

2、声音采集部分:

3、屏幕捕获部分:

4、编码,录像部分:

距离上篇文章已经过了快1年了,才有时间把正式DEMO传上来,直接上个截图看看吧:

 该DEMO演示了win10屏幕录像的核心功能,包含音源选择(支持麦克风,计算机声音和2者混合),屏幕选择(主副屏选择),鼠标,帧率,码率,硬件编码,实时预览,双录制(同时录制为flv,mp4)等基本功能。为了扩展需要,程序核心模块做成DLL动态库,可以多语言扩展,适用于C++,C#,JAVA,VB,Python等等其他语言。

一、音源选择+声音采集:

运用的技术为directshow(directsound)技术和Core Audio APIs(也叫WSAAPI,vista,win7以后适用),也用了ACM采样率转换(也可以用ffmpeg,看自己喜好),Wave API录音,也不容易,看似简单的声音捕获用到这么多技术。贴代码:

麦克风声音捕获 :



#include "stdafx.h"
#include "WaveRecorder.h"


//
// Construction/Destruction
//


//
//函数功能:
//构造函数,初始化工作
//参数说明:
//
//返回值:
//
CWaveRecorder::CWaveRecorder()
{
	
	m_hRecord=NULL;
	
	//m_Format.cbSize =0;                     //
	//m_Format.wFormatTag =WAVE_FORMAT_PCM;   //最常用的音频格式
	//m_Format.nAvgBytesPerSec=8000;          //平均数据传输率Bps: = nSamplesPerSec*nBlockAlign
	//m_Format.nBlockAlign =1;                //wFormatTag格式下最小的原子单位(byte)
	//m_Format.nChannels =1;                  //音频数据通道
	//m_Format.nSamplesPerSec =8000;          //音频采样率8000hz
	//m_Format.wBitsPerSample= 8;             //每次采样数据的位数bit
	//
	//初始化源声音格式
	m_Format.cbSize =0;
	m_Format.wFormatTag = WAVE_FORMAT_PCM;
	m_Format.nChannels = 2;	
	m_Format.wBitsPerSample= 16;
	m_Format.nSamplesPerSec = 44100;
	m_Format.nBlockAlign =  m_Format.nChannels   *   m_Format.wBitsPerSample   /   8;
	m_Format.nAvgBytesPerSec=m_Format.nSamplesPerSec   *   m_Format.nBlockAlign;

	m_bRecording=false;
    //BUFFER_NUM个音频数据缓冲
	for(int i=0;ilpData;
	}
	return NULL;
		
}

//
//函数功能:
//重新设置声音缓冲区
//参数说明:
//pHdr: [in][out] 声音缓冲区结构体指针
//返回值:
//
void CWaveRecorder::SetBuffer(LPWAVEHDR pHdr)
{
	MMRESULT mmReturn = 0;
	if(m_bRecording)
	{
		mmReturn = ::waveInPrepareHeader(m_hRecord,pHdr, sizeof(WAVEHDR));
		if(mmReturn)
		{
			return ;
		}
		else
		{
			mmReturn = ::waveInAddBuffer(m_hRecord, pHdr, sizeof(WAVEHDR));
		}
	}
}

//
//函数功能:
//增加声音输入缓冲区
//参数说明:
//pHdr: 
//返回值:
//若成功返回TRUE,否则返回FALSE
BOOL CWaveRecorder::AddInputBuffer(LPWAVEHDR pHdr,WAVEFORMATEX *format)
{
	MMRESULT mmReturn = 0;
	
	ZeroMemory(pHdr, sizeof(WAVEHDR));
	int nSize=format->nBlockAlign*m_BufferSize;
	char* pBuf=new char[nSize];
	if(pHdr->lpData)
		delete pHdr->lpData;
	pHdr->lpData = pBuf;
	pHdr->dwBufferLength = nSize;

    //为声音输入设备准备一个声音缓冲
	mmReturn = ::waveInPrepareHeader(m_hRecord,pHdr, sizeof(WAVEHDR)); //m_hRecord为声音输入设备的句柄
	if(mmReturn)
	{
		return false;
	}
    //发送声音缓冲区给数据输入设备
	mmReturn = ::waveInAddBuffer(m_hRecord, pHdr, sizeof(WAVEHDR));
	if(mmReturn)
	{
		return false;
	}
	return true;
}

计算机声音采集:这里有个问题,core audio api(WSAAPI)采集时 ,只能采集声卡非静音的情况,如果声卡静音,是没有数据的。我这里解决的方法是不停向声卡播放声音静音数据,这样既不会发生采集不到数据,又不会影响声音数据。如果您有更好的办法,请告诉我,谢谢

#include "stdafx.h"

#ifdef _WIN7

#include "PlaybackAudioCapture.h"
//#include "ClassRegister.h"
//#include "TimeCostDebug.h"
#include "Admin.h"


#include 
#include 
#include 
#include 
extern CAdmin *g_pMain;
CPlaybackCapture *m_pCap=0;

#define AUDIO_CAPTURE_CLASS _T("audio_cpature_message_class")

enum CAPTURE_STATUS 
{
	CAPTURE_START,
	CAPTURE_STOP,
	CAPTURE_ERROR
};

#define WM_CAPTUE_STATUS		WM_USER+100
#define WM_WAVE_FORMAT			WM_USER+101
#define WM_CAPTURE_DATA			WM_USER+102

  CPlaybackCaptureImpl  /
struct capture_thread_data
{
	HANDLE hEventStarted;
	HANDLE hEventStop;
	HWND hWndMessage;
	IMMDevice* pDevice;
};

class CPlaybackCaptureImpl
{
public:
	CPlaybackCaptureImpl();
	~CPlaybackCaptureImpl();

	BOOL Initialize(IPlaybackCaptureEvent* pHandler);
	VOID Destroy();

	BOOL Start();
	VOID Stop();

	BOOL IsInited() const;
	BOOL IsCapturing() const;

	IPlaybackCaptureEvent* GetEventHandler() const	{ return m_pEventHandler;}
	VOID OnThreadEnd();

	

private:
	IMMDevice* GetDefaultDevice();

private:
	HWND m_hWndMessage;
	HANDLE m_hEventStarted;
	HANDLE m_hEventStop;
	IMMDevice* m_pDevice;

	HANDLE m_hThreadCapture;

	//static CClassRegister m_sClassRegister;
	BOOL m_bInited;

	IPlaybackCaptureEvent* m_pEventHandler;

};

LRESULT CALLBACK AudioCaptureMessageProc(HWND hWnd, UINT uMsg,WPARAM wParam, LPARAM lParam)
{
	BOOL bHandled(FALSE);
	LRESULT lRet(0);

	IPlaybackCaptureEvent* pEventHandler = NULL;
	CPlaybackCaptureImpl* pThis = (CPlaybackCaptureImpl*)GetWindowLong(hWnd, GWL_USERDATA);
	if(pThis != NULL)
	{
		pEventHandler = pThis->GetEventHandler();
	}

	switch(uMsg)
	{
	case WM_NCCREATE:
		{
			CREATESTRUCT* pSC = (CREATESTRUCT*)lParam;
			if(pSC != NULL)
			{
				SetWindowLong(hWnd, GWL_USERDATA, (LONG)pSC->lpCreateParams);
			}
		}
		break;

	case WM_CAPTUE_STATUS:
		{
			if(wParam == CAPTURE_START)
			{
				if(pEventHandler != NULL) pEventHandler->OnCatpureStart(lParam);
			}
			else if(wParam == CAPTURE_STOP)
			{
				if(pEventHandler != NULL) pEventHandler->OnCaptureStop();
				if(pThis != NULL) pThis->OnThreadEnd();
			}

			bHandled = TRUE;
		}
		break;

	case WM_WAVE_FORMAT:
		{
			if(pEventHandler != NULL)
			{
				pEventHandler->OnAdjustCaptureFormat((WAVEFORMATEX*)lParam);
			}

			bHandled = TRUE;
		}
		break;

	case WM_CAPTURE_DATA:
		{
			if(pEventHandler != NULL)
			{
				pEventHandler->OnCatpureData((LPBYTE)lParam, wParam);
			}

			bHandled = TRUE;
		}
		break;

	default:
		break;
	}

	if(!bHandled)
	{
		lRet = ::DefWindowProc(hWnd, uMsg, wParam, lParam);	
	}

	return lRet;
}

//CClassRegister CPlaybackCaptureImpl::m_sClassRegister(AUDIO_CAPTURE_CLASS, AudioCaptureMessageProc);

//static VOID NotifyStatus(HWND hWndMesasge, CAPTURE_STATUS eStatus, DWORD dwUserData = 0)
//{
//	::SendMessage(hWndMesasge, WM_CAPTUE_STATUS, (WPARAM)eStatus, dwUserData);
//}
//
//static VOID NotifyWaveFormat(HWND hWndMessage, WAVEFORMATEX* pFormat)
//{
//	::SendMessage(hWndMessage, WM_WAVE_FORMAT, 0, (LPARAM)(WAVEFORMATEX*)pFormat);
//}
//
//static VOID NotifyData(HWND hWndMessage, LPBYTE pData, INT nDataLen)
//{
//	::SendMessage(hWndMessage, WM_CAPTURE_DATA, nDataLen, (LPARAM)pData);
//}

BOOL AdjustFormatTo16Bits(WAVEFORMATEX *pwfx)
{
	BOOL bRet(FALSE);

	if(pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
	{
        pwfx->wFormatTag = WAVE_FORMAT_PCM;
        pwfx->wBitsPerSample = 16;
        pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
        pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;

		bRet = TRUE;
	}
	else if(pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
	{
        PWAVEFORMATEXTENSIBLE pEx = reinterpret_cast(pwfx);
        if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pEx->SubFormat))
		{
           pEx->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
           pEx->Samples.wValidBitsPerSample = 16;
           pwfx->wBitsPerSample = 16;
           pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
           pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;

		  
		   bRet = TRUE;
        } 
	}

	return bRet;
}

UINT CaptureAudio(HWND hWndMessage, IMMDevice* pDevice, HANDLE hEventStarted, HANDLE hEventStop)
{
	HRESULT hr;
	IAudioClient *pAudioClient = NULL;
	WAVEFORMATEX *pwfx = NULL;
	REFERENCE_TIME hnsDefaultDevicePeriod(0);
	HANDLE hTimerWakeUp = NULL; 
	IAudioCaptureClient *pAudioCaptureClient = NULL;
	DWORD nTaskIndex = 0;
	HANDLE hTask = NULL;
	BYTE ABuf[10*1024];
	int nALen=0;
	BOOL bStarted(FALSE);
	do 
	{
		hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pAudioClient);
		if(FAILED(hr)) break;

		hr = pAudioClient->GetDevicePeriod(&hnsDefaultDevicePeriod, NULL);
		if(FAILED(hr)) break;

		hr = pAudioClient->GetMixFormat(&pwfx);
		if (FAILED(hr)) break;

		if(!AdjustFormatTo16Bits(pwfx)) break;

		WAVEFORMATEX format;
		format.cbSize=0;
		format.wFormatTag=1;
		format.nChannels = 2;
		format.wBitsPerSample=16;
		format.nSamplesPerSec=44100;
		format.nBlockAlign = format.nChannels * (format.wBitsPerSample / 8);
		format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
		pwfx->wFormatTag=1;
		pwfx->cbSize=0;
		BOOL bb=g_pMain->m_acm.BeginConvert(pwfx,&format);

		hTimerWakeUp = CreateWaitableTimer(NULL, FALSE, NULL);
		if(hTimerWakeUp == NULL) break;

		SetEvent(hEventStarted);

		//NotifyWaveFormat(hWndMessage, pwfx);
		hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK, 0, 0, pwfx, 0);
		if(FAILED(hr)) break;

		hr = pAudioClient->GetService(__uuidof(IAudioCaptureClient), (void**)&pAudioCaptureClient);
		if(FAILED(hr)) break;

		hTask = AvSetMmThreadCharacteristics(L"Capture", &nTaskIndex);
		if (NULL == hTask) break;

		LARGE_INTEGER liFirstFire;
		liFirstFire.QuadPart = -hnsDefaultDevicePeriod / 2; // negative means relative time
		LONG lTimeBetweenFires = (LONG)hnsDefaultDevicePeriod / 2 / (10 * 1000); // convert to milliseconds

		BOOL bOK = SetWaitableTimer(hTimerWakeUp,&liFirstFire,lTimeBetweenFires,NULL, NULL, FALSE);
		if(!bOK) break;

		hr = pAudioClient->Start();
		if(FAILED(hr)) break;

		//NotifyStatus(hWndMessage, CAPTURE_START, lTimeBetweenFires);
		bStarted = TRUE;

		HANDLE waitArray[2] = { hEventStop, hTimerWakeUp };
		DWORD dwWaitResult;
		UINT32 nNextPacketSize(0);
		BYTE *pData = NULL;
		UINT32 nNumFramesToRead;
		DWORD dwFlags;
		while(TRUE)
		{
			dwWaitResult = WaitForMultipleObjects(sizeof(waitArray)/sizeof(waitArray[0]), waitArray, FALSE, INFINITE);
			if(WAIT_OBJECT_0 == dwWaitResult) break;

			if (WAIT_OBJECT_0 + 1 != dwWaitResult)
			{
				//NotifyStatus(hWndMessage, CAPTURE_ERROR);
				break;
			}

			hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize);
			if(FAILED(hr))
			{
				//NotifyStatus(hWndMessage, CAPTURE_ERROR);
				break;
			}

			if (nNextPacketSize == 0) continue;

			hr = pAudioCaptureClient->GetBuffer(
				&pData,
				&nNumFramesToRead,
				&dwFlags,
				NULL,
				NULL
			);
			if(FAILED(hr))
			{
				//NotifyStatus(hWndMessage, CAPTURE_ERROR);
				break;
			}

			if (0 != nNumFramesToRead)
			{
				memcpy(ABuf+nALen,pData,nNumFramesToRead * pwfx->nBlockAlign);
				nALen+=nNumFramesToRead * pwfx->nBlockAlign;
				if(nALen>=8*1024)
				{
					BYTE *pDes=0;
					DWORD dwLen=0;
					BOOL bOK=g_pMain->m_acm.ConvertSample(ABuf,nALen,(void**)&pDes,&dwLen);
					if(bOK)
					{
						g_pMain->AddBuffer_Teacher((BYTE*)pDes,dwLen);
					}
					nALen=0;
				}
			}

			pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
		}

	}while(FALSE);

	g_pMain->m_acm.Close();
	if(hTask != NULL)
	{
		AvRevertMmThreadCharacteristics(hTask);
		hTask = NULL;
	}

	if(pAudioCaptureClient != NULL)
	{
		pAudioCaptureClient->Release();
		pAudioCaptureClient = NULL;
	}

	if(pwfx != NULL)
	{
		CoTaskMemFree(pwfx);
		pwfx = NULL;
	}

	if(hTimerWakeUp != NULL)
	{
		CancelWaitableTimer(hTimerWakeUp);
		CloseHandle(hTimerWakeUp);
		hTimerWakeUp = NULL;
	}

	if(pAudioClient != NULL)
	{
		if(bStarted)
		{
			pAudioClient->Stop();
			//NotifyStatus(hWndMessage, CAPTURE_STOP);
		}

		pAudioClient->Release();
		pAudioClient = NULL;
	}

	return 0;
}

UINT __stdcall CaptureTheadProc(LPVOID param)
{
	CoInitialize(NULL);

	capture_thread_data* pData = (capture_thread_data*)param;
	HWND hWndMessage = pData->hWndMessage;
	HANDLE hEventStop = pData->hEventStop;
	IMMDevice* pDevice = pData->pDevice;
	HANDLE hEventStarted = pData->hEventStarted;

	UINT nRet = CaptureAudio(hWndMessage, pDevice, hEventStarted, hEventStop);

	CoUninitialize();

	return nRet;
}

CPlaybackCaptureImpl::CPlaybackCaptureImpl()
	:m_hWndMessage(NULL), m_bInited(FALSE), m_pDevice(NULL), 
	m_pEventHandler(NULL), m_hEventStarted(NULL), m_hEventStop(NULL)
{
	m_hThreadCapture=0;
	

}

CPlaybackCaptureImpl::~CPlaybackCaptureImpl()
{
	if(m_bInited) Destroy();
}

VOID CPlaybackCaptureImpl::OnThreadEnd()
{
	if(m_hThreadCapture != NULL)
	{
		CloseHandle(m_hThreadCapture);
		m_hThreadCapture = NULL;
	}
}

IMMDevice* CPlaybackCaptureImpl::GetDefaultDevice()
{
	IMMDevice* pDevice = NULL;
	IMMDeviceEnumerator *pMMDeviceEnumerator = NULL;
	HRESULT hr = CoCreateInstance(
        __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, 
        __uuidof(IMMDeviceEnumerator),
        (void**)&pMMDeviceEnumerator);
	if(FAILED(hr)) return NULL;

    hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
    pMMDeviceEnumerator->Release();
	
	return pDevice;
}

BOOL CPlaybackCaptureImpl::Initialize(IPlaybackCaptureEvent* pHandler)
{
	if(m_bInited) return TRUE;

	m_pEventHandler = pHandler;

	do
	{
		//if(!m_sClassRegister.IsRegistered())
		//{
		//	m_sClassRegister.Register();
		//}

		//m_hWndMessage = CreateWindow(AUDIO_CAPTURE_CLASS, NULL, WS_POPUP, 
		//0, 0, 0, 0, HWND_MESSAGE, NULL, g_hInstance, this);
		//if(m_hWndMessage == NULL) break;

		m_pDevice = GetDefaultDevice();
		if(m_pDevice == NULL) break;

		m_hEventStop = CreateEvent(NULL, TRUE, FALSE, NULL);
		if(m_hEventStop == NULL) break;

		m_hEventStarted = CreateEvent(NULL, TRUE, FALSE, NULL);
		if(m_hEventStarted == NULL) break;

		m_bInited = TRUE;
	
	}while(FALSE);

	if(!m_bInited)
	{
		Destroy();
	}

	return m_bInited;
}

VOID CPlaybackCaptureImpl::Destroy()
{
	if(m_hWndMessage != NULL
		&& ::IsWindow(m_hWndMessage))
	{
		DestroyWindow(m_hWndMessage);
	}

	m_hWndMessage = NULL;

	if(m_pDevice != NULL)
	{
		m_pDevice->Release();
		m_pDevice = NULL;
	}

	if(m_hEventStop != NULL)
	{
		CloseHandle(m_hEventStop);
		m_hEventStop = NULL;
	}

	if(m_hEventStarted != NULL)
	{
		CloseHandle(m_hEventStarted);
		m_hEventStarted = NULL;
	}

	m_bInited = FALSE;
}

BOOL CPlaybackCaptureImpl::IsInited() const
{
	return m_bInited;
}

BOOL CPlaybackCaptureImpl::IsCapturing() const
{
	return m_hThreadCapture != NULL;
}

BOOL CPlaybackCaptureImpl::Start()
{

	if(!m_bInited) return FALSE;
	if(m_hThreadCapture != NULL) return TRUE;

	capture_thread_data data;
	data.hEventStop = m_hEventStop;
	data.hWndMessage = m_hWndMessage;
	data.pDevice = m_pDevice;
	data.hEventStarted = m_hEventStarted;
	
	
	m_hThreadCapture = (HANDLE)_beginthreadex(NULL, 0, &CaptureTheadProc, &data, 0, NULL);
	if(m_hThreadCapture == NULL) return FALSE;
	SetThreadPriority(m_hThreadCapture, THREAD_PRIORITY_HIGHEST);

	HANDLE arWaits[2] = {m_hEventStarted, m_hThreadCapture};
	DWORD dwWaitResult = WaitForMultipleObjects(sizeof(arWaits)/sizeof(arWaits[0]), arWaits, FALSE, INFINITE);
	if(dwWaitResult != WAIT_OBJECT_0)
	{
		Stop();
		return FALSE;
	}

	return TRUE;
}

VOID CPlaybackCaptureImpl::Stop()
{
	if(!m_bInited) return;

	if(m_hEventStop != NULL
		&& m_hThreadCapture != NULL)
	{
		SetEvent(m_hEventStop);
		OnThreadEnd();
	}

}

  CPlaybackCaptureImpl  /


  CPlaybackCapture 

CPlaybackCapture::CPlaybackCapture()
{
	m_pImpl = new CPlaybackCaptureImpl();
}

CPlaybackCapture::~CPlaybackCapture()
{
	if(m_pImpl != NULL)
	{
		delete m_pImpl;
	}
}

BOOL CPlaybackCapture::Initialize(IPlaybackCaptureEvent* pHandler)
{
	if(m_pImpl != NULL)
		return m_pImpl->Initialize(pHandler);
	else
		return FALSE;
}

VOID CPlaybackCapture::Destroy()
{
	if(m_pImpl != NULL)
		 m_pImpl->Destroy();
}

BOOL CPlaybackCapture::Start()
{	
	//if(!m_pwav)
	//{
	//	bool ret;
	//	m_pwav=new WavOutFile("1.wav",48000,16,2,ret);
	//}
	if(m_pImpl != NULL)
	{

		return m_pImpl->Start();
	}
	else
		return FALSE;
}

VOID CPlaybackCapture::Stop()
{
	//if(m_pwav)
	//{
	//	m_pwav->close();
	//	delete m_pwav;
	//	m_pwav=0;
	//}
	if(m_pImpl != NULL)
		m_pImpl->Stop();
}

BOOL CPlaybackCapture::IsInited() const
{
	if(m_pImpl != NULL)
		return m_pImpl->IsInited();
	else
		return FALSE;
}

BOOL CPlaybackCapture::IsCapturing() const
{
	if(m_pImpl != NULL)
		return m_pImpl->IsCapturing();
	else
		return FALSE;	
}

  CPlaybackCapture 


#endif

虚拟声音播放(向声卡送静音数据): 


void CAdmin::AudioTimePlay()
{
	::CoInitialize(0);
	m_pOut_DS=0;
	char XUNIAudio[30*1024];//虚拟声音
	memset(XUNIAudio,0,sizeof(XUNIAudio));
	InitOutPutAudio(0);
	const int nTime=30;//160519改成30,原来是40
	DWORD dwTime1=::timeGetTime();
	while (m_bAudioTimePlay) //repeatedly loop
	{
		if(::timeGetTime()-dwTime1>=nTime)//40ms(25帧)
		{
			int nLen=  44100*2/(1000/nTime);
			m_pOut_DS->AddBuffer(XUNIAudio,nLen);
			dwTime1=::timeGetTime();
		}
		Sleep(5);
	}
	if(m_pOut_DS)
	{
		m_pOut_DS->StopGraph();
		delete m_pOut_DS;
		m_pOut_DS=0;
	}
}

void CAdmin::CloseAudioTimePlayThread()
{
	m_bAudioTimePlay=false;
	if (m_hAudioTimePlayThread != NULL) 
	{
		WaitForSingleObject(m_hAudioTimePlayThread, INFINITE);
		m_hAudioTimePlayThread = NULL;
	}	

	if(m_pOut_DS)
	{
		m_pOut_DS->StopGraph();
		delete m_pOut_DS;
		m_pOut_DS=0;
	}

}

void CAdmin::InitOutPutAudio(BYTE* pAudioFormat)
{
	WAVEFORMATEX format;
	if(pAudioFormat)
		memcpy(&format,pAudioFormat,sizeof(WAVEFORMATEX));
	else
	{
		format.nChannels=2;
		format.wBitsPerSample=16;
		format.nSamplesPerSec=44100;
	}
	回放
	if(m_pOut_DS==0)
	{
		m_pOut_DS=new COutPut_DirectShow();
		m_pOut_DS->CreateGraph();//为什么要加这里,否则不能点播wav文件??????????????????

		format.cbSize=0;
		format.wFormatTag=1;
		format.nBlockAlign = format.nChannels * (format.wBitsPerSample / 8);
		format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
		m_pOut_DS->SetupMediaType((char*)&format,sizeof(WAVEFORMATEX));
		m_pOut_DS->CompleteAudioReceivingGraph();
	}
}

好吧,今天就到此为止,贴个DEMO链接

(91条消息) dxgi桌面屏幕录像(windows屏幕录像,硬件编码,声音捕获,音视频同步)-编解码文档类资源-CSDN文库https://download.csdn.net/download/xjb2006/85109025

 DXGI屏幕录像演示软件(QQ35744025)

你可能感兴趣的:(dxgi,MP4,flv,Windows屏幕采集,计算机播放声音采集,WSAAPI)