FileDocCategorySizeDatePackage
NativeDecoder.javaAPI DocJMF 2.1.1e14047Mon May 12 12:21:20 BST 2003com.sun.media.codec.video.vcm

NativeDecoder

public final class NativeDecoder extends BasicCodec implements DynamicPlugIn

Fields Summary
private static boolean
loaded
static Integer
processLock
protected VideoFormat
inputFormat
protected VideoFormat
outputFormat
private static String[]
supportedEncodings
private int
vcmHandle
private boolean
debug
private BitMapInfo
biIn
private BitMapInfo
biOut
private boolean
dropFrame
private boolean
keepOutputRef
private NBA
outputRef
private Control[]
controls
private DC
dc
Constructors Summary
public NativeDecoder()


      
	// Workaround for Netscape bug, where if the 
	// Class.forName fails the first time, because
	// says native libraries couldn't be loaded,
	// it succeeds the second time and
	// throws an error later.
	if (!loaded) {
	    throw new UnsatisfiedLinkError("Cannot load native libraries");
	}
	inputFormats = new VideoFormat[1];
	inputFormats[0] = new VideoFormat(null);

	outputFormats = new VideoFormat[1];
	outputFormats[0] = new RGBFormat();
    
Methods Summary
public voidclose()

	if (vcmHandle != 0)
	    VCM.icClose(vcmHandle);
	vcmHandle = 0;
	super.close();
    
voiddropNextFrame(boolean on)

	dropFrame = on;
    
public javax.media.Format[]getBaseInputFormats()

	Format [] formats = new Format[1];

	formats[0] = new VideoFormat(null);
	return formats;
    
public javax.media.Format[]getBaseOutputFormats()

	Format [] formats = new Format[1];
	formats[0] = new RGBFormat();
	return formats;
    
public java.lang.Object[]getControls()


        
	if (dc == null) {
	    dc = new DC();
	    controls = new Control[1];
	    controls[0] = dc;
	}

	return controls;
    
protected javax.media.FormatgetInputFormat()

	return inputFormat;
    
public java.lang.StringgetName()

	return "VCM Decoder";
    
protected javax.media.FormatgetOutputFormat()

	return outputFormat;
    
public javax.media.Format[]getSupportedInputFormats()

	if (supportedEncodings == null) {
	    querySupportedEncodings();
	}
	inputFormats = new VideoFormat[supportedEncodings.length];
	for (int i = 0; i < supportedEncodings.length; i++) {
	    inputFormats[i] = new VideoFormat(supportedEncodings[i]);
	}

	return inputFormats;
    
public javax.media.Format[]getSupportedOutputFormats(javax.media.Format in)

	if (in == null)
	    return outputFormats;
	
	if (matches(in, inputFormats) == null)
	    return new Format[0];

	VideoFormat video = (VideoFormat) in;
	Dimension size = video.getSize();
	if (size == null)
	    size = new Dimension(320, 240);
	RGBFormat [] tryFormats = new RGBFormat[] {
	    new RGBFormat(size, size.width * size.height * 3,
			  Format.byteArray,
			  video.getFrameRate(), // frame rate
			  24,
			  3, 2, 1,
			  3,
			  size.width * 3,
			  Format.TRUE,
			  Format.NOT_SPECIFIED), // endian

	    new RGBFormat(size, size.width * size.height * 3,
			  Format.byteArray,
			  video.getFrameRate(), // frame rate
			  24,
			  3, 2, 1,
			  3,
			  size.width * 3,
			  Format.FALSE, // flipped
			  Format.NOT_SPECIFIED), // endian

	    new RGBFormat(size, size.width * size.height,
			  Format.shortArray,
			  video.getFrameRate(), // frame rate
			  16,
			  0x07C00, 0x003e0, 0x0001F,
			  1, size.width,
			  Format.FALSE, // flipped
			  Format.NOT_SPECIFIED), // endian

	    new RGBFormat(size, size.width * size.height,
			  Format.shortArray,
			  video.getFrameRate(), // frame rate
			  16,
			  0x07C00, 0x003e0, 0x0001F,
			  1, size.width,
			  Format.TRUE,
			  Format.NOT_SPECIFIED) // endian


	};
	if (debug) System.err.println("Input format = " +
				      new BitMapInfo((VideoFormat)video));
	Vector supportedOuts = new Vector();
	int handle = VCM.icLocate("vidc", "RGB",
				  new BitMapInfo((VideoFormat) video),
				  null,
				  VCM.ICMODE_DECOMPRESS);
	if (handle != 0) {
	    for (int enum = 0; enum < tryFormats.length; enum++) {
		if ( VCM.icDecompressBegin(handle,
					   new BitMapInfo((VideoFormat) video),
					   new BitMapInfo(tryFormats[enum])) ) {
		    supportedOuts.addElement(tryFormats[enum]);
		    if (debug) System.err.println("VCM " + video.getEncoding() + " supports " + tryFormats[enum]);
		    VCM.icDecompressEnd(handle);
		} else {
		}
	    }
	    VCM.icClose(handle);
	}

	Format [] outs = new Format[supportedOuts.size()];
	for (int i = 0; i < outs.length; i++) {
	    outs[i] = (Format) supportedOuts.elementAt(i);
	}
	
	//if (debug) System.err.println("VCM.getSupportedOutputFormats: " + rgb);

	return outs;
    
