The VideoCanvas
class:
Draws the video or camera viewfinder on a Canvas
Draws the ControlBar
on top of the Canvas
Controls video playback with the overlay buttons
The following code initializes the video player:
public void initPlayer() { initializingVideo = true; // Always start player in normal mode fsMode = false; this.setFullScreenMode(fsMode); try { if (this.type == VideoOverlayMIDlet.CAMERA) { player = Manager.createPlayer("capture://video"); } else { InputStream is = this.getClass().getResourceAsStream( this.VIDEO_LOCATOR); player = Manager.createPlayer(is, this.VIDEO_LOCATOR.substring( this.VIDEO_LOCATOR.lastIndexOf('.') + 1)); } player.realize(); player.prefetch(); videoControl = (VideoControl) player.getControl("VideoControl"); if (videoControl != null) { videoControl.initDisplayMode( VideoControl.USE_DIRECT_VIDEO, this); videoControl.setDisplayFullScreen(true); if (this.type == VideoOverlayMIDlet.CAMERA) { addCommand(captureCommand); } else { player.setLoopCount(-1); } this.controlBar.setX(videoControl.getDisplayX()); this.controlBar.setY(videoControl.getDisplayY()); videoControl.setVisible(true); player.start(); // Empty paint is called to ensure // that videoControl area is clear emptyPaint = true; repaint(); serviceRepaints(); emptyPaint = false; }
The code above can raise a number of exceptions:
} catch (IOException ioe) { discardPlayer(); System.out.println(ioe.getMessage()); Display.getDisplay(this.midlet).setCurrent( new Alert("IOException:", ioe.getMessage(), null, AlertType.ERROR)); } catch (MediaException me) { discardPlayer(); System.out.println(me.getMessage()); Display.getDisplay(this.midlet).setCurrent( new Alert("MediaException:", me.getMessage(), null, AlertType.ERROR)); } catch (SecurityException se) { discardPlayer(); System.out.println(se.getMessage()); Display.getDisplay(this.midlet).setCurrent( new Alert("SecurityException", se.getMessage(), null, AlertType.ERROR)); } catch (Exception e) { discardPlayer(); System.out.println(e.getMessage()); Display.getDisplay(this.midlet).setCurrent( new Alert("Exception", e.getMessage(), null, AlertType.ERROR)); } finally { initializingVideo = false; } }
The paint
method is called when the video player
needs to be drawn on the screen.
The following code first checks if it should draw "nothing" in
order to clear the screen. Then, if the player is being initialized,
it draws a string on the screen. If the player is done, it calls the paintOverlay
method.
public void paint(Graphics g) { if (emptyPaint == true) { // Do not draw anything // Ensure that videoControl area is clear return; } int state = Player.UNREALIZED; if (player != null) { state = player.getState(); } if (initializingVideo) { paintInitString(g); } else { switch (state) { case Player.PREFETCHED: paintOverlay(g); break; case Player.STARTED: paintOverlay(g); break; case Player.CLOSED: paintString("Closing...", g); break; case Player.UNREALIZED: break; case Player.REALIZED: break; default: g.setColor(BACKGROUND_COLOR); g.fillRect(0, 0, getWidth(), getHeight()); paintString("Closing...", g); break; } } prevRepaint = System.currentTimeMillis(); }
The paintOverlay
method paints the controls on
top of the player canvas:
private void paintOverlay(Graphics g) { // Check if canvas changes (e.g., in screen rotation) if (canvasW != getWidth() || canvasH != getHeight()) { canvasW = getWidth(); canvasH = getHeight(); // Setting new location this.controlBar.setX(videoControl.getDisplayX()); this.controlBar.setY(videoControl.getDisplayY()); } video_x = videoControl.getDisplayX(); video_y = videoControl.getDisplayY(); videoW = videoControl.getDisplayWidth(); videoH = videoControl.getDisplayHeight(); // Clear areas outside the videoControl g.setColor(BACKGROUND_COLOR); g.fillRect(0, 0, canvasW, video_y); g.fillRect(0, video_y + videoH, canvasW, canvasH); g.fillRect(0, 0, video_x, videoH); g.fillRect(video_x + videoW, 0, canvasW, canvasH); // Stop painting if clearing flag is up if (hideControlBar) { return; } // Setting ControlBar boundaries // Height is fixed size controlBar.setWidth(videoW / 2); // Control Bar this.drawButtons(g); // In fullscreen mode, drawing exit button if (fsMode) { // Portrait if (canvasH > canvasW) { exitX = videoW - (videoW / 3); exitY = canvasH - (back_icon.getHeight() + 20); } // Landscape else { exitX = videoW; exitY = videoH - (back_icon.getHeight() + 20); } g.drawImage(back_icon, (exitX + canvasW) / 2, exitY, Graphics.TOP | Graphics.HCENTER); } }
The MIDlet takes pictures using the takeSnapshot
method:
private void takeSnapshot() { if (player != null) { try { byte pngImage[] = videoControl.getSnapshot( "encoding=png&width=" + videoControl.getDisplayWidth() + "&height=" + videoControl.getDisplayHeight()); player.stop(); midlet.cameraCanvasCaptured(pngImage); } catch (MediaException me) { System.out.println(me.getMessage()); Display.getDisplay(this.midlet).setCurrent( new Alert("MediaException:", me.getMessage(), null, AlertType.ERROR)); } catch (Exception e) { System.out.println(e.getMessage()); Display.getDisplay(this.midlet).setCurrent( new Alert("Exception:", e.getMessage(), null, AlertType.ERROR)); } } }
The above code calls the getSnapshot
method of the VideoControl
class and saves the result in a byte array. It then calls the main
MIDlet's cameraCanvasCaptured
method, which changes
the view to the image view.
Since it is possible to move the video controls, the class listens
for the pointerPressed
and pointerDragged
events. When these events
occur, the class changes the position of the video controls.