永发信息网

求视频和音频的通话原理

答案:2  悬赏:0  手机版
解决时间 2021-08-10 16:15

如题,请告诉我,比如QQ,是怎么实现的视频聊天和音频聊天!

原理,源码更好,我就想知道这个视频是怎么传输过去的,还有音频!重要的是音频通话。

在线等、、、、

最佳答案
一、话音的实时采集、处理、回放
首先要介绍一下Windows低层波形音频数据块结构 WAVEHDR,其声明如下:

type struct{
LPSTR lpData; //指向锁定的数据缓冲区的指针
DWORD dwBufferLength; //数据缓冲区的大小
DWORD dwByteRecorded; //录音时指明缓冲区中的数据量
DWORD dwUser; //用户数据
DWORD dwFlag; //提供缓冲区信息的标志
DWORD dwLoops; //循环播放的次数
struct wavehdr_tag * lpNext; //保留
DWORD reserved; //保留
} WAVEHDR;

声音的采集和播放都是在操作这个音频数据块结构,实际上主要用到的就是第一个成员变量lpData, 所以我们只要在分配缓冲区(内存)的同时相应分配WAVEHDR数据块结构,然后将缓冲区的指针赋给对应的数据块结构的成员变量 lpData,这样当一个缓冲区填满后,也就是一个音频数据块填满了,通过消息机制就可以在消息函数中进行处理和播放,播放完后又可通过消息函数把缓冲区再送给音频设备输入驱动程序,继续进行采集并播放,当你一次性分配多个缓冲区和数据块结构并赋给音频设备输入驱动程序后,至于把哪个缓冲区填满,然后再把哪个空缓冲区赋给设备输入驱动程序,不需人为干预,完全由Windows控制,这就是一种用动态循环缓冲区实现话音的实时采集、播放的简单而巧妙的办法。实现步骤:

1.初始化操作

①用waveInGetNumDevs()和waveOutGetNumDevs()查看当前系统波形音频输入、输出设备;
②按11025Hz,16Bit,单声道,22K/S的格式设置WAVEFORMATEX结构的成员变量,也可以改为其他WAVE格式;
③用waveInOpen(...) 和waveOutOpen(...)分别调用WAVE_FORMAT_QUERY参数查看波形输入设备是否支持所设定的格式;
④再次用waveInOpen(...) 和waveOutOpen(...)分别调用CALLBACK_WINDOW参数打开波形输入设备;
⑤分别给音频数据块和音频数据缓冲区分配、锁定全局内存;
⑥初始化音频数据块结构各成员变量,主要是将每个缓冲区指针赋给对应数据块结构中的缓冲区指针变量lpData;调用waveInPrepareHeader(...)和waveInAddBuffer(...)将音频数据块赋给输入设备驱动程序;
⑦调用waveInStart(...)函数开始录音。
2.消息操作

录音开始后,每当有采样数据填满数据块后,设备驱动程序就会发消息MM_WIM_DATA给用户窗口,相应的消息回调函数OnMmWimData(...)对数据块中的采样数据进行处理,然后就可以发送给输出设备进行回放,每当一个音频数据块播放完毕,设备驱动程序又会发出消息MM_WOM_DONE,相应的消息回调函数 OnMmWomDone(...)记录音频数据并经必要准备后重新发送给输入设备,以准备接收后续的采样数据。这样,最初为输入设备准备的音频数据块就在消息的控制下,在输入、输出设备间循环使用,无需人为控制实现了实时采集、处理和播放。

当结束通话时要关闭音频输入设备,这时音频设备驱动程序会发送MM_WIM_CLOSE消息,可在相应的消息函数OnMmWimClose(..)中清除赋给输入、输出设备的音频数据块。
TD>
二、基于TCP协议的点对点话音传输

对于声音的传送和接收主要是采用面向连接的TCP协议,并用Windows Socket进行网络编程实现,但首先要将发送和接收的函数接口放在 OnMmWimData(...)函数中,这样才能做到采集数据块填满后被发送,接收的数据收到后被播放。 Windows Socket对于从事过网络编程的人来说应该不陌生,因为我们要实现点对点通信,所以得把客户和服务器模式融合为一种模式,让服务器可以做客户,客户也可以做服务器,从而使双方都有呼叫对方和接受对方呼叫的能力,这只需增加一个监听Socket就行了。一旦呼叫连接建立成功,便在两个点之间建立了一个数据流,即使双方不讲话,每个点也在不停地收、发数据,一方有话音自然就随着这个数据流传给了对方,所以关键的问题就是怎样读取话音数据流,因为TCP提供的流式服务是不保证边界的,当发送方想一次发送 4000个字节时,调用语句Send(sBuffer,4000),并不能保证一定能发送出4000个字节;同样,接收方准备一次接收发过来的数据,调用语句Receive(rBuffer,4000),也不能保证一定能接收4000个字节,因此实际一次发送和接收的字节数会是1到4000中的任何一个值,最坏的情况是只有1个字节。相反,如果用Send函数连续发送少量数据,比如一次发送400个字节,连续发送10次,接收方用Receive函数可能一次就把这4000个字节都接收下来了,而为了实现播放,我们希望调用一次发送函数就能把缓冲区大小的话音数据发送出去,调用一次接收函数就能把对方一次发送的话音数据准确接收下来,以便进行播放,所以一种比较简单实用的办法,就是利用TCP协议发送数据时为每个数据包加个标志头.


 2
全部回答

一边录音,一边将录音的buffer通过socket发送给对方 两个事件是并列的 录音=》通过微软的WaveInXXXXX  系列函数得到写入的缓冲, 同时又一个线程吧缓冲区的数据发送出去, 同时有一个线程接受 socket过来的语音数据

好像是在调用录音函数的同一时刻触发这个事件,然后socket检测buffer中的数据
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
肥东四中从撮镇怎么坐车?
手术剪生锈了怎么去得掉
OPPO S33 S39显示歌词
我卸载杀毒软件要把注册表删除吗
温州有没有什么好的专业大学!!
TVB最近有什么好看的电视剧?
本人上初三呀,有什么好的学习方法借鉴交流一
1680c的多媒体内是什么格式?
可 以 幫 涐 做 個 字 嗎?
新区69的算是极品的多少钱5力1200伤害以上。
这样的脸型戴什么样的耳环好看些?
现在N97MINI报价多少?
QQ摩天大楼问题!!
怎么才能让QQ空间有动态图片
怎样让空间升级快
推荐资讯
家门口有一株很锋利的花草对家居风水怎样?
哪里有能用的QQ飞车加速辅助
小孩的血项高怎办?
大家来看看这双阿迪真的假的
灵翼龙卵怎么弄到的快
QQ唐宠物几级可以破蛋
做完引产要注意哪些
请问女孩在第一次的时候吃了避孕药两天后就来
dnf湖北二区几种40级轻甲套价格各是多少?
DOTA怎么修改热键?
什么网上有流星雨二
能否再给一个剑仙激活码
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?