李娜多媒体网络通信技术_第1页
李娜多媒体网络通信技术_第2页
李娜多媒体网络通信技术_第3页
李娜多媒体网络通信技术_第4页
李娜多媒体网络通信技术_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

多媒体网络通信技术大作业1、题目:基于局域网的可视对讲系统设计2、系统开发环境与工具:〔1〕、硬件环境:实验室局域网〔2〕、软件环境:WindowsXP操作系统〔3〕、开发工具:自己熟悉的面向对象的网络通信编程工具与平台,相关音频、视频编码与传输协议类库3、要求与评分标准:〔1〕要求:在以上硬软件环境下,利用适宜的开发工具,设计一套可视对讲软件,实现局域网内两台计算机之间的可视对讲功能,要求音视频信号连续性、实时性较好,满足正常交流需要。〔2〕评分标准系统原理分析〔20分〕1.系统原理概述〔10分〕2.关键技术分析〔10分〕系统总体方案设计〔30分〕1.按模块化设计要求画系统结构图〔15分〕2数据流分析〔15分〕系统具体设计〔30分〕呼叫处理模块流程图与关键代码〔6分〕音视频采集与播放模块流程图与关键代码〔6分〕音视频处理〔编解码〕模块流程图与关键代码〔6分〕音视频封包与解析模块流程图与关键代码〔6分〕音视频发送与接收模块流程图与关键代码〔6分〕系统测试与评价〔20〕实现语音通信〔6分〕实现视频通信〔6分〕实现音视频同步〔8分〕1系统原理分析1.1系统原理概述视频聊天系统应该具备提供便捷、灵活、全面的音频、视频信息的传递和效劳的功能,并且实时传输给聊天软件在线的人。本次方案采用MicrosoftVisualC++6.0编程开发视频聊天系统的一套比拟常用的解决方案。语音视频聊天采用UDP模式,在客户端之间点对点的进行,因为UDP传输速度快,TCP是面向连接的,建立连接时双方需经过三次握手,数据传输可靠,FTP、TELNET等就是基于TCP的,UDP是面向非连接的,发出信息不需对方确认,但这样速度比TCP快,但有可能丧失数据,象SMTP、TFTP等就是基于UDP的。在该方案中,通过函数库VFW〔VideoforWindows〕来实现视频捕获、影像压缩以及影像播放。微软公司提供的专门用于视频捕获开发的工具包VFW,为在Windows操作系统中实现视频捕获提供了标准的接口,从而大大降低了程序的开发难度。在视频传输方面,那么通过组建视频帧,将位图形式的视频帧压缩成帧格式的MPEG4流,传输到客户端后,解压并显示影像。同时采用线程来实现语音录制和语音回放,最终实现了通过效劳器中转的文字聊天、点对点的语音视频聊天。1.2关键技术分析可视对讲的关键技术之一是音视频同步问题。解决同步问题的方法有很多种,其中时间戳是最成熟最完美也是最复杂的解决方法,可以解决任何多媒体领域的音视频同步问题。其原理是选择一个参考时间,在生成数据流时依据参考时间上的时间给每个数据块都打上时间戳;在播放时,读取数据块上的时间戳,同时参考当前时钟上的时间来安排播放,让快于这个参考时间的包等待,丢弃慢于这个参考时间的包。在基于时间戳的同步机制中,仅仅对不同步的数据进行处理是不完备的,还需要反响机制,如基于Windows平台的DirectShow就提供这样一个反响机制,它的质量控制(QualityControl)可以将播放的状态反响给源,让源端加快或者放慢数据流的速度。多媒体文件的采集,播放及对同步的要求都非常严格,如果从多媒体文件中别离出音视频数据的数据不同步,音视频的时间差那么会越来越大,这是无法忍受的,所以在多媒体文件中,不但要求有同步机制,还要求有反响机制。可视对讲的关键技术之二是数据压缩技术。多媒体信息数字化后的数据量非常大,尤其是视频信号,数据量更大,需要占用更大的信道带宽,本钱十分昂贵。为了节省存储空间充分利用有限的信道容量传输更多视频信息,必须对视频信息进行压缩。目前,在视频图像信息的压缩方面已经取得了很大的进展。有关图像压缩编码的国际标准主要有JPEG、H.261、H.263、MPEG-1、MPEG-2、MPEG-4等。有关音频信号的压缩编码技术根本上与图像压缩技术相同,不同之处在于图像信号是二维信号,而音频信号是一维信号,相比拟而言音频信号数据压缩难度较低。可视对讲的关键技术之三是视频采集。对于视频的采集,主要采用微软公司的关于数字视频的一个软件包VFW〔VideoforWindows〕。VFW是Microsoft1992年推出的关于数字视频的一个软件包,它能使应用程序通过数字化设备并播放从传统的模拟视频源得到数字化的视频剪辑。为了解决数字视频数据量大的问题,需要对数据进行压缩,它引进了一种叫AVI的文件标准,该标准未规定如何对视频进行捕获、压缩及播放,仅规定视频和音频该如何存储在硬盘上,以及在AVI文件中交替存储视频帧和与之相匹配的音频数据。VFW给程序员提供VBX和AVICap窗口类的高级编程工具,使程序员能通过发送消息或设置属性来捕获、播放和编辑视频剪辑。用户不必专门安装VFW,在安装Windows时,安装程序会自动地安装配置视频所需的组件,如设备驱动程序、视频压缩程序等。2系统总体方案设计2.1系统模块分析2.1.1视频捕获VFW软件包主要由以下六个模块组成:〔1〕AVICAP.DLL:包含执行视频捕获的函数,它给AVI文件、I/O和视频、音频设备驱动程序提供一个高级接口;〔2〕MSVIDEO.DLL:包含一套特殊的DrawDib函数,用来处理屏幕上的视频操作;〔3〕MCIAVI.DRV:包括对VFW的MCI命令解释器的驱动程序;〔4〕AVIFILE.DLL:包含由标准多媒体I/O〔mmio〕函数提供的更高的命令,用来访问AVI文件;〔5〕压缩管理器〔ICM〕:用于管理的视频压缩/解压缩的编译码器〔Codec〕;〔6〕音频压缩管理器〔ACM〕:提供与ICM相似的效劳,适用于波形音频。AVICap支持实时的视频流捕获和单帧捕获,并提供对视频源的控制。虽然MCI也提供数字视频效劳,比方,它为显示AVI文件的视频提供了AVIVideo命令集,为视频叠加提供了overlay命令集,但这些命令主要是基于文件的操作,不能满足实时地直接从视频缓存中获取数据的要求。对于使用没有视频叠加能力的捕获卡的PC机来说,用MCI提供的命令集是无法捕获视频流的。而AVICap在捕获视频方面具有一定的优势,它能直接访问视频缓冲区,不需要生成中间文件,实时性很强,效率很高。同时,它也可将数字视频捕获到文件。在视频捕获之前需要创立一个捕获窗,所有的捕获操作及其设置都以它为根底。用AVICap窗口类创立的窗口〔通过capCreateCaptureWindow函数创立〕被称为“捕获窗”,其窗口风格一般为WS_CHILD和WS_VISIBLE。实际上,捕获窗类似于标准控制〔如按钮、列表框等〕。捕获窗具有以下功能:〔1〕将视频流和音频流捕获到一个AVI文件中;〔2〕动态地同视频和音频输入器件连接或断开;〔3〕以Overlay或Preview模式对输入的视频流进行实时显示;〔4〕在捕获时可指定所用的文件名并能将捕获文件的内容拷贝到另一个文件;〔5〕设置捕获速率;〔6〕显示控制视频源、视频格式、视频压缩的对话框;〔7〕创立、保存或载入调色板;〔8〕将图像和相关的调色板拷贝到剪贴板;〔9〕将捕获的一个单帧图像保存为DIB格式的文件。视频捕获编程涉及视频捕获的结构、宏、消息和函数。发送AVICap窗口消息所能完成的功能都能调用相应的宏来完成。如,SendMessage与capDriverConnect的作用相同,都是将创立的捕获窗同视频输入器件连接起来。灵活编写AVICap提供的回调函数可满足一些特殊需求。将宏capCaptureSequenceNoFile和用capSetCallbackOnVideoStream登记的回调函数一起使用,可使应用程序直接使用视频和音频数据。在视频聊天的应用程序中可利用这一点来获得视频帧,回调函数将捕获的图像传到远端的计算机。应用程序可用捕获窗来登记回调函数〔由用户编写,而由系统调用〕,以便在发生以下情况时,它能通知应用程序,作出相应的反响,捕获窗状态改变,出错;视频帧和音频缓存可以使用;在捕获过程中,其它应用程序处于让步〔Yield〕地位。2.1.2视频压缩解压缩视频压缩(视频编码)是把数字视频流用更少的数据位进行存放的方法。未经压缩的视频数据量非常大,所以压缩对于数字视频的存储和传输来说都是必须的。图像压缩包括一对互补系统,一个编码器(encoder)和一个解码器(decoder)。编码器利用图像数据之间的相关性。在保证图像质晕的情况下使用较少的数据以传播或存储该图像;而解码器那么把压缩后的图像复原出原始的视频数据。视频压缩解压缩采用MPEG-4标准。MPEG-4是为在国际互联网络上或移动通信设备〔例如移动〕上实时传输音/视频讯号而制定的最新MPEG标准,MPEG4采用ObjectBased方式解压缩,压缩比指标远远优于以上几种,压缩倍数为450倍(静态图像可达800倍),分辨率输入可从320×240到1280×1024,这是同质量的MPEG1和MJEPG的十倍多。MPEG-4使用图层(layer)方式,能够智能化选择影像的不同之处,是可根据图像内容,将其中的对象〔人物、物体、背景〕别离出来分别进行压缩,使图文件容量大幅缩减,而加速音/视频的传输,这不仅仅大大提高了压缩比,也使图像探测的功能和准确性更充分的表达出来。在网络传输中可以设定MPEG-4的码流速率,清晰度也可在一定的范围内作相应的变化,这样便于用户根据自己对录像时间、传输路数和清晰度的不同要求进行不同的设置,大大提高了系统使用时的适应性和灵活性。也可采用动态帧测技术,动态时快录,静态时慢录,从而减少平均数据量,节省存储空间。而且当在传输有误码或丢包现象时,MPEG-4受到的影响很小,并且能迅速恢复。MPEG-4与MPEG-1、MPEG-2以及H.264相比,更注重多媒体系统的交互性和灵活性。最显著的差异在于它采用基于对象的编码理念;即在编码时将一幅景物分成假设干个在时间和空间上相互联系的视频音频对象,分别编码后经过复用传输到接收端,在接收端再对不同对象分别解码。最后合成所需的视频和音频。这样便于对不同对象进行不同的编码和操作,也有利于不同数据类型间的融合。MPEG-4的应用前景将是非常广阔的。它的出现将对以下各方面产生较大的推动作用:数字电视、动态图像、万维网〔WWW〕、实时多媒体监控、低比特率下的移动多媒体通信、于内容存储和检索多媒系统、Internet/Intranet上的视频流与可视游戏、基于面部表情模拟的虚拟会议、DVD上的交互多媒体应用、基于计算机网络的可视化合作实验室场景应用、演播电视等。2.1.3语音的录制、回放我们主要利用线程来处理语音局部的录制、回放。线程是一个独立的执行流,是进程内部的一个独立的执行单元,相当于一个子程序,它对应于VisualC++中的CWinThread类对象。单独一个执行程序运行时,缺省地包含了一个主线程,主线程以函数地址的形式出现,提供程序的启动点,当主线程终止时,进程也随之终止。根据实际需要,应用程序可以分解成许多独立执行的线程,每个线程并行的运行在同一进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,使用该进程的全局变量和系统资源。操作系统给每个线程分配不同的CPU时间片,在某一个时刻,CPU只执行一个时间片内的线程,多个时间片中的相应线程在CPU内轮流执行,由于每个时间片时间很短,所以对用户来说,仿佛各个线程在计算机中是并行处理的。操作系统是根据线程的优先级来安排CPU的时间,优先级高的线程优先运行,优先级低的线程那么继续等待。Windows提供了两种线程:用户界面线程和工作线程〔又称为后台线程〕。这里主要介绍用户界面线程的运用。用户界面线程通常用来处理用户的输入并响应各种事件和消息,其实,应用程序的主执行线程CWinApp对象就是一个用户界面线程,当应用程序启动时自动创立和启动,同样它的终止也意味着该程序的结束,进程终止。〔1〕线程的启动创立一个用户界面线程,首先要从类CwinThread产生一个派生类,同时必须使DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE来声明和实现这个CwinThread派生类。第二步是根据需要重载该派生类的一些成员函数如:ExitInstance〔〕、InitInstance〔〕、OnIdle〔〕、PreTranslateMessage〔〕等函数。最后调用AfxBeginThread()函数的一个版本:CWinThread*AfxBeginThread(CRuntimeClass*pThreadClass,intnPriority=THREAD_PRIORITY_NORMAL,UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL)启动该用户界面线程,其中第一个参数为指向定义的用户界面线程类指针变量,第二个参数为线程的优先级,第三个参数为线程所对应的堆栈大小,第四个参数为线程创立时的附加标志,缺省为正常状态,如为CREATE_SUSPENDED那么线程启动后为挂起状态。〔2〕线程的优先级CwinThread类的成员函数用于线程优先级的操作:intGetThreadPriority〔〕;BOOLSetThradPriority〔〕(intnPriority)。〔3〕线程的挂起和恢复CWinThread类中包含了应用程序挂起和恢复它所创立的线程的函数,其中SuspendThread〔〕用来挂起线程,暂停线程的执行;ResumeThread〔〕用来恢复线程的执行。如果你对一个线程连续假设干次执行SuspendThread〔〕,那么需要连续执行相应次的ResumeThread〔〕来恢复线程的运行。〔4〕结束线程终止线程有三种途径,线程可以在自身内部调用AfxEndThread()来终止自身的运行;可以在线程的外部调用BOOLTerminateThread(HANDLEhThread,DWORDdwExitCode)来强行终止一个线程的运行,然后调用CloseHandle〔〕函数释放线程所占用的堆栈;第三种方法是改变全局变量,使线程的执行函数返回,那么该线程终止。2.1.4视频传输语音视频聊天采用用户数据报协议〔User

