基于vfw的局域网语音聊天室系统源码论文
-
- 语音视频聊天
- UDP套接字的运用
- 语音视频聊天
在实现语音视频聊天时,采用的是基于UDP套接字的点对点模式,而UDP面向的是无连接的数据服务,其套接字的使用如图10所示。

图10 UDP套接字的使用
-
-
- 视频的捕获
-
利用VFW接口,视频捕获可以分为以下几个步骤:
- 建立视频采集窗口:该窗口用来接收视频捕捉驱动程序传来的数据和消息。
- 连接视频驱动程序:将建立的视频捕捉窗口与视频设备驱动程序相连。
- 视频捕获初始化。
- 视频捕捉设置:VFW下视频捕捉参数的设置可以通过调用函数或弹出对话框的形式来实现。一般视频驱动程序允许设置的参数包括视频源选择、视频格式、视频显示格式等。
- 设置回调函数:通过回调函数来通知程序视频事件的发生,比如捕捉一帧图像成功的消息,捕捉出错的消息等。
- 结束捕捉:结束捕捉是应该有一些清除工作。如释放分配的内存,断开捕捉窗口与视频捕捉驱动程序的连接,清除视频捕捉窗口等。
窗口类为捕获数字视频流及其相关操作提供了很大的方便,灵活编写其中的回调函数可满足实时视频传输的需要,例如应用程序可直接从缓冲中取得数字视频并对其进行压缩编码后实时地传到远端的客户端。
在VC++中,采用VFW技术,客户端通过capSetCallbackOnFrame()注册回调函数,当采集卡采集到一幅图像后,系统就会自动调用回调函数,然后再回调函数中使用ICSeqCompressFrame()函数进行压缩。然后再通过Winsock将压缩后的数据发送到另一客户端。该客户端接收完一帧以后,交给ICDecompress()解压,最后用SetDIBitsToDevice()将图像显示出来。
基本的捕获设置包括设置捕获速度(每秒捕获多少帧)、是否同时捕获声频、捕获缓冲、允许最大丢失多少帧和是否使用DOS内存,以及使用键盘的哪个键或鼠标的哪个键来终止捕获等内容,这些设置使用CAPTUREPARAMS结构来描述,capCaptureGetSetup宏来得到当前的设置,然后改变此结构的成员变量,再使用capCaptureSetSetup宏设置新的设置。
设置捕获速度,通过使用capCaptureGetSetup宏来得到当前的捕捉速度,将当前的捕捉速度保存在CAPTUREPARAMS结构的dwRequestMicroSecPerFrame成员变量中,也可以通过设置此变量来改变当前设置值。
设置终止捕获,同样通过使用capCaptureGetSetup宏来得到当前的设置,当前按键设置保存在CAPTUREPARAMS结构的vKeyAbort成员中,鼠标设置保存在fAbortLeftMouse和fAbortRightMouse成员中,通过修改可以设置新的热健或者鼠标左右键,修改完成后,使用capCaptureSetSetup宏来进行更新。
捕获的时间限制,用CAPTUREPARAMS结构中的fLimitEnabled表示捕获是否有时间的限制,wTimeLimit用来设置指示捕获最大的持续时间,其单位为秒。使用capCaptureGetSetup宏来得到当前的设置值。
下面程序为设置CAPTUREPARAMS结构的实现代码:
BOOL VideoCapture::SetCapturePara()
{
CAPTUREPARMS CapParms={0};
capCaptureGetSetup(m_capwnd,&CapParms,sizeof(CapParms));
//得到当前的捕获速度
CapParms.fAbortLeftMouse = FALSE;
CapParms.fAbortRightMouse = FALSE;
CapParms.fYield = TRUE;
CapParms.fCaptureAudio = FALSE;
CapParms.wPercentDropForError = 80;
if(!capCaptureSetSetup(m_capwnd,&CapParms,sizeof(CapParms)))
{
// log.WriteString("\n Failed to set the capture parameters ");
return FALSE;
}
// Set Video Format
capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));
m_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH;
m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT;
BOOL ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));
// log.WriteString("\n Video parameters set properly");
return ret;
}
//终止一个捕获任务
BOOL VideoCapture::StopCapture()
{
capCaptureStop(m_capwnd);
capCaptureAbort(m_capwnd);
Sleep(500);
return TRUE;
}
-
-
- 捕获窗口
-
在捕获前必须创建一个捕获窗口(Capture Widnow),下面介绍有关捕获窗口的情况:创建一个AVICap捕获窗口,用capCreateCaptureWindow函数并返回一个句柄。将捕获窗口连接至捕获设备,用capDriverConnect函数来使一个捕获窗口与一个捕获设备连接或关联连接上后,就可以通过捕获窗口向捕获设备发送各种消息,可以使用函数capGetDriverDescription来获得已安装的捕获设备名称及版本,将其列举在实现程序过程中。再利用capDriverGetName函数来得到捕获设备的名称将获得的版本发送到capDriverGetVersion。如果断开捕获窗口与捕获设备的连接用capDriverDisconnect。
捕获窗口的状态,用capGetStatus函数来获得当前捕获窗口的状态,得到一个CAPSTATUS结构的拷贝。该结构的内容包含了图片的尺寸、卷轴的当前位置、overlay和preview是否已设置。由于其信息是动态的,每当捕获的视频流的尺寸发生改变,程序应该在获取捕获设备的视频格式以后及时进行刷新。而捕获窗口尺寸的改变并不影响实际的捕获视频流的尺寸。该尺寸由视频捕获设备的格式和视频对话框决定。
//捕获窗口
BOOL VideoCapture::Initialize()
{
char devname[128]={0},devversion[128]={0};
int index=0;
BOOL ret = TRUE, ret1 = TRUE, ret2 = TRUE, ret3 = TRUE;
TRACE("VideoCapture::Initialize\n");
//创建一个AVICap捕获窗口
m_capwnd = capCreateCaptureWindow("Capture",WS_POPUP,0,0,1,1,0,0);
if(!m_capwnd)
{
return FALSE;
}
//connect callback functions
ret = capSetUserData(m_capwnd,this);
//Change destroy functions also........
ret1 = capSetCallbackOnVideoStream(m_capwnd,OnCaptureVideo);
//得到已安装的捕获设备的名称及版本
ret2 = capGetDriverDescription(index,devname,100,devversion,100);
// Connect to webcam driver
//使一个捕获窗口与一个捕获设备连接或关联
ret3 = capDriverConnect(m_capwnd,index);
if(!(ret && ret1 && ret2 && ret3))
{
// Device may be open already or it may not have been
// closed properly last time.
AfxMessageBox("Unable to open Video Capture Device");
// log.WriteString("\n Unable to connect driver to the window");
m_capwnd=NULL;
return FALSE;
}
// Set the capture parameters
if(SetCapturePara()==FALSE)
{
// log.WriteString("\n Setting capture parameters failed");
capDriverDisconnect(m_capwnd); //使捕获窗口与一个捕获设备断开
return FALSE;
}
return TRUE;
}
-
-
- 视频捕获驱动
-
视频捕获必须具有视频捕获驱动才能进行,其相关内容如下:
视频捕获驱动的性能,capDriverGetCap函数得到当前连接视频驱动的硬件性能,该信息保存在CAPDRIVERCAPS结构中;视频对话框,每个视频驱动能够提供4个对话框来控制视频捕获和数字化处理视频对话框定义的视频压缩率和图像品质等。视频对话框都在视频捕获驱动中定义。这个四个对话框分别为:Video Source对话框用于控制选择视频来源(capDlgVideoSource);Video Format对话框定义视频帧的尺寸和精度,以及视频捕获卡的压缩设置(capDlgVideoFormat);Video Display对话框控制在视频捕获期间相关显示器上的显示(capDlgVideoDisplay);Video Compression对话框控制压缩和图像品质(caoDlgVideoCompression)。
-
-
- 语音录制
-
在音频的录制和播放时,采用的用户界面线程来处理,是CWinThread对象,根据前面线程的介绍,一步一步的来实现。录音用的一个CWinThread对象CAudioRec来实现,部分实现代码:
LRESULT CAudioRec::OnStartRecording(WPARAM wp, LPARAM lp)
{
if(recording) return FALSE;
//打开录音设备
MMRESULT mmReturn = ::waveInOpen( &m_hRecord, WAVE_MAPPER,
&m_WaveFormatEx, ::GetCurrentThreadId(), 0, CALLBACK_THREAD);
if(mmReturn!=MMSYSERR_NOERROR ) return FALSE;
if(mmReturn==MMSYSERR_NOERROR )
{
for(int i=0; i < MAXRECBUFFER ; i++)
{
//为录音设备准备缓存
mmReturn = ::waveInPrepareHeader(m_hRecord,
rechead[i], sizeof(WAVEHDR));
//给输入设备增加一个缓存
mmReturn = ::waveInAddBuffer(m_hRecord,
rechead[i], sizeof(WAVEHDR));
}
mmReturn = ::waveInStart(m_hRecord); //开始录音
if(mmReturn==MMSYSERR_NOERROR ) recording=TRUE;
}
return TRUE;
}
-
-
- 语音回放
-
相对录音而言,播放就简单多了,同样用的一个CWinThread对象CAudioPlay来实现,部分实现代码:
LRESULT CAudioPlay::OnWriteSoundData(WPARAM wParam, LPARAM lParam)
{
// TRACE("CAudioPlay::OnWriteSoundData\n");
MMRESULT mmResult = FALSE;
char *p=NULL;
int length=(int) wParam;
if(Playing==FALSE) return FALSE;
if(length<=0) return FALSE;
WAVEHDR *lpHdr=new WAVEHDR;
if(!lpHdr) return FALSE;
p=new char [length];
if(!p) {delete lpHdr;
return FALSE;}
ZeroMemory(lpHdr,sizeof(WAVEHDR));
ZeroMemory(p,length);
CopyMemory(p,(char*)lParam,length);
lpHdr->lpData=p;
lpHdr->dwBufferLength = length;
mmResult = ::waveOutPrepareHeader(m_hPlay, lpHdr, sizeof(WAVEHDR));
//为回放设备准备内存块
if(mmResult)
{
delete lpHdr;delete p;
return mmResult;
}
mmResult = ::waveOutWrite(m_hPlay, lpHdr, sizeof(WAVEHDR));//写数据(放音)
if(mmResult){delete lpHdr;delete p;
return mmResult; }
m_Count++;
return MMSYSERR_NOERROR;
}
相关文章:
基于vfw的局域网语音聊天室系统源码论文
语音视频聊天 UDP套接字的运用 在实现语音视频聊天时,采用的是基于UDP套接字的点对点模式,而UDP面向的是无连接的数据服务,其套接字的使用如图10所示。 图10 UDP套接字的使用 视频的捕获 利用VFW接口,视频捕获可以分为以下几个步骤: 建立视频采集窗口…...
GoogleTest : 测试框架(单元测试)
GoogleTest googletest: GoogleTest - Google Testing and Mocking Framework googletest 是一个由 Google 的测试技术团队开发的测试框架,它考虑到了谷歌的特定需求和限制。无论你使用的是 Linux、Windows 还是 Mac,只要你编写 C 代码,goo…...
商业银行财富管理“智能原生”能力呈阶梯化,AI助力商业模式趋向多元化发展
易观:金融业的财富管理从经营角度来看,是“客户与渠道管理场景运营产品研发”三位一体共同构建以客户为中心,数据驱动的业务经营体系。其中,“客户与渠道管理”是将客户利益作为核心目标,通过升级用户体验、客户全生命…...
2022年中国云市场份额:阿里云腾讯云下降
我是卢松松,点点上面的头像,欢迎关注我哦! 4月23日,IDC发布《中国公有云服务市场(2022下半年)跟踪》,占据前四的分别为阿里云(40.6%)、华为云(11.0%)、腾讯云(11.0%)、中国电信(8.7%)。咱们说重点,如下图所…...
Redis入门学习笔记【二】Redis缓存
目录 一、Redis缓存 二、Redis使用缓存遇到的问题 2.1 数据一致性 2.2缓存雪崩 2.3 缓存穿透 2.4 缓存击穿 一、Redis缓存 数据缓存是Redis最重要的一个场景,为缓存而生,在springboot中,一般有两种使用方式: 直接通过RedisT…...
go1.20环境安装以及beego框架配置
打开网址下载安装包选择对应安装包来下载安装(个人是windows,下载的1.20.3版本) 默认情况下会安装在C盘,但是我安装在了D盘目录 根据安装提示一步步next,直至完成 go get 在1.18版本之后就弃掉了,换成了install 配置自己的work…...
vue---组件逻辑复用方法:Mixin/HOC/Renderless组件
目录 1、Mixin 2、HOC 3、Renderless组件 下文通过表单校验来分别讲解Mixin/HOC/Renderless组件这三种方式。 1、Mixin 通过mixin将一个公用的validate函数同步到每一个组件中去 mixin使用详细介绍见:vue---mixin混入_maidu_xbd的博客-CSDN博客一个混入对象可…...
阳光万里,祝你上岸——免统考在职研究生
什么是在职研究生 在职研究生,是国家计划内,以在职人员身份,部分时间在职工作,部分时间在校学习的研究生教育的一种类型。在职攻读硕士方式有三种: 1.双证非全日制研究生:为普通高等教育研究生学历&#x…...
大孔树脂型号,A-722,ADS500,ADS600,ADS750,ADS800
一、产品介绍 基于吸附功能的聚苯乙烯特种树脂 Tulsimer ADS-600 是一款没有离子官能基的,由交联聚苯乙烯合成的功能强大的吸附型树脂。 Tulsimer ADS-600 主要应用于水溶液中吸附酚及其化合物,氯代烃等含氯物质,表面活性剂࿰…...
MATLAB在逐渐被Python淘汰吗?
Python和MATLAB都是常用的科学计算工具,但是它们有很多不同之处。 Python是一种通用编程语言,而MATLAB主要是用来做数值计算的。Python的基本数据类型和一般的编程语言一样普遍,但是离开了Numpy这个包,就不再有数组或者矩阵的数据…...
黑盒测试过程中【测试方法】讲解1-等价类,边界值,判定表
在黑盒测试过程中,有9种常用的方法:1.等价类划分 2.边界值分析 3.判定表法 4.正交实验法 5.流程图分析 6.因果图法 7.输入域覆盖法 8.输出域覆盖法 9.猜错法 我们一般用第1种和第2种方法最多。此处简单介绍一下这两种方法,详细介绍其…...
函数栈帧的创建和销毁
文章目录 main函数栈帧的创建为什么局部变量的值是随机值函数是怎么传参的?传参的顺序是什么?函数调用结束是怎么返回的 main函数栈帧的创建 先在栈帧里面为main函数开辟出一块空间,且这块空间由两个寄存器esp和ebp来进行维护,当在调用另一个函数时这两个寄存器就去维护为这…...
测试Ocr工具IronOCR(续:编写图片圈选程序)
上一篇文章学习了IronOCR的基本用法之后,计划做一个加载本地图片后,从图片中圈选某一位置的文字,然后调用IronOCR识别圈选区域文本的程序。本文实现从本地加载图片并完成圈选的功能。 主要的功能包括以下几点: 1ÿ…...
React之Redux的使用
文章目录 Redux 介绍概述Redux 是什么?为什么要使用 Redux?我什么时候应该使用 Redux?Redux 库和工具React-ReduxRedux ToolkitRedux DevTools 扩展 Redux 术语和概念State 管理不可变性 Immutability术语ActionAction CreatorReducerReducer…...
数据库系统概论--第五章课后习题
1.什么是数据库的完整性? 答:数据库的完整性是指数据的正确性和相容性。 2. 数据库的完整性概念与数据库的安全性概念有什么区别和联系? 答: 数据的完整性和安全性是两个不同的概念,但是有一定的联系。前者是为了防止数据库中存…...
小程序开发费用估算:如何控制项目成本?
在当今数字化的时代,小程序已经成为了很多企业和个人开展业务的重要手段。小程序的开发需要耗费时间和资源,因此在项目初期,了解预计的开发费用是非常重要的。本文将详细介绍如何估算小程序开发费用以及如何控制项目成本。 小程序开发费用 …...
【22】linux进阶——文本处理工具:cut、awk、sed
大家好,这里是天亮之前ict,本人网络工程大三在读小学生,拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识,希望能提高自己的技术的同时,也可以帮助到大家 另外其它专栏请关注: 锐捷数通实验&…...
Web3D包装生产线 HTML5+Threejs(webgl)开发
生产线三维可视化解决方案就是通过物联网、虚实联动和三维建模等先进技术,以一个3D立体模型展现出来,可以让我们很直观的看到生产线的运作以及对数据的监控。3D运用数据孪生技术可以让工业3D物联网管理系统的界面变得非常的简单易看,并且能够…...
Docker数据管理
目录 一、数据管理方式 1、数据卷 在宿主机上写入数据,传到容器 2、数据卷容器 二、容器互联 一、数据管理方式 用户在使用Docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多…...
在PowerBuilder中更改窗口继承
在PowerBuilder中更改窗口继承 PowerBuilder是Sybase公司的独资子公司PowerSoft推出的应用于客户机/服务器体系结构下的应用程序开发工具,也是一种面向对象的图形化交互式开发工具。PowerBuilder 以其简洁高效的集成开发环境、 强大的数据窗口技术、几乎无所不能的数据库访问…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
