/* * @(#)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); } }