Datagram

Protocol〕传输协议。UDP是无连接的网络协议,无连接效劳是邮政系统效劳的抽象,每个分组都携带有完整的目的地址,各分组在系统中独立传送。无连接效劳不能保证分组的先后顺序,不进行分组出错的恢复与重传,不保证传输的可靠性。UDP协议提供无连接的数据报效劳。而TCP/IP协议已经很难适应视音频通信,特别是连续的媒体流〔如视频流〕通信的要求。TCP协议是面向连接的协议,被用于各种网络上提供有序可靠数据传输的虚电路效劳。它的重传机制和拥塞控制机制〔Congestion

Control

Mechanism〕都是不适合用于实时视音频传输的。因为IP协议只提供无连接、无QOS保证的效劳,并且只是尽最大努力地传送数据报。当网络带宽缺乏而造成较长的时延和较多的丢包时,IP协议并不提供QOS反响[2]。因此,需要利用IP层之上的协议来满足网络视频实时传输的时延和丢包率的要求。UDP协议是面向非连接的网络数据协议,在正式通信前不必与对方先建立连接,直接向接收方发送数据,是一种不可靠的通信协议。正是由于UDP协议不关心网络数据传输的一系列状态,使得UDP协议在数据传输过程中节省了大量的网络状态确认和数据确认的系统资源消耗,大大提高了UDP协议的传输速度,且UDP无需连接管理,可以支持海量并发连接。但是,视频传输的特点要求传输协议能够处理传输中的延迟和抖动现象,能够处理突发的视频传送,并且能够根据接收端的接收质量判断网络状况,做出相应的反响[3]。UDP协议本身并不能很好地处理这些情况。由于UDP协议不能可靠传输视频图像,为此在应用层添加如下机制实现视频图像的可靠传输。在发送端和接收端各开一个视频缓冲区,暂存待发送和已接收的数据帧。通过流量控制,可以防止因网络拥塞导致包丧失率增加。通过确认技术,可以实现图像可靠传输。而超时处理可以防止发送端和接收端长时间等待,根据网络当前状况作出相应的反响。2.2软硬件环境两台以上电脑,分别配有摄像头、麦克风、音箱或耳机等外部设备;WindowsXP系统,MicrosoftVisualStudio6.0编程开发系统等。2.3技术要求语音视频聊天作为一种广泛的网络应用对其根底的承载网络环境有着较高的网络要求。其中应重点考虑的是网络的带宽情况、端到端的时延、丢包率、时延抖动等问题。〔1〕网络带宽需求,视频聊天对网络的带宽需求为“视频带宽+IP包头开销”,计算方法为:网络带宽=视频带宽×1.2。〔2〕端到端的时延,网络传输不可防止的会发生传输时延,通常建议视频聊天的通用时延小于150ms。〔3〕丢包率,网络数据传输经常会出现丢包现象,视频传输过程中数据丢包严重的话会影响在线视频聊天质量。因此,在设计上应将网络上的丢包率控制在1%以内。〔4〕时延抖动,由于音频/视频的传输为实时的交互,因此网络的时延抖动更为重要,一般,视频聊天的时延抖动控制在50ms内。2.4系统结构图2.4.1硬件结构系统该系统采用的是Client/Client结构,客户端是两台PC机和一个数字摄像头、耳机和麦克风。进行语音视频聊天是客户端与客户端之间直接进行的点对点的连接,它们之间的网络拓扑结构如图1。在图中,为了简便,没有画出麦克风、音箱或耳机等外部设备。图1网络拓扑结构图2.4.2系统功能模块图语音视频聊天是对整个在线客户端两两之间进行点对点的视频聊天。语音视频聊天包括了视频捕获、视频压缩、解压缩、语音录制、语音回放以及视频传输等。整个系统的功能模块图如图2所示。图2系统功能模块图系统各模块流程图语音视频聊天流程图如以下图3所示。在有两个客户在线的情况下,才能进行语音视频聊天。两个用户要进行语音视频聊天时,一个用户选中另一个用户的用户名,根据该用户名在后台链表中的对应IP地址查找用户并请求视频连接。当双方确认视频连接后就进行视频传输,并显示在客户端,同时用线程实现语音录制和回放。这样,两个用户就实现了点对点的语音视频聊天。在进行语音视频聊天的过程中,不能再与其它用户进行语音视频聊天,但能够与其它用户进行文字聊天。图3语音视频聊天流程图2.5数据流在发送端和接收端各开一个视频缓冲区,暂存待发送和已接收的数据帧。由于无线传输带宽和单片机软硬件资源的限制,压缩后的JPG图像(320×240)仍然必须在发送端分割成假设干帧,到达接受端时重组。在LINUX中,JPG图像就相当于一个普通文件,可通过open()函数翻开进行读写。2.5.1数据帧结构对每帧加上帧头结构,帧头结构定义了序列号,视频压缩格式,时戳。序列号是数据包发送的顺序标记,检测传输中是否有数据丧失,并用在接收端来重新排序。视频压缩格式标记用于接收端采用相应的解码流程。时间戳控制视频回放的时间。帧结构描述如图4所示。图4数据帧结构图像在传输过程中还涉及到缓冲区、流量控制、确认技术及超时处理等问题。〔1〕缓冲区。由于发送端存在重发数据帧的可能,接收端有可能收到乱序的数据帧,故发送端和接收端确定一个视频传输缓冲区,大小为65536(可根据要传送的图像大小适当调整)字节。发送端首先把一幅jpg图像数据一次性写入缓冲区,将其分解为假设干数据帧,各帧按照序号递增的顺序从1依次编号,使得每一帧的大小不超过2048字节,称为一个数据帧。接收端收到完整的一幅JPG图像数据后再一次性写入图像文件中。〔2〕流量控制。UDP借鉴TCP协议流量控制机制:慢启动和线性增长成倍减少过程。在连接建立后的慢启动过程中,先将发送方窗口置为最小值,每当成功传送完窗口中的数据后,就成倍地增大窗口,直到某个阈值。这就保证了网络流量不会突然增大,为其他连接留有余地。〔3〕确认技术。在可靠数据传递协议中保证数据可靠传递的根本就是要使用确认技术。为了更好地控制流量,到达最大限度地利用网络资源的目的,可采用捎带确认、累计确认和超时确认以及扩展确认这几种方式结合来实现确认。其中前3种确认方式和TCP中的用法一致。在接收方收到失序数据包时,为了最大限度地减少重传,并不是简单将其丢弃,而是将其存储在本地的失序缓冲队列中,并设置失序包计数器。接收方在计数器超过阈值或者确认定时器超时后向发送方发送扩展确认数据包。该数据包中携带本端已经收到的最大按序包序号和收到的所有失序包的序号信息。发送端收到由接收端传来的扩展确认数据包后,将根据最大确认序号和对端收到的失序包的序号计算出应该重传的数据包序号,并从重传队列中取出相应的数据包进行快速重传。〔4〕超时处理。处理超时和重传的方法之一就是发送一个请求后等待n秒,如果没有收到应答,那么重传并再等待另外N秒。这是一种线性重传的定时器,并且在重传一定次数后就放弃重传。这种方法的问题是,数据报在一个互联网上往返的时间(RTT)会从LAN上的远远小到1s变成WAN上的许多秒。影响往返时间(RTT)的因素是距离、网络速度和拥塞,当网络条件变化时,客户和效劳器之间的RTT会随着时间很快地变化。因此,必须设计一个将实际测得的RTT以及RTT随时间变化考虑在内的超时和重传算法。计算发送每个数据报的重传超时(RTO)的公式为:delta=RTT-srttsrtt←srtt+g×deltarttvar←rttvar+h×(|delta|-rttvar)RTO=srtt+4×rttvar其中,RTT为数据报的实际往返时间;srtt为平滑了的RTT估计因子;rttvar为平滑了的平均偏差估计因子;delta为测得的RTT和当前平滑了的RTT估计因子(srtt)之间的差;g为施加在RTT估计因子上的增益因子,值为1/8;h为施加在平均偏差估计因子上的增益因子,值为1/4。当重传定时器超时的时候,对下一个RTO要用一个指数退回。例如,如果RTO是2s,这段时间内应答没有收到,那么下一个RTO是4s;如果仍没有收到,下一个RT0是8s,接着是16s,依此类推。2.5.2视频图像数据传输过程以一幅图像传送为例。如一幅图像共可拆分打包成n个数据帧。某次发送编号为i,j,k,m共4帧(i<j<k<m),接收方成功收到i,m两帧。接收方将已收到的所有帧序号打包成确认帧发送出去,而不只是仅打包本次收到的i,m两帧。发送方收到确认帧后,依据确认帧里各帧序号将说明接收方是否成功收到数据帧的数组相应位置1。此时发送方依据流量控制原理选取序号大于m的帧发送,而不是发送上次的序号为j,k的帧。当帧号等于n时再从帧号1开始依据序号递增的方法选取还未收到确认帧的各帧。实验说明,这样大大减少了数据帧和确认帧的重发。因为发送方未收到确认帧并不说明确认帧由于受到线路噪声干扰或路由器缓冲区已满而被抛弃,也有可能还在寻找路由。TCP的顺序传送以帧为单位,而本文方法却是以一幅图像为单位。发送流程如图5所示,接收流程如图6所示。图5图像数据帧发送流程图图6图像数据帧接收流程图音频信号是一维信号,音频数据的收发更为简单,在这里就不作具体分析。3系统具体设计3.1呼叫处理3.1.1呼叫处理模块在实现语音视频聊天时,采用的是基于UDP套接字的点对点模式,而UDP面向的是无连接的数据效劳,其套接字的使用如图7所示。图7UDP套接字的使用3.1.2呼叫处理关键代码客户端请求连接线程〔呼叫处理〕关键代码如下:DWORDWINAPIConnectThreadFunc(LPVOIDpParam){CChatRoomDlg*pChatRoom=(CChatRoomDlg*)pParam;ASSERT(pChatRoom!=NULL);pChatRoom->m_ConnectSock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(pChatRoom->m_ConnectSock==INVALID_SOCKET){AfxMessageBox(_T("新建Socket失败!"));returnFALSE;}CStringstrServIp;pChatRoom->GetDlgItemText(IDC_IP_ADDR,strServIp);intiPort=pChatRoom->GetDlgItemInt(IDC_CONNECT_PORT);if(iPort<=0||iPort>65535){AfxMessageBox(_T("请输入适宜的端口:1-65535"));goto__Error_End;}charszIpAddr[16]={0};USES_CONVERSION;strcpy_s(szIpAddr,16,T2A(strServIp));sockaddr_inserver;server.sin_family=AF_INET;server.sin_port=htons(iPort);server.sin_addr.s_addr=inet_addr(szIpAddr);if(connect(pChatRoom->m_ConnectSock,(structsockaddr*)&server,sizeof(structsockaddr))==SOCKET_ERROR){AfxMessageBox(_T("连接失败,请重试!"));goto__Error_End;}pChatRoom->ShowMsg(_T("系统信息:连接效劳器成功!"));while(TRUE){if(SOCKET_Select(pChatRoom->m_ConnectSock)){TCHARszBuf[MAX_BUF_SIZE]={0};intiRet=recv(pChatRoom->m_ConnectSock,(char*)szBuf,MAX_BUF_SIZE,0);if(iRet>0){pChatRoom->ShowMsg(szBuf);}else{pChatRoom->ShowMsg(_T("聊天效劳器已停止,请重新进行连接!"));break;}}Sleep(500);}__Error_End:closesocket(pChatRoom->m_ConnectSock);returnTRUE;}3.2音视频采集与播放利用VFW接口,视频捕获可以分为以下几个步骤:〔1〕建立视频采集窗口:该窗口用来接收视频捕捉驱动程序传来的数据和消息。〔2〕连接视频驱动程序:将建立的视频捕捉窗口与视频设备驱动程序相连。〔3〕视频捕获初始化。〔4〕视频捕捉设置:VFW下视频捕捉参数的设置可以通过调用函数或弹出对话框的形式来实现。一般视频驱动程序允许设置的参数包括视频源选择、视频格式、视频显示格式等。〔5〕设置回调函数:通过回调函数来通知程序视频事件的发生,比方捕捉一帧图像成功的消息,捕捉出错的消息等。〔6〕结束捕捉:结束捕捉是应该有一些去除工作。如释放分配的内存,断开捕捉窗口与视频捕捉驱动程序的连接,去除视频捕捉窗口等。3.2.1捕获窗口在捕获前必须创立一个捕获窗口〔CaptureWidnow〕,下面介绍有关捕获窗口的情况:创立一个AVICap捕获窗口,用capCreateCaptureWindow函数并返回一个句柄。将捕获窗口连接至捕获设备,用capDriverConnect函数来使一个捕获窗口与一个捕获设备连接或关联连接上后,就可以通过捕获窗口向捕获设备发送各种消息,可以使用函数capGetDriverDescription来获得已安装的捕获设备名称及版本,将其列举在实现程序过程中。再利用capDriverGetName函数来得到捕获设备的名称将获得的版本发送到capDriverGetVersion。如果断开捕获窗口与捕获设备的连接用capDriverDisconnect。捕获窗口的状态,用capGetStatus函数来获得当前捕获窗口的状态,得到一个CAPSTATUS结构的拷贝。该结构的内容包含了图片的尺寸、卷轴的当前位置、overlay和preview是否已设置。由于其信息是动态的,每当捕获的视频流的尺寸发生改变,程序应该在获取捕获设备的视频格式以后及时进行刷新。而捕获窗口尺寸的改变并不影响实际的捕获视频流的尺寸。该尺寸由视频捕获设备的格式和视频对话框决定。代码如下://捕获窗口BOOLVideoCapture::Initialize(){chardevname[128]={0},devversion[128]={0};intindex=0;BOOLret=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){returnFALSE;}//connectcallbackfunctionsret=capSetUserData(m_capwnd,this);//Changedestroyfunctionsalso........ret1=capSetCallbackOnVideoStream(m_capwnd,OnCaptureVideo);//得到已安装的捕获设备的名称及版本ret2=capGetDriverDescription(index,devname,100,devversion,100);//Connecttowebcamdriver//使一个捕获窗口与一个捕获设备连接或关联ret3=capDriverConnect(m_capwnd,index);if(!(ret&&ret1&&ret2&&ret3)){//Devicemaybeopenalreadyoritmaynothavebeen//closedproperlylasttime.AfxMessageBox("UnabletoopenVideoCaptureDevice");// log.WriteString("\nUnabletoconnectdrivertothewindow");m_capwnd=NULL;returnFALSE;}//Setthecaptureparametersif(SetCapturePara()==FALSE){// log.WriteString("\nSettingcaptureparametersfailed");capDriverDisconnect(m_capwnd);//使捕获窗口与一个捕获设备断开returnFALSE;}returnTRUE;}3.2.2设置CAPTUREPARAMS结构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结构的实现代码:BOOLVideoCapture::SetCapturePara(){CAPTUREPARMSCapParms={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("\nFailedtosetthecaptureparameters");returnFALSE;}//SetVideoFormatcapGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));m_bmpinfo.bmiHeader.biWidth=IMAGE_WIDTH;m_bmpinfo.bmiHeader.biHeight=IMAGE_HEIGHT;BOOLret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));// log.WriteString("\nVideoparameterssetproperly");returnret;}//终止一个捕获任务BOOLVideoCapture::StopCapture(){capCaptureStop(m_capwnd);capCaptureAbort(m_capwnd);Sleep(500);returnTRUE;}3.3音视频处理〔编解码〕音视频编码处理就是对音视频进行压缩。MPEG-4编码算法的完整源代码如下:classCVideoEncoderX264:{

