热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WindowMobile视频会议程序的开发

Window Mobile视频会议程序的开发   适用平台 Pocket PC 2003 Phone Edition Windows Mobile 2003/SE Windows Mobile
Window Mobile视频会议程序的开发


 

适用平台

Pocket PC 2003 Phone Edition

Windows Mobile 2003/SE

Windows Mobile 5.0


开发工具

Microsoft Embedded Visual C++ 4.0

Microsoft Visual Studio 2005

及适用于各平台的SDK


摘要

本文介绍了通过使用一些开源的音频、视频编码以及实时流式传输协议库,编写适用于Windows Mobile的视频会议程序,实现桌面计算机和Windows Mobile移动设备在无线局域网上的文字、音频和视频通信,移动设备上视频会议的使用,可以给办公带来方便。


正文

编解码器的选择

这个视频会议程序中,我们选择视频画面的大小为176X144真彩色,使用桌面计算机连接的摄像头来获取,音频的品质为8kHz,8位量化,单声道。视频的捕获会依据画面的情况进行调整,在视频全速工作的时候,每秒钟的视频有30帧左右,加上音频的数据量。虽然音频和视频的品质都比较低,但是可以满足普通的视频会议的需求,直接传输原始数据将会占用比较多的网络带宽。所以,需要选择一个合适的编解码器来对音频、视频进行有效的压缩,在视频会议常用的一些标准中,我们有着比较多的选择。

1.视频编解码器的选择

  视频编解码器来源于视频压缩标准,常用的有M-JPEG、MPEG系列和H.26X系列。MPEG系列标准由ISO/ IEC 制定,主要应用于视频存储、广播电视、网络传输的上的流媒体等。H.26X标准由ITU-T(国际电信联盟电信标准化部门)制定,包括H.261、H.263、H.264,主要应用于实时视频通信领域,如视频会议、可视电话等。通常情况下,H.26X标准侧重于视频和音频信息的数据压缩效率,以适合调整该系统在特定码率下传输,MPEG系列标准则倾向于控制质量而不是控制码率。综合考虑,这里选择算法复杂度较低,易于实现的H.263算法,实现在9.6Kbps到128Kbps之间的速率传输大小为176X144(QCIF),速度在1fps到15fps之间的画面。

2.音频编解码器的选择

视频会议中传输的音频主要是语音数据,针对语音数据的压缩,ITU-T(国际电信联盟电信标准化部门)也提出了一系列的标准,下表是对一些常见标准的一个简要比较。 


名称
比特率(kbps)
复杂度
时延(ms)
编码器类型
G.722
64,56,48
30
子带编码
G.723.1
5.3,6.3
1.5
多脉冲
G726
16,24,32,40
0.125
ADPCM
G729A
8
10
CELP

这里使用G.726作为语音编解码器,选择传输速率为16kbps。原始音频为8kHz,8位,单声道,压缩比率为8。


网络传输协议的选择

视频会议进行的过程中,主要需要传输的是音频、视频这样的多媒体数据流.实时传输协议RTP(Real-time Transport Protocol)及实时传输控制协议RTCP(RTP Control Protocol)是IETF的AVT工作组发布的专门用于网络上传输多媒体数据流的一种传输协议,该协议可以实现在网络中的流媒体数据的单播和组播,同时为实时数据传输提供时序重构、帧丢失检测、数据安全等多种服务。这里使用UDP协议作为RTP协议的下层来传输数据。RTP是一种无连接的传输数据报文协议,它本身不为按顺序传送数据分组提供可靠的传送机制,也不提供流量控制或拥塞控制等服务,而是和RTCP协议一起来实现这些服务,RTCP是指接收方向数据发送方发送的控制报文,它提供网络传输QoS监测和拥塞控制、媒体间同步、识别信息、会议大小估计和控制信息量的调节等服务。在RTP会话期间,各会话成员周期性的发送RTCP控制包,利用这些控制信息可以灵活的改变数据传输速率,优化网络传输效率,更好的保证系统的实时性。


