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

NativeEncoder

public final class NativeEncoder extends BasicCodec

Fields Summary
protected RGBFormat
inputFormat
protected VideoFormat
outputFormat
private static String[]
supportedEncodings
private static BitMapInfo[]
supportedOutBMIs
private int
vcmHandle
private boolean
debug
private BitMapInfo
biIn
private BitMapInfo
biOut
private BitMapInfo
biPrev
private boolean
dropFrame
private boolean
hasQuality
private boolean
hasCrunch
private boolean
hasTemporal
private boolean
hasFastCompress
private boolean
begun
private QualityControl
qc
private Control[]
controls
private float
quality
static final int
AVIF_KEYFRAME
int
seqNo
int
keyFrameInterval
int[]
outFlags
int[]
ckid
byte[]
dataPrev
Constructors Summary
public NativeEncoder()

    
    
      
	inputFormats = new VideoFormat[1];
	inputFormats[0] = new RGBFormat();

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

	if (vcmHandle != 0) {
	    if (begun)
		VCM.icCompressEnd(vcmHandle);
	    VCM.icClose(vcmHandle);
	    begun = false;
	}
	vcmHandle = 0;
    
public java.lang.Object[]getControls()

	//System.err.println("NativeEncoder.getControls$$$$$$$");
	if (controls == null) {
	    //System.err.println("Has quality = " + hasQuality);
	    if (qc == null) {
		qc = new QualityAdapter(quality, 0f, 10000f, true) {
		    public float setQuality(float newValue) {
			quality = newValue;
			return super.setQuality(newValue);
		    }
		    
		    protected String getName() {
			return "Video Encoder Quality";
		    }
		};
		controls = new Control[1];
		controls[0] = qc;
	    } else {
		controls = new Control[0];
	    }
	}
	//System.err.println(controls);
	return controls;
    
protected javax.media.FormatgetInputFormat()

	return inputFormat;
    
public java.lang.StringgetName()

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

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

	inputFormats[0] = new RGBFormat(null,
					Format.NOT_SPECIFIED,
					Format.byteArray,
					Format.NOT_SPECIFIED, // frame rate
					24,
					3, 2, 1,
					3,
					Format.NOT_SPECIFIED,
					Format.TRUE,
					Format.NOT_SPECIFIED); // endian

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

	if (input == null || !(input instanceof RGBFormat))
	    return new VideoFormat[] {
	           new VideoFormat(null)
	    };
	if (input.matches(inputFormats[0])) {
	    if (supportedEncodings == null) {
		querySupportedEncodings();
	    }

	    Dimension frameSize = ((VideoFormat)input).getSize();
	    if (frameSize == null)
		frameSize = new Dimension(320, 240);
	    outputFormats = new VideoFormat[supportedEncodings.length];
	    
	    for (int i = 0; i < supportedEncodings.length; i++) {
		int area = frameSize.width * frameSize.height;
		int outSize = area * supportedOutBMIs[i].biBitCount / 8;
		if (outSize < area)
		    outSize = area;
		outputFormats[i] = new VideoFormat(supportedEncodings[i],
						   frameSize,
						   outSize,
						   Format.byteArray,
						   ((VideoFormat)input).getFrameRate());
	    }
	    return outputFormats;  
	} else
	    return new Format[0];
    
public synchronized voidopen()

	
	if (inputFormat == null || outputFormat == null)
	    throw new ResourceUnavailableException("Unknown formats");
	
	// Size restriction 4x4
	Dimension size = inputFormat.getSize();
	if (size == null || (size.width % 4) != 0 || (size.height % 4) != 0) {
	    Log.error("Class: " + this);
	    Log.error("  can only encode in sizes of multiple of 4 pixels.");
	    throw new ResourceUnavailableException("Wrong size.");
	}

	if (vcmHandle != 0)
	    close();

	biIn = new BitMapInfo(inputFormat);
	biOut = new BitMapInfo(outputFormat);

	vcmHandle = VCM.icLocate("vidc", VideoFormat.RGB,
				 biIn, biOut,
				 VCM.ICMODE_COMPRESS);
	if (vcmHandle == 0) {
	    throw new ResourceUnavailableException("Couldn't create compressor");
	}
	
	ICInfo icinfo = new ICInfo();
	VCM.icGetInfo(vcmHandle, icinfo);

	// Get properties of the compressor
	int flags = icinfo.dwFlags;
	//	System.err.println("Flags = " + flags);
	hasQuality = (flags & VCM.VIDCF_QUALITY) != 0;
	hasCrunch  = (flags & VCM.VIDCF_CRUNCH) != 0;
	hasTemporal = (flags & VCM.VIDCF_TEMPORAL) != 0;
	hasFastCompress = (flags & VCM.VIDCF_FASTC) != 0;

	begun = false;


	BitMapInfo testBMI = new BitMapInfo();
	VCM.icCompressGetFormat(vcmHandle, biIn, testBMI);
	biOut = testBMI;
	
	if (!VCM.icCompressBegin(vcmHandle, biIn, biOut)) {
	    VCM.icClose(vcmHandle);
	    throw new ResourceUnavailableException("Couldn't create compressor");
	} else {
	    begun = true;
	}
	seqNo = (seqNo + 3) & ~3;
    
