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

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;i<BUFFER_NUM;i++){m_Hdr[i].lpData =NULL;}m_BufferSize=3200;//80和180的倍数便于压缩}////函数功能://析构函数,清理工作//参数说明:////返回值://CWaveRecorder::~CWaveRecorder(){Stop();}BOOL CWaveRecorder::Start(DWORD proc,int nSurgestSamples,WAVEFORMATEX* format){MMRESULT mmReturn = 0;if(m_bRecording||!proc){return FALSE;}else{if(format == NULL){format=&m_Format;}m_BufferSize=nSurgestSamples;//m_hWnd=proc; //打开指定音频设备准备录制,CALLBACK_WINDOW表示hWnd是一个窗口句柄mmReturn = ::waveInOpen( &m_hRecord, WAVE_MAPPER, format,(DWORD)proc, (DWORD)this, CALLBACK_FUNCTION);if(mmReturn){//MessageBox(NULL,"failed open","",MB_OK);return FALSE;}else{// make several input buffers and add them to the input queuefor(int i=0;i<BUFFER_NUM;i++){if(!AddInputBuffer(&m_Hdr[i],format)){waveInClose(m_hRecord);return false;}}// start recordingmmReturn = ::waveInStart(m_hRecord);if(mmReturn ){waveInClose(m_hRecord);return FALSE;}m_bRecording = true;}}return TRUE;}////函数功能://开始采集声音前准备//参数说明://hWnd:     [in] 父窗口句柄//nSurgestSamples: [in] 每秒采样率//format:   [in][out] 音频数据格式//返回值://若成功返回TRUE,否则返回FALSEBOOL CWaveRecorder::Start(HWND hWnd,int nSurgestSamples,WAVEFORMATEX *format)//suggest{MMRESULT mmReturn = 0;if(m_bRecording||!hWnd){return FALSE;}else{if(format == NULL){format=&m_Format;}m_BufferSize=nSurgestSamples;m_hWnd=hWnd; //打开指定音频设备准备录制,CALLBACK_WINDOW表示hWnd是一个窗口句柄mmReturn = ::waveInOpen( &m_hRecord, WAVE_MAPPER, format,(DWORD)hWnd, NULL, CALLBACK_WINDOW);if(mmReturn){//MessageBox(NULL,"failed open","",MB_OK);return FALSE;}else{// make several input buffers and add them to the input queuefor(int i=0;i<BUFFER_NUM;i++){if(!AddInputBuffer(&m_Hdr[i],format)){waveInClose(m_hRecord);return false;}}// start recordingmmReturn = ::waveInStart(m_hRecord);if(mmReturn ){waveInClose(m_hRecord);return FALSE;}m_bRecording = true;}}return TRUE;}////函数功能:////参数说明:////返回值://若成功返回TRUE,否则返回FALSEvoid CWaveRecorder::Stop(){MMRESULT mmReturn = MMSYSERR_NOERROR;if(!m_bRecording){return;}else{m_bRecording = FALSE;Sleep(200);mmReturn = ::waveInReset(m_hRecord);if(mmReturn){return;}else{mmReturn = ::waveInClose(m_hRecord);//if(mmReturn)//TRACE(L"Error Stop\n");}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,否则返回FALSEBOOL 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_STATUSWM_USER+100#define WM_WAVE_FORMATWM_USER+101#define WM_CAPTURE_DATAWM_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 timeLONG lTimeBetweenFires = (LONG)hnsDefaultDevicePeriod / 2 / (10 * 1000); // convert to millisecondsBOOL 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);elsereturn 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();}elsereturn 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();elsereturn FALSE;}BOOL CPlaybackCapture::IsCapturing() const{if(m_pImpl != NULL)return m_pImpl->IsCapturing();elsereturn 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,原来是40DWORD 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)

老江饲料商城