FileDocCategorySizeDatePackage
GDIRenderer.javaAPI DocJMF 2.1.1e8460Mon May 12 12:21:20 BST 2003com.sun.media.renderer.video

GDIRenderer.java

/*
 * @(#)GDIRenderer.java	1.28 03/04/23
 *
 * Copyright (c) 1996-2002 Sun Microsystems, Inc.  All rights reserved.
 */

package com.sun.media.renderer.video;

import javax.media.*;
import javax.media.Format;
import javax.media.format.*;
import javax.media.renderer.VideoRenderer;
import java.awt.*;
import java.util.Vector;
import com.sun.media.*;

public class GDIRenderer extends BasicVideoRenderer {

    private static boolean available = false;
    
    static {
	try {
	    JMFSecurityManager.loadLibrary("jmgdi");
	    available = true;
	} catch (Exception e) {
	} catch (UnsatisfiedLinkError ule) {
	}
    }

    private    int        blitter       = 0;
    protected  Object     data        = null;
    //private    int        blitterAvailable = 0;
    private    int        defbitsPerPixel;
    private    int        defrMask;
    private    int        defgMask;
    private    int        defbMask;
    private    int        offsetX = 0;
    private    int        offsetY = 0;

    private    int        bytesPerPixel = 4;
    private    int        bitsPerPixel;
    private    int        rMask;
    private    int        gMask;
    private    int        bMask;
    private    int        pixelStride;
    private    int        lineStride;
    private    boolean    flipped;
    private    int        handle = 0;
    
    
    private synchronized native boolean gdiInitialize();
    private synchronized native boolean gdiSetComponent(int windowHandle);
    private synchronized native boolean gdiSetOutputSize(int width, int height);
    private synchronized native boolean gdiDraw(Object data,
						long dataBytes,
						int elSize, // 1 for byte[], 2 for short[]
						            // 4 for int[]
						int bytesPerPixel,
						int srcWidth, int srcHeight,
						int srcStride,
						int dstWidth, int dstHeight,
						int rm, int gm, int bm,
						boolean flipped,
						int windowHandle);
    private synchronized native boolean gdiFree();

    protected VideoFormat defaultFormat;
    
