基于Android设备的音视频实时监控系统的设计与实现

2,184 views
2,026 views

Published on

本文研究的主要内容,是设计一种廉价的、方便部署的、高扩展性的音视频监控系统。该系统基于 Android 嵌入式设备,以 IP 网络作为传输媒介,支持当前主流国际规范和通信协议。本文的任务是对该监控系统做出详细的需求分析,确定系统架构,给出详细设计方案,对核心技术进行分析,并列举系统实现的关键代码,最后对系统实现进行验证。

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,184
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

基于Android设备的音视频实时监控系统的设计与实现

  1. 1. 密级: 保密期限: 工程硕士研究生学位论文 题目: 基于 Android 设备的音视频实时 监控系统的设计与实现 学 号: 08R5328 姓 名: 张绍起 专 业: 软件工程
  2. 2. 导 师: 林秀琴 学 院: 计算机学院 年 月
  3. 3. 独创性(或创新性)声明 本人声明所呈交的论文是本人在导师指导下进行的研究工作及取得的研究 成果。尽我所知,除了文中特别加以标注和致谢中所罗列的内容以外,论文中不 包含其他人已经发表或撰写过的研究成果, 也不包含为获得北京邮电大学或其他 教育机构的学位或证书而使用过的材料。 与我一同工作的同志对本研究所做的任 何贡献均已在论文中作了明确的说明并表示了谢意。 申请学位论文与资料若有不实之处,本人承担一切相关责任。 本人签名: 日期: 关于论文使用授权的说明 本人完全了解北京邮电大学有关保留和使用学位论文的规定,即:研究生在 校攻读学位期间论文工作的知识产权单位属北京邮电大学。 学校有权保留并向国 家有关部门或机构送交论文的复印件和磁盘,允许学位论文被查阅和借阅;学校 可以公布学位论文的全部或部分内容,可以允许采用影印、缩印或其它复制手段 保存、汇编学位论文。 本学位论文不属于保密范围,适用本授权书。 本人签名: 日期: 导师签名: 日期:
  4. 4. 基于 Android 设备的音视频实时监控系统 的设计与实现 摘 要 出于安全等方面考虑,日常生活中有很多需要用到监控的地方, 如交通、电力、通信、金融、厂矿、场馆、森林防火、远程指挥, 甚 至是家庭安防。传统的监控系统一般需要安装专门的传输设备和网 络,价格昂贵,难以实现远距离传输。 另一方面,随着我国 3G 通信网络的全面普及,通信网络数据承 载能力取得了重大进展。在此基础上,各种智能手机、平板电脑等设 备迅速得到了普及。尤其是以 Android 作为操作系统的智能设备,如 雨后春笋般一夜之间遍地开花。Android 系统具有廉价、开放、兼容 性强、高效等特点,特别适合作为民用智能终端设备的操作系统。 本文所述内容,是研究并实现一种使用 Android 系统作为监控设 备、 通过互联网和 3G 通信网络进行数据传送的音视频实时监控系统。 这个系统具有廉价、方便远程监控、安装简单、无需安装专用设备网 络等特点, 它可以在某些对图像清晰度要求不是很高的民用领域内替 代传统监控系统。 本文通过分析系统应用场景,明确技术目标和关键技术参数, 对 本监控系统所涉及的技术层次进行划分,选定技术模型,确定层次间 接口,然后自下而上逐步进行研究和开发。在此过程中,为了使系统 具有较强的兼容性和可扩展性,力求遵循相关国际标准,采用众所周 知的编码格式和传输协议。本文所设计的系统主要由 Android 音视频 受监控端和流媒体服务器端两部分构成,主监控端可以使用 Real Player 等支持 RTSP 协议的通用流媒体播放器,也可以使用专门进行 开发的客户端进行监控。系统涉及到的技术包括 FFmpeg 移植、
  5. 5. Android 音视频采集、H.263 编码、G.723 编码、RTP/RTCP(实时传 输协议/实时控制协议) RTSP/SDP 、 (实时流协议/会话描述协议) UPnP (通用即插即用协议)等。 关键词:Android 音视频编解码 实时监控 流媒体服务器
  6. 6. DESIGN AND IMPLEMENTATION OF AUDIO AND VIDEO REAL-TIME MONITORING SYSTEM BASED ON ANDROID DEVICES ABSTRACT Due to security issues, there are many monitoring systems in our life. They are widely used in many fields, such as triffic, power, communication, banking, factory, mine, venues, forest fire prevention, long distance command, and even family security. Generally, special transport equipments and network must be deployed for traditional monitoring systems. It costs much and is hard to transport to a long distance. On the other hand, since 3G becomes overall popular in China, data-carrying capacity of the communication network has made significant progress. As a result, a variety of smart phones, tablet computers and other equipments quickly get the popularization. Android devices are the most typical case. They quickly occupied the market in every corner. Android is much suitable for being civil intelligent terminal device's operating system as it is low-priced, open, compatible and efficient. This paper studies on a monitoring system which captures media by Android-device and transports them over internet and 3G communication network. This system features as inexpensive, remote control, simple installation and independent from exclusive network devices. If the image quality is not the most important factor, traditional civil monitoring system can absolutely be replaced with this system. In this paper, the application scenarios of the system is analyzed, technical objectives and norms are given and the system is planned to develop with a hierarchical model. It is developed bottom-up after technical model is chosen and interfaces between layers are defined. International standards are used and well-known codecs and transport protocols are implemented overall to make the system compatible and flexible. This system is composed of both Android-based monitoring terminal and streaming server. To monitor, one can simply use a streaming player which support RTSP, e.g. Real Player. As well, a customized client can be developed for this. This system uses many technologies, such as FFmpeg transplant, audio and video capture on Android, H.263 codec, G.723 codec, RTP/RTCP (Real-time Transport Protocol/Real Time Control Protocol), RTSP/SDP (Real-Time Streaming Protocol/Session Description Protocol), UPnP (Universal Plug and Play), etc. KEY WORDS:Android, Codec, Real-time monitoring, Streaming server
  7. 7. 目 录 第一章 引言....................................................................................................................................... 1 1.1 课题背景................................................................................................................................. 1 1.2 课题任务................................................................................................................................. 2 1.3 论文结构................................................................................................................................. 2 第二章 相关技术...............................................................................................................................4 2.1 2.2 2.3 2.4 音频编码................................................................................................................................. 4 视频编码................................................................................................................................. 5 媒体传输协议......................................................................................................................... 6 媒体传输控制协议................................................................................................................. 7 2.4.1 RTSP 协议....................................................................................................................... 7 2.4.2 SDP 协议..........................................................................................................................8 2.5 媒体存储................................................................................................................................. 8 2.6 本章小结................................................................................................................................. 9 第三章 需求分析与架构设计.........................................................................................................10 3.1 需求分析............................................................................................................................... 10 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 应用场景........................................................................................................................ 10 网络环境........................................................................................................................ 10 功能需求........................................................................................................................ 11 性能要求........................................................................................................................ 11 兼容性与扩展性需求.................................................................................................... 11 3.2 架构设计................................................................................................................................ 12 3.2.1 网络架构........................................................................................................................ 12 3.2.2 设备选型........................................................................................................................ 12 3.2.3 软件架构........................................................................................................................ 15 3.3 本章小结................................................................................................................................ 20 第四章 详细设计与实现.................................................................................................................21 4.1 受监控端............................................................................................................................... 21 4.1.1 FFmpeg 移植................................................................................................................. 21 4.1.2 音频数据采集................................................................................................................26 4.1.3 音频编码........................................................................................................................ 29 4.1.4 音频传输........................................................................................................................ 29 4.1.5 视频帧数据采集............................................................................................................30 4.1.6 视频编码........................................................................................................................ 31 4.1.7 视频传输........................................................................................................................ 32 4.1.8 网络地址转换................................................................................................................33 4.2 流媒体服务器端................................................................................................................... 35 4.2.1 音视频媒体流接收........................................................................................................35 4.2.2 媒体持久化.................................................................................................................... 36 i
  8. 8. 4.2.3 媒体文件读取................................................................................................................39 4.2.4 音视频传输.................................................................................................................... 40 4.2.5 RTSP 服务器实现......................................................................................................... 44 4.2.6 处理同时监控问题........................................................................................................49 4.3 本章小结............................................................................................................................... 50 第五章 系统应用.............................................................................................................................51 5.1 应用内容............................................................................................................................... 51 5.2 检验方法............................................................................................................................... 51 5.2.1 受监控端........................................................................................................................ 51 5.2.2 流媒体服务器端............................................................................................................52 5.3 应用环境............................................................................................................................... 52 5.3.1 硬件环境........................................................................................................................ 52 5.3.2 网络环境........................................................................................................................ 52 5.3.3 软件环境........................................................................................................................ 53 5.4 应用效果............................................................................................................................... 53 5.4.1 功能性目标.................................................................................................................... 53 5.4.2 性能目标........................................................................................................................ 53 5.4.3 兼容性目标.................................................................................................................... 56 5.5 结论....................................................................................................................................... 58 5.6 本章小结............................................................................................................................... 58 第六章 结束语.................................................................................................................................60 6.1 论文工作总结....................................................................................................................... 60 6.2 问题和展望........................................................................................................................... 60 ii
  9. 9. 北京邮电大学软件工程硕士论文 第一章 引言 1.1 课题背景 音视频监控,是社会、企业和家庭安保的重要部分,是提供照看、监视、 指 挥、震慑、司法取证等的重要手段。音视频监控系统,就是实现音视频监控并支 持回放的设备、软件和网络所组成的应用系统。 视频监控系统的历史,已有大约二十几年。在这二十几年中,它从最早的模 拟信号,到数字监控,再到最新的 IP 网络监控,经过了翻天覆地的变化。一般 视频监控系统从技术上可以分为三代: 第一代是传统的模拟信号闭路视频监控系统(CCTV) ,他采用模拟信号进行 视频采集、传输、录制和回放,具有传输距离和容量受信号放大器和传输线缆的 硬件限制、存储设备容易损坏或丢失、录制的视频质量不高等问题,目前已被完 全淘汰。 第二代是“模拟-数字”监控系统(DVR) ,它是以数字硬盘录像机(DVR) 为核心的视频监控系统,从摄像头到 DVR 一般仍然采用模拟信号进行传输,只 是在 DVR 将模拟信号转化为数字信号并进行存储和回放。 由于 DVR 对信号进行 了数字化处理, 因此这种监控系统的传输距离不再是限制,可靠性也有了较大提 高, 视频质量也不受存储设备的影响。 此外, 有些 DVR 系统还支持 IP 网络访问。 第二代监控系统是目前最为广泛使用的监控系统, 然而由于国际上没有统一的标 准和接口规范,导致这种系统的实现五花八门、良莠不齐,各个厂家之间的系统 难以互相兼容和对接。 第三代是基于 IP 网络的视频监控系统(IPVS) ,属于下一代监控系统。IPVS 从视频采集、传输、存储到回放,均采用数字信号,以 IP 网络作为传输媒介, 支持远程传输、支持多种分辨率和编码格式。 然而, 不管是第一代还是第二代监控系统,传统的视频监控系统都必须要配 备专用摄像头、同轴电缆、视频画面分割器、矩阵、切换器、VCR、DVR 之类 的设备和网络,需要投入大量的硬件设备。一方面,繁杂的硬件和网络设施导致 了传统监控系统的成本普遍偏高,用户实际需求与投入预算往往难以匹配;另一 方面,当既有系统容量需要进行扩展时,由于设备和原网络架构的限制,就会出 现很多问题。 而第三代监控系统目前技术尚不成熟,各个厂家推出的所谓第三代 监控系统鲜有完全符合规范者,大都不过是厂家为了市场利益而打出的噱头, 并 不能从根本上解决问题。 1
  10. 10. 北京邮电大学软件工程硕士论文 由此可见,为了解决需求与成本的矛盾,为了提高监控系统的的可扩展性, 一种廉价、简洁、方便部署,近似第三代监控系统的解决方案亟待推出。目前国 内外也有相关领域的研究, 但一般都是止于理论研究与验证阶段, 不具实践性 (受 设备体积、功耗等限制) ,或没有真正运用于工程实践。 1.2 课题任务 本文研究的主要内容,是设计一种廉价的、方便部署的、高扩展性的音视频 监控系统。该系统基于 Android 嵌入式设备,以 IP 网络作为传输媒介,支持当前 主流国际规范和通信协议。本文的任务是对该监控系统做出详细的需求分析, 确 定系统架构,给出详细设计方案,对核心技术进行分析,并列举系统实现的关键 代码,最后对系统实现进行验证。 作者的主要任务,就是利用攻读硕士研究生课程过程中所学到的知识,结合 在企业工作中获得的实际经验,参考各个领域的成熟标准、规范和信息,利用成 熟的技术、应用程序框架等,实现上述监控系统,并以论文的形式对该系统进行 系统的分析与讨论。论文主要内容应包括监控系统相关技术的分析、系统的需求 分析与设计过程、系统整体应用架构(包括硬件、软件、网络等) 、系统具体实 现方式与核心代码、系统应用效果等方面内容。 1.3 论文结构 本文共分为六章,内容安排如下: 第一章 引言,介绍本课题的意义、任务、预期目标等。 第二章 相关技术,简要分析了音视频实时监控系统在开发过程中将要涉及 到的技术问题,围绕音视频编码、媒体传输协议、媒体传输控制、媒体存储等关 键问题,分别对各项技术的现状、特点进行了介绍与对比,列举了部分可选的实 现方式或协议。 第三章 需求分析与架构设计,对本文所论述的监控系统进行需求分析,明 确系统应用场景、网络环境要求、性能要求、兼容性与扩展性需求等信息,为系 统的详细设计与实现方案提供依据。 此外, 文章深入讨论和分析系统的实现方式, 通过必要的实验和计算, 确定设备形式与配置, 并对系统网络拓扑结构进行设计, 同时对系统软件、应用软件架构、框架、组件等进行选型。 第四章 详细设计与实现,详细分析设计系统每个技术细节的理论依据、工 作原理、应用算法、关键代码等信息,并最终通过软件工程管理手段,将本监控 系统完整实现。 2
  11. 11. 北京邮电大学软件工程硕士论文 第五章 系统应用,通过对系统在实际工作环境中的应用结果分析,验证系 统是否满足需求分析中提出的各项要求和指标,同时验证基于 Android 设备的音 视频实时监控系统设计的合理性、适用,以及对于本文实现方式的肯定。 第六章 结束语,对本文工作进行全面总结,给出本文所取得的成果,指出 存在的不足和改进方向。 3
  12. 12. 北京邮电大学软件工程硕士论文 第二章 相关技术 本文所研究的音视频实时监控系统,以 Android 嵌入式设备作为受监控端设 备,以 IP 网络作为传输媒介,支持当前主流国际规范和通信协议,实现实时的 音视频监控和音视频记录与回放。 要实现上述功能,所涉及的技术主要包括以下几点: 2.1 音频编码 显然, 数字计算机是无法直接处理模拟信号的。麦克风拾取的连续的音频信 号也是也是一种模拟信号,计算机或其它数字设备必须首先将其转化为数字信 号,才能进行下一步处理。然而,将音频信号进行数字化之后,其信息量是十分 巨大的。以双声道 44100Hz 采样举例,如果每个采样用 16bit 进行存储,如果采 样 1 分钟,也就是 60 秒的话,见下式: 44100×2×16×60 = 84672000bit ≈ 10Mbyte 式(2-1) 如此巨大的数据量,如果通过网络进行传输,需要的网络带宽计算方法如下 式所示: 84672000÷60 = 1411200bps ≈ 1.3Mbps 式(2-2) 这样的传输带宽要求, 对于应用系统的网络环境是比较苛刻的,尤其是在移 动通信网络环境下,目前国内尚难以持续稳定的提供这样的带宽。 所谓音频编码, 就是利用数学手段, 将连续的模拟音频信号转化为数字信息, 再通过一定的算法对该数字信息进行编码的过程, 该过程通常会通过适当降低音 频品质、或减少声音通道等手段,对音频数据进行压缩,以适应诸如剪辑、声效 处理、传输、存储、复制、回放等各种应用的需求。 目前广泛应用的音频编码格式主要有 MP3(MPEG-1 Audio Layer 3) 、AAC (Advanced Audio Coding) 、AMR(Adaptive Multi-Rate) 、G.723、G.729 等,这些 编码格式各有优点和缺点, 分别适用于不同的领域。 本文所讨论的系统采用 G.723 编码格式。 [1] G.723 编码标准文档已经被 G.726 所取代,它是有 ITU(国际电信联盟)制 定的一种双速语音编码,分别为 5.3kbps 和 6.3kbps。在这两种传输速率下,它分 别采用代数码激励线性预测(ACELP)和多脉冲最大似能量化(MP-MLQ)技术, 使得在很小的带宽下能够传输电话语音品质的音频信息。 目前,G.723 编码被广泛应用于 VoIP 服务、视频电话、无绳电话、数字卫 4
  13. 13. 北京邮电大学软件工程硕士论文 星系统、数电倍增设备(DCME)、公共交换电话网(PSTN) 、ISDN 及各种多媒体 语音信息产品领域。 2.2 视频编码 与音频数据一样,视频数据要通过计算机或其它智能数字设备进行处理, 也 必须首先量化为数字信息。在计算机中,视频媒体是以帧的形式存在的,而每一 个帧,可以看作是一幅静态的图片,由像素组成。假设一个以 15fps 录制的视频 信息,每帧的分辨率为 800x600,采用 24bit 真彩格式存储,这样的视频录制 1 分钟,也就是 60 秒,则有: 800×600×24×15×60 = 10368000000bit ≈ 9.7Gbyte 式(2-3) 如果通过网络传输,其带宽应为: 10368000000÷60 = 172800000bps ≈ 165Mbps 式(2-4) 显然目前几乎根本不可能为单个监控节点分配如此巨大的带宽。 为了解决这 一问题, 必须采用一定的算法对视频信息进行编码和压缩,使之能够达到当前主 流硬件和网络设备能够承受的水平。 所谓视频编码,也是利用数学手段,将连续的视频信号转化为数字信号, 并 对该信号进行编码,通常是以降低视频分辨率、清晰度、流畅性等为代价,对数 据进行压缩,实现视频数据量级的降低,以方便对视频信息进行剪辑、存储、 传 输、复制、回放等操作。 目前广泛应用的视频编码格式主要包括 MJPEG(Motion Joint Photographic Experts Group) 、H.263、AVC(H.264,Advanced Video Coding)等,它们同样各 有优缺点,适用于不同的应用场景。本文所讨论的系统采用 H.263 编码格式。 [2] H.263 编码, 也是 ITU 制定的一种媒体编码标准, 它是专门为低码流应用系 统而设计的。然而 H.263 编码是能够适应很宽的码流范围的,而不仅仅应用于低 码流环境。在很多应用场景下,它被认为是可以完全取代 H.261 编码的。H.263 标准的优势主要有如下几点:  使用运动补偿技术和半像素精度;  数据流层次结构的某些部分是可选的, 使得其即可适应较低的码流环境, 也可以在高码流环境下取得较高的纠错能力;  有四个协商选项来提高性能;  采用无限运动矢量和基于语义的算数编码;  采用预测算法和与 MPEG 中 P-B 帧类似的帧预测算法;  支持 Sub-QCIF、QCIF、CIF、4CIF 和 16CIF 等 5 种图像格式。 H.263 编码最初是为了用于基于公共交换电话网和其它基于电路交换的网络 5
  14. 14. 北京邮电大学软件工程硕士论文 进行视频会议和视频电话而设计的,但目前更广泛引用于基于 IP 网络和综合业 务数字网的视频会议系统。 2.3 媒体传输协议 本文中所指的传输协议是指用于实现音视频媒体传输过程的网络通信协议, 在 OSI 模型中, 处于应用层。 常用的媒体传输协议包括 HTTP (超文本传输协议) 、 MMS(微软媒体服务器)协议、RTP(实时传输协议) 、MGCP(媒体网关控制协 议)等。在这些协议中,有些适用于文本和图片信息的浏览,有些适合流媒体的 传输,有些则更适合运用于电信系统与互联网系统间的媒体互通。 本系统音视频的传输适宜采用 RTP/RTCP 协议。RTP/RTCP 协议其实是两个 [3] 协议,一个是 RTP 协议(实时传输协议) ,另一个是 RTCP 协议(实时控制协议)。 RTP 协议最初是由 IETF 在 1996 年提出的一种用于网络传输的协议, 它的目 标是保障数据传输的实时性和顺序性,但将数据的完整性置于次要方面。RTP 协议为数据提供具有实时特征的端对端传送服务, 如在组播或单播网络服务下的 交互式视频音频或模拟数据。 应用程序通常在 UDP(用户数据包协议)上运行 RTP 以便使用其多路结点 和校验服务。RTP 协议也可以与其它适合的底层网络或传输协议一起使用,如 TCP(传输控制协议) 。如果底层网络提供组播方式,那么 RTP 可以使用该组播 表传输数据到多个目的地。 [4] RTP 协议支持承载多种音视频编码格式 ,支持动态码率调整和编码格式的 切换,支持动态编码传输。它对 G.723 和 H.263 格式的音视频流的封包和传输方 [5] 法,具有明确的定义 。 RTCP 协议是 RTP 协议的伴生协议, 它用于监控服务质量并传送正在进行的 会话参与者的相关信息。 利用 RTCP 协议, 应用程序可以检测到对端的网络状态、 传输带宽、丢包率、延迟等信息,从而动态的调整数据接受或发送的码流大小、 编码格式等信息。此外,RTCP 协议还给出了一种松散的会话管理功能,可以让 应用程序简单的控制或监视数据传输参与者的会话状态 (如一个发送或接收者的 加入或退出等) 。 RTP/RTCP 协议被广泛的应用于视频电话、视频会议系统、实时监控系统等 领域。使用 RTP/RTCP 协议作为监控系统音视频的传输协议,可以保障监控的实 时性,同时也可以与几乎所有以相同协议进行媒体传输的其它监控系统、VoIP 系统等进行对接,具有很强的兼容性。 6
  15. 15. 北京邮电大学软件工程硕士论文 2.4 媒体传输控制协议 媒体传输的过程,需要通过一定的手段进行控制,比如媒体资源如何表示、 媒体的编码格式如何、媒体的发送端和接收端如何建立或拆除网络通信等,只有 在有效的管理与控制机制下,才能正常工作。本文中所讲的媒体传输控制协议, 就是用于控制媒体的传输过程的网络通信协议, 与媒体传输协议同属于 OSI 模型 中的应用层。常用的媒体传输控制协议包括 SIP(会话初始协议) 、RTSP(实时 传输流协议) 、ISUP(ISDN 用户部分)协议等。 本文中讨论的流媒体的媒体传输控制,是通过 RTSP 协议来实现的,具体的 实现形式,就是构建一个 RTSP 流媒体服务器。RTSP 流媒体服务器的通信协议 栈如图 2-1 所示,从功能角度出发,在应用层主要分为 RTSP/SDP 会话模块和 RTP/RTCP 媒体传输模块两部分。 图 2-1 RTSP 流媒体服务器通信协议栈 其中 RTSP 和 SDP 两层代表的是 RTSP/SDP 会话模块,RTP 和 RTCP 代表了 RTP/RTCP 媒体传输模块。其中 SDP 层以虚线表示,是因为 SDP 协议数据仅出 现在 RTSP 协议的部分数据包中。 RTSP/SDP 也是两个独立而又相关的协议,一个是 RTSP 协议,一个是 SDP 协议。具体讨论如下: 2.4.1 RTSP 协议 [6] RTSP 协议 ,中文为“实时流协议” ,是用来控制音视频流等流媒体的播放、 暂停、停止、录制等行为的协议,一言以蔽之就是用来控制实时数据的传输的。 RTSP 协议具有如下特点:  可扩展性强,可以很容易的加入新的方法和参数;  易实现,通过标准的类 HTTP 协议和 MIME 解析算法即可实现;  独立于传输, RTSP 协议与媒体传输协议是独立的, 因此理论上可以集成 任何媒体传输协议;  多服务器支持,RTSP 服务可以与媒体传输服务处于不同的服务器设备, 抑郁性能扩展。 7
  16. 16. 北京邮电大学软件工程硕士论文 RTSP 协议一般需要与 SDP 协议配合使用。 2.4.2 SDP 协议 [7] SDP 协议(会话描述协议) ,最初被设计为 SAP(Session Announcement Protocol,会话发布协议)的一个部件,但之后被广泛的用于与 RTSP、SIP 协议 [8] (会话初始协议) 协同工作,也可被单独用来描述多播会话。 SDP 协议的主要功能是为会话通知、 会话邀请和其它形式的多媒体会话初始 化等目的提供多媒体会话描述信息。它的设计宗旨是通用性,它可以应用于大范 围的网络环境和应用程序,而不仅仅局限于组播会话目录,但 SDP 不支持会话 内容或媒体编码的协商。 SDP 协议内容主要包括以下信息:  会话名称和意图;  会话持续时间;  构成会话的媒体;  有关接收媒体的信息(如地址,端口等) 。 通过 RTSP 协议与 SDP 协议的配合使用, 可以达到会话建立、 媒体信息查询、 编码格式协商、 传输层信息交换等目的,最终实现建立或拆除流媒体服务连接的 功能。 RTP/RTCP 媒体传输模块,从传输协议的角度讲,与受监控端媒体信息传输 的机制几乎是一样的。唯一的区别,就是流媒体服务器端媒体流信息的传输目标 和过程受 RTSP/SDP 会话模块的控制。 2.5 媒体存储 为了在一定的时间范围内,可以调取监控历史记录,作为潜在的纪念价值、 娱乐价值、案情分析、法律学证据等,必须对监控信息进行存储。信息的存储方 式主要包括数据库方式、 模拟设备录制方式、 本地文件方式、 云存储方式等几种。 其中: 数据库方式不适合大数据文件的存储;而模拟设备录制方式的工作原理与 引言中提到的第一代监控系统无异,具有诸多缺点,属于被淘汰的技术;云存储 虽然具有很大优势,但目前该技术尚不成熟,且能够提供足够带宽和可靠性服务 的厂商不多,价格也比较昂贵。因此,对于本文讨论的系统,最为可行的形式就 是本地文件存储形式。 可选的本地文件类型有: AVI、 3GP、 MP4、 QuickTime、 ASF、 VOB、 RealMedia 等。本文讨论的监控系统信息的存储,采用 QuickTime 文件格式,它是由 Apple 8
  17. 17. 北京邮电大学软件工程硕士论文 公司制定的一种用于存储音视频媒体的文件格式。该文件格式在 1998 年被 ISO (国际标准化组织)认可为 MPEG-4 的基础,它采用原子(atom)结构对媒体信 息进行存储,支持多种音视频编码,如 MJPEG、AVC、H.263、YUV、μ-law、 MP3、AC-3 等,特别适合用作截取、编辑、文件、传播、和播放等目的。 本文设计的实时监控系统以 QuickTime 作为媒体信息的文件格式, 经实验测 试,在较低码流的编码格式下,其文件增量约为 38kbps,比较适合作为监控系 统音视频媒体历史信息记录使用。 2.6 本章小结 本章对论文所讨论的音视频实时监控系统在开发过程中将要涉及到的技术 问题进行了简要分析,围绕音视频编码、媒体传输协议、媒体传输控制、媒体存 储等关键问题,分别对各项技术的现状、特点进行了介绍与对比,给出了部分可 选的实现方式或协议,并初步选定了适合本文所讨论系统的实现或协议。 9
  18. 18. 北京邮电大学软件工程硕士论文 第三章 需求分析与架构设计 本章主要内容,是对音视频实时监控系统的各方面需求进行分析,并根据分 析结果,给出系统整体架构和软硬件技术选型结果。 3.1 需求分析 需求分析就是对监控系统进行详细的分析,弄清系统功能要求、性能要求、 软硬件环境要求等,明确期待结果,确定输出内容。 3.1.1 应用场景 本文所述音视频监控系统,主要用于一般工业、商业与民用监控,具体应用 场景包括但不限于会场、商场、教室、楼宇、物业、地面车站、车辆、非特种加 工车间、厂房、仓库、农场、计算机房、民宅等。受监控端工作在常温、常压环 境,可能是移动的(如安装在车辆上) ,也可能是固定的。 要求人们能够通过本系统辨别视野内的一般车辆、人物,能够看清目标人物 的动作、表情;要求能够在一定范围内采集音频信息,要求能够听清 5 米以内的 人物对话,能够基本辨别人物音色。 3.1.2 网络环境 由于采用 Android 作为受监控端设备操作系统, 可选的网络环境就比较多了。 正如引言中描述的,本系统是基于 IP 网络的。 系统应优先选择有线网络连接,因为这是最为可靠、高效的连接方式,但缺 点是受地理环境和传输距离的限制。 如果有线网络不适用,也可以通过 WIFI 网络进行连接,同样可以获得相对 [9] 稳定的连接和最高可达 54Mbps 的带宽。 在多数室外或移动情况下,是无法保障有线网络和 WIFI 网络的。此时 3G 通信网络就成了最佳选择。综合考虑稳定性、网络覆盖范围、带宽等因素,认为 我国北方地区适合选择 WCDMA 网络,而南方则适合选择 CDMA2000 网络,其 [10] [11] 理论带宽分别可以达到 3.84Mbps 和 3.1Mbps 。 流媒体服务器端,要求具有固定的互连网 IP 地址。不过,如果受监控端、 服务器端和主监控端都在同一局域网中或处于支持 VoIP 的虚拟专用网络 (VPN) 10
  19. 19. 北京邮电大学软件工程硕士论文 中,则只要求流媒体服务器具有固定的私网 IP 地址即可。鉴于服务器处于监控 系统的中央节点,其网络接入带宽最好大于 1Mbps/终端。 3.1.3 功能需求 本文讨论的音视频监控系统需要完成的主要功能就是音视频信息的实时监 控。具体而言有以下几点:  在可见光范围内,对视角范围内的视频信息进行实时监视;  对受监控端设备周围 5m 范围内的音频信息进行实时监控;  音视频监控信息可以通过开放的网络协议实时传输;  音视频信息可以通过开放协议进行实时播放,支持主流流媒体播放器客 户端软件;  音视频信息支持存储和回放,存储格式采用常用国际标准;  要求解决内网网络地址转化(NAT)等问题。 3.1.4 性能要求 本文设计的音视频监控系统最主要的性能需求为两方面: 一个是实时性和声 音、画面流畅性,另一个是音视频的分辨率。因此,整个系统的所有性能需求均 围绕这两点提出。 为了能够达到上述两个方面的需求,使用户获得较好的使用体 验,系统满足如下指标:  音频采样率:8000Hz  音频分辨率:8bit  视频帧率:10~15fps  视频分辨率:352x288  音视频延迟:≤2000ms  音视频不同步:≤200ms  监控节点数:≤100 个  历史记录:1 个月 3.1.5 兼容性与扩展性需求 考虑到本监控系统与当前主流的基于 IP 网络的监控系统 (IPVS 或准 IPVS) 、 IP 电话(VoIP)系统、互联网流媒体系统等的兼容性,应采用国际通用标准和 传输协议,以方便与第三方系统的对接。此外,采用国际通用标准和传输协议, 11
  20. 20. 北京邮电大学软件工程硕士论文 可以在当前以及可遇见的未来时间内,在技术上做到方便扩展,通过简单的增加 受监控节点和修改服务器配置,即可扩充系统的监控点位和服务能力。 3.2 架构设计 系统架构设计过程,就是通过对系统需求进行分析,综合考虑时间、成本、 技术可行性、产品效果等多方面因素,对系统进行技术层面设计的过程。 系统架构设计的原则,是保证技术可行的基础上,追求设备的高性价比, 同 时选用遵循国际规范、实现简单、易于开发、高效稳定的软件架构。根据监控系 统需求分析, 决定采用以流媒体服务器作为中心节点,受监控端统一向服务器发 送监控信息,用户通过访问服务器进行监控的方案。 3.2.1 网络架构 本文所设计音视频实时监控系统的网络架构如图 3-1 所示。 其中流媒体服务 器具有固定 IP 地址,供主监控端通过 RTSP/SDP 协议进行访问;受监控端可以 通过有线网络、WIFI 网络或 3G 网络通过 IP 网络连接到流媒体服务器,将音视 频信息通过 RTP/RTCP 协议发送到服务器。 图 3-1 网络架构 在受监控端, 短距离固定监控设施建议采用有线网络接入的方式,通过光纤 或 UTP(非屏蔽双绞线)进行连接。考虑到成本问题,推荐使用 UTP。如果应用 环境对网络布线具有较强的限制因素,同时监控设施部署在室内,则可以考虑采 用 WIFI 网络接入方式。如果要求监控系统处于移动状态(比如车辆内部监控、 自动化厂区巡检等应用环境) ,则受监控端应采用 3G 网络接入方式。 12
  21. 21. 北京邮电大学软件工程硕士论文 3.2.2 设备选型 设备选型的主要参考因素有三方面,即实现难度、性能和价格。其中首要因 素是是否易于实现,有无技术可行性;其次要保证监控系统的性能和效果,以满 足各项技术指标;最后,还要严格控制系统成本,使得系统具有实用性和规模化 生产的可行性。  受监控端设备 在受监控端,可选的方案包括:使用 Android 成品手机或平板电脑等设备、 使用 Android ARM 开发板套件、自行设计并制作 Android 设备。 ARM 又被称为“高级精简指令集机器(Advanced RISC Machine) ,顾名思 ” 义,它是一种能够运行精简指令集的处理器。ARM 是有 ARM Ltd.公司设计的, 但是该公司并不是将 ARM 的技术细节完全隐藏起来,而是将该处理器的设计方 案、技术指标、指令集标准等信息在有限商业授权的条件下,向合作厂商开放, 并允许他们按照完全相同的方案,进行生产和销售。ARM 本身的优点,再加上 这种开放的商业模式,使得 ARM 愈发优秀并稳稳占领了移动设备市场。 很显然,使用成品手机或平板电脑等设备在性能上可以有较大的选择空间, 且实现特别容易,但是成本过高,不宜选用。自行设计并制作 Android 设备需要 专业的硬件设计和制造水平,也需要专业的生产配套设备的支持,难度过高。 故 各方面因素比较均衡的方案,就只有使用 Android 开发板套件了。好在目前市场 上 Android 开发板种类很多,各种配置均可买到,甚至还可以根据客户需求定制 开发。 13
  22. 22. 北京邮电大学软件工程硕士论文 1:1.2 图 3-2 Android 开发板 图 3-2 是本文设计的音视频监控系统受监控端所选用的 ARM 开发板设备照 片,其型号为 TQ210,配有三星 Cortex-A8 处理器(S5PV210,主频 1GHz) ,1GB DDR2 内存,能够为系统给予充分的性能支持,保障系统运行。该开发板套件的 主要部件详细参数如下:  CPU:三星 S5PV210  内存:1GB DDR2  NAND Flash:1GB  摄像头:CMOS,15fps  音频:外接 MIC  以太网接口:100Mbps  WIFI 模块:SDIO 或 USB(可选)  3G 模块:WCDMA 或 CDMA2000(可选)  显示屏:7" LCD 电阻屏(可选) Cortex-A8 处理器是一款 ARMv7 体系的 ARM 处理器,相比于之前的推出的 ARM 处理器,它的主频可以达到从 600MHz 到 1GHz。同时,它使用超标量微体 系结构和用于 SIMD 处理的 NEON 技术,与 ARM926、ARM1136 和 ARM1176 处 理器保持二进制级兼容,使得其具有高性能、低功耗、应用广等有点。 目前,Cortex-A8 处理器已广泛应用于智能手机、平板电脑、上网本、数字 14
  23. 23. 北京邮电大学软件工程硕士论文 电视等领域。尤其是三星 S5PV210 处理器(代号“蜂鸟” ,Cortex-A8 的三星公 司实现版本) ,具有强大的多媒体处理能力,特别适合作为音视频监控系统的核 心处理芯片。  流媒体服务器 服务器端设备形制已非常成熟,采用一般的机架式服务器即可。在选择具体 配置参数的时候,主要应该考虑的因素主要是性能和容量。  性能计算 根据实验测试情况,一台具有 2 颗 Intel Xeon 2.0GHz CPU、2GB DDR2 内存 的机架式服务器,在处理音视频监控信息时的负载变化如表 3-1 所示: 表 3-1 服务器负载实验表 序号 受监控节点(个) CPU 占用率(%) 内存占用(MB) 1 0 5 902 2 1 7 922 3 2 8 941 4 3 10 961 5 4 12 980 6 5 13 1000 7 6 15 1020 8 7 17 1040 9 8 18 1059 10 9 20 1079 11 10 22 1099 由此可以推算,平均每个受监控节点 CPU 占用增量约为 1.7%,内存占用增 量约为 19.7MB。则当监控节点为 100 个时,CPU 伪占用率将达到 175%,同时内 存伪占用量将达到 2872MB。 若按上述负载计算,CPU 综合参数应为实验机的 1.7 倍左右。如果要保证系 统负载最高不超过 70%, 则应为 2.4 倍左右。 据此, CPU 应选择 4 颗 Xeon 2.4GHz。 同理,内存容量应为实验数据的 2.9 倍左右,如果内存负载不超过 70%, 容 量应为实验机的 4.1 倍左右,即 4100MB。  容量计算 由于监控系统需支持历史信息回放,则必然需要进行数据存储。假设以 QuickTime 格式进行文件存储,分辨率为 352×288,实测单节点数据产生速率约 为 38kB/s。那么,30 天产生的数据量为: 30×24×60×60×38×100 = 9849600000kB ≈ 9.8TB 15 式(3-1)
  24. 24. 北京邮电大学软件工程硕士论文  最终选型 根据上述计算所得数据,以各部件标称系列进行匹配如下:  CPU:Xeon 2.4GHz,4 颗  内存:4GB  硬盘:10TB 具体设备选型推荐使用 IBM System x3650 M3,具体配置参数如下(列表中 未给出的,按标准配置考虑) :  CPU:Xeon E5160(3.0GHz,双核) 颗 ,2  内存:金士顿 2GB DDR2 800 ECC,2 条  硬盘:IBM 2TB SAS,5 块 考虑到数据存储的可靠性,可以考虑使用 RAID 技术,考虑到廉价性因素, 可以选择 RAID5 方式(IBM System x3650 M3 内建支持 RAID5) ,则此时: 10TB = (N - 1)×2TB 式(3-2) 可得 N = 6,即需要的硬盘数量为 6 块。 3.2.3 软件架构 本监控系统主要运用的是音视频媒体的实时传输技术。具体而言,包括 Android 音视频采集、音视频编解码、RTP 传输、RTSP 服务、UPnP 等。这些技 术均依赖于特定的操作系统、软件环境与应用程序框架等。  受监控端软件架构 图 3-3 受监控端软件架构 如图 3-3 所示,音视频实时监控系统的受监控端软件主要包括用户界面、 音 视频采集模块、音视频编码器、流媒体传输模块、网络地址映射模块和设备驱动 层等几部分组成。其中用户界面用于设定设备工作状态、服务器信息等,负责受 监控端的人机交互;音视频采集模块通过间接调用设备驱动层功能,采集音视频 信息; 音视频编码器负责将采集到的原始音视频信息编码成为适合通过网络进行 实时传输的格式; 网络传输的功能由流媒体传输模块实现;在流媒体传输的过程 中,如需解决内网网络地址映射的问题,则交由网络地址映射模块来解决。 16
  25. 25. 北京邮电大学软件工程硕士论文  受控端操作系统 受监控端采用 Google 公司主持开发的 Android 操作系统,具体版本为 4.1, API Level 16,代号“Jelly Bean” ,该系统具有资源占用小、运行效率高、多媒体 支持程度高、节能稳定等特点,适合本监控系统应用。 考虑到移植的方便性,可以直接选择上文中提到的 TQ210 Android 开发板套 件厂商提供的发行版本,以降低实现的复杂度。  受监控端音视频编码器 Android 系统支持录制音频和视频,MediaRecorder 对象可将其按照一定的编 码格式和存储格式保存到文件,如 3GPP 文件、M4A 文件、MP4 文件等。然而 Android 只能将音视频保存为文件,录制完成后再回放,不支持输出原始媒体流, 故无法直接将采集的到媒体实时传输出去。 为了解决这一问题,可以直接从 MediaRecorder 中采集音频波形数据和视频 帧数据, 然后使用第三方编解码库对其进行编码。本监控系统使用的是当前被广 [12] 泛使用的、公认最高效的编解码库,FFmpeg 。本文会在后续的章节详细讲解如 何将其移植到 Android 平台中并进行调用。  受监控端媒体传输组件 流媒体的传输采用 RTP/RTCP 协议。 Android 4.1 的 API 中虽然有相关的 API, 但是仅仅是一组简单的接口,还很不完善。本文选用的 RTP 应用程序 API 是 [13] jlibrtp ,它由纯 Java 语言实现,方便进行移植,且接口简单,使用灵活,支持 自定义 timestamp 和 mark 标志。  受监控端 UPnP 组件 当受监控端设备通过有线网络或 WIFI 网络接入的时候,包括某些 3G 网络 接入的情况,设备往往是处于局域网中的。这种受监控端处于局域网,而流媒体 服务器处于互联网环境的情况,就要求局域网的路由器或防火墙设备支持 VoIP 通信,或者支持 UPnP。为了保障在各种情况下都能够正常通信,在受监控端总 是需要实现 UPnP 功能的。 [14] UPnP 全称为 “通用即插即用” , 它是由 UPnP Forum 推广的一套网络协议, 其目标是使家庭网络和办公网络中的设备与设备之间能够无缝对接。UPnP 当前 被广泛应用于网络设备的发现和动态路由和端口映射控制方面。 通过使用这一技 术,应用程序可以请求路由器或防火墙设备临时(或永久)的建立一个网络地址 [15] 转换(NAT,Network Address Translation) ,使得处于互联网上的设备可以连接 到局域网中的设备上。 [16] 本文所设计的监控系统,选用 Cling ,它是一款用 Java 语言编写的 UPnP 协议开源实现,原生支持通用 Java 语言和 Android 系统,其目标就是严格遵守国 17
  26. 26. 北京邮电大学软件工程硕士论文 际规范,完整的、简洁的、广泛的实现 UPnP API。它灵活易用、代码小巧、移 植简单,特别适用于本系统的应用场景。  流媒体服务器软件架构 图 3-4 流媒体服务器软件架构 如图 3-4 所示, 流媒体服务器软件架构主要由流媒体接收模块、 流媒体会话 模块、编解码模块、持久化模块、流媒体发送模块和资源会话池等部分构成。 其 中流媒体接收模块负责接收来自于受监控端软件的实时媒体流; 接收到的媒体信 息需要通过编解码模块进行处理,以方便用于后续的各项功能;持久化模块可以 将解码后的媒体信息存储至流媒体服务器的本地硬盘, 也可以将本地硬盘中存储 的历史媒体信息读取出来; 客户端软件通过与流媒体服务器中的媒体会话模块进 行通信, 来申请媒体信息资源,媒体会话模块就可以驱动流媒体发送模块将前文 中提到的来自于实时媒体流的、 或者来自于服务器本地文件的媒体信息发送到流 媒体客户端播放器软件,从而实现监控和回放的功能。  流媒体服务器操作系统 考虑到流媒体服务器的安全性、可靠性、性能、成本等方面因素,决定选用 Linux 作为其操作系统。 目前 Linux 拥有众多支持厂商及其发行版本,每个版本都有其特点和优势。 今年来,一种开放的、以易用性为核心目标的 Linux 发行版本逐步占领了很大部 分市场,它就是 Ubuntu Linux。它是由南非著名企业家 Mark Shuttleworth 发起创 办的公司基于 Debian Linux 研发而成的,具有安全、可靠、易于维护、操作简单 等特点。 本系统选定的版本为 Ubuntu 12.04 LTS Server,64bit 版。  流媒体服务器多媒体应用框架 流媒体服务器端主要需进行三个方面的工作:其一,接收来自于受监控端的 音视频媒体并进行解码;其二,对监控媒体进行封装并存储为文件,以备日后调 取播放;其三,将监控媒体以 RTSP 服务的形式提供给主监控端,供用户对监控 节点进行实时监控。 18
  27. 27. 北京邮电大学软件工程硕士论文 为了实现上述功能,涉及到的技术包括 RTP/RTCP 流媒体传输、音视频编解 码、音视频媒体序列化(以文件的形式持久化至磁盘) 、RTSP 协议实现等。要应 用这些技术,综合考虑可行性、实现难度、效果和性能、成本等方面因素,最好 选择成熟的应用程序框架和保准的国际规范与协议实现。 通过多方面对比, 认为采用 Java 作为开发语言, JMF Java Media Framework 以 ( [17] API) 作为流媒体应用框架是最好的选择。首先,Java 语言具有安全、稳定、 开发效率高、可移植性强的特点,且 Java 语言被全球众多知名公司和组织所支 持, 拥有大量的应用程序框架和第三方功能组件, 适应各种应用场景; 其次, JMF 是原 Sun Microsystem 公司开发的一套 JavaSE 增强应用框架,支持音视频媒体的 采集、回放、编解码、传输等几乎所有流媒体技术,同时支持标准的 RTP/RTCP 协议,以及众多国际标准的音视频编码格式和文件(容器)格式,为 Java 多媒 体开发提供了完整的解决方案。 如图 3-5 所示,JMF 在处理媒体的时候,采用的是一种“输入-处理-输出” 这样的模型。它将媒体信息定义为 DataSource(数据源) ,作为输入或输出的对 象,Processor(处理器)则负责对数据源进行编码、解码、增加音效、附加视频 信息、调整音视频属性等操作。数据源的来源,既可以是利用 MediaLocator 对象 捕捉来自麦克风和摄像头的信息,也可以是其读取来自多媒体文件的信息,还有 可能是来自于网络的数据,通过 SessionManager 对象进行处理后得到的。通过 Processor 处理过的数据源,可以通过 Player 对象进行播放,使之在音箱和显示器 上表现出来, 也可以通过 SessionManager 对象以 RTP 协议的形式传输出去, 还可 以通过 DataSink 对象,将媒体信息存储到多媒体文件中。 19
  28. 28. 北京邮电大学软件工程硕士论文 图 3-5 JMF 媒体处理模型 此外,在 Processor 工作过程中,为了能够处理不同的媒体格式,尤其是需 要在多种媒体格式之间进行编解码操作的时候,需要用到的一种组件叫做 Codec (编解码器) 。它是一个多媒体转码的抽象接口,定义了一组用于编解码操作的 方法。在 JMF 中,原 Sun 公司和 IBM 公司已经分别提供了若干种常用媒体格式 的编解码器。 如果这些解码器仍然不能满足用户需求,应用程序开发人员可以自 行实现符合要求的编解码器,并通过 JMF 注册工具,将该编解码器注册到 JMF 中,这样,Processor 就可以调用自定义的编解码器进行媒体处理工作了。 从这样一个架构来看, JMF 确实是一个具有完善的功能体系和完整实现的多 媒体应用程序框架,适合本监控系统的应用。  流媒体服务器网络通信框架 考虑到流媒体服务器是监控系统的核心部件,所有流媒体信息、会话控制信 息均需要通过流媒体服务器进行处理, 因此保持流媒体服务器网络通信过程的高 效性便成了一项特别需要注意的问题。 [18] 在 Java 编程语言中,有一项 nio 技术,可以通过非阻塞的方式实现包括网 20
  29. 29. 北京邮电大学软件工程硕士论文 络通信在内的 IO(输入输出)问题,利用这一技术,可以极大的提高应用程序 网络通信效率。然而,使用 nio 接口进行应用程序开发,由于其通信过程是异步 的,也就是说数据的收发过程是随机发生的,使得程序编写难以保持清晰的结构 化思路,容易对经验不足的开发者造成不少麻烦。 [19] 为此,有人创建了一个名为 netty 的开源软件项目,专门作为 Java nio 接口 的一个应用程序框架,方便人们开发基于 nio 技术的应用程序。简单而言,netty 是一个异步的、 基于事件驱动的网络应用程序框架,用以帮助实现可维护的高性 能服务器和客户端软件。 Netty 不仅对 nio 接口的通信过程进行了封装, 还通过分 层的方式,对 FTP、SMTP、HTTP 和 RTSP 等通信协议进行了封装,使得开发者 们能够及其方便的编写基于这些协议的应用程序。 3.3 本章小结 在本章中, 对音视频实时监控系统做了系统化的需求分析,其中包括应用场 景、网络环境、性能要求、兼容性、扩展性等方面。该系统的实际设计方案与具 体技术实践,以及最终的应用验证,均以此为参考。 此外, 根据需求分析的内容,本章还对文章所讨论的音视频实时监控系统进 行了架构设计,讨论的网络架构、网络接入方式、设备选型、软件架构等方面问 题,为系统的详细设计与实现提供系统化的框架结构。 21
  30. 30. 北京邮电大学软件工程硕士论文 第四章 详细设计与实现 在本章中, 将对监控系统运用的应用程序框架进行详细的介绍,分析其工作 原理,以及如何运用于本系统的开发过程。系统中关键的设计思想、核心代码将 会进行描述和解析。 4.1 受监控端 受监控端,也就是 Android 设备端。这一部分的主要任务就是采集音视频数 据、音视频编码,并将媒体流传输到流媒体服务器端。受监控端所设计的功能模 块主要有如下几点: 4.1.1 FFmpeg 移植 在 Android 设备端,为了能够对音视频信息进行编码,必须要有相应的编解 码器。而 Android 系统并没有向应用程序层直接暴露编码解码器,其内置的 opencore 是经过定制改造的,且根据不同的设备提供商、操作系统发行版本而存 在较大差异。为了解决这一问题,就不得不向系统中移植第三方的编解码器, 以 完成音视频编码的工作。 向 Android 移植 FFmpeg,应在 Linux 系统环境下进行,本监控系统实际开发 使用的是 Ubuntu 12.04 LTS,安装 gcc、automake 等相关开发工具包。除此之外, 还应该装有 Android SDK、eclipse 及其 Android 开发插件——ADT。 移植的详细步骤如下:  下载并配置 Android NDK [20] Android NDK 是一组工具集, 它允许 Android 程序开发人员使用 native 代码 (如 C/C++代码)编写某些功能。本文中使用的 NDK 版本是 r8c,将下载好的 NDK 压缩文件解压至/opt 目录,并将如下路径添加到 PATH 环境变量中: /opt/android-ndk-r8c  下载并修改、编译 FFmpeg 源码 FFmpeg 是一个非营利性开源软件组织的名称,同时也是这个组织开发的一 个开源软件项目。FFmpeg 软件实际上是一个可移植的多媒体应用软件库,提供 了一套完整的媒体录制、编码转换和传输的方案。本文所移植的 FFmpeg 的版本 号为 1.0,可以从其官方网站上直接下载。 22
  31. 31. 北京邮电大学软件工程硕士论文 将下载好的文件解压缩为如下文件夹: ~/android/ffmpeg/jni/ffmpeg 然后建立如下文本文件: ~/android/ffmpeg/jni/Android.mk 其内容为: include $(all-subdir-makefiles) 建立文本文件: ~/android/ffmpeg/jni/ffmpeg/Android.mk 内容如下: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale LOCAL_MODULE := ffmpeg include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH)) 建立文本文件: ~/android/ffmpeg/jni/ffmpeg/av.mk 格式与 Android.mk 文件相同,内容主要是将相关源代码文件编译成目标文 件的指令,此处从略。 建立文本文件: ~/android/ffmpeg/jni/ffmpeg/config.sh 并为其增加执行权限。文件内容如下: #!/bin/bash PREBUILT=/opt/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/pre built/linux-x86 PLATFORM=/opt/android-ndk-r8c/platforms/android-9/arch-arm ./configure --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-ffserver --disable-everything --enable-encoder=h263 --enable-encoder=g723_1 23
  32. 32. 北京邮电大学软件工程硕士论文 --enable-decoder=h263 --enable-decoder=g723_1 --target-os=linux --arch=arm --enable-shared --enable-cross-compile --disable-asm --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- --cc=$PREBUILT/bin/arm-linux-androideabi-gcc --nm=$PREBUILT/bin/arm-linux-androideabi-nm --strip=$PREBUILT/bin/arm-linux-androideabi-strip --extra-cflags="-fPIC -DANDROID" --extra-ldflags="-Wl,-T,$PREBUILT/arm-linux-androideabi/lib/ldscrip ts/armelf_linux_eabi.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-linux-androideabi/4.6/crtbegin.o $PREBUILT/lib/gcc/arm-linux-androideabi/4.6/crtend.o -lc -lm -ldl" sed -i 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h sed -i 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h sed -i 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h sed -i 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h sed -i 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h sed -i 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h sed -i 's/HAVE_CBRTF 0/HAVE_CBRTF 1/g' config.h sed -i 's/HAVE_ISINF 0/HAVE_ISINF 1/g' config.h sed -i 's/HAVE_ISNAN 0/HAVE_ISNAN 1/g' config.h sed -i 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h sed -i 's/#define av_restrict restrict/#ifdef av_restrict #undef av_restrict #endif #define av_restrict/g' config.h 修改 Bug:  将各子目录 Makefile 中的 “include $(SUBDIR)../config.mak” 这一行注释 掉; 24
  33. 33. 北京邮电大学软件工程硕士论文  将 ffmpeg 目录下 Makefile、 common.mak、 library.mak 和 libavfilter/Makefile 等文件中的“clean::”全部替换为“clean:” ;  将 libavutil/time.h 文件重命名为 libavutil/fftime.h 文件;  将 libavutil/time.c 文件重命名为 libavutil/fftime.c;  将源码中所有对 libavutil/time.h 文件的引用修正为对 libavutil/fftime.h 文件的引用;  从 libavcodec/Makefile 文 件 中 注 释 掉 “ OBJS-$(!CONFIG_SMALL) += inverse.o”这一行;  将 libavformat/utils.c 文 件 中 的 “ #if FF_API_AV_GETTIME && CONFIG_SHARED && HAVE_SYMVER ” 替 换 为 “ #if FF_API_AV_GETTIME && CONFIG_SHARED && HAVE_SYMVER && 0” 。 在“~/android/ffmpeg/jni/ffmpeg”目录下执行如下命令,对 FFmpeg 源代码进 行配置: ./config.sh 执行成功后,执行如下命令,编译 FFmpeg: cd ~/android/ffmpeg export PREBUILT=/opt/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/prebuilt/linu x-x86 export PLATFORM=/opt/android-ndk-r8c/platforms/android-9/arch-arm /opt/android-ndk-r8c/ndk-build 执行成功后,会得到如下文件: ~/android/ffmpeg/libs/armeabi/libffmpeg.so  编写 native 接口 按上文中方法操作,已经获得了可以在 Android 系统中运行的 FFmpeg 多媒 体功能库。但是,Android 应用想调用这个动态链接库,还需要一个专门的 native [21] 接口,也就是通过 JNI 技术 调用 FFmpeg 中的功能。创建 native 接口项目的过 程如下:  创建 Android 工程 用 eclipse 创 建 Android 应 用 程 序 工 程 ( 本 系 统 所 用 工 程 名 称 为 “snowflake” ,工程目录为“~/workspace/snowflake” ,创建 package 和 Java ) native 类。Native 类的全名为: personal.shawn.snowflake.codec.audio.G723Encoder 25
  34. 34. 北京邮电大学软件工程硕士论文 personal.shawn.snowflake.codec.video.H263Encoder 主要定义编解码器的 Java 接口,型如: private native int open(int frame_rate, int input_width, int input_height, int output_width, int output_height); private native void close(int handle); private native int encode(int handle, byte[] input_buffer, int input_position, int input_length, byte[] output_buffer);  编写底层代码 首先生成 native 接口框架,可以通过如下命令生成: cd ~/workspace/snowflake/bin/classes javah personal.shawn.snowflake.codec.audio.G723Encoder javah personal.shawn.snowflake.codec.audio.H263Encoder 接下来, “~/android/snowflake/jni/snowflake” 创建 文件夹, 并将上述 javah 命令生成的两个“.h”文件拷贝到这个文件夹。 下一步,在这个文件夹下建立两个 C 语言源代码文件,文件名为: g723_encoder.c h263.encoder.c 这两个文件分别用于实现上文中定义的 Java native 接口中的方法,此 处内容从略。 最后,在该文件夹下建立文本文件“jni_init.c” ,内容为: #include <jni.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/avutil.h" jint JNI_OnLoad(JavaVM * vm, void * reserved) { avcodec_register_all(); av_register_all(); return JNI_VERSION_1_4; }  编译 native 接口 将上文中编译 FFmpeg 时生成的头文件按目录结构拷贝到 native 底层代 码 工 程 目 录 ( ~/android/snowflake/jni/snowflake ) 中 , 主 要 有 libavcodec 、 libavformat、libavutil 和 libswscale 这几个文件夹; 26
  35. 35. 北京邮电大学软件工程硕士论文 将 上 文 中 编 译 FFmpeg 时 生 成 的 libffmpeg.so 文 件 复 制 到 “/opt/android-ndk-r8c/platforms/android-9/arch-arm/usr/lib/” 目录,作为动态链 接使用; 在 “ ~/android/snowflake/jni/snowflake ” 文 件 夹 中 创 建 文 本 文 件 Android.mk,其内容为: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE LOCAL_SRC_FILES := snowflake := jni_init.c g723_encoder.c h263_encoder.c LOCAL_LDLIBS += -lffmpeg -llog include $(BUILD_SHARED_LIBRARY) 最后,输入如下命令,对 native 代码进行编译: cd ~/android/snowflake export PREBUILT=/opt/android-ndk-r8c/toolchains/arm-linux-androideabi-4.6/prebuilt/linu x-x86 export PLATFORM=/opt/android-ndk-r8c/platforms/android-9/arch-arm /opt/android-ndk-r8c/ndk-build 最终,将上文生成的 libffmpeg.so 和 libsnowflake.so 文件拷贝到受监控端程序 工程的“libs/armeabi”目录,并将 G723Encoder 和 H263Encoder 两个类复制到工 程源码目录,就最终完成了 FFmpeg 的移植工作。 4.1.2 音频数据采集 上文中已经提到,在 Android 应用中,如果试图使用 MediaRecoder 采集并保 存音频至文件的方式,有两种技巧行的方案: 其一是不断的将音视频保存到很小的文件,分时间片进行发送;其二是创建 一个 LocalSocket 对象的连接,用这个连接的 FileDescriptor 伪装成普通文件描述 [22] 符,然后在通过连接的另一端进行媒体的处理 。 第二种方法(LocalSocket 法)的典型代码如下:  在线程 A 中创建 LocalSocketServer 对象 LocalServerSocket serverSocket = new LocalServerSocket("socketAddress"); socket = serverSocket.accept(); 27
  36. 36. 北京邮电大学软件工程硕士论文  在 B 线程中创建 LocalSocket 对象并连接 LocalSocketServer LocalSocketAddress endpoint = new LocalSocketAddress("socketAddress"); LocalSocket clientSocket = new LocalSocket(); clientSocket.connect(endpoint);  在 B 线程中采集媒体并“保存”至 LocalSocket 文件描述符 Camera camera = Camera.open(); camera.unlock(); MediaRecorder videoRecorder = new MediaRecorder(); videoRecorder.setCamera(camera); videoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); videoRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); videoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); videoRecorder.setVideoSize(352, 288); videoRecorder.setVideoFrameRate(15); videoRecorder.setOutputFile(clientSocket.getFileDescriptor()); videoRecorder.setMaxDuration(0); videoRecorder.setPreviewDisplay(surfaceHolder.getSurface()); videoRecorder.prepare(); videoRecorder.start();  在 A 线程中通过 LocalSocketServer 读取媒体 InputStream inputStream = socket.getInputStream(); while(! stop) { int len = inputStream.available(); if(len < 0) { break; } else if(len == 0) { try { Thread.sleep(10); } 28
  37. 37. 北京邮电大学软件工程硕士论文 catch (InterruptedException e) { Log.e(getClass().getName(), "", e); } continue; } byte[] data = new byte[len]; len = inputStream.read(data); //处理数据 //handleData(data, 0, len); } 然而这两种技巧均存在问题:第一种方法的问题是传输延迟过高,且无法保 证媒体传输的连续性;第二种方法的问题是 Socket 连接对象的 FileDescriptor 不 是可探询(seekable)的,而 MediaRecorder 在将媒体保存至文件时是要不断探询 (seek)的,此外还有媒体文件封装格式等问题,应用程序很难处理这些情况。 为此,应用程序必须通过一定的手段,直接采集未编码的音频采样数据, 并 加以编码和传输。所幸,Android 还专门提供了一个 AudioRecord 接口,允许应 用程序直接采集未编码的音频采样数据。该接口的具体使用过程关键代码如下: //向 AndroidManifest.xml 文件中添加音频录制权限 <uses-permission android:name="android.permission.RECORD_AUDIO" /> //初始化 AudioRecord 对象 audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 10 * AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)); //开始录制 audioRecorder.startRecording(); //循环读取音频采样数据 int bytesGot = audioRecorder.read(data, 0, data.length); 通过这种方法,未编码的音频采样数据就被填充到 byte 数组 data 中了,实 现了音频数据的采集。 29
  38. 38. 北京邮电大学软件工程硕士论文 4.1.3 音频编码 上文中采集的音频数据,是纯音频波形采样数据,码流非常大,必须首先进 行编码才能进行传输,这里使用上文中提到的 G.723 编码。在第 4.1.1 节中,已 经阐述了将 FFmpeg 移植到 Android 的具体方法,因此音频编码工作便可以通过 JNI 接口调用 FFmpeg 的方法予以实现了。音频编码的关键代码如下: //初始化 G.723 音频编码器 g723Encoder = G723Encoder.getInstance(); //循环执行,将 4.1.2 中采集的音频采样数据进行编码 int encodedDataLength = g723Encoder.encode(data, 0, data.length, encodedData); 4.1.4 音频传输 为了将音频数据通过 RTP/RTCP 进行传输,必须首先选择一个 RTP 应用程 序框架或组件。前文中也有阐述,由于 Android 系统自带的 RTP API 尚不完善, 决定采用 jlibrtp 这个第三方应用程序组件。Jlibrtp 的移植非常简单,可直接通过 其官方网站下载源代码,并解压缩到受监控端应用程序工程中即可。 Jlibrtp 移植完毕,就可以对音频数据进行传输了。然而,为了方便使用,将 该组件进行封装是一个很好的选择。 Jlibrtp 的典型用法如下: //分别申请 RTP 和 RTCP 端口资源 DatagramSocket rtpSocket = new DatagramSocket(port); DatagramSocket rtcpSocket = new DatagramSocket(port + 1); //构造目标地址 Participant participant = new Participant(sessionAddress, sessionPort, sessionPort + 1); //初始化 RTP 会话对象 RTPSession rtpSession = new RTPSession(rtpSender.rtpSocket, rtpSender.rtcpSocket); rtpSession.addParticipant(participant); //设置负载类型(G.723 编码的负载类型代码为 4;H.263 编码的负载类型代 码为 34) rtpSession.payloadType(payloadType); //发送 RTP 数据包 long[][] result = rtpSession.sendData(new 30 byte[][]{rtpData}, null, new
  39. 39. 北京邮电大学软件工程硕士论文 boolean[]{marker}, timestamp, null); …… //销毁资源 rtpSession.endSession(); rtcpSocket.close(); rtpSocket.close(); 假设将 jlibrtp 封装为 RtpSender 类,这个类既可以用来传输音频,也可以用 来传输视频,以提高代码可复用性。 实际项目中 RTP 传输音频数据的关键代码如下: //初始化 RtpSender 对象 rtpSender = RtpSender.getInstance("demo.streamingserver.com", 24680, RtpSender.PT_G723, g723Encoder.getRtpTimestampInterval()); //循环调用,将编码后的音频数据发出 rtpSender.send(encodedData, 0, encodedDataLength, true); 4.1.5 视频帧数据采集 视频媒体数据的采集,同样不宜采用 MediaRecoder 记录到文件的方式。此 处的替代方法,是使用直接 Camera 对象进行视频拍摄,然后在 Camera 对象上设 置 PreviewCallback 的办法。关键代码如下: //向 AndroidManifest.xml 文件中添加视频录制权限 <uses-permission android:name="android.permission.RECORD_VIDEO" /> <uses-permission android:name="android.permission.CAMERA" /> //首先初始化 Camera 对象 videoRecorder = Camera.open(); Camera.Parameters params = videoRecorder.getParameters(); params.setPreviewSize(640, 480); params.setPreviewFormat(ImageFormat.NV21); videoRecorder.setParameters(params); videoRecorder.setPreviewDisplay(surfaceHolder); //实例化 PreviewCallback 实例 videoFrameCallback = new VideoFrameCallback(frameRate, targetFrameRate); //设置 PreviewCallback 并启动视频拍摄 videoRecorder.setPreviewCallback(videoFrameCallback); videoRecorder.startPreview(); 31
  40. 40. 北京邮电大学软件工程硕士论文 其中 VideoFrameCallback 是用来实现 PreviewCallback 功能的一个自定义实现 类,将其设定为 Camera 对象的回调功能后,每拍摄一帧图像,系统都将回调一 次,并将这一帧视频图像传递给回调方法。VideoFrameCallback 类的核心代码如 下: @Override public void onPreviewFrame(final byte[] data, Camera camera) { long frameNumberToSelect = (long) (targetFrameNumber * (frameRate * 1.0 / targetFrameRate) + 0.5); if(frameNumberToSelect != frameNumber) { frameNumber ++; return; } else { frameNumber ++; targetFrameNumber ++; } //data 即为视频帧数据,此处可对其进行编码和传输处理 } 4.1.6 视频编码 与音频编码类似,视频数据也可以通过 JNI 接口调用 FFmpeg 库进行 H.263 编码,具体做法如下: //首先在应用程序初始化时实例化 H.263 编码器 h263Encoder = H263Encoder.getInstance(targetFrameRate, 640, 480, 352, 288); //然后在上文用于视频捕捉的 PreviewCallback 实现类中添加代码,对帧数据 进行编码 int encodedDataLength = h263Encoder.encode(data, 0, data.length, encodedData); 这样,视频帧数据就被编码至 encodedData 数组中了。 32
  41. 41. 北京邮电大学软件工程硕士论文 4.1.7 视频传输 视频媒体传输的实现,稍显复杂,其主要原因是以太网路由器的 MTU(最 [23] 大传输单元) 所导致的。对于以太网而言,一个数据包若想不被路由器拆分, 其最大长度不得大于 1500 个字节,也就是说,如果采样 RTP 传输视频帧,一个 数据包应小于或等于 1500 字节,其中 IP 头 20 个字节、UDP 头 8 字节、RTP 头 12 字节(如图 4-1) ,则有效载荷应不大于 1460 字节。然而,很多情况下,H.263 编码的视频帧的大小,是有可能超过这个值的,因此 H.263 视频帧的传输,就必 须在应用层对其进行分包。 图 4-1 RTP 数据包格式 H.263 分包发送的格式有 3 种模式, 简单的说: 模式要求数据发送按照 GOB A (块组)对齐,即一个 RTP 包中应包括一个帧内的一个或多个完整的 GOB;B 模式要求数据发送以 MB(宏块)对齐,也就是一个 RTP 包中可以包含一个或多 个完整的 MB,而不一定是完整的 GOB,但这种模式不可以应用于 PB 帧,这种 方式允许将 H.263 帧分的更细,RTP 包也就可以更小;C 模式与 B 模式类似, 但 同样适用于 PB 帧。 显然,其中 A 模式封包最为简单,也是标准中规定所有编解码器必须实现 的模式。本监控即采用 A 模式对帧数据进行分包并传输。具体的分包算法关键 代码从略。 A 模式的负载头部如图 4-2 所示: 图 4-2 H.263 码流 A 模式负载头部 其中:  F,1bit,表示负载头部标记,A 模式该值为 0;  P,1bit,表示 PB 帧模式,0 表示普通的 I 帧或 P 帧,1 表示 PB 帧;  SBIT,3bit,表示负载内容之前忽略的 bit 数,这是由于 H.263 编码的编 码器在进行视频编码时,每个 GOB 的大小不一定是 8bit 的整数倍,而 33
  42. 42. 北京邮电大学软件工程硕士论文 H.263 规范中的每个 GOB 开头的 GSTUF 填塞有是可选的,所以会造成 GOB 不以字节起始 bit 开始,故需要此参数;  EBIT,3bit,与 SBIT 类似,用以表明负载内容之后应忽略的 bit 数;  SRC,3bit,表示源格式,000:禁止,001:Sub-QCIF,010:QCIF,011: CIF,100:4CIF,101:16CIF,110 和 111:保留;  I,1bit,表示图像编码类型,0 表示内部编码,1 表示附加编码;  U,1bit,表示无限运动矢量标志;  S,1bit,表示基于语法的算数编码标志;  A,1bit,表示高级预测模式选项;  R,4bit,保留,直接填 0;  DBQ,2bit,为差分量化参数,如果没有使用 PB 帧,直接填 0 即可;  TRB,3bit,B 帧时域参考,如果没有使用 PB 帧,直接填 0 即可;  TR,8bit,P 帧时域参考,如果没有使用 PB 帧,直接填 0 即可。 H.263 视频帧的分包传输, 本质上就是根据 GBSC 划分 H.263 码流, 按照 GOB 对齐模式进行分割,并根据图像帧的属性,填充负载头部各个参数。 4.1.8 网络地址转换 正如上文中所述,在很多情况下,媒体的传输过程需要利用 UPnP 协议实现 网络地址转换,将内网地址映射为外网地址,以达到网络通信的目的。本系统采 用一个称为 Cling 的应用程序框架,它是一款用 Java 语言编写的 UPnP 协议开源 实现,原生支持通用 Java 语言和 Android 系统,其目标就是严格遵守国际规范, 完整的、简洁的、广泛的实现 UPnP API。它灵活易用、代码小巧、移植简单, 特别适用于本系统的应用场景。 本系统中用 Cling 实现 NAT 控制的关键步骤如下:  设置权限 在被监控端应用程序工程的 AndroidManifest.xml 文件中加入下列用户权限:  android.permission.INTERNET  android.permission.ACCESS_NETWORK_STATE  android.permission.ACCESS_WIFI_STATE  android.permission.CHANGE_WIFI_STATE  添加 Cling 包 在工程中建立 libs 目录,并从 Cling 官方网站下载发布版本,解压后将下列 文件复制到 libs 目录中:  cling-core-*.jar 34
  43. 43. 北京邮电大学软件工程硕士论文  cling-support-*.jar  teleal-common-*.jar  编写代码 为了灵活的控制 NAT 详细参数, 需要取得本机 IP 地址, 作为地址映射参数。 获取本机地址的方法,是首先取得受监控设备上所有的 NetworkInterface 的列表, 然后依次列举其绑定的 IP 地址,并检查其是否为 loopback 地址(也就是类似于 127.0.0.1 这样的 IP 地址) 。为了保证网络协议的兼容性,应该排除 IPv6 类型的 IP 地址。 接下来, 需要获取 Android 系统的 WifiManager 对象, 因为 Cling 在实现 NAT 的时候需要该对象。获取的方法非常简单,直接通过 Android 应用程序 Context 中取得系统服务即可。 最后,就可以开始编写设定和撤消 NAT 条目的代码了。 以上各步骤实现的关键代码如下: //获取 WifiManager 对象 WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); //设定 NAT 信息 InetAddress localAddr = getLocalAddress(); UnsignedIntegerFourBytes lease = new UnsignedIntegerFourBytes(0); UnsignedIntegerTwoBytes ep = new UnsignedIntegerTwoBytes(12345); UnsignedIntegerTwoBytes ip = new UnsignedIntegerTwoBytes(12345); PortMapping mapping = new PortMapping(true, lease, null, ep, ip, localAddr.getHostAddress(), PortMapping.Protocol.UDP, "description"); UpnpService upnpService = new UpnpServiceImpl(new AndroidUpnpServiceConfiguration(wifiManager)); upnpService.getRegistry().addListener(new PortMappingListener(mapping)); upnpService.getControlPoint().search(); …… //取消 NAT 条目 upnpService.shutdown(); 4.2 流媒体服务器端 流媒体服务器的主要功能包括接收受监控端音视频数据流、媒体持久化、 RTSP 媒体服务器实现等几方面。流媒体服务器上各项功能的实现,以 Java 语言 35
  44. 44. 北京邮电大学软件工程硕士论文 进行开发,使用 JMF 作为最主要的应用程序库。 本节涉及的技术问题主要有以下几点: 4.2.1 音视频媒体流接收 音 视 频 媒 体 流 的 接 收 , 可 以 直 接 使 用 JMF 提 供 的 RTP/RTCP 组 件 , RTPManager。RTPManager 可以用于创建、维护和终止一个 RTP 会话,它不仅支 [24] 持点对点的数据传输,还支持一点对多点的传输,同时也支持组播(多播) 。 利用 RTPManager,不仅可以进行媒体发送,而且可以进行媒体的接收。 要实现媒体的接收过程,主要步骤如下:  初始化 RTPManager //定义音视频媒体类型 AudioFormat g723 = new AudioFormat(AudioFormat.G723_RTP); VideoFormat h263 = new VideoFormat(VideoFormat.H263_RTP); //定义接收端地址信息 SessionAddress localAddress = new SessionAddress(); 或 SessionAddress localAddress = new SessionAddress(new SessionAddress().getDataAddress(), bindDataPort); //初始化 RTPManager 对象 RTPManager rtpManager = RTPManager.newInstance(); rtpManager.initialize(localAddress); //定义 RTP 包 PT 字段 rtpManager.addFormat(g723, 4); rtpManager.addFormat(h263, 34);  加入媒体传输事件监听器 这一部很简单,直接设定监听器即可 rtpManager.addReceiveStreamListener(new Listener()); 其 中 Listener 是 一 个媒 体 传 输 事 件监 听 器 实 现类 , 他 实 现 了 JMF 中 的 ReceiveStreamListener 接口,关键代码如下: public class Listener implements ReceiveStreamListener { public void update(final ReceiveStreamEvent event) { if(event instanceof NewReceiveStreamEvent) 36
  45. 45. 北京邮电大学软件工程硕士论文 { ReceiveStream receiveStream = event.getReceiveStream(); DataSource dataSource = receiveStream.getDataSource(); } ...... } } 上文代码中得到的 dataSource 对象, 就是自受监控端发送而来的视频或音频 流数据了,可以通过处理做进一步应用。  连接媒体源 在设定好媒体传输事件监听器后, 就可以连接媒体源了。 连接媒体源的本质, 就是将媒体源(此处就是受监控端)的 IP 地址和 RTP 传输所使用的端口设定为 “目标” : SessionAddress peerAddress = new SessionAddress(senderAddress, dataPort); 或 SessionAddress peerAddress = new SessionAddress(senderAddress, SessionAddress.ANY_PORT); 然后 rtpManager.addTarget(peerAddress); 即可。  建议的实现方法 为了让应用程序能够更好的工作, 应该考虑将媒体的接收功能封装到一个类 中,并通过回调机制使得当媒体传输发生变化时通知应用程序。 4.2.2 媒体持久化 媒体持久化的过程,就是将受监控端传输来的媒体保存到磁盘的过程。在上 文中,如何接收媒体信息的问题已经进行了阐述,本节要解决的问题,是如何将 音视频信息保存至磁盘。 本监控系统以 QuickTime 文件格式对媒体信息进行存储, 其中音频媒体使用 μ-law 编码,视频使用 H.263 编码。QuickTime 文件中选择音视频编码格式的原 则,是即要保证音视频媒体的品质,又应尽量降低文件大小,以提高磁盘空间利 用率。另外,编码格式应被 JMF 所支持,也是要考虑的一个重要因素。在 JMF 支持的音频媒体格式中, μ-law 编码是可以存储于 QuickTime 的,它的采样率完 全能够支持 8000Hz,编码长度一般可以选择 8bit 或 16bit,能够充分保证音频数 37
  46. 46. 北京邮电大学软件工程硕士论文 据品质,且码率极低;视频采用 H.263 编码,除了与选择音频数据编码同样的理 由外,能够在处理过程(写文件、读文件、传输媒体)中,省去很多编解码操作, 也是一项很大的优势。 媒体持久化的主要过程如下:  合并媒体流 假设从受监控端传输来的音视频媒体以 DataSource 对象的形式呈现, 分别命 名为 ads 和 vds,要将音视频保存到一个文件中并可同步播放,首先应将音频信 息和视频信息进行合并,代码如下(在合并前,有可能需要首先对收到的数据进 行解码,此处从略) : DataSource mds = Manager.createMergingDataSource(new DataSource[]{vds, ads});  音视频编码 合并后的数据源为 mds,接下来应对其进行编码操作,使其符合 QuickTime 文件所支持的编码格式。具体过程如下: //初始化 Processor Processor p = Manager.createProcessor(mds); p.configure(); //设置输出为 QuickTime 文件格式 p.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.QUICKTIME)); //遍历媒体流,进行编码 for(TrackControl tc : p.getTrackControls()) { Format f = tc.getFormat(); if(f instanceof AudioFormat) { //是音频就转为μ-law 编码 tc.setFormat(new AudioFormat(AudioFormat.ULAW, 8000, 8, 1)); tc.setEnabled(true); } else if(f instanceof VideoFormat) { //是视频就转为 H.263 编码 tc.setFormat(new VideoFormat(VideoFormat.H263, new Dimension(352, 288), VideoFormat.NOT_SPECIFIED, 38 VideoFormat.byteArray,
  47. 47. 北京邮电大学软件工程硕士论文 VideoFormat.NOT_SPECIFIED)); tc.setEnabled(true); } else { //未知媒体通道直接禁用 tc.setEnabled(false); } } p.realize(); p.start(); DataSource tds = p.getDataOutput(); 这样一来,数据源 tds,就是符合文件支持格式的音视频信息了。  保存至文件 //构造文件 File f = new File("record-日期.mov"); MediaLocator tml = new MediaLocator(f.toURI().toURL()); //构造 DataSink 并开始录制 DataSink ds = Manager.createDataSink(tds, tml); ds.open(); ds.start();  停止文件的保存 此处之所以要专门给出停止保存的具体步骤,是因为其操作顺序很重要, 如 有偏差,可能导致文件大小为 0 字节。 //首先停止 Processor 对象 p.stop(); p.close(); //此处要保证 Processor 确已关闭,在进行下列代码 ds.stop(); ds.close(); //回收资源 p.deallocate(); 39
  48. 48. 北京邮电大学软件工程硕士论文 4.2.3 媒体文件读取 上节讨论了如何将音视频媒体流保存到磁盘文件, 其目的是当需要对历史事 件进行回放的时候,可以随时进行查阅。媒体持久化的过程本质上是对媒体进行 存储,而要实现回放,就需要系统能够将已经存储的媒体文件读取出来了。 读取媒体文件非常容易, 与媒体持久化的工作几乎是完全相反的操作,只需 保证待读取媒体文件是 JMF 所支持的存储文件类型和媒体编码格式即可。由于 此处读取的媒体文件就是 4.2.2 节中进行存储的文件,其文件类型和媒体编码格 式无疑是被 JMF 所支持的。 媒体文件读取的具体操作过程如下: //构造待读取文件对象 File f = new File("record-日期.mov"); MediaLocator ml = new MediaLocator(f.toURI().toURL()); //获取媒体流 DataSource ds = Manager.createDataSource(ml); //创建并初始化 Processor 对象 Processor p = Manager.createProcessor(ds); p.configure(); p.setContentDescriptor(ContentDescriptor.RAW_RTP); //对音视频分别进行编解码 for(TrackControl tc : p.getTrackControls()) { Format f = tc.getFormat(); if(f instanceof AudioFormat) { //是音频就转为 G.723 编码 tc.setFormat(new AudioFormat(AudioFormat.G.723, 8000, 8, 1)); tc.setEnabled(true); } else if(f instanceof VideoFormat) { //是视频就转为 H.263 编码 tc.setFormat(new VideoFormat(VideoFormat.H263, new Dimension(352, 288), VideoFormat.NOT_SPECIFIED, 40 VideoFormat.byteArray,
  49. 49. 北京邮电大学软件工程硕士论文 VideoFormat.NOT_SPECIFIED)); tc.setEnabled(true); } else { //未知媒体通道直接禁用 tc.setEnabled(false); } } p.realize(); p.start(); DataSource tds = p.getDataOutput(); 此 时 , 媒 体 文 件 即 已 实 现 读 取 , 并 转 码 成 为 了 可 以 直 接 通 过 JMF SessionManager 对象向客户端发送的数据源。 4.2.4 音视频传输 流媒体服务器端音视频传输的原理与受监控端媒体传输是相同的, 即将采集 到的音频和视频帧数据逐一进行编码,然后通过 RTP/RTCP 协议进行传输。但在 具体实现上是有区别的,主要体现在以下几个方面:  音频和视频的采集来自于网络,而不是摄像头或麦克风;  编码过程无需移植 FFmpeg,直接使用 JMF 内置的编解码器即可;  无需考虑媒体帧分包发送,尤其是 H.263 帧的分包发送问题,因为 JMF 内置的 Packetizer 可以自动解决此问题;  码流的发送过程可以直接调用 JMF 内置的 SessionManager 类实现—— RTPManager 类,而无需移植第三方 RTP 库。 假设接收并经过解码的音频和视频数据源分别为 audioDs 和 videoDs,要通 过 RTP/RTCP 传输出去,需要的步骤如下(仅以音频为例,视频的操作流程与音 频操作基本相同) :  媒体编码 //创建 Processor 对象并初始化 Processor p = Manager.createProcessor(mds); p.configure(); //设置输出为 RTP 流格式 p.setContentDescriptor(ContentDescriptor.RAW_RTP); 41
  50. 50. 北京邮电大学软件工程硕士论文 //对每个媒体流进行检测并编码 TrackControl[] trackControls = processor.getTrackControls(); for(TrackControl trackControl : trackControls) { //获取当前媒体流的格式信息 Format format = trackControl.getFormat(); if(format instanceof AudioFormat) { //对音频媒体流进行编码,即设定编码器 AudioFormat target = new AudioFormat(AudioFormat.G723_RTP); trackControl.setFormat(target); trackControl.setEnabled(true); } else { //不是音频流的直接禁用 trackControl.setEnabled(false); } } //启动码流并获取数据源 p.realize(); p.start(); PushBufferDataSource outputDataSource = (PushBufferDataSource) p.getDataOutput();  媒体传输 //设定目标主机(也就是流媒体播放器客户端程序)地址信息 InetAddress dataAddress = Inet4Address.getByName(clientAddr); SessionAddress sessionAddress = new SessionAddress(dataAddress, clientPort); //初始化本机地址信息,此处之所以用这种形式,是为了防止 JMF 对本机地 址进行反向 DNS 查询而花费过长时间(由于流媒体服务器端不总是拥有域名, 支持反向域名解析的情况就更少了,进行反向域名解析,会增加程序运行时间, 最坏的情况有可能会导致流媒体播放器客户端程序请求超时,故采用此代码形 式,以禁止反向 DNS 查询) String localHostName = InetAddress.getLocalHost().getHostName(); 42
  51. 51. 北京邮电大学软件工程硕士论文 InetAddress localAddress = Inet4Address.getByName(localHostName); SessionAddress sourceAddress = new SessionAddress(localAddress, SessionAddress.ANY_PORT); //初始化 RTPManager 类 RTPManager rtpManager = RTPManager.newInstance(); rtpManager.initialize(sourceAddress); rtpManager.addTarget(sessionAddress); //发送码流 SendStream sendStream = rtpManager.createSendStream(outputDataSource, 0); sendStream.start(); //顺便获取 SSRC,以备 RTSP 层使用 long ssrc = sendStream.getSSRC();  视频媒体编码 与音频媒体编码不同,视频媒体采用的编码格式为 H.263,且此处只支持 CIF、QCIF 和 Sub-QCIF,具体代码如下: for(TrackControl trackControl : trackControls) { //获取当前媒体流的格式信息 Format format = trackControl.getFormat(); if(format instanceof VideoFormat) { //对视频媒体流进行编码,即设定编码器 VideoFormat target = new VideoFormat(VideoFormat.H263_RTP); for(Format supported : trackControl.getSupportedFormats()) { if(! supported.matches(target)) { //禁用不兼容的媒体流 trackControl.setEnabled(false); continue; } int width = 352; int height = 288; 43
  52. 52. 北京邮电大学软件工程硕士论文 Dimension size = ((VideoFormat) format).getSize(); if(size.width < 128) { width = 128; height = 96; } else if(size.width < 176) { width = 176; height = 144; } VideoFormat Dimension(width, refFormat height), = new VideoFormat(null, VideoFormat.NOT_SPECIFIED, new null, VideoFormat.NOT_SPECIFIED); VideoFormat output = (VideoFormat) refFormat.intersects(supported); trackControl.setFormat(output); trackControl.setEnabled(true); break; } } else { //不是视频流的直接禁用 trackControl.setEnabled(false); } } 4.2.5 RTSP 服务器实现 RTSP 服务器,其本质是一个纯文本协议服务端的实现,以兼容 HTTP 协议 的语法格式,与客户端软件(通常是流媒体播放器软件)进行交互,对流媒体服 务器端的媒体编码格式、数据传输网络地址和端口等信息进行协商,并驱动流媒 体模块进行媒体数据的传输。 RTSP 协议中规定了若干种访问操作方法,包括 DESCRIBE、ANNOUNCE、 GET_PARAMETER、OPTIONS、PAUSE、PLAY、RECORD、REDIRECT、SETUP、 44
  53. 53. 北京邮电大学软件工程硕士论文 SET_PARAMETER、TEARDOWN 等。其中作为 RTSP 服务器必须要支持的方法 有:DESCRIBE、OPTIONS、PLAY、SETUP 和 TEARDOWN。  OPTIONS 用于查询服务器支持的方法,典型交互过程如下:  请求 OPTIONS rtsp://demo.streamingserver.com/mon1 RTSP/1.0 CSeq: 1 User-Agent: RealMedia Player Version 6.0.9.1235 ClientChallenge: 9e26d33f2984236010ef6253fb1887f7 CompanyID: KnKV4M4I/B2FjJ1TToLycw== GUID: 00000000-0000-0000-0000-000000000000 RegionData: 0 PlayerStarttime: [28/03/2003:22:50:23 00:00] ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586 Date: Sun, 18 Mar 2012 08:49:10 GMT <空行> 文中 rtsp://demo.streamingserver.com/mon1 是 RTSP 资源 URL, 此处用于 描述一个受监控端设备媒体信息, mon1 代表编号为 1 的受监控端设备; Cseq 的值是 1,这是 RTSP 协议规范所规定的,一个会话的起始序列号为 1,其相 应响应数据序列号与之相同;其他信息为客户端软件相关信息,供服务器端 扩展功能使用。  响应 RTSP/1.0 200 OK Server: Personal RTSP Server of Shawn/1.0 Cseq: 1 Public: DESCRIBE, SETUP, TEARDOWN, PLAY, OPTIONS <空行> 相应代码为 200,与 HTTP 协议的意义相同,表示请求已被成功处理; Public 这一行给出了本流媒体服务器所支持的方法,供客户端进行操作,上 述 5 个方法是服务器必须实现的。  DESCRIBE 用于查询服务器端媒体编码格式,服务器端通过此方法的响应值,以 SDP 协议格式为 RTSP 消息体,向客户端表明媒体格式。典型交互过程如下:  请求 45
  54. 54. 北京邮电大学软件工程硕士论文 DESCRIBE rtsp://demo.streamingserver.com/mon1 RTSP/1.0 CSeq: 2 Accept: application/sdp Date: Sun, 18 Mar 2012 08:49:10 GMT <空行> 上述请求中 Accept 参数的值为“application/sdp” ,表明此操作所期待 的相应数据体中应包含一个符合 SDP 协议规范的内容, 用以描述请求的 mon1 媒体数据的编码格式等信息。  响应 RTSP/1.0 200 OK Server: Personal RTSP Server of Shawn/1.0 Cseq: 2 Cache-Control: no-cache Content-length: <SDP 内容长度> Date: Sun, 18 Mar 2012 08:51:31 GMT Expires: Sun, 18 Mar 2012 08:51:31 GMT Content-Type: application/sdp Content-Base: rtsp://demo.streamingserver.com/mon1/ <空行> v=0 o=- 15194959636064108544 server-name-or-ip s=SessionName i=Session Description c=IN IP4 0.0.0.0 t=0 0 a=recvonly a=type:broadcast a=charset:UTF-8 a=control:* m=audio 0 RTP/AVP 4 b=AS:16 b=RR:0 a=rtpmap:4 G723/8000/1 46 15194959636064108544 IN IP4
  55. 55. 北京邮电大学软件工程硕士论文 a=control:stream=1 m=video 0 RTP/AVP 34 b=AS:256 b=RR:0 a=rtpmap:34 H263/90000 a=control:stream=2 a=cliprect:0,0,352,288 此处 Content-Type 参数的值是“application/sdp” ,意味着内容体即为一 个 SDP 协议数据包, 用以描述媒体编码参数等信息; Content-Base 参数的值, 表明了下文中 SETUP 等方法媒体流参数的参考路径;SDP 包中“m=audio 0 RTP/AVP 4”代表这是一个音频码流,其编码格式代码为 4,代表 RFC3551 中规定的 G.732 编码格式;a=rtpmap:4 G723/8000/1” “ 这一行, 同样表示 G.723 4 编码,其后是名称、采样率和声道数; “a=control:stream=1”代表当前码流编 号被定义为 1; “a=rtpmap:34 H263/90000”中的 34 是指 H.263 编码,90000 这一采样率是 RFC2190 中定义的固定值。  SETUP 客户端用来与服务器协商网络地址和端口等信息, 服务器端用来启动服务器 媒体传输相关资源,并将最终网络地址和端口等信息通知给客户端。该方法的典 型通信过程如下:  请求 SETUP rtsp://demo.streamingserver.com/mon1/stream=1 RTSP/1.0 CSeq: 3 Transport: RTP/AVP;unicast;client_port=38482-38483 Date: Sun, 18 Mar 2012 08:49:10 GMT <空行> 文中 Transport 这一行表示传输协议为 RTP,采用点对点传输模式,客 户端的 RTP 端口为 38482,RTCP 端口为 38483。  响应 RTSP/1.0 200 OK Server: Personal RTSP Server of Shawn/1.0 Cseq: 3 Cache-Control: no-cache Session: 36700495573452 Date: Sun, 18 Mar 2012 08:51:31 GMT 47
  56. 56. 北京邮电大学软件工程硕士论文 Expires: Sun, 18 Mar 2012 08:51:31 GMT Transport: RTP/AVP;unicast;source=IP_OF_SERVER;client_port=38482-38483;server_port =6970-6971 <空行> 与请求包类似,Transport 指明了传输协议为 RTP,点对点传输,客户 端端口不变,服务器端 RTP 端口为 6970,RTCP 端口为 6971。有一点需要 特别注意,当客户端发送 SETUP 请求后,流媒体服务器应在响应数据中向 客户端程序发送一个 Session 变量,其值代表了用于区别客户端会话的唯一 表示,由字母或数字组成。在以后所有的通信过程中,无论请求还是响应, 都将以这个会话标识来区别客户端与服务器端的会话关系。  PLAY 通知服务器客户端资源已准备完成,请求开始传输媒体。该方法的典型通信 过程如下:  请求 PLAY rtsp://demo.streamingserver.com/mon1 RTSP/1.0 CSeq: 5 Range: npt=0Session: 36700495573452 Date: Sun, 18 Mar 2012 08:49:10 GMT <空行> 此操作将会请求服务器开始对上文中 SETUP 请求过的所有媒体流进行 传输,也就是说,曾经利用 SETUP 方法请求多那些媒体流,PLAY 请求就会 导致这个媒体资源内相应的码流向客户端传输。 文中“Range: npt=0-”这一行表示客户端希望即刻开始传输媒体流, 且传输过程持续到客户端明确释放资源。  响应 RTSP/1.0 200 OK Server: Personal RTSP Server of Shawn/1.0 Cseq: 5 Session: 36700495573452 Range: npt=nowRTP-Info: url=rtsp://demo.streamingserver.com/mon1/stream=1,url=rtsp://demo.streamingserv 48
  57. 57. 北京邮电大学软件工程硕士论文 er.com/mon1/stream=2 <空行> 响应数据表明媒体流已成功开始发送,其中“Range: npt=now-”代表 媒体传输的开始时间点即为当前时间; RTP-Info 变量给出了在 PLAY 指令之 前通过 SETUP 方法请求的媒体流列表。  TEARDOWN 通知服务器停止媒体传输, 销毁或回收媒体传输相关的所有资源。典型通信 过程如下:  请求 TEARDOWN rtsp://demo.streamingserver.com/mon1 RTSP/1.0 CSeq: 7 Session: 36700495573452 Date: Sun, 18 Mar 2012 08:49:48 GMT <空行> 注意请求中的 Session 变量,标记了客户端与服务器端的会话关系, 据 此来查询待释放资源信息。  响应 RTSP/1.0 200 OK Server: Personal RTSP Server of Shawn/1.0 Cseq: 7 Session: 36700495573452 Connection: Close <空行> 至此,流媒体服务器就应该已经停止了媒体流的发送,并全部释放或 回收了相关资源。此处应该特别注意的是“Connection: Close”这一行,目的 是通知客户端释放与服务器之间的 RTSP 连接。之所以需要这样一个参数, 是因为在绝大多数情况下,RTSP 协议的通信过程使用的是 TCP 协议,而且 是长连接,即在整个会话过程中,网络连接是一直存在的。通过这个参数向 客户端发送连接关闭的消息,可以促使客户端程序及时关闭连接,回收网络 连接资源。 4.2.6 处理同时监控问题 在监控系瀀

×