FileDocCategorySizeDatePackage
NativeEncoder.javaAPI DocJMF 2.1.1e12397Mon May 12 12:21:26 BST 2003com.sun.media.codec.video.cinepakpro

NativeEncoder

public class NativeEncoder extends BasicCodec

Fields Summary
private RGBFormat
inputFormat
private VideoFormat
outputFormat
private static boolean
loaded
private static boolean
canLoad
private int
peer
private boolean
newframe
private int
current_offset
int
returnVal
private boolean
bCcontextAllocated
private Control[]
controls
private DC
dc
Constructors Summary
public NativeEncoder()


	
     //****************************************************************
     //* Codec Methods
     //****************************************************************/

    // Initialize default formats.
     
 

	inputFormats = new RGBFormat[1];
	inputFormats[0] = new RGBFormat(
				null,			// any size
				Format.NOT_SPECIFIED,	// maxDataLen
				Format.intArray,
				Format.NOT_SPECIFIED,	// any frame rate.
				32,
				0x00FF0000,
				0x0000FF00,
				0x000000FF);

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

	if (peer != 0)
	    freeCinepakEncoder(peer);
	peer = 0;
    
private final javax.media.format.VideoFormatcomputeOutputFormat(javax.media.Format in)

	// Calculate the properties
	RGBFormat rgb = (RGBFormat) in;
	Dimension size = rgb.getSize();
	int maxDataLength = size.width * size.height * 3;
	VideoFormat cinepak = new VideoFormat(
								VideoFormat.CINEPAK,
					   			size, 
								maxDataLength,
					   			Format.byteArray,
								rgb.getFrameRate() );
		
	return cinepak;
private native intencodeCinepakFrame(int instance, int[] inData, int dataStart, byte[] outData)

public voidfinalize()

	close();
    
private native intfreeCinepakEncoder(int instance)

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 "CinepakPro Encoder by CTi";
    
protected javax.media.FormatgetOutputFormat()

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

		if (in == null)
		    return outputFormats;
	
		// Make sure the input is RGB video format
		if (!verifyInputFormat(in))
		    return new Format[0];
	
		Format out [] = new Format[ 1 ];
		out[0] = computeOutputFormat(in);
			
		return out;
    
private native intinitCinepakEncoder(int width_pixels, int height_pixels, int rowPitch_bytes, int colorDepth_bpp, int dibType, int dataRate_kBps, double frameDuration_ms, int forceKeyFrameEvery_f, boolean doFractionInterCodeBook, boolean doLogRequested, boolean doBlackAndWhite, double initKIRatio, boolean doUseAdaptiveKIRatio, int NatKeyThreshold, int SpatialTemporalHint)

public voidopen()

		if (!canLoad)
	    	throw new ResourceUnavailableException("Unable to load" +
						   " native CinepakPro converter");

		if (!loaded) 
		{
	    	try 
			{
				//JMFSecurityManager.loadLibrary( "CvidPro" );
				JMFSecurityManager.loadLibrary("jmutil");
				JMFSecurityManager.loadLibrary("jmfCVIDPro");
				loaded = true;
	    	} 
			catch (Throwable t) 
			{
				canLoad = false;
				throw new ResourceUnavailableException("Unable to load " +
								       "native cinepak encoder");
	    	}
		}

		if (inputFormat == null || outputFormat == null)
		    throw new ResourceUnavailableException("Formats not set " +
							   "on the cinepak encoder");
	
		if (peer != 0)
		    close();

		Dimension size = inputFormat.getSize();
				
		try 
		{
	    	peer = initCinepakEncoder(
							// source image info
						size.width, 
						size.height, 
						inputFormat.getLineStride(),
						inputFormat.getBitsPerPixel(),		// should be 24
						9,									// BGR888 packed 24 bpp 
															// TODO:  make smarter based on pixel stride, etc.
							// data rate params
						300000,								// 300 KB/s
						1000.0/inputFormat.getFrameRate(),	// 15 fps
						30,									// keyframes every 2s
						
							//job flags - don't recommend turning any other than B&W on
						false,								// fraction intercodebooks
						false,								// logging
						false,								// black and white
						
							// user knobs
						2.1,								// K/I ratio
						false,								// adapt K/I
						3500,								// nat key insertion threshold
						13									// ratio of smooths to skips is 13/8 or about 8:5
							);	
		} 
		catch (Throwable t) 
		{
		}
	
		if (peer == 0)
		{
		    throw new ResourceUnavailableException("Unable to initialize cinepak encoder");
		}
    
