EasyPlayerPro Windows播放器进行本地对讲喊话音频采集功能实现
需求
在安防行业应用中,除了在本地看到摄像机的视频和进行音频监听外,还有一个重要的功能,那就是对讲. 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
技术支持
QQ交流群:544917793
获取更多信息
EasyDarwin开源流媒体服务器:www.EasyDarwin.org
EasyDSS商用流媒体解决方案:www.EasyDSS.com
EasyNVR无插件直播方案:www.EasyNVR.com
Copyright © EasyDarwin Team 2012-2017
EasyPlayerPro Windows播放器进行本地对讲喊话音频采集功能实现的更多相关文章
- EasyPlayerPro windows播放器本地音频播放音量控制实现
背景描述 作为一个播放器, 除了能播放视频和声音外,音量控制是绝对不能缺少的功能; 本文在音视频播放的基础上,增加对音量的控制: 实现流程 调用mixerGetDevCaps获取音频输出设备列表; 打 ...
- EasyPlayerPro windows播放器本地配置文件配置方法介绍
需求背景 应EasyPlayerPro某客户需求,在EasyPlayerPro启动时,自动播放指定的url源, 不需要每次都去手动填写, 且实现自动播放,不需要手动的单击播放按钮: 为响应该需求,特增 ...
- EasyPlayerPro Windows播放器本地快照抓拍截图功能实现方法
背景描述 作为一个播放器,截图功能必不可少; 下面主要记录一下截图功能的实现: 实现流程 将解码后的帧进行格式转换(目标格式为RGB24); 采用独立的线程进行截图处理; 截图可保存为BMP或JPG两 ...
- EasyPlayerPro Windows播放器实时流进行本地缓冲区即时回放功能实现
背景描述 参照国内视频监控行业监控软件,实现当前视频的即时回放功能,例如: 监控人员发现刚刚的某个视频点有可疑,就像录像回放一样,想倒回去看一下,但又不想切换到录像回放界面, 此处就体现即时回放的价值 ...
- EasyPlayerPro windows播放器在播放RTMP视频显示重复异常问题解决
问题来源 2017.12.18 今日有杭州某教育领域客户反馈EasyPlayerPro在播放一个rtmp源时,画面显示异常的问题.截图如下: 问题复现 一番思考, 将显示格式改为D3D显示, 正常, ...
- EasyPlayerPro Windows播放器全屏模式下GDI显示出现黑屏问题解决
问题来源 2017.12.21 前天有杭州某教育领域客户反馈有部分视频源在全屏模式下显示黑屏: 问题复现 EasyPlayerPro由于没有实现单个窗口完全全屏,故没有暴露该问题,晚上加班,加上单个窗 ...
- EasyPlayerPro Windows播放器读取xml配置文件中的特殊字符问题
问题被反馈 今日一客户反馈说播放不了带用户名密码的流, 奇怪,这个问题不存在啊-,按照客户的说法, 是将url地址保存在配置文件中,然后再打开EasyPlayerPro运行: 问题复现 在EasyPl ...
- EasyPlayerPro Windows播放器电子放大/局部放大播放功能实现
背景描述 在视频监控软件中,我们看到很多的软件都有电子放大功能, 按住鼠标左键不放,框选一个区域,再松开鼠标左键,即对选中的区域进行放大显示, 且可以重复该操作,逐步放大所需显示的区域, 有没有觉得, ...
- EasyPlayer RTSP Windows播放器D3D,GDI的几种渲染方式的选择区别
EasyPlayer-RTSP windows播放器支持D3D和GDI两种渲染方式,其中D3D支持格式如下: DISPLAY_FORMAT_YV12 DISPLAY_FORMAT_YUY2 DISPL ...
随机推荐
- 牛客网 牛客小白月赛1 F.三视图
F.三视图 链接:https://www.nowcoder.com/acm/contest/85/F来源:牛客网 这个题自己想一下三维的,正视图和左视图中y轴为行数,x轴和z轴是列数,因为 ...
- popcount 算法分析
转载: http://blog.csdn.net/gaochao1900/article/details/5646211 http://www.cnblogs.com/Martinium/archiv ...
- Using Single Alert For Messages And Confirmation Messages In Oracle Forms With Set_Alert_Button_Property
Learn how to use single Oracle Form's Alert object for warning/information messages and confirmation ...
- python selenium中调用js
python 中js中单引号和双引号混合编程 js = 'document.getElementsByName("m:ybzbxmbd:b_BIANHAO")[0].setAttr ...
- 国家商用password(五)基于SM2的软件授权码生成及校验
将公开密钥算法作为软件注冊算法的优点是Cracker非常难通过跟踪验证算法得到注冊机.以下.将介绍使用SM2国密算法进行软件注冊的方法. 生成授权码 选择SM2椭圆曲线參数(P,a,b,N,Gx,Gy ...
- Solidworks如何改变零件颜色
如图所示装配体有三个零件,现在我想把移动件的颜色变成红色 鼠标左键单击要改变颜色的零件(这里点击"移动件"),然后在弹出的菜单中选择颜色,最后点击"编辑颜色" ...
- Python 可视化Twitter中指定话题中Tweet的词汇频率
CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-7-8 @author: guaguastd @name: pl ...
- 每天5道面试题(二)java基础
说出Servlet的生命周期,并说出Servlet和CGI的差别 Servlet被server实例化后,容器执行其init方法,请求到达时执行其service方法,service方法自己主动派遣执行与 ...
- TCP/IP详解 卷一(第二章 链路层)
在TCP/IP协议族中,链路层主要有三个目的: 1.为IP模块发送和接收IP数据报 2.为ARP模块发送ARP请求和接收ARP应答 3.为RARP请求和接收RARP应答 TCP/IP支持多种不同的链路 ...
- Linux ps 命令查看进程启动及运行时间
引言 同事问我怎样看一个进程的启动时间和运行时间,我第一反应当然是说用 ps 命令啦.ps aux或ps -ef不就可以看时间吗? ps aux选项及输出说明 我们来重新复习下ps aux的选项,这是 ...