EasyPlayerPro-win本地音频采集实现
来源:互联网 发布:培训机构网络推广方案 编辑:程序博客网 时间:2024/05/23 14:21
EasyPlayerPro-win本地音频采集实现
需求
在安防行业应用中,除了在本地看到摄像机的视频和进行音频监听外,还有一个重要的功能,那就是对讲. EasyPlayerPro-win为了减轻二次开发者的工作量,将本地音频采集也进行了集成.
功能特点
支持获取本地所有音频输入设备列表;
可任意选择任一音频输入设备;
可设置采样率和采样精度及位率;
可设置编码格式(当前支持G711A,G711U,AAC);
实现流程
采用DirectSound8进行本地音频采集;
将采集到的音频数据写入编码队列;
在编码线程中获取源始音频数据,进行音频编码;
编码完成后,将编码数据回调给上层应用;
//获取声音采集设备列表int GetAudioCaptureDeviceList(int *num, SOUND_CAPTURE_DEVICE_INFO **pDeviceInfo);int OpenAudioCaptureDevice(int captureDeviceIndex);int GetSupportWaveFormatList(int *num, WAVEFORMATEX **ppWaveFormatEx);int StartCapture(int waveFormatExIndex, DirectSoundCaptureCallback callback, void *userptr);int StopCapture();void CloseAudioCaptureDevice();static LPTHREAD_START_ROUTINE __stdcall _lpDirectSoundCaptureThread ( LPVOID _pParam );
代码实现
//开始采集音频int DirectSoundCapturer::StartCapture(int waveFormatExIndex, DirectSoundCaptureCallback callback, void *userptr){if (NULL == pSoundCaptureThread) return -1;if (NULL == pSoundCaptureThread->pSupportWaveFormatEx) return -1;if (waveFormatExIndex< 0 || waveFormatExIndex>=pSoundCaptureThread->supportWaveFormatExCount) return -2;HRESULT hr = S_OK;WAVEFORMATEX *_wfxInput = (WAVEFORMATEX*)&pSoundCaptureThread->pSupportWaveFormatEx[waveFormatExIndex];memcpy(&pSoundCaptureThread->inWaveFormatEx, _wfxInput, sizeof(WAVEFORMATEX));DSCBUFFERDESC dscbd;ZeroMemory( &dscbd, sizeof(DSCBUFFERDESC) );pSoundCaptureThread->dwNotifySize = max( 1024, _wfxInput->nAvgBytesPerSec / 8 );pSoundCaptureThread->dwNotifySize -= pSoundCaptureThread->dwNotifySize % _wfxInput->nBlockAlign;pSoundCaptureThread->dwCaptureBufferSize = pSoundCaptureThread->dwNotifySize * 16;dscbd.dwSize = sizeof(DSCBUFFERDESC);dscbd.dwBufferBytes = pSoundCaptureThread->dwCaptureBufferSize;dscbd.lpwfxFormat = _wfxInput;hr = pSoundCaptureThread->lpDirectSoundCapture8->CreateCaptureBuffer( &dscbd, &pSoundCaptureThread->lpDSBCapture, NULL);if (FAILED(hr)) return -3;if (NULL == pSoundCaptureThread->lpDSBCapture) return -4;pSoundCaptureThread->dwNextCaptureOffset = 0;hr = pSoundCaptureThread->lpDSBCapture->QueryInterface( IID_IDirectSoundNotify, (PVOID*)&pSoundCaptureThread->lpDSNotify );for( INT i = 0; i < 16; i++ ) { pSoundCaptureThread->DSBPosNotify[i].dwOffset = (pSoundCaptureThread->dwNotifySize * i) + pSoundCaptureThread->dwNotifySize - 1; pSoundCaptureThread->DSBPosNotify[i].hEventNotify = pSoundCaptureThread->hCaptureNotifyEvent;}hr = pSoundCaptureThread->lpDSNotify->SetNotificationPositions( 16, pSoundCaptureThread->DSBPosNotify);hr = pSoundCaptureThread->lpDSBCapture->Start( DSCBSTART_LOOPING );//m_fIsCapture = TRUE;if (SUCCEEDED(hr)){ if (NULL == pSoundCaptureThread->hCaptureNotifyThread) { pSoundCaptureThread->flag = 0x01; pSoundCaptureThread->userPtr = this; pSoundCaptureThread->captureCallback = callback; pSoundCaptureThread->callbackUserPtr = userptr; pSoundCaptureThread->hCaptureNotifyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_lpDirectSoundCaptureThread, pSoundCaptureThread, 0, NULL); while (pSoundCaptureThread->flag!=0x02 && pSoundCaptureThread->flag!=0x00) {Sleep(100);} }}return hr;}//获取源始音频数据int DirectSoundCapturer::ProcessCaptureData(){HRESULT hrRet = 0;LONG lLockSize;if (NULL == pSoundCaptureThread) return -1;if (pSoundCaptureThread->flag == 0x03) return -1;if (NULL == pSoundCaptureThread->lpDSBCapture) return -1;do { DWORD dwCapturePos, dwReadPos; hrRet = pSoundCaptureThread->lpDSBCapture->GetCurrentPosition( &dwCapturePos, &dwReadPos ); lLockSize = dwReadPos - pSoundCaptureThread->dwNextCaptureOffset; if( lLockSize < 0 ) lLockSize += pSoundCaptureThread->dwCaptureBufferSize; // Block align lock size so that we are always write on a boundary lLockSize -= (lLockSize % pSoundCaptureThread->dwNotifySize); if( lLockSize == 0 ) { hrRet = -1; break; } PVOID pCapturedData[2] = {NULL, NULL}; DWORD dwCaptureLength[2] = {0, 0}; // Lock the capture buffer down hrRet = pSoundCaptureThread->lpDSBCapture->Lock( pSoundCaptureThread->dwNextCaptureOffset, lLockSize, &pCapturedData[0], &dwCaptureLength[0], &pCapturedData[1], &dwCaptureLength[1], 0L ); if( FAILED( hrRet ) ) { hrRet = -2; break; } if (NULL != pSoundCaptureThread->captureCallback) { pSoundCaptureThread->captureCallback(&pSoundCaptureThread->inWaveFormatEx, pSoundCaptureThread->callbackUserPtr, (unsigned char *)pCapturedData[0], (int)dwCaptureLength[0], (unsigned char *)pCapturedData[1], (int)dwCaptureLength[1]); } pSoundCaptureThread->dwNextCaptureOffset += dwCaptureLength[0]; pSoundCaptureThread->dwNextCaptureOffset %= pSoundCaptureThread->dwCaptureBufferSize; // Circular buffer if( pCapturedData[1] != NULL ) { pSoundCaptureThread->dwNextCaptureOffset += dwCaptureLength[1]; pSoundCaptureThread->dwNextCaptureOffset %= pSoundCaptureThread->dwCaptureBufferSize; // Circular buffer } pSoundCaptureThread->lpDSBCapture->Unlock( pCapturedData[0], dwCaptureLength[0], pCapturedData[1], dwCaptureLength[1] );} while(0);return hrRet;}
关于EasyPlayerPro
EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP、RTMP、HTTP、HLS、UDP、RTP、File等多种流媒体协议播放、支持本地文件播放,支持本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种功能特性,核心基于ffmpeg,稳定、高效、可靠、可控,支持Windows、Android、iOS三个平台,目前在多家教育、安防、行业型公司,都得到的应用,广受好评!
EasyPlayerPro:https://github.com/EasyDSS/EasyPlayerPro
点击链接加入群【EasyPlayer & EasyPlayerPro】:544917793
技术支持
邮件:support@easydarwin.org
QQ交流群:544917793
EasyPlayerPro是一款非常稳定的全协议/全功能播放器组件,可以通过以上渠道进行更深入的技术与合作咨询;
获取更多信息
EasyDarwin开源流媒体服务器:www.EasyDarwin.org
EasyDSS商用流媒体解决方案:www.EasyDSS.com
EasyNVR无插件直播方案:www.EasyNVR.com
Copyright © EasyDarwin Team 2012-2017