/* * @(#)ACMCodec.java 1.18 99/07/16 */ package com.ibm.media.codec.audio; import java.util.*; import java.io.*; import javax.media.*; import javax.media.format.*; import javax.media.format.*; import com.sun.media.format.*; import com.sun.media.util.*; public class ACMCodec implements Codec, DynamicPlugIn { /** * Holds the supported input formats */ private Vector supportedInputFormats = null; /** * Holds the supported output formats */ private Vector supportedOutputFormats = null; /** * The actual input formats array to be returned */ private AudioFormat[] inputFormats = null; /** * The actual output formats array to be returned */ private AudioFormat[] outputFormats = null; /** * The input format for the codec */ private AudioFormat inputFormat = null; /** * The output format for the codec */ private AudioFormat outputFormat = null; /** * This hold the native handle for this instance's ACM codec */ private long nativeHandle; static { com.sun.media.JMFSecurityManager.loadLibrary("jmacm"); } /** * Obtain the collection of objects that * control the object that implements this interface. * <p> * * If no controls are supported, a zero length * array is returned. * * @return the collection of object controls */ public Object[] getControls() { // no controls implemented return new Control[0]; } /** * Obtain the object that implements the specified * <code>Class</code> or <code>Interface</code> * The full class or interface name must be used. * <p> * * If the control is not supported then <code>null</code> * is returned. * * @return the object that implements the control, * or <code>null</code>. */ public Object getControl(String controlType) { // no controls implemented return null; } /** * Returns a descriptive name for the plug-in. * This is a user readable string. */ public String getName() { return "ACM Wrapper Codec"; } /** * Opens the plug-in software or hardware component and acquires * necessary resources. If all the needed resources could not be * acquired, it throws a ResourceUnavailableException. Buffer should not * be passed into the plug-in without first calling this method. */ public void open() throws ResourceUnavailableException { nativeHandle = openACMStream(inputFormat, outputFormat); if (nativeHandle == 0) throw new ResourceUnavailableException("ACM stream coun't been opened"); } /** * Opens an ACM stream to be used for transcoding * * @param inputFormat the input format for this codec * @param outputFormat the ourpur format for this codec * @return the native handle of the ACM codec or 0 if codec couldn't be open */ private native long openACMStream(AudioFormat inputFormat, AudioFormat outputFormat); /** * Closes the plug-in component and releases resources. No more data * will be accepted by the plug-in after a call to this method. The * plug-in can be reinstated after being closed by calling * <code>open</code>. */ public void close() { closeACMStream(nativeHandle); } /** * Closes the ACM stream used for transcoding. * * @param nativeHandle the native handle of the ACM codec */ private native void closeACMStream(long nativeHandle); /** * Resets the state of the plug-in. Typically at end of media or when media * is repositioned. */ public void reset() { resetACMStream(nativeHandle); } /** * Resets the ACM stream. * * @param nativeHandle the native handle of the ACM codec */ private native void resetACMStream(long nativeHandle); /** * Lists the possible input formats supported by this plug-in. */ public Format[] getSupportedInputFormats() { if (inputFormats != null) return inputFormats; else { supportedInputFormats = new Vector(); fillSupportedInputFormats(); int size = supportedInputFormats.size(); inputFormats = new AudioFormat[size]; for (int index = 0; index < size; index++) { inputFormats[index] = (AudioFormat)supportedInputFormats.elementAt(index); } return inputFormats; } } /** * Fills the supportedInputFormat Vector with the ACM supported input * formats. */ private native void fillSupportedInputFormats(); /** * Lists the possible output formats of the processed data. * If <code>input</code> is non-null, then it lists the possible * output formats given that the input buffer is of the format specified * by <code>input</code>. If <code>input</code> is null, then it lists * all possible output formats that this plug-in advertises. */ public Format[] getSupportedOutputFormats(Format input) { if (input == null) { outputFormats= new AudioFormat[1]; outputFormats[0] = new AudioFormat(null); return outputFormats; } if (!(input instanceof AudioFormat)) { outputFormats = new AudioFormat[0]; return outputFormats; } else { /* fillSuppotedFormats(input) is called since each call to getSupportedOutputFoprmats(input) can have a different parameter and we wouldn't like to hold all supported formats for all input possibilites ahead (will be a huge overhead */ supportedOutputFormats = new Vector(); fillSupportedOutputFormats((AudioFormat)input); int size = supportedOutputFormats.size(); outputFormats = new AudioFormat[size]; for (int index = 0; index < size; index++) outputFormats[index] = (AudioFormat)supportedOutputFormats.elementAt(index); return outputFormats; } } /** * Fills the supportedOutputFormat Vector with the ACM supported output * formats. */ private native void fillSupportedOutputFormats(AudioFormat input); /** * Set the buffer input format. * * @return false if the format is not supported. */ public Format setInputFormat(Format format) { if (!(format instanceof AudioFormat)) { return null; } inputFormat = (AudioFormat)format; return format; } /** * Set the buffer output format. * * @return false if the format is not supported. */ public Format setOutputFormat(Format format) { if (!(format instanceof AudioFormat)) return null; outputFormat = (AudioFormat)format; return format; } /** * Process the media * * @return BUFFER_PROCESSED_OK if the processing is successful. Other * possible return codes are defined in PlugIn. * @see PlugIn */ public int process(Buffer input, Buffer output) { // shouldn't it be done in the module ? if (input.isEOM()) { output.setLength(0) ; output.setEOM(true); return BUFFER_PROCESSED_OK; } int oldInputOffset = input.getOffset(); // preper destination data int destLength = getDestinationBufferSize(nativeHandle, input.getLength()); if (output.getData() == null || destLength > ((byte[])output.getData()).length) { byte[] destination = new byte[destLength]; output.setData(destination); } output.setLength(destLength); output.setOffset(0); output.setFormat(outputFormat); if (!ACMProcess(nativeHandle, (byte[])input.getData(), input.getOffset(), input.getLength(), input, (byte[])output.getData(), output.getLength(), output)) return BUFFER_PROCESSED_FAILED; if (oldInputOffset != input.getOffset()) return BUFFER_PROCESSED_OK | INPUT_BUFFER_NOT_CONSUMED; else return BUFFER_PROCESSED_OK; } /** * Gets the estimated size of the destination data. * * @param nativeHandle the native handle of the ACM codec * @param inputSize the size of the input data * * @return the size of the destination data */ private native int getDestinationBufferSize(long nativeHandle, int input); /** * Does the ACM codec processing * * @param nativeHandle the native handle of the ACM codec * @param input the input data * @param inputLength the length of the input data * @param inputBuffer the input Buffer object, passed for offset update * @param output the output data * @param outputLength the length of the output data * @param outputBuffer the output Buffer object, passed for length update * * @return false if an error has occur */ private native boolean ACMProcess(long nativeHandle, byte[] input, int inputOffset, int inputLength, Buffer inputBuffer, byte[] output, int outputLength, Buffer outputBuffer); /** * An array of format objects that cover the generic input formats * that this plugin supports. For example, a VideoRenderer may not * know the exact RGBFormat it supports, so it returns a dummy RGBFormat * with mostly unspecified values. */ public Format[] getBaseInputFormats() { Format[] formats = new Format[1]; formats[0] = new AudioFormat(null); return formats; } /** * An array of format objects that cover the generic output formats * that this plugin supports. For example, a Codec may not * know the exact output RGBFormat it supports, so it returns a dummy * RGBFormat with mostly unspecified values. */ public Format[] getBaseOutputFormats() { return getBaseInputFormats(); } }