public intprocess(javax.media.Buffer inBuffer, javax.media.Buffer outBuffer)

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

	int inFlags = 0;
	int outBufFlags = 0;
	
	Object outData = outBuffer.getData();

	if (outData == null || !(outData instanceof byte[]) ||
	    ((byte[])outData).length < outputFormat.getMaxDataLength())
	    outData = new byte[outputFormat.getMaxDataLength()];
	outBuffer.setData(outData);
	outBuffer.setFormat(outputFormat);

	if (dataPrev == null && hasTemporal) {
	    dataPrev = new byte[inputFormat.getMaxDataLength()];
	}

	if ((seqNo % keyFrameInterval) == 0) {
	    inFlags |= VCM.ICCOMPRESS_KEYFRAME;
	}
	
	seqNo++;
	int returnVal = VCM.icCompress(vcmHandle,
				       inFlags,
				       biOut,
				       outData,
				       biIn,
				       inBuffer.getData(),
				       ckid,
				       outFlags,
				       seqNo,
				       outputFormat.getMaxDataLength(),
				       (int) quality,
				       biIn,
				       dataPrev);

	if ((outFlags[0] & AVIF_KEYFRAME) != 0) 
	    outBufFlags |= Buffer.FLAG_KEY_FRAME;

	Object tempdata = dataPrev;
	if (hasTemporal) {
	    dataPrev = (byte[]) inBuffer.getData();
	    inBuffer.setData(tempdata);
	}
	
	if (returnVal < 0) {
	    return BUFFER_PROCESSED_FAILED;
	}
	outBuffer.setFormat(outputFormat);
	outBuffer.setSequenceNumber(seqNo);
	outBuffer.setLength(biOut.biSizeImage);
	outBufFlags = (outBuffer.getFlags() & ~Buffer.FLAG_KEY_FRAME) |
	    outBufFlags |
	    Buffer.FLAG_NO_SYNC;
	outBuffer.setFlags(outBufFlags);
	return BUFFER_PROCESSED_OK;
    
private static synchronized voidquerySupportedEncodings()


	ICInfo icinfo = new ICInfo();
	BitMapInfo biOut = new BitMapInfo();
	int i = 0;
	Vector listEncoding = new Vector();
	Vector listBMI = new Vector();
	
	while (true) {
	    boolean result = VCM.icInfoEnum("vidc", i, icinfo);
	    if (!result || i > 30)
		break;
	    else {
		int handle = VCM.icOpen("vidc", icinfo.fccHandler, VCM.ICMODE_COMPRESS);
		if (handle != 0) {
		    BitMapInfo biIn = new BitMapInfo("RGB", 320, 240);
		    biOut = new BitMapInfo("RGB", 320, 240);
		    VCM.icCompressGetFormat(handle, biIn, biOut);
		    if (biOut.fourcc.equalsIgnoreCase(icinfo.fccHandler) &&
			!(icinfo.fccHandler.equalsIgnoreCase(VideoFormat.MJPG) ||
			  icinfo.fccHandler.equalsIgnoreCase("dmb1"))) {
			listEncoding.addElement(biOut.fourcc);
			listBMI.addElement(biOut);
		    }
		    VCM.icClose(handle);
		}
	    }
	    i++;
	}

	supportedEncodings = new String[listEncoding.size()];
	supportedOutBMIs = new BitMapInfo[listEncoding.size()];
	for (i = 0; i < supportedEncodings.length; i++) {
	    supportedEncodings[i] = (String) listEncoding.elementAt(i);
	    supportedOutBMIs[i] = (BitMapInfo) listBMI.elementAt(i);
	}
    
public javax.media.FormatsetInputFormat(javax.media.Format in)

	if (in instanceof RGBFormat) {
	    if (matches(in, inputFormats) != null) {
		inputFormat = (RGBFormat) in;
		if (begun) {
		    close();
		    try {
			// Update outputsize
			Dimension frameSize = ((RGBFormat)in).getSize();
			int area = frameSize.width * frameSize.height;
			int outSize = area * 24 / 8;
			outputFormat =
			    new VideoFormat(outputFormat.getEncoding(),
					    frameSize,
					    outSize,
					    Format.byteArray,
					    inputFormat.getFrameRate());
			
			open();
		    } catch (Exception e) {
			return null;
		    }
		}
		return in;
	    } else {
		//System.err.println("VCMEncoder didn't match:\n" + in);
	    }
	}

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

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