    public GDIRenderer() {
	super("Windows GDI Renderer");

	if (available) {
	    if (gdiInitialize()) {
		Class arrayType;

		if (defbitsPerPixel <= 8)
		    arrayType = Format.byteArray;
		else if (defbitsPerPixel <= 16)
		    arrayType = Format.shortArray;
		else if (defbitsPerPixel <= 24)
		    arrayType = Format.byteArray;
		else
		    arrayType = Format.intArray;

		defaultFormat = new RGBFormat(null, Format.NOT_SPECIFIED,
					      arrayType,
					      Format.NOT_SPECIFIED, // frame rate
					      defbitsPerPixel,
					      defrMask, defgMask, defbMask,
					      (defbitsPerPixel == 24)? 3:1,
					      Format.NOT_SPECIFIED,
					      Format.NOT_SPECIFIED,
					      Format.NOT_SPECIFIED);

		supportedFormats = new VideoFormat[8];
		supportedFormats[0] = defaultFormat;

		// The remaining are general formats supported by GDI
		// 15 bit
		supportedFormats[1] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.shortArray,
						    Format.NOT_SPECIFIED, // frame rate
						    16,
						    0x7C00, 0x03E0, 0x001F,
						    1,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED);
		// 15 bit
		supportedFormats[2] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.byteArray,
						    Format.NOT_SPECIFIED, // frame rate
						    16,
						    0x7C00, 0x03E0, 0x001F,
						    2,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    RGBFormat.LITTLE_ENDIAN);
		// 16 bit
		supportedFormats[3] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.shortArray,
						    Format.NOT_SPECIFIED, // frame rate
						    16,
						    0xF800, 0x07E0, 0x001F,
						    1,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED);
		// 16 bit
		supportedFormats[4] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.byteArray,
						    Format.NOT_SPECIFIED, // frame rate
						    16,
						    0xF800, 0x07E0, 0x001F,
						    2,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    RGBFormat.LITTLE_ENDIAN);
		// 24 bit
		supportedFormats[5] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.byteArray,
						    Format.NOT_SPECIFIED, // frame rate
						    24,
						    3, 2, 1,
						    3,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED);
		// 32 bit xRGB
		supportedFormats[6] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.intArray,
						    Format.NOT_SPECIFIED, // frame rate
						    32,
						    0x00FF0000, 0x0000FF00, 0x000000FF,
						    1,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED);
		// 32 bit xRGB
		supportedFormats[7] = new RGBFormat(null,
						    Format.NOT_SPECIFIED,
						    Format.byteArray,
						    Format.NOT_SPECIFIED, // frame rate
						    32,
						    3, 2, 1,
						    4,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED,
						    Format.NOT_SPECIFIED);
	    } else {
		System.err.println("GDIRenderer. gdiInitialize() failed");
		available = false;
	    }
	}
    }

    public void open() throws ResourceUnavailableException {
	if (!available)
	    throw new ResourceUnavailableException("GDI not available !!!");
	handle = 0;
	if (blitter == 0)
	    gdiInitialize();
	if (blitter == 0)
	    throw new ResourceUnavailableException("GDIRenderer couldn't open");
    }

    public synchronized void reset() {
	handle = 0;
    }
    
    public void close() {
	if (available)
	    gdiFree();
    }

    /**
     * Set the data input format.
     * @return false if the format is not supported.
     */
    public Format setInputFormat(Format format) {
	if (!available)
	    return null;
	if (super.setInputFormat(format) != null) {
	    if (inputFormat instanceof RGBFormat) {
		RGBFormat rgbf = (RGBFormat) inputFormat;
		bitsPerPixel = rgbf.getBitsPerPixel();
		rMask = rgbf.getRedMask();
		gMask = rgbf.getGreenMask();
		bMask = rgbf.getBlueMask();
		lineStride = rgbf.getLineStride();
		pixelStride = rgbf.getPixelStride();
		flipped = (rgbf.getFlipped() == Format.TRUE);
		if (inputFormat.getDataType() == Format.byteArray && bitsPerPixel > 16) {
		    int bypp = bitsPerPixel / 8;
		    rMask = 0xFF << ((rMask - 1) * 8);
		    gMask = 0xFF << ((gMask - 1) * 8);
		    bMask = 0xFF << ((bMask - 1) * 8);
		}
	    } else if (inputFormat instanceof IndexedColorFormat) {
		bitsPerPixel = 8;
		lineStride = ((IndexedColorFormat)format).getLineStride();
	    } else
		return null;
	    
	    // Inform the native code of the input format change
	    if (outWidth == -1 || outHeight == -1) {
		outWidth = inWidth;
		outHeight = inHeight;
	    }

	    if (component != null)
		component.setSize(outWidth, outHeight);
	    // All's well
	    return format;
	} else {
	    // Unsupported format
	    return null;
	}
    }

    protected int doProcess(Buffer buffer) {
	return doProcess(buffer, false);
    }

    protected synchronized int doProcess(Buffer buffer, boolean repainting) {
	if (!available || component == null)
	    return BUFFER_PROCESSED_OK;
	if (handle == 0)
	    handle = com.sun.media.util.WindowUtil.getWindowHandle(component);
	if (handle == 0)
	    return BUFFER_PROCESSED_OK;
	if (!repainting) {
	    if (!buffer.getFormat().equals(inputFormat)) {
		if (setInputFormat(buffer.getFormat()) == null)
		    return BUFFER_PROCESSED_FAILED;
	    }
	}
	if (!repainting)
	    data = getInputData(buffer);

	int elSize = 1;
	if (data instanceof short[])
	    elSize = 2;
	else if (data instanceof int[])
	    elSize = 4;

	bytesPerPixel = bitsPerPixel / 8;

	long dataBytes = 0;
	if (data instanceof NBA) {
	    dataBytes = ((NBA)data).getNativeData();
	}

	if (data == null)
	    return BUFFER_PROCESSED_OK;
	
	if (outWidth > 0 && outHeight > 0) {
	    int returned =  (gdiDraw(data, dataBytes, elSize, bytesPerPixel,
				     inWidth, inHeight,
				     lineStride / pixelStride, outWidth, outHeight,
				     rMask, gMask, bMask, flipped, handle))?
		BUFFER_PROCESSED_OK : BUFFER_PROCESSED_FAILED;
	    return returned;
	} else
	    return BUFFER_PROCESSED_OK;
    }

    protected synchronized void repaint() {
	if (!isStarted() && data != null)
	    doProcess(null, true);
    }

    protected synchronized void setAvailable(boolean available) {
	super.setAvailable(available);
	handle = 0;
    }
}