FileDocCategorySizeDatePackage
ACMCodec.javaAPI DocJMF 2.1.1e9515Mon May 12 12:21:22 BST 2003com.ibm.media.codec.audio

ACMCodec.java

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