网络可视电话的软件设计计划书.docx
《网络可视电话的软件设计计划书.docx》由会员分享,可在线阅读,更多相关《网络可视电话的软件设计计划书.docx(95页珍藏版)》请在冰豆网上搜索。
![网络可视电话的软件设计计划书.docx](https://file1.bdocx.com/fileroot1/2023-1/8/98a9483e-fa54-4ce5-a627-29ce81c1fed7/98a9483e-fa54-4ce5-a627-29ce81c1fed71.gif)
网络可视电话的软件设计计划书
网络可视电话的软件设计计划书
第一章引言
1.1课题背景
1.1.1背景知识
电话作为人们日常生活、工作中不可缺少的通信工具,以其方便、快捷等特点被广泛应用,但普通电话机只能提供语音通信服务。
可视电话使人们在通话时不仅能够听到对方的声音,而且还能够看到对方的图像。
它不仅适用于家庭生活,而且还可以广泛应用于各项商务活动、远程教学、保密监控、医院护理、医疗诊断、科学考察等不同行业的多种领域,因而有着广阔的市场前景。
1964年,美国贝尔实验室提出了第一个可视电话解决方案。
但是由于受各种技术条件的限制,可视电话一直没有取得实质性进展。
八十年代末,随着通信、计算机、语音和视频编解码技术的不断发展,可视电话在世界各国得到了迅速发展。
为了实现互联互通,以推动可视电话和视频会议系统的发展,国际电信联盟(ITU-T)于九十年代推出了包括H.310、H.320、H.321、H.322、H.323和H.324的系列多媒体通信标准。
在上述标准中,以H.320、H.324和H.323应用最为广泛。
近年来,由于IP网的迅猛发展,基于H.323的可视电话终端和会议电视系统逐渐占据了主导地位,各大厂商纷纷推出基于H.323的应用。
值得注意的是,基于会话发起协议(SIP)的可视电话也开始出现。
1.1.2可视电话的基本结构和核心技术
1.可视电话的基本结构
ITU-T推出的H.32X系列标准是框架性协议,服从不同标准的可视电话终端,具有类似的结构。
可视电话的基本结构包括视频输入/输出单元、视频编解码器、语音输入/输出单元、语音编解码器、延时单元、数据处理单元(可选)、系统控制单元、多媒体数据复用/解复用单元和网络接口单元。
不同的标准适用的网络不同,因此有不同的通信控制协议、多媒体数据打包协议和不同的网络接口单元,但是视频和语音输入/输出单元、视频编解码器、语音编解码器相似。
语音和视频压缩技术是可视电话的核心技术。
可视电话作为一种消费产品,要想走入寻常百姓家,必须能够提供足够好的语音和视频质量,同时占用的信道带宽要尽量小。
语音编码技术和视频编码技术的发展就是围绕着上述两点展开的:
在保证压缩后语音和图象质量的同时,尽量提高压缩效率。
我们在具体选用语音和视频压缩标准的时候,也要结合这两点来选择。
2.语音编码技术
语音通信是可视电话最基本的功能。
受网络条件的限制,可视电话通常工作在较低码率下。
为了适应这种低码率语音应用,ITU-T推出了G.72X系列语音压缩标准。
其中G.723.1、G.728、G.729和G.729A,在可视电话中得到了广泛应用。
表1列出了各个语音标准所采用的技术、码率、时延和语音质量等。
本文所论述的网络可视电话的软件就是依照这种方式进行的。
1.1.3开发系统的几点建议
(1)、开发系统不必贪大求全,力争简单实用。
应从大处着眼,小处着手,循序渐进,逐步完善。
(2)、对开发过程中的各种文档应当注意保存。
这是系统开发所要求的必要条件。
(3)、尽可能取得对程序设计重视,使用简化的程序代码保证整个系统开发的清晰。
1.2相关技术介绍
1.2.1结构化生命周期法简介
结构化生命周期法是一种传统的系统开发方法,其基本思想是把整个系统开发过程分成若干个阶段,每个阶段进行若干活动,每项活动应用一系列标准、规范、方法和技术,完成一个或多个任务,形成符合给定规范的产品。
采用结构化生命周期法来开发系统时,应遵循的主要原则:
(1)、用户参与的原则
(2)、“先逻辑后物理”的原则
(3)、“自顶向下”的原则
(4)、工作成果描述(主要指文档)标准化的原则
其具体开发步骤可分为以下四步:
a系统规划
b系统开发
c系统的运行及维护
d系统评价
其中系统开发又分为以下四个步骤:
(a)系统分析
.系统初步调查
.系统可行性研究
.现行系统的详细调查
.新系统逻辑方案的提出
(b)系统设计
.系统总体结构设计
系统总体功能设计
.系统总体物理结构设计
系统详细设计
.代码设计
.输入输出设计
(c)系统实施
.程序设计
系统测试
1.2.2开发技术——快速原型法简介
快速原型法是80年代发展起来的,旨在缩短开发周期,提高开发效率和用户对系统的满意程度。
其基本思想是在系统开发的初期,尽快构造出系统的原型,使用户能及早地运行这个系统原型,通过使用它、熟悉它,受到启发并取得经验,然后对系统的目标和功能提出更精确、具体的要求,研制人员据此逐渐修改和完善原型,使它满足用户的需求,最后完成系统的开发。
该方法大大提高了系统开发效率,弥补了结构化生命周期法来开发的时间长的缺陷。
通常采用原型法需要以下四个阶段:
(1)、明确用户的基本要求
(2)、研制系统的原型
(3)、使用、评价系统原型
(4)、修改和完善原型
1.2.3本系统开发方法的选择
基于以上开发方法的优劣和本系统的实际情况,本系统总体上采用结构化生命周期法进行系统规则、系统分析和系统设计,但在系统实施阶段采用原型法。
在开发程序的方法上,本系统将采用VISUALC++开发工具编制一个网络可视电话的软件,用以实现客户端与服务端管理。
第二章系统目标
开发一个网络可视电话的软件,将能够体现windows平台下使用网络通话的功能。
具体目标是,分网络传输部分、音频输入、音频输出、视频输入、视频输出、音频视频压缩、音频波形显示、界面。
共创建个线程,音频输入线程、音频输出线程(这两个有WINAPI隐式创建)、音频视频压缩传送线程和主线程。
因为音频的采样率比视频采样率高得多,这里的音频的采样率为8000Hz而视频仅为20左右,所以从宏观来看,音频是连续的,而视频是非连续的,这也就是无须为视频输入输出创建独立线程的原因。
●网络传输:
基于UDP协议,有两组SOCKET,一组用于指令发送和接受(要求可靠),另一组负责音频视频数据的传送和接受(不保证可靠性)。
●音频输入:
通过waveIn函数族完成连续的录音
●音频输出:
通过waveOut函数族完成连续的放音
●视频输入:
通过cap函数族对视频进行捕获
●视频输出:
通过cap函数族实现视频输出
●音频视频压缩:
音频压缩采用G.729标准(8:
1,1kbps),视频压缩采用H.263+标准
●音频波形显示:
将PCM音频数据以波形动态地显示出来
●界面:
与用户交互
第三章系统需求分析
3.1系统使用协议
网络传输采用UDP协议,音频压缩采用G.729标准,视频压缩采用H.263标准
3.2性能参数
●以音频帧为基准,每帧音频数据有240个采样点,时间为240*1000/8000=30ms,8000为音频的采样率。
●数据接收端队列缓冲延迟:
30*3=90ms
●数据发送端录音延迟:
30ms
●数据压缩解压耗时:
<40ms
●网络延迟:
<100ms>
●总延迟:
<260ms
●根据VOIP标准,总延迟<300ms是人可以接受的,以上计算是保守的,实际情况可能会好得多。
●视频格式:
176*144,24bit
●带宽需求
数据类型
带宽需求(byte/sec)
带宽总需求(Kbyte/sec)
音频
1000
~9.2*2(视频质量一般的情况下)
视频
~8000(会随图象质量的变化而有较大变化)
帧头
~200
3.3功能需求
基于系统需求分析,该系统需要实现以下基本功能:
●软件一般自动运行(当操作系统启动时运行),与服务器通讯,向服务器传送登录信息.注:
目前并没有服务器介入,而直接是客户与客户的通讯
●进入监听状态,等候呼叫
●呼叫,可以从地址簿呼叫,也可直接打入IP呼叫
●与被叫方取得联系后,等待发送方回应,当超过一定时间或由用户终止时,取消呼叫
●被叫方接受呼叫请求时,开始实时视频通讯,直到任意一方中断对话或非人为中断
(图1,数据发送示意)
3.3系统运行环境
系统运行环境:
Windows2000及其以上
3.4MFC简述
MFC(MicrosoftFoundationClass)指的是Microsoft基础类,是用来为Windows开发C++GUI应用程序。
MFC是一种十分优秀的工具,使得面向对象的软件函数包装技术演变成为一种可以进行代码复用、简化了程序的复杂性并使程序更加有效的软件开发环境..对于使用WindowsAPI进行应用程序开发的人员来说,MFC使程序员大大提高了程序开发效率.你不必创建GDU对象,不必编写许多代码行对这些对象进行初始化,并且小心地跟踪其生命周期的运行情况,你只需建立一个MFC类的实例,使用其默认值,然后让撤消程序来清除系统资源即可.
3.5服务器与客户端SOCKET设计
本程序都采用sock的DLL模型,该模型允许应用程序以Windows消息的形式接收网络事件通知。
这个模型是为了适应Windows的消息驱动环境而设置的,用于对性能要求不高的网络应用程序,最大可连接64个客户端。
使用该模型基本满足本程序要求。
第四章系统设计
4.1概要设计
本次毕业设计的内容就是设计出网络可视电话系统,在此基础上实现系统模型各个子系统的基本功能。
此系统用建立一个sock的DLL文件来进行网络可视电话的网络数据。
在系统功能需求分析的基础上,结合VisualC++程序编制的特点,得到下图所示的系统功能模块图。
图4-1服务端模块
图4-2客户端主模块
4.2流程图
下面用我们用数据流图(DFD,DataFlowDiagram),也就是从数据传递和加工的角度,以图形的方式刻画数据流从输入到输出的移动变换过程。
如下图所示:
本图只是画出了系统得一部分的功能流程图,因为本程序是一个windows程序,由较多的功能,主要是基于消息驱动的,所以有一些功能不能有流程图表达出来,如,消息的传递,当系统接到客户端传递来的信息后,就调用一个函数,将随机的产生出一些信息。
让图象能在第一时间显示出来。
4.3详细设计
4.3.1模块的使用
1、AVIOMgr是一个可视通信的通用模块,在NetTalk中是一个独立的模块,对它进行一些简单的处理,可以做成静态库、动态库或ActiveX控件,以用于其他软件。
AVIOMgr封装了包括:
视频采集、视频压缩、音频采集、音频压缩、音频播放、数据传输、命令控制等一系列与可视通讯有关的功能。
一切对AVIOMgr的控制和AVIOMgr的信息反馈仅通过几个简单的消息和几个简单的函数调用就能完成。
VFW函数族中某些函数的疑惑:
capDriverConnect
capDriverDisconnect
这两个函数的调用必须在同一个线程内,而且似乎还必须同在主线程内,否则就会造成capDriverDisconnect的调用失败,具体是何原因还不太清楚。
2、对Socket(UDP)编程的一些看法:
sendto\rcevfrom是阻塞型的函数,通过WSASelect等函数的调用,可以把这两个函数变成非阻塞的(异步),这需要创建用来接收消息的窗口,在调用WSASelect的时候,隐含地创建了一个线程。
而我却习惯于用阻塞型的,创建一个线程,其中有一个循环,不断调用rcevfrom。
有些书上说异步的效率要高一些,当我觉得我这种方法的效率不会低。
以前做过的第三只眼远程控制软件和NetTalk均采用这种结构,并未发现任何性能上的不足。
4.4程序设计
4.4.1程序窗口的设计
由于此应用程序采用的是基于对话框的开发,系统应用程序的各个不同功能是通过选择主对话框窗口中的不同按钮来完成的,每个功能模块由一个或多个对话框实现。
该应用程序的主对话框(即运行应用程序后出现的对话框)如图所示:
本文系统整个系统的调用主要是通过系统的模块进行组成和完善的,系统的呼叫,可以直接对已经设置好的IP或用户名,进行呼叫。
通讯录可以对自己经常用到的用户进行保存IP,以便下一次的联系。
设置是快捷方式或者本系统的一般配置。
建立好后,就可以输入代码(以下是部分程序代码):
//NetTalk
//主窗口消息
LRESULTCMainWnd:
:
WndProc(UINTuMsg,WPARAMwParam,LPARAMlParam)
{
switch(uMsg)
{
caseWM_HOTKEY:
//热键弹出
if(wParam==1)
{
ShowWindow(m_hWnd,SW_SHOWNORMAL);
SetForegroundWindow(m_hWnd);
SetActiveWindow(m_hWnd);
}
break;
caseWM_USER_SETUP:
OnSetup((SETUP*)lParam);
break;
caseWM_TRAYNOTIFY:
OnTrayNotify(wParam,lParam);
break;
caseIOM_AUDIO:
OnAudioData((BOOL)wParam,(CAVIOMgr*)lParam);
break;
caseWM_INITDIALOG:
returnOnInitDialog();
caseWM_DESTROY:
OnDestroy();
break;
caseWM_CLOSE:
OnClose();
break;
caseWM_LBUTTONDOWN:
{
POINTpoint;
point.x=GET_X_LPARAM(lParam);
point.y=GET_Y_LPARAM(lParam);
OnLButtonDown(wParam,point);
}break;
caseWM_LBUTTONUP:
{
POINTpoint;
point.x=GET_X_LPARAM(lParam);
point.y=GET_Y_LPARAM(lParam);
OnLButtonUp(wParam,point);
}break;
caseWM_MOUSEMOVE:
{
POINTpoint;
point.x=GET_X_LPARAM(lParam);
point.y=GET_Y_LPARAM(lParam);
OnMouseMove(wParam,point);
}break;
caseWM_COMMAND:
returnOnCommand(wParam,lParam);
break;
caseWM_ERASEBKGND:
OnEraseBkgnd((HDC)wParam);
returnTRUE;
caseWM_TIMER:
OnTimer(wParam);
break;
caseWM_SETCURSOR:
returnOnSetCursor((HWND)wParam,LOWORD(lParam),HIWORD(lParam));
break;
caseWM_CTLCOLOREDIT:
return(LRESULT)OnCtrlColorEdit((HDC)wParam,(HWND)lParam);
break;
caseWM_CTLCOLORSTATIC:
return(LRESULT)OnCtrlColorStatic((HDC)wParam,(HWND)lParam);
break;
caseIOM_NOTIFY:
OnIOMNotify(wParam,lParam);
break;
caseWM_SLD:
{
if(((HWND)lParam)==((HWND)m_sldAudioOut))
{
//设置输出音量
m_VoOutCtrl.SetCurrentVolume((m_VoOutCtrl.GetMaximalVolume()-m_VoOutCtrl.GetMinimalVolume())*m_sldAudioOut.GetPos()/100);
}
else
if(((HWND)lParam)==((HWND)m_sldAudioIn))
{
//设置输入音量
m_VoInCtrl.SetCurrentVolume((m_VoInCtrl.GetMaximalVolume()-m_VoInCtrl.GetMinimalVolume())*m_sldAudioIn.GetPos()/100);
}
else
if(((HWND)lParam)==((HWND)m_sldVideoQ))
{
//设置视频质量
m_VQ=m_sldVideoQ.GetPos();
AVIO.SetVideoQuality(m_VQ);
}
}
break;
default:
returnCDialogX:
:
WndProc(uMsg,wParam,lParam);
}
returnTRUE;
}
SetWindowPos(m_hwndTT,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
/*INITIALIZEMEMBERSOFTHETOOLINFOSTRUCTURE*/
ti.cbSize=sizeof(TOOLINFO);
ti.uFlags=TTF_SUBCLASS;
ti.hinst=hInstX;
ti.uId=0;
ti.lpszText=szTip;
//
ti.hwnd=m_btnClose;
GetClientRect(m_btnClose,&ti.rect);
strcpy(szTip,"关闭NetTalk");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnMin;
GetClientRect(m_btnMin,&ti.rect);
strcpy(szTip,"最小化");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnHelp;
GetClientRect(m_btnHelp,&ti.rect);
strcpy(szTip,"帮助");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnAbout;
GetClientRect(m_btnAbout,&ti.rect);
strcpy(szTip,"关于...");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnLocal;
GetClientRect(m_btnLocal,&ti.rect);
strcpy(szTip,"本地视频");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnOutview;
GetClientRect(m_btnOutview,&ti.rect);
strcpy(szTip,"对方视频");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnOnoff;
GetClientRect(m_btnOnoff,&ti.rect);
strcpy(szTip,"传送/不传送本地视频");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_btnMsg;
GetClientRect(m_btnMsg,&ti.rect);
strcpy(szTip,"文本对话");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_sldAudioIn;
GetClientRect(m_sldAudioIn,&ti.rect);
strcpy(szTip,"调节麦克风音量");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_sldAudioOut;
GetClientRect(m_sldAudioOut,&ti.rect);
strcpy(szTip,"调节输出音量");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
ti.hwnd=m_sldVideoQ;
GetClientRect(m_sldVideoQ,&ti.rect);
strcpy(szTip,"调节视频质量");
SendMessage(m_hwndTT,TTM_ADDTOOL,0,(LPARAM)(LPTOOLINFO)&ti);
/*------------------------------------------------------------------------------*/
//画主窗口界面
voidCMainWnd:
:
OnEraseBkgnd(HDChdc)
{
RECTrc;
GetClientRect(m_hWnd,&rc);
HDChMemDC=CreateCompatibleDC(hdc);
HBITMAPhFace=LoadBitmap(hInstX,LPCTSTR(IDB_FACE));
HBITMAPhob=(HBITMAP)SelectObject(hMemDC,hFace);
//画标题条(如果被Hilight的话)
if(m_bHilightTitleBar)
{
RECTrc;
SetRect(&rc,5,5,168,22);
m_bHilightTitleBar=TRUE;
HBITMAPhb=LoadBitmap(hInstX,LPCTSTR(IDB_TITLE2));
DrawTransBmpX(hMemDC,rc,hb,0,0,0);
DeleteObject(hb);