public voidopen()


	if (inputFormat == null || outputFormat == null)
	    throw new ResourceUnavailableException("Formats not set!");

	Dimension size = inputFormat.getSize();
	//Object bi = inputFormat.getExtraData();
	Object bi = null;
	String inFourCC = inputFormat.getEncoding();

	biOut = new BitMapInfo();

	// Translate from AviVideoFormat to BitMapInfo
	if (inputFormat instanceof AviVideoFormat) {
	    bi = new BitMapInfo(inputFormat);
	    if (debug) System.err.println("VCM.open, BMI = " + bi);
	}


	if (bi != null && bi instanceof BitMapInfo) {
	    biIn = (BitMapInfo) bi;
	} else
	    biIn = new BitMapInfo(inFourCC, size.width, size.height);

	String cramHack = inFourCC;
	if (cramHack.equalsIgnoreCase("cram"))
	    cramHack = "msvc";

	vcmHandle = VCM.icLocate("vidc", "RGB",
				 biIn, null,
				 VCM.ICMODE_DECOMPRESS);

	if (debug) System.err.println("open.vcmHandle for " + inFourCC + " = " + vcmHandle);
	
	if (vcmHandle == 0)
	    throw new ResourceUnavailableException("Could not open VCM driver");

	BitMapInfo testOut = new BitMapInfo();
	//VCM.icDecompressGetFormat(vcmHandle, biIn, testOut);

	if (debug) System.err.println("open.preferred out = " + testOut);
	// biOut = testOut;

	
	// new trial
	biOut = new BitMapInfo(outputFormat);
	if (debug) System.err.println("open.requested out = " + biOut);
	
	boolean tryFlip = true;
	boolean result;
	
	result = VCM.icDecompressBegin(vcmHandle, biIn, biOut);

	if (result == false) {
	    if (debug) System.err.println("VCM.open : Could not set i/o format");
	    close();
	    throw new ResourceUnavailableException("Formats not supported");
	}
	if (debug) System.err.println("VCM.open success!");
	super.open();
    
public intprocess(javax.media.Buffer inBuffer, javax.media.Buffer outBuffer)

	if (isEOM(inBuffer)) {
	    propagateEOM(outBuffer);
	    return BUFFER_PROCESSED_OK;
	}

	Format outf = outBuffer.getFormat();
	outBuffer.setFormat(outputFormat);
	Object outBuf = validateData(outBuffer, 0, true);
	int bufType = 1;

	if (outputFormat.getDataType() == Format.shortArray) {
	    bufType = 2;
	}

	Object inBuf = getInputData(inBuffer);
	long flags = 0;
	int size = inBuffer.getLength();
	if (size < 2)
	    return BUFFER_PROCESSED_FAILED;
	Object header = inBuffer.getHeader();
	if (header != null && header instanceof Integer) {
	    flags = ((Integer)header).intValue();
	}

	if (dropFrame)
	    flags |= 0x20000000L;

	biIn.biSizeImage = size;
	// biOut.biHeight = -outputFormat.getSize().height;
	int result;
	synchronized (processLock) {
	    long outBytes = getNativeData(outBuf);
	    long inBytes = getNativeData(inBuf);
	    if (!keepOutputRef) {
		result = VCM.icDecompress(vcmHandle, flags,
					  biIn, inBuf, inBytes, biOut, outBuf, outBytes,
					  bufType);
	    } else {
		if (outputRef == null)
		    outputRef = new NBA(byte[].class, outputFormat.getMaxDataLength());
		result = VCM.icDecompress(vcmHandle, flags, biIn, inBuf, inBytes,
					  biOut, null,
					  outputRef.getNativeData(), bufType);
		if (outBytes != 0) {
		    outputRef.copyTo((NBA)outBuf);
		} else {
		    outputRef.copyTo((byte[])outBuf);
		}
	    }
	}
	if (dropFrame)
	    outBuffer.setDiscard(true);
	else
	    outBuffer.setLength(outputFormat.getMaxDataLength());

	if (result < 0)
	    return BUFFER_PROCESSED_FAILED;
	else
	    return BUFFER_PROCESSED_OK;
    
