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

DDRenderer.java

/*
 * @(#)DDRenderer.java	1.31 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 DDRenderer extends BasicVideoRenderer
implements com.sun.media.util.DynamicPlugIn {

    private static boolean available = false;
    private static Integer processLock = new Integer(1);
    static {
	try {
	    JMFSecurityManager.loadLibrary("jmddraw");
	    available = true;
	} catch (Exception e) {
	} catch (UnsatisfiedLinkError ule) {
	}
    }

    private    int        blitter     = 0;
    private static boolean yuyvInUse  = true;
    private    boolean    yuyvInUseByMe = false;
    protected  Object     data        = null;
    //private    int        blitterAvailable = 0;
    private    int        defbitsPerPixel;
    private    int        defrMask;
    private    int        defgMask;
    private    int        defbMask;
    private    int        offX = 0;
    private    int        offY = 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    upsideDown;

    private    int        offsetY;
    private    int        offsetU;
    private    int        offsetV;
    
    private synchronized native boolean dxInitialize();
    private synchronized native boolean dxSetComponent(int windowHandle);
    private synchronized native boolean dxSetInputFormat(int width, int height,
							 int strideX, int bpp,
							 int rm, int gm, int bm, boolean flipped);
    private synchronized native boolean dxSetFourCCInputFormat(int width,
							       int height,
							       int yuvType);
    private synchronized native boolean dxSetOutputSize(int width, int height);
    private synchronized native boolean dxDraw(Object array, long bytes,
					       int width, int height);
    private synchronized native boolean dxFree();

    protected VideoFormat defaultFormat;
    private int fccSupported = 0;
    private final int YUYV = YUVFormat.YUV_YUYV;
    private final int P420 = YUVFormat.YUV_420;
    private final int P422 = YUVFormat.YUV_422;

    public DDRenderer() {
	super("DirectDraw Renderer");

	if (available) {
	    if (dxInitialize()) {
		Class arrayType;
		int nFormats = 1;
		
		if (defbitsPerPixel <= 8)
		    arrayType = Format.byteArray;
		else if (defbitsPerPixel <= 16)
		    arrayType = Format.shortArray;
		else if (defbitsPerPixel <= 24)
		    arrayType = Format.byteArray;
		else
		    arrayType = Format.intArray;

		if (defbitsPerPixel == 24) {
		    defrMask = 3; defgMask = 2; defbMask = 1;
		}

		
		if (yuyvInUse)
		    fccSupported = 0;
		if ((fccSupported & (YUYV)) != 0)
		    nFormats+=2;

		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[nFormats];
		supportedFormats[0] = defaultFormat;

		if ((fccSupported & (YUYV)) != 0) {
		    supportedFormats[1] = new YUVFormat(YUVFormat.YUV_422);
		    supportedFormats[2] = new YUVFormat(YUVFormat.YUV_420);
		}

	    } else {
		available = false;
	    }
	}
    }

    public synchronized void open() throws ResourceUnavailableException {
	if (!available)
	    throw new ResourceUnavailableException("DirectDraw not available");
	if (inputFormat instanceof YUVFormat) {
	    yuyvInUse = true;
	    yuyvInUseByMe = true;
	}
    }

    public void reset() {
    }
    
    public synchronized void close() {
	if (available) {
	    dxFree();
	    if (yuyvInUseByMe) {
		yuyvInUseByMe = false;
		yuyvInUse = false;
	    }
	}
    }

    /**
     * Set the data input format.
     * @return false if the format is not supported.
     */
    public synchronized 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();
		if (bitsPerPixel == 24)
		    lineStride /= 3;
		pixelStride = rgbf.getPixelStride();
		if (rgbf.getFlipped() == Format.TRUE)
		    upsideDown = true;
		else
		    upsideDown = false;
		// Inform the native code of the input format change
		if (!dxSetInputFormat(inWidth, inHeight, lineStride,
				      bitsPerPixel, rMask, gMask, bMask, upsideDown))
		    return null;
	    } else if (inputFormat instanceof IndexedColorFormat) {
		lineStride = ((IndexedColorFormat)format).getLineStride();
	    } else if (inputFormat instanceof YUVFormat) {
		if ((fccSupported  & (YUYV)) == 0)
		    return null;
		YUVFormat yuv = (YUVFormat) inputFormat;
		int yuvType = yuv.getYuvType();
		if (yuvType != YUVFormat.YUV_420 &&
		    yuvType != YUVFormat.YUV_422)
		    return null;
		lineStride = yuv.getStrideY();
		pixelStride = 1;
		offsetY = yuv.getOffsetY();
		offsetU = yuv.getOffsetU();
		offsetV = yuv.getOffsetV();
		
		if (!dxSetFourCCInputFormat(inWidth, inHeight, yuvType))
		    return null;
	    } else
		return null;
	    
	    if (outWidth == -1 || outHeight == -1) {
		outWidth = inWidth;
		outHeight = inHeight;
	    }
	    // Determine the bytesPerPixel of the data data
	    Class dataType =  inputFormat.getDataType();
	    if (dataType == Format.intArray)
		bytesPerPixel = 4;
	    else if (dataType == Format.shortArray)
		bytesPerPixel = 2;
	    else if (dataType == Format.byteArray)
		bytesPerPixel = 1;

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

    protected synchronized void removingComponent() {
	if (blitter != 0)
	    dxFree();
    }

    protected synchronized int doProcess(Buffer buffer) {
	if (!available || component == null)
	    return BUFFER_PROCESSED_OK;
	synchronized (this) {
	    if (!componentAvailable)
		return BUFFER_PROCESSED_OK;
	    
	    if (blitter == 0) {
		int handle = com.sun.media.util.WindowUtil.getWindowHandle(component);
		if (handle != 0) {
		    dxSetComponent(handle);
		    inputFormat = new VideoFormat(null);
		}
		if (blitter == 0) {
		    System.err.println("Could not create blitter");
		    return BUFFER_PROCESSED_FAILED;
		}
	    }
	    
	    if (!buffer.getFormat().equals(inputFormat)) {
		if (setInputFormat(buffer.getFormat()) == null)
		    return BUFFER_PROCESSED_FAILED;
	    }

	    synchronized (processLock) {
		long dataBytes = 0;
		data = getInputData(buffer);
		if (data instanceof NBA) {
		    dataBytes = ((NBA)data).getNativeData();
		}

		if (data == null)
		    return BUFFER_PROCESSED_OK;
		
		if (outWidth > 0 && outHeight > 0)
		    return (dxDraw(data, dataBytes, outWidth, outHeight))?
			BUFFER_PROCESSED_OK : BUFFER_PROCESSED_FAILED;
		else
		    return BUFFER_PROCESSED_FAILED;
	    }
	}
    }

    protected synchronized void repaint() {
	if (!isStarted() && data != null && blitter != 0)
	    if (outWidth > 0 && outHeight > 0) {
		long dataBytes = 0;
		if (data instanceof NBA) {
		    dataBytes = ((NBA)data).getNativeData();
		}
		
		dxDraw(data, dataBytes, outWidth, outHeight);
	    }
    }

    /****************************************************************
     * DynamicPlugIn methods
     ****************************************************************/
    
    public Format [] getBaseInputFormats() {
	Format [] formats = new Format[2];
	formats[0] = new RGBFormat();
	formats[1] = new YUVFormat();
	return formats;
    }

    public Format [] getBaseOutputFormats() {
	Format [] formats = new Format[0];
	return formats;
    }

    /****************************************************************
     * Local Methods
     ****************************************************************/

    protected Color getPreferredBackground() {
	return new Color(255, 0, 255);
    }
}