手机视频播放详解

池瑞楠

摘 要 本文提出了一个手机视频播放系统,在对系统功能模块进行分析的基础上,详细讨论了系统的设计和实现方法,并给出了系统的实现结果,对手机多媒体开发具有很好的学习借鉴和应用价值。

关键词:J2ME,视频播放系统,MMAPI

一、引言

J2ME是Sun公司为小型的消费电子设备(如手机、PDA、电视机顶盒等)而推出的一项Java技术,由于其良好的可移植性、资源占用少和较高的安全性等特点,在移动设备开发领域特别是手机应用软件开发方面得到了广泛的应用。

另一方面,随着人们生活水平的提高,彩屏手机已经在手机市场上确立了主流地位;同时,手机用户在娱乐方面要求也越来越高。视频品质越来越高的移动设备已经
成为一种消费时尚,各大移动服务提供商也开始向手机用户提供视频服务功能,因此基于J2ME技术的手机视频开发也就不可避免地成为当前手机开发中的热点。
本文将详细讨论如何在支持J2ME的手机上开发一个视频播放系统。

二、系统的功能

本文所提出的手机视频播放系统,要求能够实现在支持J2ME技术的手机上播放本地视频文件和网络视频文件,并实现一些基本的视频播放的控制功能,例如暂
停、重播、全屏、黑屏、音量大小调节、静音等。运行本系统后,用户通过菜单选择是播放本地视频还是网络视频,如果用户选择播放本地视频,则系统会给出本地
可以播放的视频列表供用户选择,用户选择并确认后,开始播放本地视频文件;如果用户选择播放网络视频,则用户需要输入网络视频文件的地址,成功连接网络视
频服务器后,则可以开始播放网络视频文件。

根据系统的功能,将其划分成以下几个功能模块:

界面设计模块:主要考虑人性化,当用户第一次使用时,可以很清楚地明白如何操作。

本地视频播放模块:通过列表选项,供用户选择所要播放的视频,并通过一个Canvas类来实现视频的播放。

网络视频播放模块:通过输入网络地址,来访问网络中的视频资源,将视频文件的显示作为一个Item控件添加到Form类屏幕上进行播放。

视频控制模块:提供一些基本的视频播放控制功能,例如暂停、重播、全屏、黑屏、音量大小调节、静音等。这些功能可以通过编写一个视频播放的屏幕类来实现。

事件处理模块:对用户的各种按钮、按键动作进行响应。这部分是通过编写相应的事件处理方法来实现的。

三、系统的设计与实现

1.手机视频开发的基本方法

要在手机上进行多媒体文件的播放,需要用到J2ME提供的MMAPI(Moblile Media API),它为各种不同格式的多媒体文件提供了一套规范的播放和录制音频/视频文件的统一接口。

使用MMAPI进行多媒体播放的基本流程是:首先从数据源上读取多媒体数据内容(这些数据内容的格式可能各不相同),然后将这些多媒体数据内容传输给
DataSource类进行处理,DataSource类读取并将它们转换为统一的格式,最后由Player类负责播放这些数据。这对于手机音频开发和手
机视频开发都是适用的。

具体来说,其基本的开发过程可以分成下面的几个步骤来进行:

首先,MMAPI使用了Manager类来创建一个Player对象,然后由Player对象读取视频数据,视频数据既可以是本地视频文件的数据,也可以是网络视频文件的数据。

如果读取的是本地视频文件的数据,方法如下:

InputStream ins = getClass().getResourceAsStream("/test1.mpg"); // 创建本地视频数据的输入流

Player player = Manager.createPlayer(ins, "video/mpeg"); // 创建读取本地视频数据的Player对象

如果读取的是网络视频文件中的数据,则在createPlayer()方法中直接指定网络视频文件的URL即可:

Player player = Manager.createPlayer("http://127.0.0.1/test2.mpg"); // 创建读取网络视频数据的Player对象

创建了Player对象之后,通过Player对象的getControl()方法创建一个VideoControl对象来对需要播放的数据进行控制。VideoControl是一个用来播放视频的控件接口,视频的播放必须通过这个接口才能正常播放。

VideoControl vc;

vc = (VideoControl) player.getControl("VideoControl");