public:

CVideoEncoderX264(void);

~CVideoEncoderX264(void);

virtualboolConnect(CVideoEnDecodeNotify*pNotify,constCVideoEnDecodeItem&Item);

virtualvoidRelease(void);

virtualvoidEncode(BYTE*pInData,intnLen,BYTE*pOutBuf,int&nOutLen,int&nKeyFrame);private:

x264_picture_tm_Pic;

x264_t*h;x264_param_tparam;voidFlush(void);

};文件:VideoEncoderX264.cppboolCVideoEncoderX264::Connect(CVideoEnDecodeNotify*pNotify,constCVideoEnDecodeItem&Item){

CBase::Connect(pNotify,Item);

ParseSize(Item.m_stSize);

x264_param_default(¶m);

param.i_threads=1;

param.i_frame_total=0;

param.i_width

=m_nWidth;

param.i_height=m_nHeight;

param.i_keyint_min=Item.m_nKeyInterval;

param.i_keyint_max=Item.m_nKeyInterval*10;

param.i_fps_num=Item.m_nFps;*/

param.i_log_level=X264_LOG_NONE;if((h=x264_encoder_open(¶m))==NULL){returnfalse;

}/*Createanewpic*/x264_picture_alloc(&m_Pic,X264_CSP_I420,param.i_width,param.i_height);

returntrue;}voidCVideoEncoderX264::Release(void){

Flush();x264_picture_clean(&m_Pic);x264_encoder_close(h);

CBase::Release();}voidCVideoEncoderX264::Encode(BYTE*pInData,intnLen,BYTE*pOutBuf,int&nOutLen,int&nKeyFrame){

if(nLen!=param.i_width*param.i_height*3)return;

param.i_frame_total++;memcpy(m_Pic.img.plane[0],pInData,param.i_width*param.i_height);memcpy(m_Pic.img.plane[1],pInData+param.i_width*param.i_height,param.i_width*param.i_height/4);memcpy(m_Pic.img.plane[2],pInData+param.i_width*param.i_height*5/4,param.i_width*param.i_height/4);

m_Pic.i_pts=(int64_t)param.i_frame_total*param.i_fps_den;staticx264_picture_tpic_out;

x264_nal_t*nal=NULL;inti_nal,i;if(&m_Pic){m_Pic.i_type=X264_TYPE_AUTO;m_Pic.i_qpplus1=0;}

//TraceTime("x264_encoder_encodebegin");if(x264_encoder_encode(h,&nal,&i_nal,&m_Pic,&pic_out)<0)

{

return;}//TraceTime("x264_encoder_encode

end");intnOutCanUse=nOutLen;nOutLen=0;for(i=0;i<i_nal;i++){inti_size=0;if((i_size=x264_nal_encode(pOutBuf+nOutLen,&nOutCanUse,1,&nal[i]))>0){

nOutLen+=i_size;

nOutCanUse-=i_size;}}nKeyFrame=pic_out.i_type==X264_TYPE_IDR;//||(pic_out.i_type==X264_TYPE_I&&coCfg->x264_max_ref_frames==1)}voidCVideoEncoderX264::Flush(void){

