Java/2D Graphics GUI/JMF
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 A motion detection algoritm for use with the Java Media Framework API (JMF).
- 2 javax.media
- 3 Media player
- 4 Query the installed version of the JMF
- 5 Renderer for RGB images using AWT Image using Java Media API
- 6 Sample program to demonstrate FramePositioningControl.
- 7 Select a media file from tjelocal file system and gain statistics
A motion detection algoritm for use with the Java Media Framework API (JMF).
/**
* A motion detection algoritm for use with the Java Media Framework API (JMF).
* The main idea of the algorithm is to compare the pixelcolours of two successive frames in an incoming videostream.
* To prevent noise to be mistaken for motion each frame is divided into many small squares for which only the mean colour is used for compairson.
* @version 2002-09-26
* @author Mattias Hedlund, mathed-8.
* @author Fredrik Jonsson, frejon-9.
* @author David Åberg, davabe-9 all students at Luleå University of Technology.
*/
import javax.media.*;
import javax.media.format.*;
import java.awt.*;
import java.io.IOException;
public class MotionDetectionEffect implements Effect {
/**
* The initial square side.
*/
private final static int INITIAL_SQUARE_SIZE = 5;
public final static Format[] supportedFormat = new Format[] { //
new RGBFormat(null, //
Format.NOT_SPECIFIED, //
Format.byteArray, //
Format.NOT_SPECIFIED, //
24, //
3, 2, 1, //
3, Format.NOT_SPECIFIED, //
Format.TRUE, //
Format.NOT_SPECIFIED) //
};
private Format inputFormat;
private Format outputFormat;
private Format[] inputFormats;
private Format[] outputFormats;
private int[] bwPixels;
private byte[] bwData;
/**
* Visual mode is set.
*/
private boolean visualize = true;
/**
* Server mode is set.
*/
private boolean serverActive = true;
/**
* Update requested is set.
*/
private boolean updateRequested;
private int avg_ref_intensity;
private int avg_img_intensity;
/**
* The RGBFormat of the inbuffer.
*/
private RGBFormat vfIn = null;
/**
* Four different thresholds. Set initial values here.
*/
private int[] threshs = { 20, 30, 40, 50 };
private int det_thresh = threshs[1];
/**
* The corresponding colours to the four different thresholds.
*/
private int[] colors = { 0x00FF0000, 0x00FF9900, 0x00FFFF00, 0x00FFFFFF };
/**
* The mean values of all squares in an image.
*/
private int[] newImageSquares = null;
/**
* The mean values of all squares in an image.
*/
private int[] oldImageSquares = null;
/**
* The difference of all the mean values of all squares in an image.
*/
private int[] changedSquares = null;
/**
* The number of squares fitted in the image.
*/
private int numberOfSquaresWide;
/**
* The number of squares fitted in the image.
*/
private int numberOfSquaresHigh;
/**
* The number of squares fitted in the image.
*/
private int numberOfSquares;
/**
* The square side, in pixels.
*/
private int sqSide = INITIAL_SQUARE_SIZE;
/**
* The square area, in pixels.
*/
private int sqArea = 0;
/**
* The amount of pixels left when all normal sized squares have been removed.
*/
private int sqWidthLeftover = 0;
/**
* The amount of pixels left when all normal sized squares have been removed.
*/
private int sqHeightLeftover = 0;
/**
* Optional, less processing is needed if some pixels are left out during some of the calculations.
*/
private int pixelSpace = 0;
/**
* Image property.
*/
private int imageWidth = 0;
/**
* Image property.
*/
private int imageHeight = 0;
/**
* Image property.
*/
private int imageArea = 0;
/**
* Initialize the effect plugin.
*/
public MotionDetectionEffect() {
inputFormats = new Format[] { new RGBFormat(null, Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED, 24, 3, 2, 1, 3, Format.NOT_SPECIFIED, Format.TRUE, Format.NOT_SPECIFIED) };
outputFormats = new Format[] { new RGBFormat(null, Format.NOT_SPECIFIED, Format.byteArray, Format.NOT_SPECIFIED, 24, 3, 2, 1, 3, Format.NOT_SPECIFIED, Format.TRUE, Format.NOT_SPECIFIED) };
}
/**
* Get the inputformats that we support.
* @return All supported Formats.
*/
public Format[] getSupportedInputFormats() {
return inputFormats;
}
/**
* Get the outputformats that we support.
* @param input the current inputformat.
* @return All supported Formats.
*/
public Format[] getSupportedOutputFormats(Format input) {
if (input == null) {
return outputFormats;
}
if (matches(input, inputFormats) != null) {
return new Format[] { outputFormats[0].intersects(input) };
} else {
return new Format[0];
}
}
/**
* Set the input format.
*
*/
public Format setInputFormat(Format input) {
inputFormat = input;
return input;
}
/**
* Set our output format.
*
*/
public Format setOutputFormat(Format output) {
if (output == null || matches(output, outputFormats) == null)
return null;
RGBFormat incoming = (RGBFormat) output;
Dimension size = incoming.getSize();
int maxDataLength = incoming.getMaxDataLength();
int lineStride = incoming.getLineStride();
float frameRate = incoming.getFrameRate();
int flipped = incoming.getFlipped();
int endian = incoming.getEndian();
if (size == null)
return null;
if (maxDataLength < size.width * size.height * 3)
maxDataLength = size.width * size.height * 3;
if (lineStride < size.width * 3)
lineStride = size.width * 3;
if (flipped != Format.FALSE)
flipped = Format.FALSE;
outputFormat = outputFormats[0].intersects(new RGBFormat(size, maxDataLength, null, frameRate, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED, lineStride, Format.NOT_SPECIFIED, Format.NOT_SPECIFIED));
return outputFormat;
}
/**
* Process the buffer. This is where motion is analysed and optionally visualized.
*
*/
public synchronized int process(Buffer inBuffer, Buffer outBuffer) {
int outputDataLength = ((VideoFormat) outputFormat).getMaxDataLength();
validateByteArraySize(outBuffer, outputDataLength);
outBuffer.setLength(outputDataLength);
outBuffer.setFormat(outputFormat);
outBuffer.setFlags(inBuffer.getFlags());
byte[] inData = (byte[]) inBuffer.getData();
byte[] outData = (byte[]) outBuffer.getData();
int[] sqAvg = null;
int[] refsqAvg = null;
vfIn = (RGBFormat) inBuffer.getFormat();
Dimension sizeIn = vfIn.getSize();
int pixStrideIn = vfIn.getPixelStride();
int lineStrideIn = vfIn.getLineStride();
imageWidth = (vfIn.getLineStride()) / 3; //Divide by 3 since each pixel has 3 colours.
imageHeight = ((vfIn.getMaxDataLength()) / 3) / imageWidth;
imageArea = imageWidth * imageHeight;
int r, g, b = 0; //Red, green and blue values.
if (oldImageSquares == null) { //For the first frame.
changeSqSize(INITIAL_SQUARE_SIZE);
updateRequested = true;
}
//Copy all data from the inbuffer to the outbuffer. The purpose is to display the video input on the screen.
System.arraycopy(inData, 0, outData, 0, outData.length);
// Simplify the image to black and white, image information shrinks to one third of the original amount. Less processing needed.
bwPixels = new int[outputDataLength / 3];
for (int ip = 0; ip < outputDataLength; ip += 3) {
int bw = 0;
r = (int) inData[ip] & 0xFF;
g = (int) inData[ip + 1] & 0xFF;
b = (int) inData[ip + 2] & 0xFF;
bw = (int) ((r + b + g) / (double) 3);
bwPixels[ip / 3] = bw; //Now containing a black and white image.
}
if (updateRequested) {
updateRequested = false;
updateSquares();
return BUFFER_PROCESSED_OK;
} else {
updateSquares();
oldNewChange();
int c = 0;
for (int i = 0; i < changedSquares.length; i++) {
if (changedSquares[i] > det_thresh) {
c++;
}
}
if (c > 10 && serverActive) {
// try{
System.out.println("Motion detected (motion at " + c + "areas");
// multicast.send("Motion detected"); - Disabled
// } catch(IOException e){}
}
// If chosen, the detected motion is presented on top of the video input, thus covering the edges of the moving object.
if (visualize) {
for (int i = 1; i <= numberOfSquares; i++) { // For all blobs
if ((changedSquares[i - 1] > threshs[0])) { // Critical threshold, if less, then no motion is said to have occured.
if (((i % numberOfSquaresWide) != 0) && (numberOfSquares - i) > numberOfSquaresWide) {//Normal square, the other cases is not presented!
int begin = ((((i % numberOfSquaresWide) - 1) * sqSide) + ((i / numberOfSquaresWide) * imageWidth * sqSide)) * 3; //Calculate start of square.
if (changedSquares[i - 1] > threshs[3]) { //Very strong motion.
b = (byte) (colors[3] & 0xFF);
g = (byte) ((colors[3] >> 8) & 0xFF);
r = (byte) ((colors[3] >> 16) & 0xFF);
} else if (changedSquares[i - 1] > threshs[2]) { //Strong motion.
b = (byte) (colors[2] & 0xFF);
g = (byte) ((colors[2] >> 8) & 0xFF);
r = (byte) ((colors[2] >> 16) & 0xFF);
} else if (changedSquares[i - 1] > threshs[1]) { //Weak motion.
b = (byte) (colors[1] & 0xFF);
g = (byte) ((colors[1] >> 8) & 0xFF);
r = (byte) ((colors[1] >> 16) & 0xFF);
} else { //The Weakest motion detected.
b = (byte) (colors[0] & 0xFF);
g = (byte) ((colors[0] >> 8) & 0xFF);
r = (byte) ((colors[0] >> 16) & 0xFF);
}
for (int k = begin; k < (begin + (sqSide * imageWidth * 3)); k = k + (imageWidth * 3)) { //Ev <=
for (int j = k; j < (k + (sqSide * 3)); j = j + 3) {
try {
outData[j] = (byte) b;
outData[j + 1] = (byte) g;
outData[j + 2] = (byte) r;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Nullpointer: j = " + j + ". Outdata.length = " + outData.length);
System.exit(1);
}
}
}
}
}
}
}
}
return BUFFER_PROCESSED_OK;
}
// Methods for interface PlugIn
public String getName() {
return "Motion Detection Codec";
}
public void open() {
}
public void close() {
}
public void reset() {
}
// Methods for interface javax.media.Controls
public Object getControl(String controlType) {
System.out.println(controlType);
return null;
}
public Object[] getControls() {
return null;
}
// Utility methods.
public Format matches(Format in, Format outs[]) {
for (int i = 0; i < outs.length; i++) {
if (in.matches(outs[i]))
return outs[i];
}
return null;
}
// Credit : example at www.java.sun.ru
byte[] validateByteArraySize(Buffer buffer, int newSize) {
Object objectArray = buffer.getData();
byte[] typedArray;
if (objectArray instanceof byte[]) { // Has correct type and is not null
typedArray = (byte[]) objectArray;
if (typedArray.length >= newSize) { // Has sufficient capacity
return typedArray;
}
byte[] tempArray = new byte[newSize]; // Reallocate array
System.arraycopy(typedArray, 0, tempArray, 0, typedArray.length);
typedArray = tempArray;
} else {
typedArray = new byte[newSize];
}
buffer.setData(typedArray);
return typedArray;
}
/**
* Sets the current pixelspace, default is zero.
* This is mainly for use where limited processing capacity are availible. Some pixels are left out in the calculations.
* @param newSpace the space between two successive pixels.
*/
private void setPixelSpace(int newSpace) {
pixelSpace = newSpace;
}
/**
* Changes the size of the square shaped area that divides the detection area into many small parts.
* @param newSide the side of the square, in pixels.
*/
private void changeSqSize(int newSide) {
sqSide = newSide;
sqArea = newSide * newSide;
int wid = (imageWidth / sqSide); //The number of squares wide.
int hei = (imageHeight / sqSide); //The number of squares high.
sqWidthLeftover = imageWidth % sqSide;
sqHeightLeftover = imageHeight % sqSide;
if (sqWidthLeftover > 0) {
wid++;
}
if (sqHeightLeftover > 0) {
hei++;
}
numberOfSquaresWide = wid;
numberOfSquaresHigh = hei;
numberOfSquares = wid * hei;
newImageSquares = new int[numberOfSquares];
oldImageSquares = new int[numberOfSquares];
changedSquares = new int[numberOfSquares];
}
/**
* Calculates the average colour in each square thus indirect eliminate noise.
* @param startX the starting position of this square, in pixels, left edge.
* @param startY the starting position of this square, in pixels, bottom edge.
* @param sqWidth the width of this square, in pixels.
* @param sqHeight the height of this square, in pixels.
* @return The average greyscale value for this square.
*/
private int averageInSquare(int startX, int startY, int sqWidth, int sqHeight) {
int average = 0;
for (int i = 0; i < sqHeight; i = i + 1 + pixelSpace) {// For all pixels
for (int j = 0; j < sqWidth; j = j + 1 + pixelSpace) {
average += bwPixels[(((startY + i) * imageWidth) + (startX + j))]; //Sum all the pixel values.
}
}
average = average / (sqWidth * sqHeight); //Divide by the number of pixels to get the average value.
return average;
}
/**
* Backup the most recent frame examined. For the new frame, calculate the average greyscale value for all squares.
*/
private void updateSquares() {
System.arraycopy(newImageSquares, 0, oldImageSquares, 0, newImageSquares.length);
int sqCount = 0; //Keep track of the current square
for (int j = 0; j < (imageHeight); j = j + sqSide) { //For all squares
for (int i = 0; i < (imageWidth); i = i + sqSide) {
if (i <= (imageWidth - sqSide) && j <= (imageHeight - sqSide)) {
newImageSquares[sqCount] = averageInSquare(i, j, sqSide, sqSide); //No edge!
} else if (i > (imageWidth - sqSide) && j <= (imageHeight - sqSide)) {
newImageSquares[sqCount] = averageInSquare(i, j, sqWidthLeftover, sqSide); //Right edge!
} else if (i <= (imageWidth - sqSide) && j > (imageHeight - sqSide)) {
newImageSquares[sqCount] = averageInSquare(i, j, sqSide, sqHeightLeftover); //Bottom edge!
} else if (i > (imageWidth - sqSide) && j > (imageHeight - sqSide)) {
newImageSquares[sqCount] = averageInSquare(i, j, sqWidthLeftover, sqHeightLeftover); //Bottom right edge!
}
sqCount++;
}
}
}
/**
* Calculate the difference per square between currently stored frames.
*/
private void oldNewChange() {
for (int i = 0; i <= (numberOfSquares - 1); i++) { //For all squares
int difference = Math.abs((newImageSquares[i]) - (oldImageSquares[i])); //Compare each square with the corresponding square in the previous frame.
changedSquares[i] = difference; //Save the difference.
}
}
public synchronized void updateModel(boolean visualize, boolean serverActive, boolean simplified, int[] threshs, int[] colors, int sqSide, int det_thresh) {
this.visualize = visualize;
this.serverActive = serverActive;
if (sqSide != this.sqSide)
changeSqSize(sqSide);
if (!simplified) {
System.out.println((colors == null) + " " + (this.colors == null));
System.arraycopy(colors, 0, this.colors, 0, colors.length);
System.arraycopy(threshs, 0, this.threshs, 0, colors.length);
this.det_thresh = det_thresh;
System.out.println("New det_threhsh: " + this.det_thresh);
}
updateRequested = true;
}
/**
*Check if the visualize variable is set.
*@returns the current value.
*/
public boolean isVisual() {
return visualize;
}
/**
*Get the current threshold values in a vector.
*@returns the current values.
*/
public int[] getThreshholds() {
return threshs;
}
/**
*Check if the server is active.
*@returns the current value.
*/
public boolean isServerActive() {
return serverActive;
}
public int[] getColors() {
return colors;
}
/**
*Get the current square side.
*@returns the current value.
*/
public int getSqSide() {
return sqSide;
}
}
javax.media
//-----------------------------------------------------------------------//
// //
// T e s t I m a g e 3 //
// //
// Copyright (C) Herve Bitteur 2000-2007. All rights reserved. //
// This software is released under the terms of the GNU General Public //
// License. Please contact the author at herve.bitteur@laposte.net //
// to report bugs & suggestions. //
//-----------------------------------------------------------------------//
package omr.jai;
import omr.jai.ImageInfo;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Arrays;
import javax.media.jai.InterpolationNearest;
import javax.media.jai.InterpolationBilinear;
public class TestImage3
extends JPanel
{
//RenderedImage image;
PlanarImage image;
// Affine tranform
final float ratio = 4f;
AffineTransform scaleXform = AffineTransform.getScaleInstance(ratio, ratio);
private static char WHITE = "-"; // And transparent
private static char[] charTable = new char[]
{
"#", // 0 Black
"$", // 1
"*", // 2
"0", // 3
"o", // 4
"+", // 5
".", // 6
WHITE // 7
};
//------------//
// TestImage3 //
//------------//
public TestImage3()
{
JFrame frame = new JFrame(getClass().getName());
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(this);
image = decodeImage(new String[] {
"#-###############",
"-----------------",
"#################",
"-----------------",
"#################",
"-----------------",
"#################",
"-----------------",
"#################",
"-----------------",
"#################",
"-----------------",
"-----------------",
"-----------------",
"---####----------",
"-------##--------",
"---------####----",
"-------------#---",
"-------------#---",
"-----------------",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"--#############--",
"-----------------",
"-----------------",
"---####----------",
"-------##--------",
"---------####----",
"-------------#---",
"-------------#---",
"-----------------",
"--#############--",
"--#############--",
"-----------------",
"-----------------"
});
// checkImageFormat();
ImageInfo.print(image);
// Scaling
final float scale = 1f;
ParameterBlock pb = new ParameterBlock()
.addSource(image)
.add(scale)
.add(scale)
.add(0f)
.add(0f)
.add(new InterpolationNearest());
image = JAI.create("scale", pb);
dumpPixels(0, 0, 5, 7);
if (false) {
System.out.println("\nBand Selection");
image = JAI.create("bandselect",image,new int[] {0, 1, 2});
ImageInfo.print(image);
dumpPixels(0, 0, 5, 7);
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100, 100);
frame.pack();
frame.setSize(100, 250);
frame.setVisible(true);
}
private void dumpPixels (int x0,
int y0,
int w,
int h)
{
Raster raster = image.getData();
int[] pixel = null;
System.out.print("pixels=");
for (int y = y0; y < y0+h; y++) {
System.out.println();
for (int x = x0; x <= x0+w; x++) {
pixel = raster.getPixel(x, y, pixel);
System.out.print(" [");
for (int i = 0; i < pixel.length; i++) {
System.out.print(String.format("%3x", pixel[i]));
}
System.out.print("]");
}
}
System.out.println();
}
//------//
// main //
//------//
public static void main(String... args)
{
new TestImage3();
}
//----------------//
// paintComponent //
//----------------//
public void paintComponent(Graphics g)
{
// For background
super.paintComponent(g);
// Meant for visual check
if (image != null) {
Graphics2D g2 = (Graphics2D) g;
g2.drawRenderedImage (image, scaleXform);
//g2.drawImage (image, 1, 1, this);
}
}
//-------------//
// decodeImage //
//-------------//
public static PlanarImage decodeImage (String[] rows)
{
// Create the DataBuffer to hold the pixel samples
final int width = rows[0].length();
final int height = rows.length;
// Create Raster
Raster raster;
if (true) {
raster = Raster.createPackedRaster
(DataBuffer.TYPE_INT, width, height,
new int[] {0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},// bandMasks RGBA
null);
} else {
raster = Raster.createInterleavedRaster
(DataBuffer.TYPE_BYTE, width, height,
4,// num of bands
null);
}
// Populate the data buffer
DataBuffer dataBuffer = raster.getDataBuffer();
int index = 0;
for (String row : rows) {
for (int x = 0; x < width; x++) {
int argb = toARGB(row.charAt(x));
dataBuffer.setElem(index, argb);
index++;
}
}
// Dump
// final int size = width * height;
// System.out.println("DataBuffer :");
// for (int i = 0; i < size; i++) {
// if (i % width == 0) {
// System.out.println();
// }
// System.out.print(String.format("%8x ", dataBuffer.getElem(i)));
// }
// System.out.println();
// Create the image
BufferedImage bufferedImage = new BufferedImage
(width, height, BufferedImage.TYPE_INT_ARGB);
bufferedImage.setData(raster);
// Dump
// System.out.println("BufferedImage :");
// for (int y = 0; y < height; y++) {
// System.out.println();
// for (int x = 0; x < width; x++) {
// System.out.print(String.format("%8x ", bufferedImage.getRGB(x, y)));
// }
// }
// System.out.println();
return PlanarImage.wrapRenderedImage(bufferedImage);
}
//--------//
// toARGB //
//--------//
/**
* Compute the ARGB pixel that corresponds to the given char
*
* @param c the char
* @return the corresponding pixel value (ARGB format)
*/
private static int toARGB (char c)
{
// Check the char
if (c == WHITE) {
return 0x00ffffff; // Totally transparent / white
} else {
for (int i = charTable.length -1; i >= 0; i--) {
if (charTable[i] == c) {
int level = 3 + i * 36; // Range 3 .. 255 (not too bad)
return
255 << 24 | // Alpha (opaque)
level << 16 | // R
level << 8 | // G
level; // B
}
}
}
return 0x00ffffff; // Totally transparent / white
}
//------------------//
// checkImageFormat //
//------------------//
/**
* Check if the image format (and especially its color model) is
* properly handled by Audiveris.
*
* @throws ImageFormatException is the format is not supported
*/
private void checkImageFormat()
{
// Check nb of bands
int numBands = image.getSampleModel().getNumBands();
if (numBands != 1) {
if (numBands == 3) {
image = colorToGray(image);
} else {
throw new RuntimeException
("Unsupported sample model" +
" numBands=" + numBands);
}
}
// Check pixel size
ColorModel colorModel = image.getColorModel();
int pixelSize = colorModel.getPixelSize();
if (pixelSize != 8) {
System.out.println("pixelSize=" + pixelSize +
" colorModel=" + colorModel);
image = grayToGray256(image);
}
}
//--------//
// invert //
//--------//
private static PlanarImage invert (PlanarImage image)
{
return JAI.create("Invert",
new ParameterBlock()
.addSource(image)
.add(null)
.add(null)
.add(null)
.add(null)
.add(null),
null);
}
//-------------//
// colorToGray //
//-------------//
private static PlanarImage colorToGray (PlanarImage image)
{
System.out.println("Converting color image to gray ...");
double[][] matrix = { {0.114d, 0.587d, 0.299d, 0.0d} };
return JAI.create("bandcombine",
new ParameterBlock()
.addSource(image)
.add(matrix),
null);
}
//---------------//
// grayToGray256 //
//---------------//
private static PlanarImage grayToGray256 (PlanarImage image)
{
System.out.println("Converting gray image to gray-256 ...");
ColorSpace colorSpace = ColorSpace.getInstance
(java.awt.color.ColorSpace.CS_GRAY);
// int[] bits = new int[]{8};
// int opaque = Transparency.OPAQUE;
// int dataType = DataBuffer.TYPE_BYTE;
// ColorModel colorModel = new ComponentColorModel
// (colorSpace, bits, false, false, opaque, dataType);
return JAI.create("colorConvert", image, colorSpace, null);
}
}
//-----------------------------------------------------------------------//
////
//I m a g e I n f o //
////
//Copyright (C) Herve Bitteur 2000-2007. All rights reserved. //
//This software is released under the terms of the GNU General Public //
//License. Please contact the author at herve.bitteur@laposte.net //
//to report bugs & suggestions. //
//-----------------------------------------------------------------------//
import java.awt.Transparency;
import java.awt.image.*;
import java.io.File;
import javax.media.jai.*;
public class ImageInfo
{
public static void main(String[] args)
{
// Open the image (using the name passed as a command line parameter)
PlanarImage pi = JAI.create("fileload", args[0]);
// Get the image file size (non-JAI related).
File image = new File(args[0]);
System.out.println("Image file size: "+image.length()+" bytes.");
print(pi);
}
public static void print (PlanarImage pi)
{
// Show the image dimensions and coordinates.
System.out.print("Image Dimensions: ");
System.out.print(pi.getWidth()+"x"+pi.getHeight()+" pixels");
// Remember getMaxX and getMaxY return the coordinate of the next point!
System.out.println(" (from "+pi.getMinX()+","+pi.getMinY()+" to " +
(pi.getMaxX()-1)+","+(pi.getMaxY()-1)+")");
if ((pi.getNumXTiles() != 1)||(pi.getNumYTiles() != 1)) { // Is it tiled?
// Tiles number, dimensions and coordinates.
System.out.print("Tiles: ");
System.out.print(pi.getTileWidth()+"x"+pi.getTileHeight()+" pixels"+
" ("+pi.getNumXTiles()+"x"+pi.getNumYTiles()+" tiles)");
System.out.print(" (from "+pi.getMinTileX()+","+pi.getMinTileY()+
" to "+pi.getMaxTileX()+","+pi.getMaxTileY()+")");
System.out.println(" offset: "+pi.getTileGridXOffset()+","+
pi.getTileGridXOffset());
}
// Display info about the SampleModel of the image.
SampleModel sm = pi.getSampleModel();
System.out.println("Number of bands: "+sm.getNumBands());
System.out.print("Data type: ");
switch(sm.getDataType()) {
case DataBuffer.TYPE_BYTE: System.out.println("byte"); break;
case DataBuffer.TYPE_SHORT: System.out.println("short"); break;
case DataBuffer.TYPE_USHORT: System.out.println("ushort"); break;
case DataBuffer.TYPE_INT: System.out.println("int"); break;
case DataBuffer.TYPE_FLOAT: System.out.println("float"); break;
case DataBuffer.TYPE_DOUBLE: System.out.println("double"); break;
case DataBuffer.TYPE_UNDEFINED:System.out.println("undefined"); break;
}
// Display info about the ColorModel of the image.
ColorModel cm = pi.getColorModel();
if (cm != null)
{
System.out.println("Number of color components: "+
cm.getNumComponents());
System.out.println("Bits per pixel: "+cm.getPixelSize());
System.out.print("Image Transparency: ");
switch(cm.getTransparency()) {
case Transparency.OPAQUE: System.out.println("opaque"); break;
case Transparency.BITMASK: System.out.println("bitmask"); break;
case Transparency.TRANSLUCENT:
System.out.println("translucent"); break;
}
}
else System.out.println("No color model.");
}
}
Media player
/*
* @(#)MDIApp.java 1.3 01/03/13
*
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import java.awt.BorderLayout;
import java.awt.CheckboxMenuItem;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.EndOfMediaEvent;
import javax.media.Manager;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.PrefetchCompleteEvent;
import javax.media.RealizeCompleteEvent;
import javax.media.Time;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.UIManager;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import com.sun.media.ui.MessageBox;
public class MDIApp extends Frame {
/*************************************************************************
* MAIN PROGRAM / STATIC METHODS
*************************************************************************/
public static void main(String args[]) {
MDIApp mdi = new MDIApp();
}
static void Fatal(String s) {
MessageBox mb = new MessageBox("JMF Error", s);
}
/*************************************************************************
* VARIABLES
*************************************************************************/
JMFrame jmframe = null;
JDesktopPane desktop;
FileDialog fd = null;
CheckboxMenuItem cbAutoLoop = null;
Player player = null;
Player newPlayer = null;
String filename;
/*************************************************************************
* METHODS
*************************************************************************/
public MDIApp() {
super("Java Media Player");
// Add the desktop pane
setLayout( new BorderLayout() );
desktop = new JDesktopPane();
desktop.setDoubleBuffered(true);
add("Center", desktop);
setMenuBar(createMenuBar());
setSize(640, 480);
setVisible(true);
try {
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (Exception e) {
System.err.println("Could not initialize java.awt Metal lnf");
}
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
} );
Manager.setHint(Manager.LIGHTWEIGHT_RENDERER, new Boolean(true));
}
private MenuBar createMenuBar() {
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
String command = ae.getActionCommand();
if (command.equals("Open")) {
if (fd == null) {
fd = new FileDialog(MDIApp.this, "Open File",
FileDialog.LOAD);
fd.setDirectory("/movies");
}
fd.show();
if (fd.getFile() != null) {
String filename = fd.getDirectory() + fd.getFile();
openFile("file:" + filename);
}
} else if (command.equals("Exit")) {
dispose();
System.exit(0);
}
}
};
MenuItem item;
MenuBar mb = new MenuBar();
// File Menu
Menu mnFile = new Menu("File");
mnFile.add(item = new MenuItem("Open"));
item.addActionListener(al);
mnFile.add(item = new MenuItem("Exit"));
item.addActionListener(al);
// Options Menu
Menu mnOptions = new Menu("Options");
cbAutoLoop = new CheckboxMenuItem("Auto replay");
cbAutoLoop.setState(true);
mnOptions.add(cbAutoLoop);
mb.add(mnFile);
mb.add(mnOptions);
return mb;
}
/**
* Open a media file.
*/
public void openFile(String filename) {
String mediaFile = filename;
Player player = null;
// URL for our media file
URL url = null;
try {
// Create an url from the file name and the url to the
// document containing this applet.
if ((url = new URL(mediaFile)) == null) {
Fatal("Can"t build URL for " + mediaFile);
return;
}
// Create an instance of a player for this media
try {
player = Manager.createPlayer(url);
} catch (NoPlayerException e) {
Fatal("Error: " + e);
}
} catch (MalformedURLException e) {
Fatal("Error:" + e);
} catch (IOException e) {
Fatal("Error:" + e);
}
if (player != null) {
this.filename = filename;
JMFrame jmframe = new JMFrame(player, filename);
desktop.add(jmframe);
}
}
}
class JMFrame extends JInternalFrame implements ControllerListener {
Player mplayer;
Component visual = null;
Component control = null;
int videoWidth = 0;
int videoHeight = 0;
int controlHeight = 30;
int insetWidth = 10;
int insetHeight = 30;
boolean firstTime = true;
public JMFrame(Player player, String title) {
super(title, true, true, true, true);
getContentPane().setLayout( new BorderLayout() );
setSize(320, 10);
setLocation(50, 50);
setVisible(true);
mplayer = player;
mplayer.addControllerListener((ControllerListener) this);
mplayer.realize();
addInternalFrameListener( new InternalFrameAdapter() {
public void internalFrameClosing(InternalFrameEvent ife) {
mplayer.close();
}
} );
}
public void controllerUpdate(ControllerEvent ce) {
if (ce instanceof RealizeCompleteEvent) {
mplayer.prefetch();
} else if (ce instanceof PrefetchCompleteEvent) {
if (visual != null)
return;
if ((visual = mplayer.getVisualComponent()) != null) {
Dimension size = visual.getPreferredSize();
videoWidth = size.width;
videoHeight = size.height;
getContentPane().add("Center", visual);
} else
videoWidth = 320;
if ((control = mplayer.getControlPanelComponent()) != null) {
controlHeight = control.getPreferredSize().height;
getContentPane().add("South", control);
}
setSize(videoWidth + insetWidth,
videoHeight + controlHeight + insetHeight);
validate();
mplayer.start();
} else if (ce instanceof EndOfMediaEvent) {
mplayer.setMediaTime(new Time(0));
mplayer.start();
}
}
}
Query the installed version of the JMF
/*******************************************************************************
* GUIManagerQuery - A Graphical User Interface built atop the ManagerQuery
* class allowing the user to query the installed version of the JMF as to its
* support in termsof different players, processors, and protocols.
*
* @author Spike Barlow
******************************************************************************/
import java.awt.*;
import java.awt.event.*;
import javax.media.*;
import java.util.*;
public class GUIManagerQuery extends Frame implements ActionListener {
/** The version of the JMF. */
protected Label versionLabel;
/** Button to print JMF"s hints. */
protected Button hintsButton;
/** Button to print list of players. */
protected Button playersButton;
/** Button to print list of processors. */
protected Button processorsButton;
/** Button to print list of data sources. */
protected Button sourcesButton;
/** TextField in which user can enter protocols or content types. */
protected TextField contentsField;
/** Area in which the results are displayed. */
protected TextArea results;
/***************************************************************************
* Construct the GUIManagerQuery object, constructing the various components
* and laying them out on the screen.
**************************************************************************/
public GUIManagerQuery() {
super("GUIManagerQuery");
setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
versionLabel = new Label("JMF v" + Manager.getVersion());
add(versionLabel, "North");
Panel lower = new Panel();
lower.add(new Label("Content/Protocol"));
contentsField = new TextField(32);
lower.add(contentsField);
add(lower, "South");
results = new TextArea(20, 80);
results.setEditable(false);
add(results, "Center");
Panel controls = new Panel();
controls.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
hintsButton = new Button("Hints");
gbc.gridx = 0;
gbc.gridy = 0;
controls.add(hintsButton, gbc);
hintsButton.addActionListener(this);
playersButton = new Button("Players");
gbc.gridy = 1;
controls.add(playersButton, gbc);
playersButton.addActionListener(this);
processorsButton = new Button("Processors");
gbc.gridy = 2;
controls.add(processorsButton, gbc);
processorsButton.addActionListener(this);
sourcesButton = new Button("DataSources");
gbc.gridy = 3;
controls.add(sourcesButton, gbc);
sourcesButton.addActionListener(this);
add(controls, "East");
}
/***************************************************************************
* Respond to button presses from the user indicating the desire for
* information such as a list of players.
**************************************************************************/
public void actionPerformed(ActionEvent e) {
int type;
String[] cons;
////////////////////////////////////////////////////////////////
// Handle hints - simplest case [no need to check content types]
////////////////////////////////////////////////////////////////
if (e.getSource() == hintsButton) {
results.setText(ManagerQuery.getHints());
}
/////////////////////////////////////////////////////////////////////
// Players, processors, or datasources. Need to check the contents
// field and if it has text in there then use that as a qualifier
// in the search for classes. However if empty then generate a
// complete list of all classes of the required type. User may
// enter multiple content types either comma or space separated,
// hence use of StringTokenizer.
////////////////////////////////////////////////////////////////////
else {
if (e.getSource() == playersButton)
type = ManagerQuery.HANDLERS;
else if (e.getSource() == processorsButton)
type = ManagerQuery.PROCESSORS;
else
type = ManagerQuery.DATASOURCES;
String contents = contentsField.getText();
if (contents == null || contents.length() == 0)
cons = null;
else {
StringTokenizer tokenizer = new StringTokenizer(contents,
" ,\t;");
cons = new String[tokenizer.countTokens()];
for (int i = 0; i < cons.length; i++)
cons[i] = tokenizer.nextToken();
}
if (cons != null && cons.length > 0)
results.setText(ManagerQuery
.getHandlersOrProcessors(cons, type));
else if (type == ManagerQuery.HANDLERS)
results.setText(ManagerQuery.getHandlers());
else if (type == ManagerQuery.PROCESSORS)
results.setText(ManagerQuery.getProcessors());
else
results.setText(ManagerQuery.getDataSources());
}
}
/***************************************************************************
* Main method - construct a GUIManagerQuery frame and show it on the
* screen.
**************************************************************************/
public static void main(String[] args) {
GUIManagerQuery gui = new GUIManagerQuery();
gui.pack();
gui.setSize(640, 600);
gui.show();
}
}
Renderer for RGB images using AWT Image using Java Media API
/*
* @(#)SampleAWTRenderer.java 1.3 01/03/13
*
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import javax.media.*;
import javax.media.renderer.VideoRenderer;
import javax.media.Format;
import javax.media.format.VideoFormat;
import javax.media.format.RGBFormat;
import java.awt.*;
import java.awt.image.*;
import java.awt.color.ColorSpace;
import java.awt.event.*;
import java.util.Vector;
/**
* Renderer for RGB images using AWT Image.
*/
public class SampleAWTRenderer implements javax.media.renderer.VideoRenderer {
/*************************************************************************
* Variables and Constants
*************************************************************************/
// The descriptive name of this renderer
private static final String name = "Sample AWT Renderer";
protected RGBFormat inputFormat;
protected RGBFormat supportedRGB;
protected Format[] supportedFormats;
protected MemoryImageSource sourceImage;
protected Image destImage;
protected Buffer lastBuffer = null;
protected int inWidth = 0;
protected int inHeight = 0;
protected Component component = null;
protected Rectangle reqBounds = null;
protected Rectangle bounds = new Rectangle();
protected boolean started = false;
/*************************************************************************
* Constructor
*************************************************************************/
public SampleAWTRenderer() {
// Prepare supported input formats and preferred format
int rMask = 0x000000FF;
int gMask = 0x0000FF00;
int bMask = 0x00FF0000;
supportedRGB = new RGBFormat(null, // size
Format.NOT_SPECIFIED, // maxDataLength
int[].class, // buffer type
Format.NOT_SPECIFIED, // frame rate
32, // bitsPerPixel
rMask, gMask, bMask, // component masks
1, // pixel stride
Format.NOT_SPECIFIED, // line stride
Format.FALSE, // flipped
Format.NOT_SPECIFIED // endian
);
supportedFormats = new VideoFormat[1];
supportedFormats[0] = supportedRGB;
}
/****************************************************************
* Controls implementation
****************************************************************/
/**
* Returns an array of supported controls
**/
public Object[] getControls() {
// No controls
return (Object[]) new Control[0];
}
/**
* Return the control based on a control type for the PlugIn.
*/
public Object getControl(String controlType) {
try {
Class cls = Class.forName(controlType);
Object cs[] = getControls();
for (int i = 0; i < cs.length; i++) {
if (cls.isInstance(cs[i]))
return cs[i];
}
return null;
} catch (Exception e) { // no such controlType or such control
return null;
}
}
/*************************************************************************
* PlugIn implementation
*************************************************************************/
public String getName() {
return name;
}
/**
* Opens the plugin
*/
public void open() throws ResourceUnavailableException {
sourceImage = null;
destImage = null;
lastBuffer = null;
}
/**
* Resets the state of the plug-in. Typically at end of media or when media
* is repositioned.
*/
public void reset() {
// Nothing to do
}
public void close() {
// Nothing to do
}
/*************************************************************************
* Renderer implementation
*************************************************************************/
public void start() {
started = true;
}
public void stop() {
started = false;
}
/**
* Lists the possible input formats supported by this plug-in.
*/
public Format[] getSupportedInputFormats() {
return supportedFormats;
}
/**
* Set the data input format.
*/
public Format setInputFormat(Format format) {
if (format != null && format instanceof RGBFormat && format.matches(supportedRGB)) {
inputFormat = (RGBFormat) format;
Dimension size = inputFormat.getSize();
inWidth = size.width;
inHeight = size.height;
return format;
} else
return null;
}
/**
* Processes the data and renders it to a component
*/
public synchronized int process(Buffer buffer) {
if (component == null)
return BUFFER_PROCESSED_FAILED;
Format inf = buffer.getFormat();
if (inf == null)
return BUFFER_PROCESSED_FAILED;
if (inf != inputFormat || !buffer.getFormat().equals(inputFormat)) {
if (setInputFormat(inf) != null)
return BUFFER_PROCESSED_FAILED;
}
Object data = buffer.getData();
if (!(data instanceof int[]))
return BUFFER_PROCESSED_FAILED;
if (lastBuffer != buffer) {
lastBuffer = buffer;
newImage(buffer);
}
sourceImage.newPixels(0, 0, inWidth, inHeight);
Graphics g = component.getGraphics();
if (g != null) {
if (reqBounds == null) {
bounds = component.getBounds();
bounds.x = 0;
bounds.y = 0;
} else
bounds = reqBounds;
g.drawImage(destImage, bounds.x, bounds.y, bounds.width, bounds.height, 0, 0, inWidth, inHeight, component);
}
return BUFFER_PROCESSED_OK;
}
/****************************************************************
* VideoRenderer implementation
****************************************************************/
/**
* Returns an AWT component that it will render to. Returns null
* if it is not rendering to an AWT component.
*/
public java.awt.ruponent getComponent() {
if (component == null) {
component = new Canvas() {
public Dimension getPreferredSize() {
return new Dimension(getInWidth(), getInHeight());
}
public void update(Graphics g) {
}
public void paint(Graphics g) {
// TODO: Need to repaint image if the movie is in paused state
}
};
}
return component;
}
/**
* Requests the renderer to draw into a specified AWT component.
* Returns false if the renderer cannot draw into the specified
* component.
*/
public boolean setComponent(java.awt.ruponent comp) {
component = comp;
return true;
}
/**
* Sets the region in the component where the video is to be
* rendered to. Video is to be scaled if necessary. If <code>rect</code>
* is null, then the video occupies the entire component.
*/
public void setBounds(java.awt.Rectangle rect) {
reqBounds = rect;
}
/**
* Returns the region in the component where the video will be
* rendered to. Returns null if the entire component is being used.
*/
public java.awt.Rectangle getBounds() {
return reqBounds;
}
/*************************************************************************
* Local methods
*************************************************************************/
int getInWidth() {
return inWidth;
}
int getInHeight() {
return inHeight;
}
private void newImage(Buffer buffer) {
if (!(buffer.getData() instanceof int[]))
return;
int[] data = (int[]) buffer.getData();
RGBFormat format = (RGBFormat) buffer.getFormat();
//data = processImage(buffer);
data = (int[]) buffer.getData();
DirectColorModel dcm = new DirectColorModel(format.getBitsPerPixel(), format.getRedMask(), format.getGreenMask(), format.getBlueMask());
sourceImage = new MemoryImageSource(format.getLineStride(), format.getSize().height, dcm, (int[]) data, 0, format.getLineStride());
sourceImage.setAnimated(true);
sourceImage.setFullBufferUpdates(true);
if (component != null) {
destImage = component.createImage(sourceImage);
component.prepareImage(destImage, component);
}
}
private int[] processImage(Buffer buf) {
int[] data = (int[]) buf.getData();
int[] ret = new int[data.length];
RGBFormat fmt = (RGBFormat) buf.getFormat();
DirectColorModel dcm = new DirectColorModel(fmt.getBitsPerPixel(), fmt.getRedMask(), fmt.getGreenMask(), fmt.getBlueMask());
int[] rgb;
int k;
for (int i = 0; i < data.length; i++) {
rgb = dcm.getComponents(data[i], null, 0);
k = toGray(rgb);
rgb[0] = rgb[1] = rgb[2] = k;
ret[i] = dcm.getDataElement(rgb, 0);
}
return ret;
}
private int toGray(int[] rgb) {
return (int) (0.2125 * rgb[0] + 0.7154 * rgb[1] + 0.0721 * rgb[2]);
}
}
Sample program to demonstrate FramePositioningControl.
/*
* @(#)Seek.java 1.2 01/03/13
*
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.ruponent;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import javax.media.ConfigureCompleteEvent;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.Duration;
import javax.media.EndOfMediaEvent;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.PrefetchCompleteEvent;
import javax.media.RealizeCompleteEvent;
import javax.media.ResourceUnavailableEvent;
import javax.media.SizeChangeEvent;
import javax.media.Time;
import javax.media.control.FramePositioningControl;
import javax.media.protocol.DataSource;
/**
* Sample program to demonstrate FramePositioningControl.
*/
public class Seek extends Frame implements ControllerListener, ActionListener {
Player p;
FramePositioningControl fpc;
Object waitSync = new Object();
boolean stateTransitionOK = true;
int totalFrames = FramePositioningControl.FRAME_UNKNOWN;
Panel cntlPanel;
Button fwdButton;
Button bwdButton;
Button rndButton;
/**
* Given a DataSource, create a player and use that player
* as a player to playback the media.
*/
public boolean open(DataSource ds) {
System.err.println("create player for: " + ds.getContentType());
try {
p = Manager.createPlayer(ds);
} catch (Exception e) {
System.err.println("Failed to create a player from the given DataSource: " + e);
return false;
}
p.addControllerListener(this);
p.realize();
if (!waitForState(p.Realized)) {
System.err.println("Failed to realize the player.");
return false;
}
// Try to retrieve a FramePositioningControl from the player.
fpc = (FramePositioningControl)p.getControl("javax.media.control.FramePositioningControl");
if (fpc == null) {
System.err.println("The player does not support FramePositioningControl.");
System.err.println("There"s no reason to go on for the purpose of this demo.");
return false;
}
Time duration = p.getDuration();
if (duration != Duration.DURATION_UNKNOWN) {
System.err.println("Movie duration: " + duration.getSeconds());
totalFrames = fpc.mapTimeToFrame(duration);
if (totalFrames != FramePositioningControl.FRAME_UNKNOWN)
System.err.println("Total # of video frames in the movies: " + totalFrames);
else
System.err.println("The FramePositiongControl does not support mapTimeToFrame.");
} else {
System.err.println("Movie duration: unknown");
}
// Prefetch the player.
p.prefetch();
if (!waitForState(p.Prefetched)) {
System.err.println("Failed to prefetch the player.");
return false;
}
// Display the visual & control component if there"s one.
setLayout(new BorderLayout());
cntlPanel = new Panel();
fwdButton = new Button("Forward");
bwdButton = new Button("Backward");
rndButton = new Button("Random");
fwdButton.addActionListener(this);
bwdButton.addActionListener(this);
rndButton.addActionListener(this);
cntlPanel.add(fwdButton);
cntlPanel.add(bwdButton);
cntlPanel.add(rndButton);
Component vc;
if ((vc = p.getVisualComponent()) != null) {
add("Center", vc);
}
add("South", cntlPanel);
setVisible(true);
return true;
}
public void addNotify() {
super.addNotify();
pack();
}
/**
* Block until the player has transitioned to the given state.
* Return false if the transition failed.
*/
boolean waitForState(int state) {
synchronized (waitSync) {
try {
while (p.getState() < state && stateTransitionOK)
waitSync.wait();
} catch (Exception e) {}
}
return stateTransitionOK;
}
public void actionPerformed(ActionEvent ae) {
String command = ae.getActionCommand();
if (command.equals("Forward")) {
int dest = fpc.skip(1);
System.err.println("Step forward " + dest + " frame.");
} else if (command.equals("Backward")) {
int dest = fpc.skip(-1);
System.err.println("Step backward " + dest + " frame.");
} else if (command.equals("Random")) {
if (totalFrames == FramePositioningControl.FRAME_UNKNOWN)
System.err.println("Cannot jump to a random frame.");
else {
int randomFrame = (int)(totalFrames * Math.random());
randomFrame = fpc.seek(randomFrame);
System.err.println("Jump to a random frame: " + randomFrame);
}
}
int currentFrame = fpc.mapTimeToFrame(p.getMediaTime());
if (currentFrame != FramePositioningControl.FRAME_UNKNOWN)
System.err.println("Current frame: " + currentFrame);
}
/**
* Controller Listener.
*/
public void controllerUpdate(ControllerEvent evt) {
if (evt instanceof ConfigureCompleteEvent ||
evt instanceof RealizeCompleteEvent ||
evt instanceof PrefetchCompleteEvent) {
synchronized (waitSync) {
stateTransitionOK = true;
waitSync.notifyAll();
}
} else if (evt instanceof ResourceUnavailableEvent) {
synchronized (waitSync) {
stateTransitionOK = false;
waitSync.notifyAll();
}
} else if (evt instanceof EndOfMediaEvent) {
p.setMediaTime(new Time(0));
//p.start();
//p.close();
//System.exit(0);
} else if (evt instanceof SizeChangeEvent) {
}
}
/**
* Main program
*/
public static void main(String [] args) {
if (args.length == 0) {
prUsage();
System.exit(0);
}
MediaLocator ml;
if ((ml = new MediaLocator(args[0])) == null) {
System.err.println("Cannot build media locator from: " + args[0]);
prUsage();
System.exit(0);
}
DataSource ds = null;
// Create a DataSource given the media locator.
try {
ds = Manager.createDataSource(ml);
} catch (Exception e) {
System.err.println("Cannot create DataSource from: " + ml);
System.exit(0);
}
Seek seek = new Seek();
if (!seek.open(ds))
System.exit(0);
}
static void prUsage() {
System.err.println("Usage: java Seek <url>");
}
}
Select a media file from tjelocal file system and gain statistics
/**********************************************************************
* GUIMediaStatistics - a GUI allowing the user to select a media
* file from tjelocal file system and gain statistics on that media
* (audio or video) concerning its tracks and their format/composition.
*
* The class is built atop the MediaStatistics class and arguably
* provides a more user friendly mechanism for determining the
*format of media.
*
* @author Spike Barlow
***********************************************************************/
import java.awt.*;
import java.awt.event.*;
import javax.media.*;
import java.util.*;
public class GUIMediaStatistics extends Frame implements ActionListener {
/** Object to determine the format ofthe media. Performs all the real work. */
protected MediaStatistics stats;
/** User wants to search for a file. */
protected Button browseButton;
/** User wants to know the format of the current file. */
protected Button getStatsButton;
/** Current state of processing. */
protected int state;
/** Where the format informationis displayed. */
protected TextArea results;
/** Area i which the user can type the name of a file. */
protected TextField mediaField;
/** Pause in milliseconds between checks to see if format is known. */
public static final int PAUSE = 50;
/** Maximum wait before giving up on determining theformat. */
public static final int MAX_WAIT_PERIOD = 10000;
/** Directory that the user last searched for files. */
protected String lastDirectory;
/**********************************************************************
* Construct the GUIMediaStatistics object, constructing the various
* components and laying them out on the screen.
**********************************************************************/
public GUIMediaStatistics() {
super("GUIMediaStatistics");
setLayout(new BorderLayout());
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0); } });
Panel filePanel = new Panel();
filePanel.add(new Label("File:"));
mediaField = new TextField(40);
filePanel.add(mediaField);
browseButton =new Button("browse...");
filePanel.add(browseButton);
browseButton.addActionListener(this);
getStatsButton = new Button("get stats...");
filePanel.add(getStatsButton);
getStatsButton.addActionListener(this);
add(filePanel,"North");
results = new TextArea(80,10);
results.setEditable(false);
add(results,"Center");
}
/************************************************************************
* Respond to user button presses - either browsing for a file or
* gathering format info on the current file.
************************************************************************/
public void actionPerformed(ActionEvent e) {
/////////////////////////////////
// Browse - use FileDialog class.
/////////////////////////////////
if (e.getSource() == browseButton) {
FileDialog choice = new FileDialog(this, "Media File Choice",
FileDialog.LOAD);
if (lastDirectory != null)
choice.setDirectory(lastDirectory);
choice.show();
String selection = choice.getFile();
if (selection != null) {
lastDirectory = choice.getDirectory();
mediaField.setText("file://" + choice.getDirectory()
+ selection);
}
}
////////////////////////////////////////////////////////
// Get statistics - create a MediaStatistics object and
// monitor its progress.
///////////////////////////////////////////////////////
else {
stats = new MediaStatistics(mediaField.getText());
monitorAndReport();
}
}
/************************************************************************
* Monitor the progress of the MediaStatistics object as it attempts to
* determineformatinformation for the current file. It periodically
* polls the object, obtaining a report from it and printing it to the
* screen. The polling stops as soon as the format is known, it is
* found that it isimpossible to determine a format, or a certain time
* period is exceeded.
**************************************************************************/
private void monitorAndReport() {
int elapsed = 0;
state = stats.getState();
while (elapsed < MAX_WAIT_PERIOD
&& (state != MediaStatistics.FAILED && state != MediaStatistics.KNOWN)) {
results.setText(stats.getReport());
try {
Thread.sleep(PAUSE);
} catch (Exception e) {
}
elapsed += PAUSE;
state = stats.getState();
}
if (state == MediaStatistics.FAILED || state == MediaStatistics.KNOWN)
results.setText(stats.getReport());
else
results.setText("Timing out after maximum period of "
+ MAX_WAIT_PERIOD + "ms");
}
/***************************************************************************
* Main method - construct a GUIMediaStatistics frame and show it on the
* screen.
**************************************************************************/
public static void main(String[] args) {
GUIMediaStatistics gui = new GUIMediaStatistics();
gui.pack();
gui.setSize(600, 400);
gui.show();
}
}