出现一个问题,最近在用手机播放自己的server视频的时候,声音可以出来,但是视频是黑的,也不出异常,求高手帮助!
手机5800,播放本机拍摄的mp4,3gp文件
代码就是网上搜的J2me video play 代码
player = Manager.createPlayer(url);
player.play();
------------------------------------------
package videoP;
import java.io.*;
import java.util.*;
import java.io.IOException;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
public class SimpleVideoDemo extends MIDlet implements CommandListener,
ItemCommandListener {
private Display display;
private Player player;
private VideoControl vc, vc2;
private List vlist;
private Alert anAlert;
private TextField url, areaurl;
private Form form, urlform, v, areaform;
private long duration; // 影片持续时间
private static CanvasVideo canvasvideo = null;
// 命令按钮
private Command ExitCmd = new Command("退出程序", Command.EXIT, 1);
private Command NetCmd = new Command("网络视频", Command.SCREEN, 1);
private Command ABackCmd = new Command("返回", Command.BACK, 1);
private Command ASureCmd = new Command("确认", Command.SCREEN, 1);
private Command AStopCmd = new Command("暂停", Command.STOP, 1);
private Command APlayCmd = new Command("播放", Command.SCREEN, 1);
private Command AExitCmd = new Command("退出", Command.EXIT, 1);
private Command AreaCmd = new Command("本地视频", Command.SCREEN, 1);
private Command VStopCmd = new Command("暂停", Command.STOP, 1);
private Command VPlayCmd = new Command("播放", Command.SCREEN, 1);
private Command VExitCmd = new Command("退出", Command.EXIT, 1);
private Command UBackCmd = new Command("返回", Command.BACK, 1);
private Command LBackCmd = new Command("返回", Command.BACK, 1);
private Command ConnectCmd = new Command("连接服务器", Command.BACK, 1);
public SimpleVideoDemo() {
display = Display.getDisplay(this);
canvasvideo = new CanvasVideo(display);
// 主菜单界面form
form = new Form("视频播放系统");
StringItem item;
item = new StringItem("视 频 服 务 一:", " 网 络 视 频 ", Item.HYPERLINK);
item.setDefaultCommand(NetCmd);
form.append(item);
item.setItemCommandListener(this); // 为item注册监听器
item = new StringItem("视 频 服 务 二:", " 本 地 媒 体 ", Item.HYPERLINK);
item.setDefaultCommand(AreaCmd);
form.append(item);
item.setItemCommandListener(this); // 为item注册监听器
form.addCommand(ExitCmd);
// 本地视频列表的界面
Image img;
try {
img = Image.createImage("/3zhe.png");
} catch (java.io.IOException err14) {
img = null;
}
Image[] liArray = null;
try {
Image licon = Image.createImage("/3zhe.png");
liArray = new Image[] { licon, licon, licon, licon, licon, licon };
} catch (java.io.IOException err1) {
System.out.print("load failed....");
liArray = null;
}
String[] lsArray = { "最终幻想", "六月的雨", "第一次", "仙剑主题歌", "天仙子", "爆笑小猴子" };
vlist = new List("请选择影视节目", Choice.IMPLICIT, lsArray, liArray);
vlist.addCommand(LBackCmd);
// 本地视频选择确认界面
areaform = new Form("当前影视");
areaurl = new TextField("影片名:", "b", 20, TextField.ANY);
areaform.addCommand(ABackCmd);
areaform.append(areaurl);
item = new StringItem("请确认", "\n确定播放吗?", Item.BUTTON);
item.setDefaultCommand(ASureCmd);
areaform.append(item);
item.setItemCommandListener(this); // 为item注册监听器
// 网络视频网址输入界面
urlform = new Form("网络视频通道...");
url = new TextField("请输入视频地址:", "http://192.168.1.106:9527/streaming/2012.mp4", 100,
TextField.URL);
urlform.append(url);
urlform.addCommand(UBackCmd);
urlform.addCommand(ConnectCmd);
// 视频播放完毕提示
anAlert = new Alert("温馨提示!", "您点播的影视节目已播放完毕,欢迎再次点播!", img,
AlertType.INFO);
anAlert.setTimeout(2000);
// 网络视频播放界面
v = new Form("网络视频已启动...");
// 为各个界面注册监听器
form.setCommandListener(this);
vlist.setCommandListener(this);
areaform.setCommandListener(this);
urlform.setCommandListener(this);
}
public void startApp() {
canvasvideo.startApp();
}
public void pauseApp() {
canvasvideo.pauseApp();
}
/*
* 假如关闭了MIDlet程序,则会调用destroyApp()方法,因此需要在destroyApp()方法里面添加释放资源的代码
*/
protected void destroyApp(boolean unconditional) {
System.out.println("the video close!");
form = null;
try {
canvasvideo.defplayer();
} catch (MediaException err4) {
System.out.print("err4");
}
}
// Command按钮的事件处理
public void commandAction(Command c, Displayable d) {
// 如果在主菜单中按了"退出程序"
if (c == ExitCmd) {
destroyApp(false);
notifyDestroyed();
}
// 如果在网络视频网址输入界面按了"连接服务器"
if (c == ConnectCmd) {
System.out.println("try to connect to server");
canvasvideo.start();
}
// 如果在网络视频网址输入界面按了"返回"
if (c == UBackCmd) {
System.out.println("show main of the video screen");
display.setCurrent(form);
}
// 如果在本地视频列表界面按了"返回"
if (c == LBackCmd) {
System.out.println("main screen of the video play ");
display.setCurrent(form);
}
// 如果在本地视频选择确认界面按了"返回"
if (c == ABackCmd) {
System.out.println("show play list please choose one ...");
display.setCurrent(vlist);
}
// 如果选择播放本地视频
if (d.equals(vlist)) {
if (c == List.SELECT_COMMAND) {
// 根据用户选择的不同,修改areaurl文本框中的文本信息
switch (((List) d).getSelectedIndex()) {
case 0:
System.out.println("您选择了《最终幻想》,请确认...否则请返回!");
areaurl.setString("`最终幻想`");
display.setCurrent(areaform);
break;
case 1:
System.out.println("您选择了《六月的雨》,请确认...否则请返回!");
areaurl.setString("`六月的雨`");
display.setCurrent(areaform);
break;
case 2:
System.out.println("您选择了《第一次》,请确认...否则请返回!");
areaurl.setString("`第一次`");
display.setCurrent(areaform);
break;
case 3:
System.out.println("您选择了《仙剑主题歌》,请确认...否则请返回!");
areaurl.setString("`仙剑主题歌`");
display.setCurrent(areaform);
break;
case 4:
System.out.println("您选择了《天仙子》,请确认...否则请返回!");
areaurl.setString("`天仙子`");
display.setCurrent(areaform);
break;
case 5:
System.out.println("您选择了《爆笑小猴子》,请确认...否则请返回!");
areaurl.setString("`爆笑小猴子`");
display.setCurrent(areaform);
break;
}
}
}
}
// StringItem控件的事件处理
public void commandAction(Command c, Item item) {
// 如果在主菜单中如果选择播放网络视频
if (c == NetCmd) {
System.out.println("input the url of the video server....");
display.setCurrent(urlform);
}
// 如果在主菜单中如果选择播放本地视频
if (c == AreaCmd) {
System.out.println("choose your video...");
display.setCurrent(vlist);
}
// 如果在本地视频选择确认界面中按了"确定"
if (c == ASureCmd) {
System.out.println("try to open local video");
display.setCurrent(canvasvideo);
canvasvideo.start();
}
}
/*************************************************************************/
// 视频播放屏幕类(内部类)
class CanvasVideo extends Canvas implements PlayerListener,
CommandListener, Runnable {
private Display parentDisplay;
private Thread t;
private static final int VB_W = 2; // Video 边界宽度
private static final int VB_H = 15; // Video 边界高度
private boolean vis = true;
private int canvasW; // Canvas宽度
private int canvasH; // Canvas高度
private int videoW; // 视频屏幕宽度
private int videoH; // 视频屏幕高度
static final int VOLUME_LEVEL = 50; // 音量初始化为50
private int volumesetting = VOLUME_LEVEL; // 音量级别
private int mCount, mMaximum;
private int mInterval;
private int mWidth, mHeight, mX, mY, mRadius;
public CanvasVideo(Display display) {
this.parentDisplay = display;
canvasW = getWidth(); // 获取手机屏幕的宽
canvasH = getHeight(); // 获取手机屏幕的高
videoW = canvasW - 2 * VB_W; // 获取手机屏幕中可用于视频显示的区域的宽
videoH = canvasH - 2 * VB_H - 4;// 获取手机屏幕中可用于视频显示的区域的高
mCount = 0;
mMaximum = 36;
mInterval = 100; // 线程执行的间隔时间
// 计算角度
int halfWidth = (canvasW - mRadius) / 2;
int halfHeight = (canvasH - mRadius) / 2;
mRadius = Math.min(halfWidth, halfHeight);
// 通过匿名类创建了一个定时器对象
TimerTask task = new TimerTask() {
public void run() {
mCount = (mCount + 1) % mMaximum;
repaint(0, 0, canvasW, VB_H + 2);
}
};
Timer timer = new Timer();
// 在执行任务前等待0秒,然后每过mInterval毫秒再执行一次
timer.schedule(task, 0, mInterval);
}
// 在手机屏幕上绘图
public void paint(Graphics g) {
g.setColor(0, 0, 0); // 黑色
g.fillRect(0, 0, canvasW, canvasH); // 绘制与手机屏幕一样大小的矩形
g.setColor(255, 255, 255); // 白色
g.drawString("影片长度:" + time2String(duration), canvasW, VB_H,
Graphics.BOTTOM | Graphics.RIGHT);
g.drawLine(0, VB_H + 1, canvasW, VB_H + 1);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE));
g.drawString("影片载入中...请稍后!", canvasW / 2, canvasH / 2 + 10,
Graphics.TOP | Graphics.HCENTER);
g.setColor(255, 0, 0); // 红色
// 绘制弧度为90度的的饼图
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 0, 90);
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 180, 90);
g.setColor(255, 255, 255); // 白色
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 90, 90);
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 270, 90);
g.drawLine(canvasW / 2, 0, canvasW / 2, VB_H);
int theta = -(mCount * 360 / mMaximum);
// 点击播放时,如player处于STARTED状态,则先清除"状态:暂停..."字符串,
// 然后再绘制"状态:"字符串
if (player.getState() == player.STARTED) {
g.setColor(0, 0, 0);
g.fillRect(0, 0, canvasW / 2, VB_H);
g.setColor(255, 255, 255);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_MEDIUM));
g
.drawString("状态:", VB_W, VB_H, Graphics.BOTTOM
| Graphics.LEFT);
// 清除饼图与"影片载入中...请稍后!"字符串
g.setColor(0, 0, 0);
g.fillRect(0, VB_H + 10, canvasW, canvasH - VB_H + 10);
g.setColor(255, 255, 255);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE));
// 在手机屏幕的底部绘制字符串
g.drawString("视频已打开...请欣赏^_^...!", canvasW / 2, canvasH - VB_H
- 4, Graphics.TOP | Graphics.HCENTER);
// 画播放视频时的播放动画
g.setColor(0, 0, 255);
g.drawArc(canvasW / 4, 0, VB_H, VB_H, 0, 360);
g.setColor(0, 255, 0);
g.fillArc(canvasW / 4, 0, VB_H, VB_H, theta + 90, 90);
g.setColor(0x00ff0000);
g.fillArc(canvasW / 4, 0, VB_H, VB_H, theta + 270, 90);
}
// 点击暂停时,如player处于PREFETCHED状态,则先清除"状态:正在播放..."字符串,
// 然后绘制"状态:暂停..."
if (player.getState() == player.PREFETCHED) {
g.setColor(0, 0, 0);
g.fillRect(0, 0, canvasW / 2, VB_H);
g.setColor(255, 255, 255);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_MEDIUM));
g.drawString("状态:暂停...", VB_W, VB_H, Graphics.BOTTOM
| Graphics.LEFT);
}
if (player.getState() == player.STARTED) {
g.setColor(255, 0, 0);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE));
// 在可用于视频显示的区域中间绘制字符串
g.drawString("黑屏状态,按9键返回", videoW / 2, videoH / 2 + VB_H - 4,
Graphics.TOP | Graphics.HCENTER);
}
}
// 释放资源
/*
* 释放资源也需要根据当前播放器播放的状态而采取不同的方法,这是因为网络数据传输的
* 过程中也许不能够一次性地完整读取所有视频数据,也许中间有一定的中断,所以需要判
* 断不同的情况。如果Player处于正在播放状态STARTED,则表示已经完成播放了视频一部分
* 数据或者全部数据,则可以使用stop()方法停止播放,假如还有新的数据,将会从新的数据
* 开始播放。如果已经到达PREFETCHED状态,但是又不能播放,则表示数据可能是错误的或
* 者其他硬件已经占用了设备等原因造成的,因此使用deallocate()方法释放排斥资源以方便其他设备的使用。
*/
void defplayer() throws MediaException {
if (player != null) {
if (player.getState() == Player.STARTED) {
player.stop(); // 停止播放
}
if (player.getState() == Player.PREFETCHED) {
player.deallocate(); // 释放资源
}
if (player.getState() == Player.REALIZED
|| player.getState() == Player.UNREALIZED) {
player.close(); // 关闭player对象
}
}
player = null;
}
void reset() {
player = null;
}
void stopPlayer() {
try {
defplayer();
} catch (MediaException err13) {
System.err.println("err13");
}
reset();
}
// player监听事件处理方法
/*
* 因为视频播放往往对机器的资源要求很高,同时无线网络的带宽往往很小,所以应该改
* 进视频播放的程序,只有视频播放的Player对象准备就绪后,才运行开始播放视频,
* 不应该让视频播放程序占用太多的资源,因此应该增加对Player对象的各种状态的判断。
*/
/*
* 首先增加一个Player播放对象的监听器PlayerListener,并实现PlayerListener监听器
* 的处理方法playerUpdate(),在playerUpdate()方法中判断视频播放是否结束了,可以
* 使用参数event获得视频正在播放的各种状态。
*/
public void playerUpdate(Player player, String event, Object data) {
if (event == PlayerListener.END_OF_MEDIA) { // 判断是否播放结束
try {
defplayer(); // 释放资源
areaurl.setString("z");
System.out.println("over again!");
display.setCurrent(anAlert, form);
} catch (MediaException err8) {
System.out.print("err8");
}
reset();
}
}
public void start() {
t = new Thread(this);
System.out.println("start thread !");
t.start();
}
// 为了防止阻塞,使用线程
public void run() {
if (((areaurl.getString()).substring(0, 1)).equals("`")) {
System.out.println("open local video ");
// canvasvideo.areaplay(areaurl.getString());
areaplay(areaurl.getString());
} else {
System.out.println("open video on server");
netplay(url.getString());
}
}
// 本地视频播方法
void areaplay(String url) {
try {
// 在创建新对象之前先释放资源
defplayer();
InputStream ins = getClass().getResourceAsStream("/" + url);
player = Manager.createPlayer(ins, "video/mpeg");
player.addPlayerListener(this);
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.prefetch(); // 使player对象进入PREFETCH状态
// 获取视频时长,用于在视频播放时显示
try {
duration = player.getDuration();
} catch (Exception err9) {
System.err.println("err9");
reset();
}
player.start(); // 播放视频
} catch (Exception err10) {
anAlert = new Alert("视频出错!");
anAlert.setTimeout(2000);
display.setCurrent(areaform);
areaform.append("打开视频时可能出错..请重试!");
reset();
}
}
// 网络视频播放方法
void netplay(String url) {
try {
// 在创建新对象之前先释放资源
defplayer();
player = Manager.createPlayer(url);
player.addPlayerListener(this);
player.realize(); // 准备播放
vc = (VideoControl) player.getControl("VideoControl");
if (vc != null) {
Item 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.prefetch();
try {
duration = player.getDuration();
StringItem si2 = new StringItem("影片时长:",
time2String(duration) + "秒");
v.append(si2);
} catch (Exception err11) {
System.err.println("err11");
reset();
}
player.start(); // 播放视频
} catch (Throwable err11) {
urlform.append("连接超时或服务器地址不正确");
reset();
}
}
// 将long型的视频时间转换为字符串格式
private String time2String(long time) {
time = time / 1000000;
String strTime = "" + (time % 10);
time = time / 10;
strTime = (time % 6) + strTime;
time = time / 6;
strTime = (time % 10) + ":" + strTime;
time = time / 10;
strTime = (time % 6) + strTime;
time = time / 6;
return strTime;
}
/*
* 为了防止网络阻塞造成的死机假象,需要使用线程来控制程序的播放。但是线程的控制是由手机的操作系统来控制的,线程可能会有暂停的
* 可能,而线程恢复以后则会调用程序的startApp方法,因此需要在
* startApp方法中调用状态判断方法,用来判断是否继续播放还是释放资源。
*/
// 开始播放
public void startApp() {
try {
if (player != null && player.getState() == Player.PREFETCHED) {
player.start();
} else {
defplayer();
display.setCurrent(form);
}
} catch (MediaException err2) {
System.err.println("err2");
reset();
}
}
// 暂停播放
public void pauseApp() {
try {
if (player != null && player.getState() == Player.STARTED) {
player.stop();
} else {
defplayer();
}
} catch (MediaException err3) {
System.err.println("err3");
reset();
}
}
// CanvasVideo类的事件处理方法
public void commandAction(Command c, Displayable d) {
// 如果在播放本地视频时按了"暂停"按钮
if (c == AStopCmd) {
try {
pauseApp();
repaint(0, 0, canvasW / 2, VB_H); // 重画屏幕上部的状态信息
System.out.println("local pause");
this.removeCommand(AStopCmd);
this.addCommand(APlayCmd);
} catch (Exception err6) {
System.err.println("err6");
}
}
// 如果在暂停本地视频时按了"播放"按钮
if (c == APlayCmd) {
try {
player.start();
repaint(0, 0, canvasW / 2, VB_H); // 重画屏幕上部的状态信息
System.out.println("continue to play");
this.removeCommand(APlayCmd);
this.addCommand(AStopCmd);
} catch (Exception err7) {
System.err.println("err7");
}
}
// 如果在播放本地视频时按了"退出"按钮
if (c == AExitCmd) {
areaurl.setString("z");
System.out.println("local video play stop");
player.close(); // 关闭并删除player对象
System.gc();
display.setCurrent(anAlert, vlist);
}
// 如果在播放网络视频时按了"退出"按钮
if (c == VExitCmd) {
System.out.println("net work video play stop choose others");
player.close(); // 关闭并删除player对象
System.gc();
display.setCurrent(anAlert, urlform);
}
// 如果在播放网络视频时按了"暂停"按钮
if (c == VStopCmd) {
try {
pauseApp();
System.out.println("net pause");
v.removeCommand(VStopCmd);
v.addCommand(VPlayCmd);
} catch (Exception ds) {
System.err.println("ds");
}
}
// 如果在暂停网络视频时按了"播放"按钮
if (c == VPlayCmd) {
try {
player.start();
System.out.println("continue play");
v.removeCommand(VPlayCmd);
v.addCommand(VStopCmd);
} catch (Exception err5) {
System.err.println("err5");
}
}
}
// 手机键盘事件处理方法(只对使用Canvas类的本地视频有效)
public void keyPressed(int keyCode) {
int g = getGameAction(keyCode);
if (g == LEFT) {
System.out.println("音量减5");
adjustvolume(-5, false);
}
if (g == RIGHT) {
System.out.println("音量加5");
adjustvolume(5, false);
}
if (g == FIRE) {
adjustvolume(0, true);
}
switch (keyCode) {
case Canvas.KEY_NUM1:
try {
/*
* 对网络视频播放无效 if (vc != null) {
* System.out.println("正常屏幕-全屏"); setFullScreenMode(true);
* repaint(); }
*/
if (vc2 != null) {
System.out.println("正常屏幕-全屏");
setFullScreenMode(true);
repaint();
}
} catch (Exception err16) {
System.out.println("err16");
}
break;
case Canvas.KEY_NUM3:
try {
/*
* 对网络视频播放无效 if (vc != null) {
* System.out.println("全屏-正常屏幕"); setFullScreenMode(false);
* repaint(); }
*/
if (vc2 != null) {
System.out.println("全屏-正常屏幕");
setFullScreenMode(false);
repaint();
}
} catch (Exception err17) {
System.out.println("err17");
}
break;
case Canvas.KEY_NUM7:
System.out.println("黑屏状态,按9键返回");
vc2.setVisible(false);
// vc.setVisible(false);
break;
case Canvas.KEY_NUM9:
System.out.println("视频显示状态为true");
vc2.setVisible(true);
// vc.setVisible(true);
break;
case Canvas.KEY_NUM0:
System.out.println("重新播放");
try {
defplayer();
start();
} catch (Exception err18) {
System.out.println("err18");
}
}
}
// 音量控制方法
private void adjustvolume(int increment, boolean mute) {
if (player != null) {
// 获取VolumeControl对象,用于控制音量
VolumeControl volume = (VolumeControl) player
.getControl("VolumeControl");
if (volume != null) {
// 目前音量级别
volumesetting = volume.getLevel();
// 如果不是消音
if (mute != true) {
// 调整音量
volumesetting += increment;
volumesetting = volume.setLevel(volumesetting);
System.out.println(volumesetting);
} else {
volume.setMute(!volume.isMuted());
if (volume.isMuted()) {
System.out.println("静音");
} else {
System.out.println("取消静音");
}
}
}
}
}
}
}
手机5800,播放本机拍摄的mp4,3gp文件
代码就是网上搜的J2me video play 代码
player = Manager.createPlayer(url);
player.play();
------------------------------------------
package videoP;
import java.io.*;
import java.util.*;
import java.io.IOException;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
public class SimpleVideoDemo extends MIDlet implements CommandListener,
ItemCommandListener {
private Display display;
private Player player;
private VideoControl vc, vc2;
private List vlist;
private Alert anAlert;
private TextField url, areaurl;
private Form form, urlform, v, areaform;
private long duration; // 影片持续时间
private static CanvasVideo canvasvideo = null;
// 命令按钮
private Command ExitCmd = new Command("退出程序", Command.EXIT, 1);
private Command NetCmd = new Command("网络视频", Command.SCREEN, 1);
private Command ABackCmd = new Command("返回", Command.BACK, 1);
private Command ASureCmd = new Command("确认", Command.SCREEN, 1);
private Command AStopCmd = new Command("暂停", Command.STOP, 1);
private Command APlayCmd = new Command("播放", Command.SCREEN, 1);
private Command AExitCmd = new Command("退出", Command.EXIT, 1);
private Command AreaCmd = new Command("本地视频", Command.SCREEN, 1);
private Command VStopCmd = new Command("暂停", Command.STOP, 1);
private Command VPlayCmd = new Command("播放", Command.SCREEN, 1);
private Command VExitCmd = new Command("退出", Command.EXIT, 1);
private Command UBackCmd = new Command("返回", Command.BACK, 1);
private Command LBackCmd = new Command("返回", Command.BACK, 1);
private Command ConnectCmd = new Command("连接服务器", Command.BACK, 1);
public SimpleVideoDemo() {
display = Display.getDisplay(this);
canvasvideo = new CanvasVideo(display);
// 主菜单界面form
form = new Form("视频播放系统");
StringItem item;
item = new StringItem("视 频 服 务 一:", " 网 络 视 频 ", Item.HYPERLINK);
item.setDefaultCommand(NetCmd);
form.append(item);
item.setItemCommandListener(this); // 为item注册监听器
item = new StringItem("视 频 服 务 二:", " 本 地 媒 体 ", Item.HYPERLINK);
item.setDefaultCommand(AreaCmd);
form.append(item);
item.setItemCommandListener(this); // 为item注册监听器
form.addCommand(ExitCmd);
// 本地视频列表的界面
Image img;
try {
img = Image.createImage("/3zhe.png");
} catch (java.io.IOException err14) {
img = null;
}
Image[] liArray = null;
try {
Image licon = Image.createImage("/3zhe.png");
liArray = new Image[] { licon, licon, licon, licon, licon, licon };
} catch (java.io.IOException err1) {
System.out.print("load failed....");
liArray = null;
}
String[] lsArray = { "最终幻想", "六月的雨", "第一次", "仙剑主题歌", "天仙子", "爆笑小猴子" };
vlist = new List("请选择影视节目", Choice.IMPLICIT, lsArray, liArray);
vlist.addCommand(LBackCmd);
// 本地视频选择确认界面
areaform = new Form("当前影视");
areaurl = new TextField("影片名:", "b", 20, TextField.ANY);
areaform.addCommand(ABackCmd);
areaform.append(areaurl);
item = new StringItem("请确认", "\n确定播放吗?", Item.BUTTON);
item.setDefaultCommand(ASureCmd);
areaform.append(item);
item.setItemCommandListener(this); // 为item注册监听器
// 网络视频网址输入界面
urlform = new Form("网络视频通道...");
url = new TextField("请输入视频地址:", "http://192.168.1.106:9527/streaming/2012.mp4", 100,
TextField.URL);
urlform.append(url);
urlform.addCommand(UBackCmd);
urlform.addCommand(ConnectCmd);
// 视频播放完毕提示
anAlert = new Alert("温馨提示!", "您点播的影视节目已播放完毕,欢迎再次点播!", img,
AlertType.INFO);
anAlert.setTimeout(2000);
// 网络视频播放界面
v = new Form("网络视频已启动...");
// 为各个界面注册监听器
form.setCommandListener(this);
vlist.setCommandListener(this);
areaform.setCommandListener(this);
urlform.setCommandListener(this);
}
public void startApp() {
canvasvideo.startApp();
}
public void pauseApp() {
canvasvideo.pauseApp();
}
/*
* 假如关闭了MIDlet程序,则会调用destroyApp()方法,因此需要在destroyApp()方法里面添加释放资源的代码
*/
protected void destroyApp(boolean unconditional) {
System.out.println("the video close!");
form = null;
try {
canvasvideo.defplayer();
} catch (MediaException err4) {
System.out.print("err4");
}
}
// Command按钮的事件处理
public void commandAction(Command c, Displayable d) {
// 如果在主菜单中按了"退出程序"
if (c == ExitCmd) {
destroyApp(false);
notifyDestroyed();
}
// 如果在网络视频网址输入界面按了"连接服务器"
if (c == ConnectCmd) {
System.out.println("try to connect to server");
canvasvideo.start();
}
// 如果在网络视频网址输入界面按了"返回"
if (c == UBackCmd) {
System.out.println("show main of the video screen");
display.setCurrent(form);
}
// 如果在本地视频列表界面按了"返回"
if (c == LBackCmd) {
System.out.println("main screen of the video play ");
display.setCurrent(form);
}
// 如果在本地视频选择确认界面按了"返回"
if (c == ABackCmd) {
System.out.println("show play list please choose one ...");
display.setCurrent(vlist);
}
// 如果选择播放本地视频
if (d.equals(vlist)) {
if (c == List.SELECT_COMMAND) {
// 根据用户选择的不同,修改areaurl文本框中的文本信息
switch (((List) d).getSelectedIndex()) {
case 0:
System.out.println("您选择了《最终幻想》,请确认...否则请返回!");
areaurl.setString("`最终幻想`");
display.setCurrent(areaform);
break;
case 1:
System.out.println("您选择了《六月的雨》,请确认...否则请返回!");
areaurl.setString("`六月的雨`");
display.setCurrent(areaform);
break;
case 2:
System.out.println("您选择了《第一次》,请确认...否则请返回!");
areaurl.setString("`第一次`");
display.setCurrent(areaform);
break;
case 3:
System.out.println("您选择了《仙剑主题歌》,请确认...否则请返回!");
areaurl.setString("`仙剑主题歌`");
display.setCurrent(areaform);
break;
case 4:
System.out.println("您选择了《天仙子》,请确认...否则请返回!");
areaurl.setString("`天仙子`");
display.setCurrent(areaform);
break;
case 5:
System.out.println("您选择了《爆笑小猴子》,请确认...否则请返回!");
areaurl.setString("`爆笑小猴子`");
display.setCurrent(areaform);
break;
}
}
}
}
// StringItem控件的事件处理
public void commandAction(Command c, Item item) {
// 如果在主菜单中如果选择播放网络视频
if (c == NetCmd) {
System.out.println("input the url of the video server....");
display.setCurrent(urlform);
}
// 如果在主菜单中如果选择播放本地视频
if (c == AreaCmd) {
System.out.println("choose your video...");
display.setCurrent(vlist);
}
// 如果在本地视频选择确认界面中按了"确定"
if (c == ASureCmd) {
System.out.println("try to open local video");
display.setCurrent(canvasvideo);
canvasvideo.start();
}
}
/*************************************************************************/
// 视频播放屏幕类(内部类)
class CanvasVideo extends Canvas implements PlayerListener,
CommandListener, Runnable {
private Display parentDisplay;
private Thread t;
private static final int VB_W = 2; // Video 边界宽度
private static final int VB_H = 15; // Video 边界高度
private boolean vis = true;
private int canvasW; // Canvas宽度
private int canvasH; // Canvas高度
private int videoW; // 视频屏幕宽度
private int videoH; // 视频屏幕高度
static final int VOLUME_LEVEL = 50; // 音量初始化为50
private int volumesetting = VOLUME_LEVEL; // 音量级别
private int mCount, mMaximum;
private int mInterval;
private int mWidth, mHeight, mX, mY, mRadius;
public CanvasVideo(Display display) {
this.parentDisplay = display;
canvasW = getWidth(); // 获取手机屏幕的宽
canvasH = getHeight(); // 获取手机屏幕的高
videoW = canvasW - 2 * VB_W; // 获取手机屏幕中可用于视频显示的区域的宽
videoH = canvasH - 2 * VB_H - 4;// 获取手机屏幕中可用于视频显示的区域的高
mCount = 0;
mMaximum = 36;
mInterval = 100; // 线程执行的间隔时间
// 计算角度
int halfWidth = (canvasW - mRadius) / 2;
int halfHeight = (canvasH - mRadius) / 2;
mRadius = Math.min(halfWidth, halfHeight);
// 通过匿名类创建了一个定时器对象
TimerTask task = new TimerTask() {
public void run() {
mCount = (mCount + 1) % mMaximum;
repaint(0, 0, canvasW, VB_H + 2);
}
};
Timer timer = new Timer();
// 在执行任务前等待0秒,然后每过mInterval毫秒再执行一次
timer.schedule(task, 0, mInterval);
}
// 在手机屏幕上绘图
public void paint(Graphics g) {
g.setColor(0, 0, 0); // 黑色
g.fillRect(0, 0, canvasW, canvasH); // 绘制与手机屏幕一样大小的矩形
g.setColor(255, 255, 255); // 白色
g.drawString("影片长度:" + time2String(duration), canvasW, VB_H,
Graphics.BOTTOM | Graphics.RIGHT);
g.drawLine(0, VB_H + 1, canvasW, VB_H + 1);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE));
g.drawString("影片载入中...请稍后!", canvasW / 2, canvasH / 2 + 10,
Graphics.TOP | Graphics.HCENTER);
g.setColor(255, 0, 0); // 红色
// 绘制弧度为90度的的饼图
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 0, 90);
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 180, 90);
g.setColor(255, 255, 255); // 白色
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 90, 90);
g.fillArc(canvasW / 2 - canvasW / 4 + 10, VB_H + 10,
canvasW / 4 * 2 - 20, canvasW / 4 * 2 - 20, 270, 90);
g.drawLine(canvasW / 2, 0, canvasW / 2, VB_H);
int theta = -(mCount * 360 / mMaximum);
// 点击播放时,如player处于STARTED状态,则先清除"状态:暂停..."字符串,
// 然后再绘制"状态:"字符串
if (player.getState() == player.STARTED) {
g.setColor(0, 0, 0);
g.fillRect(0, 0, canvasW / 2, VB_H);
g.setColor(255, 255, 255);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_MEDIUM));
g
.drawString("状态:", VB_W, VB_H, Graphics.BOTTOM
| Graphics.LEFT);
// 清除饼图与"影片载入中...请稍后!"字符串
g.setColor(0, 0, 0);
g.fillRect(0, VB_H + 10, canvasW, canvasH - VB_H + 10);
g.setColor(255, 255, 255);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE));
// 在手机屏幕的底部绘制字符串
g.drawString("视频已打开...请欣赏^_^...!", canvasW / 2, canvasH - VB_H
- 4, Graphics.TOP | Graphics.HCENTER);
// 画播放视频时的播放动画
g.setColor(0, 0, 255);
g.drawArc(canvasW / 4, 0, VB_H, VB_H, 0, 360);
g.setColor(0, 255, 0);
g.fillArc(canvasW / 4, 0, VB_H, VB_H, theta + 90, 90);
g.setColor(0x00ff0000);
g.fillArc(canvasW / 4, 0, VB_H, VB_H, theta + 270, 90);
}
// 点击暂停时,如player处于PREFETCHED状态,则先清除"状态:正在播放..."字符串,
// 然后绘制"状态:暂停..."
if (player.getState() == player.PREFETCHED) {
g.setColor(0, 0, 0);
g.fillRect(0, 0, canvasW / 2, VB_H);
g.setColor(255, 255, 255);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_MEDIUM));
g.drawString("状态:暂停...", VB_W, VB_H, Graphics.BOTTOM
| Graphics.LEFT);
}
if (player.getState() == player.STARTED) {
g.setColor(255, 0, 0);
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE));
// 在可用于视频显示的区域中间绘制字符串
g.drawString("黑屏状态,按9键返回", videoW / 2, videoH / 2 + VB_H - 4,
Graphics.TOP | Graphics.HCENTER);
}
}
// 释放资源
/*
* 释放资源也需要根据当前播放器播放的状态而采取不同的方法,这是因为网络数据传输的
* 过程中也许不能够一次性地完整读取所有视频数据,也许中间有一定的中断,所以需要判
* 断不同的情况。如果Player处于正在播放状态STARTED,则表示已经完成播放了视频一部分
* 数据或者全部数据,则可以使用stop()方法停止播放,假如还有新的数据,将会从新的数据
* 开始播放。如果已经到达PREFETCHED状态,但是又不能播放,则表示数据可能是错误的或
* 者其他硬件已经占用了设备等原因造成的,因此使用deallocate()方法释放排斥资源以方便其他设备的使用。
*/
void defplayer() throws MediaException {
if (player != null) {
if (player.getState() == Player.STARTED) {
player.stop(); // 停止播放
}
if (player.getState() == Player.PREFETCHED) {
player.deallocate(); // 释放资源
}
if (player.getState() == Player.REALIZED
|| player.getState() == Player.UNREALIZED) {
player.close(); // 关闭player对象
}
}
player = null;
}
void reset() {
player = null;
}
void stopPlayer() {
try {
defplayer();
} catch (MediaException err13) {
System.err.println("err13");
}
reset();
}
// player监听事件处理方法
/*
* 因为视频播放往往对机器的资源要求很高,同时无线网络的带宽往往很小,所以应该改
* 进视频播放的程序,只有视频播放的Player对象准备就绪后,才运行开始播放视频,
* 不应该让视频播放程序占用太多的资源,因此应该增加对Player对象的各种状态的判断。
*/
/*
* 首先增加一个Player播放对象的监听器PlayerListener,并实现PlayerListener监听器
* 的处理方法playerUpdate(),在playerUpdate()方法中判断视频播放是否结束了,可以
* 使用参数event获得视频正在播放的各种状态。
*/
public void playerUpdate(Player player, String event, Object data) {
if (event == PlayerListener.END_OF_MEDIA) { // 判断是否播放结束
try {
defplayer(); // 释放资源
areaurl.setString("z");
System.out.println("over again!");
display.setCurrent(anAlert, form);
} catch (MediaException err8) {
System.out.print("err8");
}
reset();
}
}
public void start() {
t = new Thread(this);
System.out.println("start thread !");
t.start();
}
// 为了防止阻塞,使用线程
public void run() {
if (((areaurl.getString()).substring(0, 1)).equals("`")) {
System.out.println("open local video ");
// canvasvideo.areaplay(areaurl.getString());
areaplay(areaurl.getString());
} else {
System.out.println("open video on server");
netplay(url.getString());
}
}
// 本地视频播方法
void areaplay(String url) {
try {
// 在创建新对象之前先释放资源
defplayer();
InputStream ins = getClass().getResourceAsStream("/" + url);
player = Manager.createPlayer(ins, "video/mpeg");
player.addPlayerListener(this);
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.prefetch(); // 使player对象进入PREFETCH状态
// 获取视频时长,用于在视频播放时显示
try {
duration = player.getDuration();
} catch (Exception err9) {
System.err.println("err9");
reset();
}
player.start(); // 播放视频
} catch (Exception err10) {
anAlert = new Alert("视频出错!");
anAlert.setTimeout(2000);
display.setCurrent(areaform);
areaform.append("打开视频时可能出错..请重试!");
reset();
}
}
// 网络视频播放方法
void netplay(String url) {
try {
// 在创建新对象之前先释放资源
defplayer();
player = Manager.createPlayer(url);
player.addPlayerListener(this);
player.realize(); // 准备播放
vc = (VideoControl) player.getControl("VideoControl");
if (vc != null) {
Item 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.prefetch();
try {
duration = player.getDuration();
StringItem si2 = new StringItem("影片时长:",
time2String(duration) + "秒");
v.append(si2);
} catch (Exception err11) {
System.err.println("err11");
reset();
}
player.start(); // 播放视频
} catch (Throwable err11) {
urlform.append("连接超时或服务器地址不正确");
reset();
}
}
// 将long型的视频时间转换为字符串格式
private String time2String(long time) {
time = time / 1000000;
String strTime = "" + (time % 10);
time = time / 10;
strTime = (time % 6) + strTime;
time = time / 6;
strTime = (time % 10) + ":" + strTime;
time = time / 10;
strTime = (time % 6) + strTime;
time = time / 6;
return strTime;
}
/*
* 为了防止网络阻塞造成的死机假象,需要使用线程来控制程序的播放。但是线程的控制是由手机的操作系统来控制的,线程可能会有暂停的
* 可能,而线程恢复以后则会调用程序的startApp方法,因此需要在
* startApp方法中调用状态判断方法,用来判断是否继续播放还是释放资源。
*/
// 开始播放
public void startApp() {
try {
if (player != null && player.getState() == Player.PREFETCHED) {
player.start();
} else {
defplayer();
display.setCurrent(form);
}
} catch (MediaException err2) {
System.err.println("err2");
reset();
}
}
// 暂停播放
public void pauseApp() {
try {
if (player != null && player.getState() == Player.STARTED) {
player.stop();
} else {
defplayer();
}
} catch (MediaException err3) {
System.err.println("err3");
reset();
}
}
// CanvasVideo类的事件处理方法
public void commandAction(Command c, Displayable d) {
// 如果在播放本地视频时按了"暂停"按钮
if (c == AStopCmd) {
try {
pauseApp();
repaint(0, 0, canvasW / 2, VB_H); // 重画屏幕上部的状态信息
System.out.println("local pause");
this.removeCommand(AStopCmd);
this.addCommand(APlayCmd);
} catch (Exception err6) {
System.err.println("err6");
}
}
// 如果在暂停本地视频时按了"播放"按钮
if (c == APlayCmd) {
try {
player.start();
repaint(0, 0, canvasW / 2, VB_H); // 重画屏幕上部的状态信息
System.out.println("continue to play");
this.removeCommand(APlayCmd);
this.addCommand(AStopCmd);
} catch (Exception err7) {
System.err.println("err7");
}
}
// 如果在播放本地视频时按了"退出"按钮
if (c == AExitCmd) {
areaurl.setString("z");
System.out.println("local video play stop");
player.close(); // 关闭并删除player对象
System.gc();
display.setCurrent(anAlert, vlist);
}
// 如果在播放网络视频时按了"退出"按钮
if (c == VExitCmd) {
System.out.println("net work video play stop choose others");
player.close(); // 关闭并删除player对象
System.gc();
display.setCurrent(anAlert, urlform);
}
// 如果在播放网络视频时按了"暂停"按钮
if (c == VStopCmd) {
try {
pauseApp();
System.out.println("net pause");
v.removeCommand(VStopCmd);
v.addCommand(VPlayCmd);
} catch (Exception ds) {
System.err.println("ds");
}
}
// 如果在暂停网络视频时按了"播放"按钮
if (c == VPlayCmd) {
try {
player.start();
System.out.println("continue play");
v.removeCommand(VPlayCmd);
v.addCommand(VStopCmd);
} catch (Exception err5) {
System.err.println("err5");
}
}
}
// 手机键盘事件处理方法(只对使用Canvas类的本地视频有效)
public void keyPressed(int keyCode) {
int g = getGameAction(keyCode);
if (g == LEFT) {
System.out.println("音量减5");
adjustvolume(-5, false);
}
if (g == RIGHT) {
System.out.println("音量加5");
adjustvolume(5, false);
}
if (g == FIRE) {
adjustvolume(0, true);
}
switch (keyCode) {
case Canvas.KEY_NUM1:
try {
/*
* 对网络视频播放无效 if (vc != null) {
* System.out.println("正常屏幕-全屏"); setFullScreenMode(true);
* repaint(); }
*/
if (vc2 != null) {
System.out.println("正常屏幕-全屏");
setFullScreenMode(true);
repaint();
}
} catch (Exception err16) {
System.out.println("err16");
}
break;
case Canvas.KEY_NUM3:
try {
/*
* 对网络视频播放无效 if (vc != null) {
* System.out.println("全屏-正常屏幕"); setFullScreenMode(false);
* repaint(); }
*/
if (vc2 != null) {
System.out.println("全屏-正常屏幕");
setFullScreenMode(false);
repaint();
}
} catch (Exception err17) {
System.out.println("err17");
}
break;
case Canvas.KEY_NUM7:
System.out.println("黑屏状态,按9键返回");
vc2.setVisible(false);
// vc.setVisible(false);
break;
case Canvas.KEY_NUM9:
System.out.println("视频显示状态为true");
vc2.setVisible(true);
// vc.setVisible(true);
break;
case Canvas.KEY_NUM0:
System.out.println("重新播放");
try {
defplayer();
start();
} catch (Exception err18) {
System.out.println("err18");
}
}
}
// 音量控制方法
private void adjustvolume(int increment, boolean mute) {
if (player != null) {
// 获取VolumeControl对象,用于控制音量
VolumeControl volume = (VolumeControl) player
.getControl("VolumeControl");
if (volume != null) {
// 目前音量级别
volumesetting = volume.getLevel();
// 如果不是消音
if (mute != true) {
// 调整音量
volumesetting += increment;
volumesetting = volume.setLevel(volumesetting);
System.out.println(volumesetting);
} else {
volume.setMute(!volume.isMuted());
if (volume.isMuted()) {
System.out.println("静音");
} else {
System.out.println("取消静音");
}
}
}
}
}
}
}