东北大学毕业设计(论文) 第4章 系统设计
无线网络RTCP数据包数据接收模块设置RTP会话参数设置RTP传输参数创建RTP会话RTP监听接口设置目的地址视频数据存放区注销RTP会话RTP数据包RTCP监听接口视频解码模块
控制信息存放区图4.9 数据接收模块内部流程图
(6) 解码:解码模块的主要功能是将接收模块发送过来的数据解码还原后交给显示模块显示。视频解码模块的开始阶段和结束阶段与视频编码阶段基本相似,是由接收模块进行调度,使用FFmpeg库中的方法具体实现,这里不再赘述。解码模块内部流程图如图4.10所示。
视频解码模块初始化FFmpeg申请解码器接收模块设置解码器参数解码前视频缓存区解码后视频缓存区显示模块解码关闭解码器释放资源注销FFmpeg 图4.10 数据接收模块内部流程图
(7) 显示:将解码后的数据实时的显示出来。当系统运行时,系统系统UI模块首先会在Create模式中创建显示窗口资源,当所有资源都准备就绪之后系统UI进入Start模
-28-
东北大学毕业设计(论文) 第4章 系统设计
式。每当解码模块处理完数据时,它将会首先将这些数据传送至显示模块的待显示数据缓存区之中,然后向系统UI模块发出更新通知,系统UI收到这个通知后即会启动显示模块进行更新。显示模块首先会根据系统UI创建的视频显示窗口尺寸和待显示的视频尺寸来计算视频在显示窗口中的显示位置,最后显示视频画面。显示模块流程图如图4.11所示。
系统UI模块onCreate准备视频预览窗口显示视频画面onStart显示模块设置显示区域onStop解码模块待显示数据缓冲区 图4.11 显示模块内部流程图
(8) 会话参与者管理:会话参与者模块的主要功能是为了方便用户使用本软件进行视频。将IP地址和端口号保存到数据库里面,然后以列表的形式供用户选择。图4.12为会话参与者管理模块图。包括添加参与者、修改参与者、删除参与者、查找参与者四个功能。
会话参与者管理添加参与者修改参与者删除参与者查找参与者 图4.12 参与者管理模块
4.2.3 数据库设计
本系统使用SQLite数据库来实现数据的存储。SQLite作为一款轻型的数据库,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常
-29-
东北大学毕业设计(论文) 第4章 系统设计
的低,在嵌入式设备中,可能只需要几百K的内存就够了。作为移动设备,由于资源有限,SQLite无疑是最好的选择。
在Android端为了避免用户不厌其烦的输入IP地址和端口号,因此设计了一张表来保存其IP地址和端口号。在SQLite中创建数据库Video_Client。
数据库表tb_video_configs结构如表4.1所示。
表4.1 tb_video_configs
字段 _id ip port Name 类型 integer varchar(64) numeric varchar(32) 主键 Yes 外键 空值 No No No No 说明 ID ip地址 端口 名称 4.2 本章小结
本章对基于Android的视频通话系统的设计进行了详细的介绍。根据上一章系统分析做出的需求,确定了系统的各个模块,明确了各个模块的功能了。在此基础上完成了数据库的设计。
-30-
东北大学毕业设计(论文) 第5章 系统实现
第5章 系统实现
本章在上一章对基于Android的视频通话系统详细设计基础上,完成系统整体的实现。主要包括以下模块的实现:硬件检测、数据采集、压缩编码、数据发送、数据接收、解码、数据呈现、会话参与者管理。
5.1 功能子模块的实现
5.1.1 硬件检测模块
硬件检测是视频通话中必不可少的一个环节。视频通话是建立在硬件基础上的,因此在开始视频前必须进行视频检测。视频检测功能的实现是依赖JMF框架来实现的。硬件检测主要在CaptureDeviceDetector类中。其核心代码在detectCaptureDevices()方法中,核心代码如下。
public void detectCaptureDevices() { populateDeviceMap();
if (!hasDSoundCapture) { //判断是否存在Direct Sound捕获组件 autoDetectDSoundCapture(); //检测设备 }
if (!hasJavaSoundCapture) { //判断是否存在Java Sound捕获组件
autoDetectJavaSoundCapture(); //检测是否存在Java Sound捕获组件 }
String osName = System.getProperty(\ //获得系统名字 if (osName.contains(\
detectVFWCapture(); //检测是否存在VFM捕获组件 } else if (osName.contains(\ if (!autoDetectSunVideoCapture()) { autoDetectV4LCapture(); } }
}
//检测音频设备
private void autoDetectDSoundCapture() {
autoDetect(DIRECT_SOUND_AUTO_CLASS);
} //检测视频设备
private void autoDetectJavaSoundCapture() { autoDetect(JAVA_SOUND_AUTO_CLASS);
}
-31-
东北大学毕业设计(论文) 第5章 系统实现
5.1.2 数据采集模块
数据采集模块主要任务是对摄像头进行控制和读取,一方面将本方的视频预览画面传送到系统UI模块中,另一方面将摄像头采集到的YUV420P像素格式的原始视频数据传送到编码模块。
PC端的数据采集使用JMF框架的CaptureDeviceManager组件来进行。首先通过CaptureDeviceManager类使用查询机制和注册表来定位设备,然后将设备的信息放入CaptureDeviceInfo对象中返回。在CaptureDeviceInfo中包含了设备的相关信息。利用JMFUtils工具类中的initializeCaptureDataSource()方法获得数据采集的数据源。至此数据采集的准备工作就已经完成了。接下来需要做的就是利用得到的数据源来创建媒体处理器对象和媒体播放器对象。模块的核心代码如下:
CaptureDeviceInfo videoDevice = configPanel.getVideoDevice(); Format videoFormat = configPanel.getVideoFormat();
CaptureDeviceInfo audioDevice = configPanel.getAudioDevice(); Format audioFormat = configPanel.getAudioFormat(); try {
dataSource = createDataSource(videoDevice, videoFormat, audioDevice, audioFormat); //创建数据源对象
} catch (Exception e) {
if (dataSource == null) { dataSource = createDataSource(videoDevice, videoFormat, audioDevice, audioFormat); } }
DataSource cloneableDataSource = Manager.createCloneableDataSource(dataSource);//创建克隆数据源
DataSource processorDataSource = ((SourceCloneable)cloneableDataSource).createClone(); player = Manager.createRealizedPlayer(cloneableDataSource); //创建媒体播放对象 processor = Manager.createProcessor(processorDataSource); //创建媒体处理对象
processor.addControllerListener(new MyControllerListener(processor));//绑定媒体处理对象监听器
Android端的视频采集使用Google提供的API来实现。主要使用Android系统的Camera类、SurfaceView类和MediaRecorder类来实现。Camera类是控制摄像头的主要API。SurfaceView类用于向用户提供摄像头预览。MediaRecorder类用于录制视频。MediaRecorder的setOutputFile()可以将数据保存到本地文件,因此可以考虑创建一个LocalSocketServer。设置MediaRecorder的输出文件为LocalSocket.getFileDescritpor()。开启另一个线程来获得数据。核心代码如下。
if(videoLocalThread == null) {
videoReceiverSocket = new LocalSocket(); try { videoServiceSocket = new LocalServerSocket(\创建本地Socket videoReceiverSocket.connect(new LocalSocketAddress(\ //获得接收端的socket
-32-