www.pudn.com > MobileVideoIP.zip > VideoPlayer.java
package example.mmademo;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.Spacer;
import javax.microedition.lcdui.StringItem;
import javax.microedition.media.Control;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.media.control.GUIControl;
import javax.microedition.media.control.RateControl;
import javax.microedition.media.control.RecordControl;
import javax.microedition.media.control.VideoControl;
import javax.microedition.media.control.VolumeControl;
/**
* Play Video/Capture in a Form using MMAPI
*
*/
public class VideoPlayer extends Form
implements Runnable, CommandListener, PlayerListener {
private static final String TITLE_TEXT = "MobileVideoIP Player (Form) ";
private static Player player = null;
private static boolean isCapturePlayer;
private static Image logo = null;
private Display parentDisplay;
private long duration;
private final Command backCommand = new Command("Back", Command.BACK, 1);
private final Command playCommand = new Command("Play", Command.ITEM, 1);
private final Command snapCommand = new Command("Snapshot", Command.ITEM, 1);
private final Command pauseCommand = new Command("Pause", Command.ITEM, 10);
private Item videoItem;
private StringItem status;
private StringItem audioStatus;
private StringItem time;
// private RateControl rc;
private int currentVolume;
private boolean muted;
private int currentRate = 100000;
private VideoControl vidc;
// pause/resume support
private boolean suspended = false;
private boolean restartOnResume = false;
private long restartMediaTime;
public VideoPlayer(Display parentDisplay) {
super(TITLE_TEXT);
this.parentDisplay = parentDisplay;
initialize();
}
void initialize() {
addCommand(backCommand);
addCommand(snapCommand);
setCommandListener(this);
try {
if (logo == null)
logo = Image.createImage("/icons/logo.png");
} catch (Exception ex) {
logo = null;
}
if ( logo == null)
System.out.println("can not load logo.png");
}
/*
* Respond to commands, including back
*/
public void commandAction(Command c, Displayable s) {
//try {
if (s == this) {
if (c == backCommand) {
close();
parentDisplay.setCurrent(VideoTest.getList());
}
else if (videoItem != null && c == snapCommand) {
doSnapshot();
}
else if (videoItem == null && c == pauseCommand) {
removeCommand(pauseCommand);
addCommand(playCommand);
pause();
}
else if (videoItem == null && c == playCommand) {
startPlaying();
removeCommand(playCommand);
addCommand(pauseCommand);
}
}
//} catch (Exception e) {
// System.out.println("DEBUG: GOT EXCEPTION in VideoPlayer.commandAction("+c.toString()+","+s.toString()+")!");
// e.printStackTrace();
//}
}
/**
* Loops to see if volume and rate have been changed.
*/
public void run() {
P.rint("VideoPlayer:run()");
//try {
while (player != null) {
P.rint("VideoPlayer:run():while loop");
// sleep 200 millis. If suspended,
// sleep until MIDlet is restarted
do {
try {
Thread.sleep(200);
} catch (InterruptedException ie) {
}
} while (player != null && suspended);
synchronized (this) {
if (player == null)
return;
long k = player.getMediaTime();
time.setText("Pos: " + (k / 1000000) + "." + ((k / 10000) % 100));
}
}//while
//} catch (Exception e) {
// System.out.println("DEBUG: GOT EXCEPTION in VideoPlayer.run()!");
// e.printStackTrace();
//}
}//run /* */
/**
* Called by MIDlet after instantiating this object.
* Creates the player. XXX
*/
public void open(String url) { //capture://video theCamera
P.rint("VideoPlayer:open()");
try {
synchronized (this) {
if ( player == null ) {
player = Manager.createPlayer(url); //creating player for the url
player.addPlayerListener(this);
isCapturePlayer = url.startsWith("capture:");
}
}
player.realize(); //realise
//set to use_gui_primitive
if ( (vidc = (VideoControl) player.getControl("VideoControl")) != null ) {
videoItem = (Item)vidc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, null);
//vidc.setDisplaySize(240, 140);
} else if (logo != null) {
append(new ImageItem("", logo, ImageItem.LAYOUT_CENTER,""));
}
Control [] controls = player.getControls();
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof GUIControl && controls[i] != vidc) {
append((Item) controls[i]);
}
}
status = new StringItem("Status: ","");
status.setLayout(Item.LAYOUT_NEWLINE_AFTER);
append(status);
time = new StringItem("","");
time.setLayout(Item.LAYOUT_NEWLINE_AFTER);
append(time);
player.prefetch();
if (videoItem == null)
addCommand(pauseCommand);
else {
Spacer spacer = new Spacer(3, 10);
spacer.setLayout(Item.LAYOUT_NEWLINE_BEFORE);
append(spacer);
append(videoItem); ///append the videoItem, if don't append snapShot will get blank screen
}
//Thread t = new Thread(this);
//t.start(); //loops to set display of volume and rate
} catch (Exception ex) {
error(ex);
ex.printStackTrace();
close();
}
}//open /**/
/**
* Start
*/
//XXX
public void startPlaying() {
P.rint("VideoPlayer:startPlaying()");
if (player == null)
return;
try {
duration = player.getDuration();
//P.rint("VideoPlayer:start(): duration is "+duration);
player.start(); //without this will get black square
} catch (Exception ex) {
System.err.println(ex);
error(ex);
close();
}
}//startPlaying
// general purpose error method, displays on screen as well to output
public void error(Exception e) {
Alert alert = new Alert("Error");
alert.setString(e.getMessage());
parentDisplay.setCurrent(alert);
e.printStackTrace();
}
public void error(String s) {
Alert alert = new Alert("Error");
alert.setString(s);
alert.setTimeout(2000);
parentDisplay.setCurrent(alert, this);
}
public void close() {
synchronized (this) {
pause(); //stop()
if (player != null) {
player.close();
player = null;
}
}
VideoTest.getInstance().nullPlayer();
}
public void pause() {
if ( player != null) {
try {
player.stop();
} catch (MediaException me) {
System.err.println(me);
}
}
}
/**
* Sets the text to show playing-state and rate.
*/
private synchronized void updateStatus() {
if (player == null)
return;
status.setText(
((player.getState() == Player.STARTED) ? "Playing, ": "Paused, ") +
"Rate: " + (currentRate/1000) + "%\n");
}
public void playerUpdate(Player plyr, String evt, Object evtData) {
//try {
if ( evt == END_OF_MEDIA ) { //loop around playing forever
try {
player.setMediaTime(0);
//player.start();
} catch (MediaException me) {
System.err.println(me);
}
} else if (evt == STARTED || evt == STOPPED) {
updateStatus();
}
//} catch (Exception e) {
// System.out.println("DEBUG: GOT EXCEPTION in VideoPlayer.playerUpdate("+evt.toString()+")!");
// e.printStackTrace();
//}
}
/**
* Initiates the snapshot.
*/
private void doSnapshot() {
P.rint("VideoPlayer:doSnapshot()");
new SnapshotThread().start();
}
/**
* Inner class Snapshot which is a thread.
* Performs image processing and then appends to this form.
*/
//XXX
class SnapshotThread extends Thread {
public void run() {
try {
//byte [] snap = vidc.getSnapshot("encoding=jpeg"); //use this for sun WTK emulator
byte [] snap = vidc.getSnapshot("encoding=jpeg&width=100&height=100"); //use this for N93 real device
if (snap != null) {
Image im = Image.createImage(snap, 0, snap.length);
//XXX start imageProcessing
int imgCols = im.getWidth();
int imgRows = im.getHeight();
int[] oneDPix = new int[imgCols * imgRows];
im.getRGB(oneDPix, 0, imgCols, 0, 0, imgCols, imgRows);
int[][][] threeDPix = convertToThreeDim( oneDPix, imgCols, imgRows);
threeDPix = drawDiagonal(threeDPix, imgRows, imgCols);
threeDPix = drawHorizontal(threeDPix, imgRows, imgCols);
threeDPix = drawVertical(threeDPix, imgRows, imgCols);
int[] snap2 = convertToOneDim(threeDPix, imgCols, imgRows);
im = Image.createRGBImage(snap2, imgCols, imgRows, false);
//XXX end imageProcessing
//XXX
ImageItem imi = new ImageItem("", im, 0, "");
append(imi);
/*
if(targetColor>620){
P.rint( Long.toString(targetColor) );//+" diff: "+ (System.currentTimeMillis()-timeR) );
timeR = System.currentTimeMillis();
} /* */
}
} catch (MediaException me) {
//System.err.println(me);
error(me);
} catch (Exception e) {
//System.out.println("DEBUG: GOT EXCEPTION in VideoPlayer.SnapshotThread.run()!");
//e.printStackTrace();
error(e);
}
}
}//end class Snapshot which is a thread
long timeR = 0;
public synchronized void stopVideoPlayer() {
// stop & deallocate
player.deallocate();
}
/**
* Deallocate the player and the display thread.
* Some VM's may stop players and threads
* on their own, but for consistent user
* experience, it's a good idea to explicitly
* stop and start resources such as player
* and threads.
*/
public synchronized void pauseApp() {
suspended = true;
if (player != null && player.getState() >= Player.STARTED) {
// player was playing, so stop it and release resources.
if (!isCapturePlayer) {
restartMediaTime = player.getMediaTime();
}
player.deallocate();
// make sure to restart upon resume
restartOnResume = true;
} else {
restartOnResume = false;
}
}
/**
* If the player was playing when the MIDlet was paused,
* then the player will be restarted here.
*/
public synchronized void startApp() {
suspended = false;
if (player != null && restartOnResume) {
try {
player.prefetch();
if (!isCapturePlayer) {
try {
player.setMediaTime(restartMediaTime);
} catch (MediaException me) {
System.err.println(me);
}
}
player.start();
} catch (MediaException me) {
System.err.println(me);
}
}
restartOnResume = false;
}
//------------ start image processing code -------------------
/**
* Convert the int array of image to a 3D array.
*/
public static int[][][] convertToThreeDim(int[] oneDPix, int imgCols, int imgRows) {
//Create the new 3D array to be populated
// with color data.
int[][][] data = new int[imgRows][imgCols][4];
for (int row = 0; row < imgRows; row++) {
//Extract a row of pixel data into a
// temporary array of ints
int[] aRow = new int[imgCols];
for (int col = 0; col < imgCols; col++) {
int element = row * imgCols + col;
aRow[col] = oneDPix[element];
}//end for loop on col
//Move the data into the 3D array. Note
// the use of bitwise AND and bitwise right
// shift operations to mask all but the
// correct set of eight bits.
for (int col = 0; col < imgCols; col++) {
//Alpha data
data[row][col][0] = (aRow[col] >> 24) & 0xFF;
//Red data
data[row][col][1] = (aRow[col] >> 16) & 0xFF;
//Green data
data[row][col][2] = (aRow[col] >> 8) & 0xFF;
//Blue data
data[row][col][3] = (aRow[col]) & 0xFF;
}//end for loop on col
}//end for loop on row
return data;
}//end convertToThreeDim
//The purpose of this method is to convert the
// data in the 3D array of ints back into the
// 1d array of type int. This is the reverse
// of the method named convertToThreeDim.
public static int[] convertToOneDim(int[][][] data, int imgCols, int imgRows) {
//Create the 1D array of type int to be
// populated with pixel data, one int value
// per pixel, with four color and alpha bytes
// per int value.
int[] oneDPix = new int[imgCols * imgRows * 4];
//Move the data into the 1D array. Note the
// use of the bitwise OR operator and the
// bitwise left-shift operators to put the
// four 8-bit bytes into each int.
for (int row = 0, cnt = 0; row < imgRows; row++) {
for (int col = 0; col < imgCols; col++) {
oneDPix[cnt] = ((data[row][col][0] << 24) & 0xFF000000)
| ((data[row][col][1] << 16) & 0x00FF0000)
| ((data[row][col][2] << 8) & 0x0000FF00)
| ((data[row][col][3]) & 0x000000FF);
cnt++;
}//end for loop on col
}//end for loop on row
return oneDPix;
}//end convertToOneDim
/**
* Draw diagonal white line.
*/
public static int[][][] drawDiagonal(int[][][] threeDPix, int imgRows, int imgCols) {
//Display some interesting information
System.out.println("Program test");
System.out.println("Width = " + imgCols);
System.out.println("Height = " + imgRows);
//Get slope value from the TextField
int slope = 1;
//Draw a white diagonal line on the image
for (int col = 0; col < imgCols; col++) {
int row = (int) (slope * col);
if (row > imgRows - 1)
break;
//Set values for alpha, red, green, and
// blue colors.
threeDPix[row][col][0] = (byte) 0xff;
threeDPix[row][col][1] = (byte) 0xff;
threeDPix[row][col][2] = (byte) 0xff;
threeDPix[row][col][3] = (byte) 0xff;
}//end for loop
//Return the modified array of image data.
return threeDPix;
}//draw diagonal
/**
* Draw horizontal white line.
*/
public static int[][][] drawHorizontal(int[][][] threeDPix, int imgRows, int imgCols) {
for (int col = 0; col < imgCols; col++) {
int horiLevel = imgRows/2; //make sure not beyond image boundaries
threeDPix[horiLevel][col][0] = (byte) 0xff;
threeDPix[horiLevel][col][1] = (byte) 0xff;
threeDPix[horiLevel][col][2] = (byte) 0xff;
threeDPix[horiLevel][col][3] = (byte) 0xff;
}//end for loop
return threeDPix;
}//draw horizontal
/**
* Draw vertical white line.
*/
public static int[][][] drawVertical(int[][][] threeDPix, int imgRows, int imgCols) {
for (int row = 0; row < imgRows; row++) {
int vertiLevel = imgCols/2; //make sure not beyond image boundaries
threeDPix[row][vertiLevel][0] = (byte) 0xff;
threeDPix[row][vertiLevel][1] = (byte) 0xff;
threeDPix[row][vertiLevel][2] = (byte) 0xff;
threeDPix[row][vertiLevel][3] = (byte) 0xff;
}//end for loop
return threeDPix;
}//draw vertical
}//class