基于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 以其简洁高效的集成开发环境、 强大的数据窗口技术、几乎无所不能的数据库访问…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

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进…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...