public synchronized intprocess(javax.media.Buffer inBuffer, javax.media.Buffer outBuffer)

		Object header = null;
		
		if (isEOM(inBuffer)) 
		{
		    propagateEOM(outBuffer);
		    return BUFFER_PROCESSED_OK;
		}
			
		Format inFormat = inBuffer.getFormat();
		Format outFormat = outBuffer.getFormat();
		int [] inData = (int[]) inBuffer.getData();
		boolean flipped = ((RGBFormat) inFormat).getFlipped() == Format.TRUE;
	
		if (outputFormat.getEncoding().equals(VideoFormat.CINEPAK))
		{
		    byte [] outData = (byte[]) outBuffer.getData();
		    if (	outData == null 
				||	(outData.length < outputFormat.getMaxDataLength()) 
				)
			{
//				int	iMaxDataSize = 50000;		// make it 500k to be safe
			
				outData = new byte[outputFormat.getMaxDataLength()];
//				outData = new byte[ iMaxDataSize ];
				
				outBuffer.setData(outData);
		    }
		    
		    if (outFormat == null)
			{
				outBuffer.setFormat(outputFormat);
			}
		    
		    if (peer == 0) 
			{
				try
				{
			    	open();
				} 
				catch (ResourceUnavailableException re) 
				{
			    	return BUFFER_PROCESSED_FAILED;
				}
		    }
		    
		    Dimension size = inputFormat.getSize();
		    returnVal = encodeCinepakFrame(
							peer,
				   			inData,
							0,
						   	outData );
				   
		    if (returnVal > 0)
			{
				outBuffer.setLength(returnVal);
				outBuffer.setOffset(0);
				inBuffer.setLength(0);
				outBuffer.setTimeStamp(inBuffer.getTimeStamp());

				if ( wasKeyFrame( peer ) ) {
				    outBuffer.setFlags( Buffer.FLAG_KEY_FRAME );
				} else {
				    outBuffer.setFlags( outBuffer.getFlags() &
							~Buffer.FLAG_KEY_FRAME);
				}

				return BUFFER_PROCESSED_OK;
			}
			
		    outBuffer.setDiscard(true);
		    return BUFFER_PROCESSED_FAILED;
		}// if outputformat is CINEPAK
	
		return BUFFER_PROCESSED_FAILED;	
	
public voidreset()

	// Anything to do?
    
public javax.media.FormatsetInputFormat(javax.media.Format input)

	if (!verifyInputFormat(input))
	    return null;
		
	inputFormat = (RGBFormat) input;
	
	return inputFormat;
public javax.media.FormatsetOutputFormat(javax.media.Format output)

	if (matches(output, outputFormats) == null)
	{
	    return null;
	}
	outputFormat = (VideoFormat) output;
	
	return outputFormat;
private booleanverifyInputFormat(javax.media.Format input)

	if (!(input instanceof RGBFormat))
	{
	    return false;
	}
			
	RGBFormat rgb = (RGBFormat) input;
	if ( //rgb.getDataType() != Format.intArray ||
	     rgb.getBitsPerPixel() != 32 ||
	     rgb.getRedMask() != 0x00FF0000 ||
	     rgb.getGreenMask() != 0x0000FF00 ||
	     rgb.getBlueMask() != 0x000000FF ||
	     rgb.getSize() == null ||
	     rgb.getLineStride() < rgb.getSize().width ||
	     rgb.getPixelStride() != 1 )
	{
	    return false;
	}

	return true;
private native booleanwasKeyFrame(int instance)