程序的编写

    考虑到初步实现的有效性和开发工作的简化,这个程序只实现点对点视频会议的功能。使用TCP协议来进行会议控制,RTP协议进行数据传输。其中需要使用的H.263编解码使用开源的tmn/tmndec2.0库(来自http://www.h263l.com),G.726编解码使用OpenH323中关于G.726的部分程序(来自http:// www.openh323.org),RTP使用开源的Jrtplib库(来自http://research.edm.luc.ac.be/jori/jrtplib/jrtplib.html),版本为3.4.0。以上这些开源的包均要经过一定的修改才能够在EVC下编译、使用。

PC端程序

PC端程序需要实现的主要功能有:音频采集,视频捕获,相应的编解码传输,以及将接收到的文字信息进行显示,接收到的音频和视频画面解码播放。该程序在Windows 2000/XP平台上,使用VS.net2003中的VC++.net进行开发。Windows平台提供了一系列方便的API,比较容易的实现对音频、摄像头等设备的操作。使用WaveIn系列函数捕获音频,WaveOut系列函数进行音频播放,使用VFW(Video For Windows)进行视频捕获以及回放。同时要提供一个友好的界面。和界面相关的这里不再赘述。

1.使用VFW(Video For Windows)操作摄像头

VFW(Video For Windows)当中提供了一系列函数,来操作摄像头。使用这个需要包含头文件vfw.h,并且使用vfw32.lib库。基本步骤是,使用capCreateCaptureWindow来创建一个视频捕获窗口,用capSetCallbackOnVideoStream来设置捕获到新的视频数据的回调函数,capCaptureGetSetup和capCaptureSetSetup用来获得和设置捕获参数,使用capDriverConnect来连接设备。在设备和驱动都正常时,这些初始化工作将逐步完成,在这些操作成功完成后,这里使用capCaptureSequenceNoFile函数来开始视频捕获,有新的视频数据将不存入文件,而是存在回调函数的类型为videohdr_tag结构体的参数中,该结构体中的lpData和dwBytesUsed将分别指示这一帧数据的开始地址和长度。有了这些数据,就可以在程序中进行使用,显示在本地窗口或者压缩后发送出去。需要结束视频捕获,使用capCaptureAbort来停止,capDriverDisconnect来断开设备。

2.使用WaveIn/WaveOut系列函数来操作音频设备

这方面资料很多,这里简要叙述一下。需要包含mmsystem.h头文件,以及使用Winmm.lib库。

录音的操作:用waveInOpen来打开录音设备,该函数的WAVEFORMATEX类型的参数用来设置录音的质量,接着要为录音的音频数据准备缓冲,使用waveInPrepareHeader函数,其中的wavehdr_tag结构体类型的参数,其中的lpData和dwBufferlength将指示缓冲的地址和大小。做好准备工作之后,用WaveInStart开始录音。这里为了不断监视录音数据,可以开始一个线程循环监听(在CALL_BACKTHREAD模式的时候),在其中用GetMessage来获得消息,有新的音频数据到来将会有MM_WIM_DATA消息,在这个消息中取得音频数据,并且进行使用。停止录音的时候,用waveInUnprepareHeader来清除缓冲,waveInReset停止录音,waveInClose关闭录音设备。

播放声音的操作:用waveOutOpen打开音频输出设备,该函数的WAVEFORMATEX参数用来设置放音的质量,用waveOutPrepareHeader函数来给放音准备缓冲,在准备这个缓冲的时候将需要播放的数据安排好,具体就在这个函数的wavehdr_tag类型的参数中,进行播放时,用waveOutWrite函数,这个函数将引用waveOutPrepareHeader准备好的wavehdr_tag类型的参数,播放其对应的缓冲数据的内容。注意音频播放完成后将有WOM_DONE消息,在其中可以做释放缓冲的操作。停止播放时,用waveOutClose关闭音频输出设备。

3.使用H.263对视频画面压缩解压

Tmn/tmndec2.0库良好的封装为使用提供了极大的方便,InitH263Encoder和InitH263Decoder函数用来初始化编解码器,退出程序时用ExitH263Encoder和ExitH263Decoder来释放编解码器。

开始视频捕获之后,在视频捕获的回调函数中,使用CompressFrame函数进行压缩,注意使用这个函数之前需要设置好压缩参数,第一个类型为CParam的参数将指示需要压缩的数据所在的地址,还要设置好压缩的回调函数以将压缩后的数据写入到一个指定的缓冲当中。使用tmn库,定义一个函数,并且设置WriteByteFunction等于这个函数就可以设置这个回调函数。CompressFrame执行之后,将回调WriteByteFunction函数,在这个函数中将压缩后的数据写入需要的缓冲区,同时CompressFrame返回这一帧画面压缩后的数据的长度,以字节为单位。

在收到网络发送过来的视频数据后,用DecompressFrame进行解压,解压后的数据将以RGB数据类型存入这个函数所跟的参数指示的缓冲区中。读取这个缓冲区的数据进行远程视频的显示。

4.使用G.726对音频压缩解压

为了方便操作,作者将OpenH323中的G.726部分程序进行封装,提供了g726_Encode和g726_Decode两个函数,这两个函数的输入参数分别是压缩前后和解压前后存放数据的缓冲区的指针。在本地计算机有新的音频数据需要发送时,用g726_Encode进行压缩;从网络接收到新的音频数据时,用g726_Decode进行解压播放。

5.使用RTP进行数据传输

使用JrtpLib提供的RTPSession类,方便的调用RTP来进行传输,使用的时候用这个类来定义两个变量,RTP的传输将使用它们。

程序开始的时候要初始化RTP,初始化RTP数据发送的步骤:定义一个类型为RTPSessionParams的变量,用SetOwnTimestampUnit来设置时间戳,SetMaximumPacketSize来设置最大的RTP包大小,SetSourceTimeoutMultiplier来设置数据超时,定义一个类型为RTPUDPv4TransmissionParams的变量,用SetPortbase设置发送的基端口,注意这个必须是偶数,默认值为5000。初始化RTP数据接收步骤和这个相同。在设置好这些参数之后,使用RTPSession的Create方法来建立RTP数据接收和发送,这个方法所跟的参数正是RTPSessionParams和RTPUDPv4TransmissionParams这两个类型。

会议开始时要建立RTP会话,这里仅使用到RTP点对点的会话功能。在开始一个新的会话时,用RTPIPv4Address(intIP,PORT_DATA)来建立一个新的地址,其中intIP是由inet_addr通过IP地址字符串计算得来,使用AddDestination将这个地址增加到发送的地址列表中。结束一个会话的时候,用DeleteDestination来删除这个会话地址。

程序退出的时候,用RTPSession的Destroy来清理RTP所使用过的资源。


Windows Mobile端程序

Windows Mobile设备上安装的Windows CE操作系统提供了和桌面Windows很接近的WIN32 API,大多数WIN32 API的函数在Windows CE中都存在。目前这个初步的程序尚未编写视频捕获部分,这个程序中所要实现的功能,视频解码显示,录音和播放,H.263、G.726压缩和解压以及RTP会话,通过将VC++程序移植到EVC,都很方便、快捷的得以实现。由此也体会到微软公司产品,标准统一的平台以及开发环境,给软件开发工作带来的巨大方便。

作者使用的设备是Pocket PC 2003系统,上面没有对VFW的支持,所以在显示远程画面的时候,使用的GDI,将解压后的数据组合成一幅位图,再显示到窗口中。

解压显示部分代码如下:

retvalue=DecompressFrame(data,size,rgbdata,buffersize);



CBitmap bitmap;   

bitmap.CreateBitmap(176,144,1,24,rgbdata);


CWnd* pWnd=GetDlgItem(IDC_REMOTEVIDEO);

pWnd->UpdateWindow();


CDC* pDC=pWnd->GetDC();

CDC bitmapDC;

      

bitmapDC.CreateCompatibleDC(pDC);

CBitmap* pOldBitmap = bitmapDC.SelectObject(&bitmap);

pDC->BitBlt(0,0,176,144,&bitmapDC,0,0,SRCCOPY);

bitmapDC.SelectObject(pOldBitmap);

bitmap.DeleteObject();


会议流程

以上部分只实现了基本的数据的采集、收发和使用,这个程序的另外一个重要部分就是会议的控制。由于作者时间和水平有限,这里临时使用了自己订立的一个协议,通过TCP来交换指令,实现对会议会话的流程控制。

会议的基本流程如下表所示:


呼叫方(PC/Windows Mobile)                   被呼叫方(PC/ Windows Mobile)

|                    1发出会议邀请(R)                        |

|--------------------------------------------------------------------------------------------> |

|                    2 接受邀请(Y)                            |

|<---------------------------------------------------------------------------------------------|

|                    3 确认接受&#xff08;A&#xff09;                           |

|--------------------------------------------------------------------------------------------> |

|                    4  RTP会话                                |

|<-------------------------------------------------------------------------------------------> |

|                    5 断开&#xff08;D&#xff09;                              |

|<---------------------------------      或者    -------------------------------------> |

|                    6 确认断开&#xff08;C&#xff09;                           |

|<---------------------------------      或者    -------------------------------------> |

|                    7 终止RTP会话                            |


会议过程中的数据收发

以上部分已经建立起一个可以进行会议数据收发的环境&#xff0c;提供好了相关的函数&#xff0c;在会议过程中&#xff0c;将使用这些函数来实现将本地数据发送到对方以及接收对方数据的功能。

RTP数据发送&#xff0c;使用SendPacket函数。

m_sessData.rtpSend.SendPacket(data, length, 0, false, 10UL);

RTP接收&#xff0c;这里使用的方法是使用它的OnRtpPacket函数&#xff0c;当RTP会话建立并且增加了目标地址后&#xff0c;从目标地址发送数据过来&#xff0c;将会调用这个函数&#xff0c;在这个函数里面取得装载数据并使用。

void RTPAppSession::OnRTPPacket(RTPPacket *pack, const RTPTime &receivetime, const RTPAddress *senderaddress)

{

       dlg->SendMessage(WM_CHAT_DATA_ARRIVED,(WPARAM)pack->GetPayloadData(),(LPARAM)(pack->GetPayloadLength()));

}



结论和展望

本文主要讲解了使用一些现有的库和WIN32 API&#xff0c;实现一个简单的PC和Windows Mobile相互通信的视频会议的过程。通过对这个程序的编写&#xff0c;极大的丰富了本人的知识&#xff0c;锻炼了动手能力。目前这个程序能够实现视频会议的基本功能&#xff0c;并且在PC和Windows Mobile上都可以稳定流畅的运行&#xff0c;但是距离实用的差距很大&#xff0c;是一种积极的学习和尝试。

后期作者将继续努力&#xff0c;使用SIP协议以及Windows Mobile 5.0的新功能等更加新的资源&#xff0c;完善和丰富这个程序的功能。

希望通过这篇文章和读者交流自己的经验和感受&#xff0c;促进学习&#xff0c;共同进步。


    本人才疏学浅&#xff0c;经验有限&#xff0c;文中会存在不少错误&#xff0c;欢迎朋友们批评指正&#xff01;

 


推荐阅读
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了VoLTE端到端业务详解|VoLTE用户注册流程相关的知识,希望对你有一定的参考价值。书籍来源:艾怀丽 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
  • Carve库在Visual Studio2015中的编译方法及注意事项
    本文介绍了在Visual Studio2015中编译Carve库的方法及注意事项。首先下载Carve库,并使用Visual Studio2015打开,生成后在bin目录下会生成.lib文件。同时,本文还指出了之前在Visual Studio2017中编译的问题,并提醒需要根据对应的平台进行编译,否则会出现报错。详细的步骤和注意事项请参考原文链接。 ... [详细]
  • 本文分享了一位Android开发者多年来对于Android开发所需掌握的技能的笔记,包括架构师基础、高级UI开源框架、Android Framework开发、性能优化、音视频精编源码解析、Flutter学习进阶、微信小程序开发以及百大框架源码解读等方面的知识。文章强调了技术栈和布局的重要性,鼓励开发者做好学习规划和技术布局,以提升自己的竞争力和市场价值。 ... [详细]
  • 本文介绍了使用Rust语言编写、保存和编译程序的简单步骤。首先,打开记事本文件并编写程序代码,然后将代码保存到一个以.rs为扩展名的文件中。接下来,使用rustc命令来编译运行程序。最后,通过命令行运行编译后的程序,得到输出结果。如果遇到编译错误,可以下载Build Tools for Visual Studio 2017来解决。 ... [详细]
  • {moduleinfo:{card_count:[{count_phone:1,count:1}],search_count:[{count_phone:4 ... [详细]
  • Introduction(简介)Forbeingapowerfulobject-orientedprogramminglanguage,Cisuseda ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
  • 线程漫谈——线程基础
    本系列意在记录Windwos线程的相关知识点,包括线程基础、线程调度、线程同步、TLS、线程池等。进程与线程理解线程是至关重要的,每个进程至少有一个线程,进程是线程的容器,线程才是真正的执行体,线程必 ... [详细]
  • Linux防火墙配置—允许转发
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 电脑f5键是什么作用
    常见问题f5常见问题韩亚整形医院源码,vscode写前端代码,ubuntu低配,tomcat下载路径乱码,爬虫_gscu,php精粹pdf,广州快速seo优化排名,aspwap网站 ... [详细]
  • UDP千兆以太网FPGA_verilog实现(四、代码前期准备UDP和IP协议构建)
    UDP:userDatagramprotocol用户数据报协议无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETFRFC76 ... [详细]
author-avatar
猪猪爱tai旸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有