原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。
http://zhangjunhd.blog.51cto.com/113473/25467
本文主要介绍JMF整体框架概念。
author: ZJ 06-11-14
JMF(Java Media Framework)是Sun 公司提出的Java 媒体架构。它是对应Java 2平台标准版(J2SE)的一种可选用的应用编程接口(API)。JMF的源代码通过SCSL(Sun 社团源代码许可模式)发布这一强大的媒体工具包,可以在任何版本(1.1.x及以上版本)的Java平台上的运行。
JMF2.1.1技术提供了先进的媒体处理能力,从而扩展了Java 平台的功能。JMF所提供的多媒体功能如下:
l可以在Java Applet 和应用程序中播放各种媒体文件。它提供了对各种主要媒体形式和编码的支持,如JPEG、H.263、MP3、Macromedias Flash。JMF 2.1.1 还支持多种媒体类型如Quicktime、MOV、Microsoft AVI和MPEG-1。
l在互联网上传输音频和视频数据流。
l可以利用摄像机一类的设备截取音频和视频并保存为多媒体文件。
l处理多媒体文件转换文件格式。
l在互联网上广播音频和视频数据。
1. JMF基本构架
JMF的两层架构:
(1) 相对上层的负责多媒体文件的控制,使用和处理,并支持网络资源和识别采集设备等额外控制功能;
(2) 相对下层不仅提供编解码器,渲染器,还提供plug-in架构来直接存取多媒体文件使JMF能更轻易的被延伸和定制;
JMF的架构图:
![](https://i-blog.csdnimg.cn/blog_migrate/8829693630d3c1575fdc31635a3436e5.jpeg)
图1 JMF架构图
2.JMF的运作模式
图2根据VCR的运作模式来对比JMF运作过程,我们可以发现JMF与真实世界中的VCR运作模式相似。整个过程如同是VCR提供了一个熟悉的构造模型来录影(音)、处理、以及呈现基于时间的媒体(time-based media)。当你使用VCR播放一个电影时,你是以录影带的方式提供VCR一个媒体流(media stream)。VCR将之读入并分析、解译录影带上的资料,并把适当的讯号送到用户的电视和音响。JMF也是使用这个同样的模型架构。一个数据源(data source)会将媒体流(media stream)封装起来,就有如录影带一般。而一个播放器(player)会提供处理以及控制,类似VCR所提供的控制机制。使用JMF播放、和捕捉影音则需要适当的输入输出装置如麦克风、照相机、音响、以及屏幕等等。
图2 VCR运作模式
3. JMF上层结构
3.1时间模型(time model)
JMF 对媒体时间信息的获取如下
lTimeBase Time:系统当前时钟。
lMediaTime:一个媒体流的整个播放时间。
lMediaStartTime:媒体开始播放的时间。
lTimeBaseStartTime:当开始播放的时候TimeBase的时间。
lRate:时钟和TimeBase的关系,可以是1倍2倍或负值(重放playback的时候)。
这样我们得到的播放位置的公式为:
MediaTime = MediaStartTime + Rate (TimeBaseTime - TimeBaseStartTime)
3.2管理器(managers)
JMF API主要由一些接口组成,这些接口定义了用于捕获(capture)、处理(process)和播放(present)基于时间的媒体的对象的行为和相互作用的过程。为了能和已经存在的类实现无缝连接,JMF引入了一些中介对象—管理器(Manager)。JMF中使用了四种Manager:
lManager:管理器(Manager)负责处理播放器(Player)、处理器(Processor)、数据源(DataSource)、数据池(DataSink)的创建。
lPackageManager:保存用户创建的播放器(Player),处理器(Processor),数据源(DataSource),数据池(DataSink)类的注册信息。
lCaptureDeviceManager:对可用的媒体捕获设备进行注册。
lPlugInManager:保持底层的JMF插件(如复用器(Multiplexers),分离器(DemultiPlexers),编解码器(Codecs),渲染器(Effects)和显示器(Render)的注册信息。
3.3事件模型(event model)
JMF是利用一个结构化的事件报告机制来使基于JMF的程序获知媒体系统当前的状态,并使它能对媒体驱动的错误状态,比如未知源错误状态(Resource Unavailable)进行响应。在任何时候,当一个JMF 对象需要报告当前的状态, 它将发出一个MediaEvent事件。
对于任何一个能发送MediaEvent的JMF对象而言,JMF都定义了一个相应的侦听接口(listener interface)。为了能在某一MediaEvent事件发生时得到相应的通知,必须实现适当的侦听接口以及在对应的类体中注册该接口中处理MediaEvent事件的方法体,并通过调用addListener方法来接收此MediaEvent事件。
JMF中的Controller objects,例如播放器(Player)和处理器(Processor),以及Control objects 例如GainControl 都可以发出MediaEvent 事件。
JMF的事件模型如图3 所示:
图3 JMF 架构的事件模型
3.4数据模型(data model)
JMF的媒体播放器利用数据源(DataSources)对象来进行媒体内容的传输。数据源(DataSource)对象封装了该媒体的位置信息和能够播放该媒体的软件和相关协议信息。一旦封装后,该数据源就不能用于传递其它媒体数据。
DataSource通常用两种方式来定义,媒体定位器(MediaLocator) 或URL(Universal Resource Locator)。媒体定位器(MediaLocator)类似于URL而且可以创建自一个URL,即使在没有安装相应的协议处理机制的情况下,也能构造MediaLocator。(在Java中, 构建一个URL必须在系统中有相应的协议处理机制。)
数据源(DataSource)可以管理一组源数据流(SourceStream)对象。标准的数据源(DataSource)是以一定数量字节作为一个传输单位的。而缓冲数据源(Buffer Data Source)用一个缓冲(Buffer)对象作为传输单位。JMF 定义了几种数据源(DataSource)对象如图4 所示:
图4 JMF 架构的数据模型
3.4.1Push and Pull数据源
媒体数据可以从不同的数据源得到的。比如本地的或网络上的文件或实时的广播。JMF根据数据传输的发起点的不同,对这些数据源进行了分类:
(1) Pull Data-Source:客户端发起数据传输并进行控制。适用于这种数据传输方式的协议有HTTP和FILE。JMF定义了两类Pull Data-Source,PullDataSource和PullBufferDataSource。后者是用一个缓冲(Buffer)对象进行数据传输的。
(2) Push Data-Source:服务器端发起数据传输并进行控制。此种数据源包括媒体广播,组播和VOD。相应的协议有RTP协议和SGI公司为其VOD系统开发的MediaBase协议。JMF 定义了两类Push Data-Source,PushDataSource和PushBufferDataSource。
JMF定义了两类特殊的数据源,克隆数据源(cloneable data sources)和合并数据源(merging data sources)。
一个克隆数据源可以克隆一个pull或push数据源。你可以调用管理器(manager)的createCloneableDataSource方法并传递相应的数据源对象来克隆一个数据源。一旦一个数据源被传递到createCloneableDataSource方法,你就只能对这个克隆数据源以及它的克隆体进行处理,原始数据源对象不能被直接使用。
克隆数据源(cloneable data sources)实现SourceCloneable接口,其中定义了一个方法叫createClone。通过调用该方法,你可以为你的原始数据源复制出任意数量的克隆体,并由创建它们的克隆数据源(cloneable data sources)对其进行管理。
一个合并数据源(merging data sources)可以将来自于多个数据源的源数据流合并为一个数据源。这样可以对一系列得数据源进行统一管理。
你可以调用管理器(manager)的createMergingDataSource方法并传递相应的数据源来创建一个合并数据源。需要注意的是,待合并的数据源必须是同一种类型的。例如你不能将一个PullDataSource和一个PushDataSource合并。该合并源的持续时间为其中最长的数据源的持续时间。它的内容类型(ContentType)为application/mixed-media。
一个克隆数据源可以克隆一个pull或push数据源。你可以调用管理器(manager)的createCloneableDataSource方法并传递相应的数据源对象来克隆一个数据源。一旦一个数据源被传递到createCloneableDataSource方法,你就只能对这个克隆数据源以及它的克隆体进行处理,原始数据源对象不能被直接使用。
克隆数据源(cloneable data sources)实现SourceCloneable接口,其中定义了一个方法叫createClone。通过调用该方法,你可以为你的原始数据源复制出任意数量的克隆体,并由创建它们的克隆数据源(cloneable data sources)对其进行管理。
一个合并数据源(merging data sources)可以将来自于多个数据源的源数据流合并为一个数据源。这样可以对一系列得数据源进行统一管理。
你可以调用管理器(manager)的createMergingDataSource方法并传递相应的数据源来创建一个合并数据源。需要注意的是,待合并的数据源必须是同一种类型的。例如你不能将一个PullDataSource和一个PushDataSource合并。该合并源的持续时间为其中最长的数据源的持续时间。它的内容类型(ContentType)为application/mixed-media。
3.4.3数据格式(data formats)
在JMF架构中,Format对象中保存了媒体的格式(format)信息。它并不包括编码参数和全局时间信息。只是描述了该格式的编码名称和数据类别。图5 表示JMF对音频格式和视频格式的定义:
![](https://i-blog.csdnimg.cn/blog_migrate/c1a5201abe6b9bdc458302c4ee1796ff.jpeg)
图5 JMF 架构的数据格式
在AudioFormat中,描述了音频格式的属性,如采样频率、每次采样的数据位数和信道数等等。在VideoFormat中则描述了视频数据的类型如H.263 等。
3.6控制器(controls)
JMF架构中,控制器(Control)提供了对对象的属性进行设置和查询的机制。控制器(Control)为相应的用户提供了对对象进行操纵的接口。这些对象包括Controller(播放器player或处理器processor)对象,DataSource对象,DataSink对象和其他JMF 插件。
3.6.1标准控制器(standard controls)
JMF 提供的标准控制器如图6所示:
图6 JMF 架构的标准控制
(1)CachingControl:监视和显示下载进度。
(2)GainControl:对媒体播放属性(如音量)进行控制,它还提供了对媒体播放属性变化的监控。图7所示:
图7 GainControl 模型
(3)Multiplexer和DataSink:对数据流进行读写。
(4)FramePositionControl和FrameGrabbingControl:为处理器和播放器提供了基于帧的处理能力。例如在播放时能提供基于帧的定位、对视频流进行静态帧的读写等。
(5)TrackControl:是FormatControl中的一种。提供了对媒体数据中单独信道的处理功能。
(6)PortControl和MonitorControl:提供了对媒体捕获设备的控制功能。
(7)BufferControl:提供了对用户端Buffer的控制功能。
3.6.2编解码控制器(codec controls)
JMF 同样提供了几种对硬件和软件编解码器进行控制的编解码器:
(1)BitRateControl:控制编码率和输出媒体的编码率。
(2)FrameRateControl:提供帧率的修改。
(3)H261Control:提供了对H.261 协议的视频编码中的静态图像传输模式的控制。
(4)H263Control:提供了对H.263 协议中编码参数如非限制矢量算术编码等的控制。
(5)KeyFrameControl:提供了关键帧之间间隔的规范。
(6)MpegAudioControl:提供了基于MPEG 的音频的编码能力信息和规范。
(7)QualityControl:提供了在编解码过程中播放质量与CPU占用率的最佳的平衡规范。
(8)SilenceSuppressionControl:提供了基于音频编解码的静音压缩规范。
3.7用户接口组件(user interface components)
控制器(control)可以提供接入到用户控制组件,以使得用户可以得到对媒体的控制。你可以调用getControlCompont方法来得到默认的用户控制组件。该方法返回一个AWT组件,你可以将该组件加到你的小应用程序或应用程序的显示容器组件中。
Controller(播放器player或处理器processor)同样可以提供接入到用户控制组件。例如,一个播放器(player)可以同时提供一个可视组件和一个控制面板组件。你可以通过调用播放器的getVisualComponent和getControlPanelComponent方法来得到这些组件。
4. 播放(presentation)
在JMF中,播放过程由Controller接口完成。Controller接口定义了基本的状态和控制机制,使得实现它的对象可以对基于时间的媒体(time-based media)进行控制,播放或捕获。Controller接口定义了一个媒体controller经历的不同状态,并提供了一种机制控制这些状态的转换。
Controller注册了许多特定的MediaEvents,来获知它的状态的变化。你必须实现ControllerListener接口,来获得来自于Controller(如播放器Player)的MediaEvents。
JMF API定义了两种Controllers:播放器(Players)和控制器(Processors)。播放器和管理器是用来处理一个特定的数据源,通常建立后不再处理其它媒体数据。
图8为JMF Controllers
![](https://i-blog.csdnimg.cn/blog_migrate/97cda4cebf74a4a6ce34aaeea47cc775.jpeg)
4.1播放器(Players)
播放器(Player)对一个媒体数据输入流进行处理,并实现时间上的精确播放。数据源(DataSource)将输入流传递到播放器。播放器将声音或(和)视频传递到相应的目标地(destination)。
图9为JMF播放器模型
播放器(Player)对一个媒体数据输入流进行处理,并实现时间上的精确播放。数据源(DataSource)将输入流传递到播放器。播放器将声音或(和)视频传递到相应的目标地(destination)。
图9为JMF播放器模型
![](https://i-blog.csdnimg.cn/blog_migrate/d8b44eb7095098da17500e117bb6fa04.jpeg)
播放器在处理和显示媒体数据过程中不提供任何控制。通过继承Clock和Controller类,播放器可支持标准的用户控制功能以及部分限制操作。
图10为JMF 播放器
图10为JMF 播放器
![](https://i-blog.csdnimg.cn/blog_migrate/3e186dfad80ed9187921a376dc98876a.jpeg)
4.1.1播放器状态(Player States)
播放器对象有多种状态,JMF中定义了6 种状态。在正常情况下播放器对象需要经历每个状态,然后才能播放媒体数据。下面是对这些状态的说明:
(1)Unrealized:在这种状态下播放器对象已经被实例化,但是并不知道它需要播放的媒体的任何信息。
(2)Realizing:当调用realize方法时,播放器对象的状态从Unrealized转变为Realizing。 在这种状态下Player对象正在确定它需要占用资源。在此过程中,播放器取得的资源都是那些只需取得一次的资源,不是那些独占的资源。
(3)Realized:在这种状态下播放器对象已经确定了它需要的资源并且也知道要播放的媒体的类型(type)。
(4)Prefetching:当调用prefectch方法时,播放器对象的状态从Realized变为Prefetching 在该状态下的播放器对象正在为播放媒体做一些准备工作。其中包括加载媒体数据而需要获得的独占资源等。这个过程被称为预取Prefetch。
(5)Refetched:当播放器对象完成了预取操作后就到达了该状态。
(6)Started:当调用start方法后播放器对象就进入了该状态并开始播放媒体。
图11为播放器的状态转换图
播放器对象有多种状态,JMF中定义了6 种状态。在正常情况下播放器对象需要经历每个状态,然后才能播放媒体数据。下面是对这些状态的说明:
(1)Unrealized:在这种状态下播放器对象已经被实例化,但是并不知道它需要播放的媒体的任何信息。
(2)Realizing:当调用realize方法时,播放器对象的状态从Unrealized转变为Realizing。 在这种状态下Player对象正在确定它需要占用资源。在此过程中,播放器取得的资源都是那些只需取得一次的资源,不是那些独占的资源。
(3)Realized:在这种状态下播放器对象已经确定了它需要的资源并且也知道要播放的媒体的类型(type)。
(4)Prefetching:当调用prefectch方法时,播放器对象的状态从Realized变为Prefetching 在该状态下的播放器对象正在为播放媒体做一些准备工作。其中包括加载媒体数据而需要获得的独占资源等。这个过程被称为预取Prefetch。
(5)Refetched:当播放器对象完成了预取操作后就到达了该状态。
(6)Started:当调用start方法后播放器对象就进入了该状态并开始播放媒体。
图11为播放器的状态转换图
![](https://i-blog.csdnimg.cn/blog_migrate/345a2fbd4960a0f60ebf1ab29e38b3d5.jpeg)
当一个播放器从一个状态转换到另一个状态时,它将给出TransitionEvents。通过ControllerListener接口,你的程序可以确定播放器在什么状态并作出相应的反应。
使用这种时间报告机制,你可以通过控制一个播放器对象的Realizing和Prefetching的开始点来管理它的缓冲时间(start latency)。同时,你也可以在调用播放器的方法前确定播放器是否在其适当的状态。
使用这种时间报告机制,你可以通过控制一个播放器对象的Realizing和Prefetching的开始点来管理它的缓冲时间(start latency)。同时,你也可以在调用播放器的方法前确定播放器是否在其适当的状态。
4.1.2每个状态下播放器对象可执行的方法
为了避免混乱情况,在一个播放器所有状态下,不是所有的方法都能被调用的。下表定义了JMF规定的限制。如果你在一个播放器对象的当前状态下,调用了一个非法的方法,播放器对象将抛出异常或错误。
为了避免混乱情况,在一个播放器所有状态下,不是所有的方法都能被调用的。下表定义了JMF规定的限制。如果你在一个播放器对象的当前状态下,调用了一个非法的方法,播放器对象将抛出异常或错误。
4.2处理器(Processors)
处理器(Processors)同样可以用来播放媒体数据。处理器是一种特殊的播放器,它可以对输入媒体流进行过程控制。处理器支持所有播放器拥有的播放控制功能。
除了将媒体数据传送至播放终端外,处理器可以将媒体数据输出至一个数据源(DataSource),此数据源可以作为其它的播放器或处理器的数据源,或是通过其它的处理器对其进行进一步操作控制,或将其传输到一个文件进行存储。
图12为处理器模型
处理器(Processors)同样可以用来播放媒体数据。处理器是一种特殊的播放器,它可以对输入媒体流进行过程控制。处理器支持所有播放器拥有的播放控制功能。
除了将媒体数据传送至播放终端外,处理器可以将媒体数据输出至一个数据源(DataSource),此数据源可以作为其它的播放器或处理器的数据源,或是通过其它的处理器对其进行进一步操作控制,或将其传输到一个文件进行存储。
图12为处理器模型
![](https://i-blog.csdnimg.cn/blog_migrate/7c60616186f8a667aa2d02d636bee766.jpeg)
处理器对应的接口是Processor。在JMF API中Processor接口继承了Player接口。
图13 为JMF处理器
图13 为JMF处理器
![](https://i-blog.csdnimg.cn/blog_migrate/aafeb7d07ed352995d654d33bd6e74a6.jpeg)
如图12 所示,处理器对象除了支持播放器对象支持的所有功能外,还可以对输入的媒体数据流进行处理,并通过数据源向其他的播放器对象或处理器对象输出数据。
4.2.1处理器状态(Processor States)
如图13所示,除了在播放器中提到了的6种状态以外,处理器对象还包括两种新的状态。这两种状态是在Unrealized状态之后,在Realizing 状态之前。
(1)Configuring:当调用configure方法后,处理器对象进入该状态。在该状态下处理器对象连接到数据源并获取输入数据的格式信息。
(2)Configured:当完成数据源连接,获得输入数据格式的信息后,处理器对象就处于Configured状态。
图14为处理器的状态转换图
如图13所示,除了在播放器中提到了的6种状态以外,处理器对象还包括两种新的状态。这两种状态是在Unrealized状态之后,在Realizing 状态之前。
(1)Configuring:当调用configure方法后,处理器对象进入该状态。在该状态下处理器对象连接到数据源并获取输入数据的格式信息。
(2)Configured:当完成数据源连接,获得输入数据格式的信息后,处理器对象就处于Configured状态。
图14为处理器的状态转换图
![](https://i-blog.csdnimg.cn/blog_migrate/d6551b84495db645c0e4ba6132ec660e.jpeg)
4.2.2每个状态下控制器对象可执行的方法
4.3 Controller 事件
Controller(播放器或控制器)注册的ControllerEvents被分为三类:改变通知(change notifications),关闭事件(closed events),状态转变事件(transtion events):
(1)改变通知事件如RateChangeEvent,DurationUpdateEvent,FormatChangeEvent表明一些Controller的属性的改变。
(2)状态转变事件可以使你的程序对Controller对象的状态转变作出反应。
(3)当Controller关闭时,它将注册关闭事件。
图15 为JMF Controller事件
Controller(播放器或控制器)注册的ControllerEvents被分为三类:改变通知(change notifications),关闭事件(closed events),状态转变事件(transtion events):
(1)改变通知事件如RateChangeEvent,DurationUpdateEvent,FormatChangeEvent表明一些Controller的属性的改变。
(2)状态转变事件可以使你的程序对Controller对象的状态转变作出反应。
(3)当Controller关闭时,它将注册关闭事件。
图15 为JMF Controller事件
![](https://i-blog.csdnimg.cn/blog_migrate/7972cb2002760be91b9d472ecf18217d.jpeg)
5.媒体处理者结构(MediaHandler Construction)
播放器(Players),处理器(Processors),数据池(DataSinks)都是媒体处理者的一种,它们都从数据源(DataSource)中读取数据。每个媒体处理者都是为专为一个数据源创建的。
图16为JMF的媒体处理者结构
播放器(Players),处理器(Processors),数据池(DataSinks)都是媒体处理者的一种,它们都从数据源(DataSource)中读取数据。每个媒体处理者都是为专为一个数据源创建的。
图16为JMF的媒体处理者结构
![](https://i-blog.csdnimg.cn/blog_migrate/64077a7b915db45dd68de9bdb1ca55dd.jpeg)
6.参考资料
JMF2.0 API Guide
JMF2.0 API Guide