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