创建了VideoControl对象之后,就必须把VideoControl对象播放的视频图像显示到手机屏幕上。将VideoControl对象播放的
视频图像显示到手机屏幕上的方法有两种,一种是通过一个Canvas类来实现,一种是作为一个Item控件添加到Form类手机屏幕上。本文将在本地视频
的播放中采用第一种方法,在网络视频的播放中采用第二种方法来实现。

2.基本视频播放的实现

(1)本地视频的播放

本地视频的播放是通过一个Canvas类来实现的。在程序中,通过继承一个Canvas类,并使用VideoControl类的
initDisplayMode()方法指定第一个参数的值为VideoControl.USE_DIRECT_VIDEO,指定第二个参数为具体的
Canvas对象(在本程序中即为this)。另外,可以通过VideoControl对象的setDisplayLocation()方法设置视频屏幕
在手机屏幕上的坐标位置,通过setDisplaySize()设置视频屏幕的大小。

在本系统的程序中设计了一个本地视频播放方法areaplay(),将该方法放在自定义的视频屏幕类CanvasVideo类中,实现的核心代码如下:

// 本地视频播方法
void areaplay(String url) {
   try {
      InputStream ins = getClass().getResourceAsStream("/" + url);
      player = Manager.createPlayer(ins, "video/mpeg");
      player.realize(); // 准备播放
      vc2 = (VideoControl) player.getControl("VideoControl");
      if (vc2 != null) {
         vc2.initDisplayMode(VideoControl.USE_DIRECT_VIDEO, this);
         // 获取视频的原始大小
         int frameW = vc2.getSourceWidth();
         int frameH = vc2.getSourceHeight();
         // 计算视频屏幕在手机屏幕上的坐标
         if (frameW > videoW) {
            frameW = videoW;
         }
         if (frameH > videoH) {
            frameH = videoH;
         }
         int frameX = (videoW - frameW) / 2 + VB_W;
         int frameY = (videoH - frameH) / 2 + VB_H;
         // 设置视频屏幕坐标,使视频在手机屏幕的中间显示
         vc2.setDisplayLocation(frameX, frameY);
         // 设置视频屏幕大小
         vc2.setDisplaySize(frameW, frameH);
         vc2.setVisible(true);
         this.addCommand(AStopCmd);
         this.addCommand(AExitCmd);
         this.setCommandListener(this);
      }
      player.start(); // 播放视频
   }
   catch (Exception err10) {
      display.setCurrent(areaform);
      areaform.append("打开视频时可能出错..请重试!");
      reset();
   }
}

程序中,设置播放的本地视频屏幕在手机屏幕的中间,大小为视频的原始大小。如果视频的原始大小变大了,以致在手机屏幕上显示不了,则让视频按手机屏幕的大小显示。

网络视频的播放采用了将视频播放作为一个Item控件添加到Form类手机屏幕上的方法来实现。程序中,需要使用VideoControl类的
initDisplayMode()方法指定第一个参数的值为VideoControl.USE_GUI_PRIMITIVE,指定第二个参数为
null。

同样,在本系统的程序中设计了一个网络视频播放方法netplay(),将该方法也是放在自定义的视频屏幕类CanvasVideo类中,具体的代码如下:

// 网络视频播放方法
void netplay(String url) {
   try {
      player = Manager.createPlayer(url);
      player.realize(); // 准备播放
      vc = (VideoControl) player.getControl("VideoControl");
      if (vc != null) {
         Item video;
         video = (Item) vc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null);
         v.deleteAll();
         v.append(video);
         v.addCommand(VStopCmd);
         v.addCommand(VExitCmd);
         v.setCommandListener(this);
         display.setCurrent(v);
      }
      player.start(); // 播放视频
   }
   catch (Throwable err11) {
      urlform.append("连接超时或服务器地址不正确");
      reset();
   }
}

利用上述方法进行的本地/网络视频播放能完成从头到尾播放视频中的每个画面,播放完成后自动停止播放,不能重新播放。

3.视频播放的改进

手机视频播放往往对手机资源要求很高,同时由于无线网络的带宽往往很小,所以应该改进前面给出视频播放的程序,只有视频播放的Player对象准备就绪
后,才开始播放视频,不应该让视频播放程序占用太多的资源。为此,本文将对上面提出的基本视频播放程序进行改进,增加了对Player对象的各种状态的判
断。