/*
* @(#)AWTRenderer.java 1.25 02/08/21
*
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.media.renderer.video;
import javax.media.*;
import javax.media.renderer.VideoRenderer;
import javax.media.Format;
import javax.media.format.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.Vector;
import com.sun.media.*;
import com.sun.media.util.Arch;
/**
* Renderer for RGB images using AWT Image.
* @since JMF 2.0
*/
public class AWTRenderer extends BasicVideoRenderer implements Blitter {
/*************************************************************************
* Variables and Constants
*************************************************************************/
// The descriptive name of this renderer
private static final String MyName = "AWT Renderer";
private transient Vector cacheInputData = null;
private transient Vector cacheInputImage = null;
private transient Vector cacheOutputImage = null;
private transient Image lastImage = null;
private RGBFormat supportedRGB = null;
private RGBFormat supportedOther = null;
private transient int lastWidth = 1;
private transient int lastHeight = 1;
private Blitter blitter = null;
static public String vendor = null;
static public boolean runningOnMac = false;
static {
try {
vendor = System.getProperty("java.vendor");
if (vendor != null) {
vendor = vendor.toUpperCase();
if (vendor.startsWith("APPLE")) {
runningOnMac = true;
}
}
} catch (Throwable e) {
// Non-fatal error. No need to do anything.
}
}
/*************************************************************************
* Constructor
*************************************************************************/
public AWTRenderer() {
this(MyName);
}
public AWTRenderer(String name) {
super(name);
// Prepare supported input formats and preferred format
int rMask, gMask, bMask;
if ((Arch.getArch() & Arch.SOLARIS) != 0 && !runningOnMac) {
rMask = 0x000000FF;
gMask = 0x0000FF00;
bMask = 0x00FF0000;
} else {
bMask = 0x000000FF;
gMask = 0x0000FF00;
rMask = 0x00FF0000;
}
supportedRGB = new RGBFormat(null, Format.NOT_SPECIFIED,
Format.intArray,
Format.NOT_SPECIFIED, // frame rate
32,
rMask, gMask, bMask,
1, Format.NOT_SPECIFIED,
Format.FALSE, // flipped
Format.NOT_SPECIFIED // endian
);
supportedOther = new RGBFormat(null, Format.NOT_SPECIFIED,
Format.intArray,
Format.NOT_SPECIFIED, // frame rate
32,
bMask, gMask, rMask,
1, Format.NOT_SPECIFIED,
Format.FALSE, // flipped
Format.NOT_SPECIFIED // endian
);
supportedFormats = new VideoFormat[2];
supportedFormats[0] = supportedRGB;
supportedFormats[1] = supportedOther;
// Setting ColorModel does not really work on the Mac.
// So there's only one format supported by the Mac.
if (runningOnMac)
supportedFormats[1] = supportedRGB;
try {
Class cls = Class.forName("com.sun.media.renderer.video.Java2DRenderer");
blitter = (Blitter) cls.newInstance();
//blitter.setRenderer(this);
} catch (Throwable t) {
if (t instanceof ThreadDeath)
throw (ThreadDeath) t;
blitter = this;
}
}
public boolean isLightWeight() {
return false;
}
/*************************************************************************
* PlugIn methods
*************************************************************************/
/**
* Opens the plug-in software or hardware component and acquires
* necessary resources. If all the needed resources could not be
* acquired, it throws a ResourceUnavailableException. Data should not
* be passed into the plug-in without first calling this method.
*/
public void open() throws ResourceUnavailableException {
cacheInputData = new Vector();
cacheInputImage = new Vector();
cacheOutputImage = new Vector();
}
/**
* Resets the state of the plug-in. Typically at end of media or when media
* is repositioned.
*/
public synchronized void reset() {
cacheInputData = new Vector();
cacheInputImage = new Vector();
cacheOutputImage = new Vector();
}
/*************************************************************************
* Renderer methods
*************************************************************************/
/**
* Set the data input format.
* @return false if the format is not supported.
*/
public Format setInputFormat(Format format) {
if (super.setInputFormat(format) != null) {
reset();
return format;
} else
return null;
}
/**
* Processes the data and renders it to the output device
* represented by this renderer.
*/
protected synchronized int doProcess(Buffer buffer) {
if (component == null)
return BUFFER_PROCESSED_OK;
if (!buffer.getFormat().equals(inputFormat)) {
Format in = buffer.getFormat();
if (matches(in, supportedFormats) == null)
return BUFFER_PROCESSED_FAILED;
else {
inputFormat = (RGBFormat) in;
}
}
Object data = buffer.getData();
if (!(data instanceof int[]))
return BUFFER_PROCESSED_FAILED;
int cacheSize = cacheInputData.size();
int i;
boolean found = false;
for (i = 0; i < cacheSize; ++i) {
Object bufKnown = cacheInputData.elementAt(i);
if (bufKnown == data) {
found = true;
break;
}
}
// Data not cached? Add to the cache and create a new Image wrapper.
if (!found)
i = blitter.newData(buffer,
cacheInputImage,
cacheOutputImage,
cacheInputData);
// Couldn't create Image
if (i < 0)
return BUFFER_PROCESSED_FAILED;
RGBFormat format = (RGBFormat)buffer.getFormat();
Dimension size = format.getSize();
inWidth = size.width;
inHeight = size.height;
if (outWidth == -1)
outWidth = size.width;
if (outHeight == -1)
outHeight = size.height;
lastImage = blitter.process(buffer,
cacheInputImage.elementAt(i),
cacheOutputImage.elementAt(i),
size);
lastWidth = size.width;
lastHeight = size.height;
if (!isLightWeight()) {
Graphics g = component.getGraphics();
if (g != null) {
blitter.draw(g, component, lastImage, 0, 0, outWidth, outHeight,
0, 0, size.width, size.height);
}
} else {
component.repaint();
}
return BUFFER_PROCESSED_OK;
}
protected void repaint() {
if (!isStarted() && lastImage != null) {
Graphics g = component.getGraphics();
blitter.draw(g, component, lastImage, 0, 0, outWidth, outHeight,
0, 0, lastWidth, lastHeight);
}
}
/**
* Returns an AWT component that it will render to. Returns null
* if it is not rendering to an AWT component.
*/
public java.awt.Component getComponent() {
if (component == null) {
if (isLightWeight()) {
component = new LightComponent();
component.setBackground(getPreferredBackground());
if (compListener == null)
compListener = new CompListener();
component.addComponentListener(compListener);
} else
component = super.getComponent();
}
return component;
}
public synchronized void resized(Component c) {
super.resized(c);
if (blitter != this)
blitter.resized(c);
}
/****************************************************************
* Blitter methods
****************************************************************/
public Image process(Buffer buffer, Object cacheInputImage,
Object cacheOutputImage, Dimension size) {
MemoryImageSource sourceImage = (MemoryImageSource)cacheInputImage;
Image lastImage = (Image) cacheOutputImage;
sourceImage.newPixels(0, 0, size.width, size.height);
return lastImage;
}
public void draw(Graphics g, Component component, Image lastImage,
int dx, int dy, int dw, int dh,
int sx, int sy, int sw, int sh) {
if (g != null)
g.drawImage(lastImage, dx, dy, dw, dh,
sx, sy, sw, sh, component);
}
public void paint(Graphics g) {
if (g != null && lastImage != null)
blitter.draw(g, component, lastImage, 0, 0, outWidth, outHeight,
0, 0, lastWidth, lastHeight);
}
public int newData(Buffer buffer, Vector cacheInputImage,
Vector cacheOutputImage, Vector cacheInputData) {
Object data = buffer.getData();
if (!(data instanceof int[]))
return -1;
RGBFormat format = (RGBFormat) buffer.getFormat();
DirectColorModel dcm = new DirectColorModel(format.getBitsPerPixel(),
format.getRedMask(),
format.getGreenMask(),
format.getBlueMask());
MemoryImageSource sourceImage = new MemoryImageSource(format.getLineStride(),
format.getSize().height,
dcm,
(int[])data, 0,
format.getLineStride());
sourceImage.setAnimated(true);
sourceImage.setFullBufferUpdates(true);
Image destImage = null;
if (component != null) {
destImage = component.createImage(sourceImage);
component.prepareImage(destImage, component);
}
cacheOutputImage.addElement(destImage);
cacheInputData.addElement(data);
cacheInputImage.addElement(sourceImage);
return cacheInputImage.size() - 1;
}
public class LightComponent extends Component {
public synchronized void paint(Graphics g) {
AWTRenderer.this.paint(g);
}
public synchronized void update(Graphics g) {
}
public Dimension getMinimumSize() {
return new Dimension(1, 1);
}
public Dimension getPreferredSize() {
return myPreferredSize();
}
public synchronized void addNotify() {
super.addNotify();
setAvailable(true);
}
public synchronized void removeNotify() {
setAvailable(false);
super.removeNotify();
}
}
}
|