x264_picture_tpic_out;x264_nal_t*nal;inti_nal,i;inti_file=0;if(x264_encoder_encode(h,&nal,&i_nal,NULL,&pic_out)<0){}

}解码代码不做详细分析。3.4.语音处理3.4.1语音录制在音频的录制和播放时,采用的用户界面线程来处理,是CWinThread对象,根据前面线程的介绍,一步一步的来实现。录音用的一个CWinThread对象CAudioRec来实现,局部实现代码:LRESULTCAudioRec::OnStartRecording(WPARAMwp,LPARAMlp){if(recording) returnFALSE;//翻开录音设备MMRESULTmmReturn=::waveInOpen(&m_hRecord,WAVE_MAPPER&m_WaveFormatEx,::GetCurrentThreadId(),0,CALLBACK_THREAD);if(mmReturn!=MMSYSERR_NOERROR) returnFALSE;if(mmReturn==MMSYSERR_NOERROR){for(inti=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;}returnTRUE;}3.4.2语音回放相对录音而言,播放就简单多了,同样用的一个CWinThread对象CAudioPlay来实现,局部实现代码:LRESULTCAudioPlay::OnWriteSoundData(WPARAMwParam,LPARAMlParam){// TRACE("CAudioPlay::OnWriteSoundData\n");MMRESULTmmResult=FALSE;char*p=NULL;intlength=(int)wParam;if(Playing==FALSE) returnFALSE;if(length<=0) returnFALSE;WAVEHDR*lpHdr=newWAVEHDR;if(!lpHdr) returnFALSE;p=newchar[length];if(!p) {deletelpHdr;returnFALSE;}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){deletelpHdr;deletep;returnmmResult;}mmResult=::waveOutWrite(m_hPlay,lpHdr,sizeof(WAVEHDR));//写数据(放音)if(mmResult){deletelpHdr;deletep;returnmmResult;}m_Count++;returnMMSYSERR_NOERROR;}3.5音视频发送与接收视频采集采用AVICap从视

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论