本文资源下载:(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,否则返回FALSE
BOOL 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,否则返回FALSE
void 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;i<BUFFER_NUM;i++)if(m_Hdr[i].lpData){delete m_Hdr[i].lpData;m_Hdr[i].lpData =NULL;}}
}//
//函数功能:
//获得采集到的声音
//参数说明:
//pHdr: [in][out] 声音数据缓冲区结构体指针
//返回值:
//声音数据缓冲区采集到的声音数据指针
char* CWaveRecorder::GetData(LPWAVEHDR pHdr)
{MMRESULT mmReturn = 0;if(m_bRecording){//清除在waveInPrepareHeader函数中做的准备mmReturn = ::waveInUnprepareHeader(m_hRecord, pHdr, sizeof(WAVEHDR));if(mmReturn){return 0;}return pHdr->lpData;}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 <mmdeviceapi.h>
#include <Audioclient.h>
#include <process.h>
#include <avrt.h>
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+102CPlaybackCaptureImpl  /
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<PWAVEFORMATEXTENSIBLE>(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)

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

  1. java queue源码_Java高并发系列之ArrayBlockingQueue源码解析

    JUC包下定义了一个接口:BlockingQueue.其实现类有ArrayBlockingQueue等.本文先来介绍一下ArrayBlockingQueue.从字面可以看出,ArrayBlocking ...

  2. 局域网聊天软件源码解析

    飞鸽传书卵又会孵出好多蚕宝宝,飞鸽传书最新版桌子带着轻蔑的飞鸽传书神气说,剩下的,爸爸说,大大的眼睛,他去墙角下捉蜘蛛放在自己的飞鸽传书铅笔盒里,这多有意义啊,还上课扭头说话. 我的飞鸽传书班主任姓王 ...

  3. webbench源码解析

    webbench源码解析 webbench简介 webbench是一款用C编写的开源工具,主要用来在Linux下进行网站压力测试.最多可以模拟3万个连接去测试网站的负载能力,并可以设置运行的客户端数. ...

  4. YYCache 源码解析(一):使用方法,架构与内存缓存的设计

    YYCache是国内开发者ibireme开源的一个线程安全的高性能缓存组件,代码风格简洁清晰,阅读它的源码有助于建立比较完整的缓存设计的思路,同时也能巩固一下双向链表,线程锁,数据库操作相关的知识. ...

  5. 美团Leaf源码——号段模式源码解析

    前言 分布式ID生成策略基本要求就是全局不重复,最好还能递增,长度较短,性能高,可用性强.关于相关的实现方案有很多,本文着重使用美团开源的分布式ID生成解决方案--Leaf. 关于Leaf,美团官方的 ...

  6. clickhouse原理解析与开发实战 pdf_重识SSM,“超高频面试点+源码解析+实战PDF”,一次性干掉全拿走...

    重识SSM,"超高频面试点"+"源码解析"+"实战PDF",一次性干掉全拿走!! 01 超高频面试点知识篇 1.1 Spring超高频面试点 ...

  7. Spring @Resource 源码解析 – 为什么是ByName注入

    前言 上篇博客[@Autowired 源码为什么是ByType注入]跟着源码详细的说明了@Autowired在Spring源码里面是如何设计为byType注入的.本篇博客的主要内容就是源码追踪探究@R ...

  8. SEAL全同态加密开源库(七) rns剩余数系统-源码解析

    SEAL全同态加密开源库(七) rns剩余数系统-源码解析 2021SC@SDUSC 2021-11-14 前言 这是SEAL开源库代码分析报告第六篇,本篇将分析util文件夹中的rns.h和rns. ...

  9. SEAL全同态加密开源库(八) rns源码解析(2)

    SEAL全同态加密开源库(七) rns剩余数系统-源码解析 2021SC@SDUSC 2021-11-21 前言 这是SEAL开源库代码分析报告第七篇,本篇将继续分析util文件夹中的rns.h和rn ...

  10. 源码解析异常is expected to be of type ‘xxx‘ but was actually of type ‘xxx‘ 是如何发生的

    前言 这篇博客是对[@Resource 源码解析]做的一个补丁.主要会讲解在使用@Resource的时候发生的is expected to be of type 'xxx' but was actua ...

最新文章

  1. golang count 单字符 字符串 统计函数
  2. JS一起学04:函数返回值、定时器、随机数、自动播放的幻灯片
  3. 对 带头结点的单链表 的操作
  4. php refcount,php的函数的形参refcount为何要加2
  5. hibernate和struts实现分页
  6. node获取图片路径_Deno 正式发布,彻底弄明白和 node 的区别
  7. 云承软件和云溪哪个好_诺承木工开料机使用什么软件好
  8. js案例:动态生成表格
  9. 最详细的Extmail安装文档
  10. 学plc还是学java_要学PLC想走PLC工程师之路的看看
  11. 屏幕录像专家V7.5注册机
  12. 人工智能终将自我进化?排除无用功能,让自己更加完美?
  13. ASAN Runtime【源码分析】(一)——初始化
  14. 无人驾驶技术入门(五)| 没有视觉传感器,还谈什么无人驾驶?
  15. 6410同时支持colorkey和aphablend
  16. JVM (JAVA虚拟机)
  17. 计算机网络复习04——网络层
  18. 【Spring Cloud】OpenFeign和Spring Cloud Loadbalancer调用失败后的重试机制比较
  19. 用MSYS2安装mingw
  20. 运营管理整改报告范文_快递整改报告怎么写

热门文章

  1. 问题:找不到该项目,该项目不在指定目录下.......请确认位置......
  2. python识别手写数字knn_手写数字识别以及Python sklearn KNN实现
  3. pboc c语言 开发,APDU
  4. R语言和Python交互
  5. 微信小程序上传图片失败总结
  6. java项目组会议纪要
  7. java程序中,如何设置周一为一周的开始?如何设置周一为一周的第一天? 或者说,如何理解java的setFirstDayOfWeek()方法?
  8. Word 2013新建文档默认使用自己设置的样式
  9. MS17010原生打法
  10. python科赫雪花小包裹_034 实例8-科赫雪花小包裹-Go语言中文社区