private static synchronized voidquerySupportedEncodings()

	ICInfo icinfo = new ICInfo();
	BitMapInfo biOut = new BitMapInfo();
	int i = 0;
	Vector listEncoding = new Vector();
	
	while (true) {
	    icinfo = new ICInfo();
	    boolean result = VCM.icInfoEnum("vidc", i, icinfo);
	    if (!result || i > 30)
		break;
	    else {
		if (!(icinfo.fccHandler == null ||
		      icinfo.fccHandler.equalsIgnoreCase(VideoFormat.MJPG) ||
		      icinfo.fccHandler.equalsIgnoreCase(VideoFormat.CINEPAK)
		      )) {
		    int handle = VCM.icOpen("vidc", icinfo.fccHandler, VCM.ICMODE_DECOMPRESS);
		    if (handle != 0) {
			if (icinfo.fccHandler.equalsIgnoreCase("ir41")) // hack
			    icinfo.fccHandler = "IV41";
			if (icinfo.fccHandler.equalsIgnoreCase("ir50")) // hack
			    icinfo.fccHandler = "IV50";
			if (icinfo.fccHandler.equalsIgnoreCase("ir32")) // hack
			    icinfo.fccHandler = "IV32";
			listEncoding.addElement(icinfo.fccHandler.toUpperCase());
			VCM.icClose(handle);
		    }
		}
	    }
	    i++;
	}
	listEncoding.addElement("YVU9");
	supportedEncodings = new String[listEncoding.size()];
	for (i = 0; i < supportedEncodings.length; i++) {
	    supportedEncodings[i] = (String) listEncoding.elementAt(i);
	}
    
public voidreset()

	if (vcmHandle != 0) {
	    VCM.icDecompressEnd(vcmHandle);
	    VCM.icDecompressBegin(vcmHandle, biIn, biOut);
	}
    
public javax.media.FormatsetInputFormat(javax.media.Format in)

	if (supportedEncodings == null) {
	    querySupportedEncodings();
	}
	String encoding = in.getEncoding();
	if (  encoding.equalsIgnoreCase(VideoFormat.CINEPAK) ||
	      encoding.equalsIgnoreCase(VideoFormat.MJPG) ||
	      encoding.equalsIgnoreCase("RGB")                  )
	    return null;

	if ( encoding.equalsIgnoreCase("mpg4") ||
	     encoding.equalsIgnoreCase("mp42") ||
	     encoding.equalsIgnoreCase("mp43") ||
	     encoding.equalsIgnoreCase("iv32")  )
	    keepOutputRef = true;
	else
	    keepOutputRef = false;
	
	if (in instanceof VideoFormat) {
	    if (matches(in, inputFormats) != null) {
		inputFormat = (VideoFormat) in;

		if (opened) {
		    try {
			close();
			Format [] ofs =
			    getSupportedOutputFormats(inputFormat);
			if (ofs.length < 1)
			    return null;
			else if (ofs.length == 1)
			    outputFormat = (RGBFormat) ofs[0];
			else {
			    for (int i = 0; i < ofs.length; i++) {
				if (((RGBFormat)outputFormat).getBitsPerPixel() ==
				    ((RGBFormat)ofs[i]).getBitsPerPixel() &&
				    ((RGBFormat)outputFormat).getFlipped() ==
				    ((RGBFormat)ofs[i]).getFlipped()) {
				    outputFormat = (VideoFormat) ofs[i];
				    break;
				}
			    }
			}
			open();
		    } catch (Exception e) {
			return null;
		    }
		}
		return in;
	    }
	}

	return null;
    
public javax.media.FormatsetOutputFormat(javax.media.Format out)

	if (out instanceof RGBFormat) {
	    outputFormat = (RGBFormat) out;
	    if (debug) System.err.println("VCM.setOutputFormat : "  + outputFormat);
	    return out;
	}
	
	return null;