/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 2.0.6
 *
 * Do not make changes to this file unless you know what you are doing--modify
 * the SWIG interface file instead.
 * ----------------------------------------------------------------------------- */

package io.humble.video;
import io.humble.ferry.*;
/**
 * An object that describes Containers that HumbleVideo can write MediaPacket objects

 * to.
 */
public class MuxerFormat extends ContainerFormat {
  // JNIHelper.swg: Start generated code
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>
  /**
   * This method is only here to use some references and remove
   * a Eclipse compiler warning.
   */
  @SuppressWarnings("unused")
  private void noop()
  {
    Buffer.make(null, 1);
  }

  private volatile long swigCPtr;

  /**
   * Internal Only.
   */
  protected MuxerFormat(long cPtr, boolean cMemoryOwn) {
    super(VideoJNI.MuxerFormat_SWIGUpcast(cPtr), cMemoryOwn);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.
   */
  protected MuxerFormat(long cPtr, boolean cMemoryOwn,
      java.util.concurrent.atomic.AtomicLong ref)
  {
    super(VideoJNI.MuxerFormat_SWIGUpcast(cPtr),
     cMemoryOwn, ref);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that obj is proxying for.
   *
   * @param obj The java proxy object for a native object.
   * @return The raw pointer obj is proxying for.
   */
  protected static long getCPtr(MuxerFormat obj) {
    if (obj == null) return 0;
    return obj.getMyCPtr();
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that we're proxying for.
   *
   * @return The raw pointer we're proxying for.
   */
  protected long getMyCPtr() {
    if (swigCPtr == 0) throw new IllegalStateException("underlying native object already deleted");
    return swigCPtr;
  }

  /**
   * Create a new MuxerFormat object that is actually referring to the
   * exact same underlying native object.
   *
   * @return the new Java object.
   */
  @Override
  public MuxerFormat copyReference() {
    if (swigCPtr == 0)
      return null;
    else
      return new MuxerFormat(swigCPtr, swigCMemOwn, getJavaRefCount());
  }

  /**
   * Compares two values, returning true if the underlying objects in native code are the same object.
   *
   * That means you can have two different Java objects, but when you do a comparison, you'll find out
   * they are the EXACT same object.
   *
   * @return True if the underlying native object is the same.  False otherwise.
   */
  public boolean equals(Object obj) {
    boolean equal = false;
    if (obj instanceof MuxerFormat)
      equal = (((MuxerFormat)obj).swigCPtr == this.swigCPtr);
    return equal;
  }

  /**
   * Get a hashable value for this object.
   *
   * @return the hashable value.
   */
  public int hashCode() {
     return (int)swigCPtr;
  }

  // <<<<<<<<<<<<<<<<<<<<<<<<<<<
  // JNIHelper.swg: End generated code

  @Override
  public String toString()
  {
    StringBuilder result = new StringBuilder();

    result.append(this.getClass().getName()+"@"+hashCode()+"[");
    result.append("name:"+getName()+";");
    result.append("description:"+getLongName()+";");
    result.append("mimetype:"+getMimeType()+";");
    result.append("extensions:"+getExtensions()+";");
    result.append("]");
    return result.toString();
  }

  /**
   * Return a collection of all output formats installed on this system.
   * @return the list.
   */
  public static java.util.Collection<MuxerFormat>
  getFormats()
  {
    java.util.Collection<MuxerFormat> retval =
      new java.util.HashSet<MuxerFormat>();
    int count = getNumFormats();
    for(int i = 0; i< count;++i)
    {
      MuxerFormat fmt = getFormat(i);
      if (fmt != null)
        retval.add(fmt);
    }
    return retval;
  }

/**
 * Name for format.
 */
  public String getName() {
    return VideoJNI.MuxerFormat_getName(swigCPtr, this);
  }

/**
 * Descriptive name for the format, meant to be more human-readable

 * than name.
 */
  public String getLongName() {
    return VideoJNI.MuxerFormat_getLongName(swigCPtr, this);
  }

/**
 * A comma-separated list of supported filename extensions
 */
  public String getExtensions() {
    return VideoJNI.MuxerFormat_getExtensions(swigCPtr, this);
  }

/**
 * Flags that tell you what capabilities this format supports.

 *

 * @return a bitmask of Flags
 */
  public int getFlags() {
    return VideoJNI.MuxerFormat_getFlags(swigCPtr, this);
  }

/**
 * Get the default audio codec for this format.
 */
  public Codec.ID getDefaultAudioCodecId() {
    return Codec.ID.swigToEnum(VideoJNI.MuxerFormat_getDefaultAudioCodecId(swigCPtr, this));
  }

/**
 * Get the default video codec for this format.
 */
  public Codec.ID getDefaultVideoCodecId() {
    return Codec.ID.swigToEnum(VideoJNI.MuxerFormat_getDefaultVideoCodecId(swigCPtr, this));
  }

/**
 * Get the default subtitle coded for this format.
 */
  public Codec.ID getDefaultSubtitleCodecId() {
    return Codec.ID.swigToEnum(VideoJNI.MuxerFormat_getDefaultSubtitleCodecId(swigCPtr, this));
  }

/**
 * Get the mime type for this format.
 */
  public String getMimeType() {
    return VideoJNI.MuxerFormat_getMimeType(swigCPtr, this);
  }

/**
 * Return the sink format in the list of registered sink formats

 * which best matches the provided parameters, or return NULL if

 * there is no match.

 *

 * @param shortName if non-NULL checks if short_name matches with the

 * names of the registered formats

 * @param filename if non-NULL checks if filename terminates with the

 * extensions of the registered formats

 * @param mimeType if non-NULL checks if mime_type matches with the

 * MIME type of the registered formats
 */
  public static MuxerFormat guessFormat(String shortName, String filename, String mimeType) {
    long cPtr = VideoJNI.MuxerFormat_guessFormat(shortName, filename, mimeType);
    return (cPtr == 0) ? null : new MuxerFormat(cPtr, false);
  }

  public Codec.ID guessCodec(String shortName, String filename, String mimeType, MediaDescriptor.Type type) {
    return Codec.ID.swigToEnum(VideoJNI.MuxerFormat_guessCodec(swigCPtr, this, shortName, filename, mimeType, type.swigValue()));
  }

/**
 * Get total number of different codecs this container can output.
 */
  protected int getNumSupportedCodecs() {
    return VideoJNI.MuxerFormat_getNumSupportedCodecs(swigCPtr, this);
  }

/**
 * Get the 'best' codec tag for the given codec id for this container.
 */
  public long getBestCodecTag(Codec.ID id) {
    return VideoJNI.MuxerFormat_getBestCodecTag(swigCPtr, this, id.swigValue());
  }

/**
 * Get the Codec.ID for the n'th codec supported by this container.

 *

 * @param n The n'th codec supported by this codec. Lower n are higher priority.

 *   n must be < #getNumSupportedCodecs()

 * @return the Codec.ID at the n'th slot, or Codec.ID.CODEC_ID_NONE if none.
 */
  protected Codec.ID getSupportedCodecId(int n) {
    return Codec.ID.swigToEnum(VideoJNI.MuxerFormat_getSupportedCodecId(swigCPtr, this, n));
  }

/**
 * Get the 32-bit Codec Tag for the n'th codec supported by this container.

 *

 * @param n The n'th codec supported by this codec. Lower n are higher priority.

 *   n must be < #getNumSupportedCodecs()

 * @return the codec tag at the n'th slot, or 0 if none.
 */
  protected long getSupportedCodecTag(int n) {
    return VideoJNI.MuxerFormat_getSupportedCodecTag(swigCPtr, this, n);
  }

/**
 * Get the number of input formats this install can demultiplex (read)

 * from.

 *

 * @return the number of formats
 */
  public static int getNumFormats() {
    return VideoJNI.MuxerFormat_getNumFormats();
  }

/**
 * Return an object for the input format at the given index.

 *

 * @param index an index for the input format list we maintain

 *

 * @return a format object for that input or null if

 *   unknown, index < 0 or index >= #getNumInstalledInputFormats()
 */
  public static MuxerFormat getFormat(int index) {
    long cPtr = VideoJNI.MuxerFormat_getFormat(index);
    return (cPtr == 0) ? null : new MuxerFormat(cPtr, false);
  }

}


/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 2.0.6
 *
 * Do not make changes to this file unless you know what you are doing--modify
 * the SWIG interface file instead.
 * ----------------------------------------------------------------------------- */

package io.humble.video;
import io.humble.ferry.*;
/**
 * Creates a graph (or map) of Filter objects that can modify MediaRaw

 * objects to do lots of advanced stuff like edge-detection, cropping,

 * blurring, etc.
 */
public class FilterGraph extends Configurable {
  // JNIHelper.swg: Start generated code
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>
  /**
   * This method is only here to use some references and remove
   * a Eclipse compiler warning.
   */
  @SuppressWarnings("unused")
  private void noop()
  {
    Buffer.make(null, 1);
  }

  private volatile long swigCPtr;

  /**
   * Internal Only.
   */
  protected FilterGraph(long cPtr, boolean cMemoryOwn) {
    super(VideoJNI.FilterGraph_SWIGUpcast(cPtr), cMemoryOwn);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.
   */
  protected FilterGraph(long cPtr, boolean cMemoryOwn,
      java.util.concurrent.atomic.AtomicLong ref)
  {
    super(VideoJNI.FilterGraph_SWIGUpcast(cPtr),
     cMemoryOwn, ref);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that obj is proxying for.
   *
   * @param obj The java proxy object for a native object.
   * @return The raw pointer obj is proxying for.
   */
  protected static long getCPtr(FilterGraph obj) {
    if (obj == null) return 0;
    return obj.getMyCPtr();
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that we're proxying for.
   *
   * @return The raw pointer we're proxying for.
   */
  protected long getMyCPtr() {
    if (swigCPtr == 0) throw new IllegalStateException("underlying native object already deleted");
    return swigCPtr;
  }

  /**
   * Create a new FilterGraph object that is actually referring to the
   * exact same underlying native object.
   *
   * @return the new Java object.
   */
  @Override
  public FilterGraph copyReference() {
    if (swigCPtr == 0)
      return null;
    else
      return new FilterGraph(swigCPtr, swigCMemOwn, getJavaRefCount());
  }

  /**
   * Compares two values, returning true if the underlying objects in native code are the same object.
   *
   * That means you can have two different Java objects, but when you do a comparison, you'll find out
   * they are the EXACT same object.
   *
   * @return True if the underlying native object is the same.  False otherwise.
   */
  public boolean equals(Object obj) {
    boolean equal = false;
    if (obj instanceof FilterGraph)
      equal = (((FilterGraph)obj).swigCPtr == this.swigCPtr);
    return equal;
  }

  /**
   * Get a hashable value for this object.
   *
   * @return the hashable value.
   */
  public int hashCode() {
     return (int)swigCPtr;
  }

  // <<<<<<<<<<<<<<<<<<<<<<<<<<<
  // JNIHelper.swg: End generated code

/**
 * Creates a new FilterGraph.
 */
  public static FilterGraph make() {
    long cPtr = VideoJNI.FilterGraph_make();
    return (cPtr == 0) ? null : new FilterGraph(cPtr, false);
  }

/**
 * Add a filter with the given name to the graph.

 * @return An object that refers to the new filter.
 */
  public Filter addFilter(FilterType type, String name) {
    long cPtr = VideoJNI.FilterGraph_addFilter(swigCPtr, this, FilterType.getCPtr(type), type, name);
    return (cPtr == 0) ? null : new Filter(cPtr, false);
  }

/**
 * @return the filter with the given name, or null if not found.
 */
  public Filter getFilter(String name) {
    long cPtr = VideoJNI.FilterGraph_getFilter(swigCPtr, this, name);
    return (cPtr == 0) ? null : new Filter(cPtr, false);
  }

/**
 * Add a FilterAudioSource.

 * @param name the name; must be unique in graph

 * @param timeBase timebase of frames that will be input. If null 1/sampleRate is assumed.

 * @param sampleRate the audio sample rate

 *

 * @param format the sample format

 *

 * @return The FilterSource that was added.

 * @throws RuntimeException if name is already in graph.

 * @throws InvalidArgument if any argument is invalid.
 */
  public FilterAudioSource addAudioSource(String name, int sampleRate, AudioChannel.Layout channelLayout, AudioFormat.Type format, Rational timeBase) {
    long cPtr = VideoJNI.FilterGraph_addAudioSource(swigCPtr, this, name, sampleRate, channelLayout.swigValue(), format.swigValue(), Rational.getCPtr(timeBase), timeBase);
    return (cPtr == 0) ? null : new FilterAudioSource(cPtr, false);
  }

/**
 * Add a FilterPictureSource.

 * @param name the name; must be unique in graph

 * @param width the width in pixels of MediaPicture objects that will be added to this source.

 * @param height the height in pixels  of MediaPicture objects that will be added to this source.

 * @param format the pixel format

 * @param timeBase timebase of frames that will be input. If null, 1/Global.DEFAULT_PTS_PER_SECOND is assumed.

 * @param pixelAspectRatio pixel aspect ratio. If null, 1/1 is assumed.

 *

 * @return The FilterSource that was added.

 * @throws RuntimeException if name is already in graph.

 * @throws InvalidArgument if any argument is invalid.
 */
  public FilterPictureSource addPictureSource(String name, int width, int height, PixelFormat.Type format, Rational timeBase, Rational pixelAspectRatio) {
    long cPtr = VideoJNI.FilterGraph_addPictureSource(swigCPtr, this, name, width, height, format.swigValue(), Rational.getCPtr(timeBase), timeBase, Rational.getCPtr(pixelAspectRatio), pixelAspectRatio);
    return (cPtr == 0) ? null : new FilterPictureSource(cPtr, false);
  }

/**
 * Add a FilterAudioSink.

 * @param name the name; must be unique in graph

 * @param sampleRate the audio sample rate

 *

 * @param format the sample format

 *

 * @return The FilterAudioSink that was added.

 * @throws RuntimeException if name is already in graph.

 * @throws InvalidArgument if any argument is invalid.
 */
  public FilterAudioSink addAudioSink(String name, int sampleRate, AudioChannel.Layout channelLayout, AudioFormat.Type format) {
    long cPtr = VideoJNI.FilterGraph_addAudioSink(swigCPtr, this, name, sampleRate, channelLayout.swigValue(), format.swigValue());
    return (cPtr == 0) ? null : new FilterAudioSink(cPtr, false);
  }

/**
 * Add a FilterPictureSink.

 * @param name the name; must be unique in graph

 * @param format the pixel format desired of pictures taken from this sink.

 * @return The FilterPictureSink that was added.

 * @throws RuntimeException if name is already in graph.

 * @throws InvalidArgument if any argument is invalid.
 */
  public FilterPictureSink addPictureSink(String name, PixelFormat.Type format) {
    long cPtr = VideoJNI.FilterGraph_addPictureSink(swigCPtr, this, name, format.swigValue());
    return (cPtr == 0) ? null : new FilterPictureSink(cPtr, false);
  }

/**
 * @return number of FilterSource added so far.
 */
  public int getNumSources() {
    return VideoJNI.FilterGraph_getNumSources(swigCPtr, this);
  }

/**
 * @param index The n'th of #getNumSoruces() FilterSources attached to this FilterGraph.

 * @return the FilterSource

 * @throws InvalidArgument if index < 0 || index >= #getNumSources()
 */
  public FilterSource getSource(int index) {
    long cPtr = VideoJNI.FilterGraph_getSource__SWIG_0(swigCPtr, this, index);
    return (cPtr == 0) ? null : new FilterSource(cPtr, false);
  }

/**
 * @param name unique name of a FilterSource in this FilterGraph. Should have been added with #addSource(FilterSource,String).

 * @throws PropertyNotFoundException if not in graph.
 */
  public FilterSource getSource(String name) {
    long cPtr = VideoJNI.FilterGraph_getSource__SWIG_1(swigCPtr, this, name);
    return (cPtr == 0) ? null : new FilterSource(cPtr, false);
  }

/**
 * @return number of FilterSink added so far.
 */
  public int getNumSinks() {
    return VideoJNI.FilterGraph_getNumSinks(swigCPtr, this);
  }

/**
 * @param index The n'th of #getNumSoruces() FilterSinks attached to this FilterGraph.

 * @return the FilterSink

 * @throws InvalidArgument if index < 0 || index >= #getNumSinks()
 */
  public FilterSink getSink(int index) {
    long cPtr = VideoJNI.FilterGraph_getSink__SWIG_0(swigCPtr, this, index);
    return (cPtr == 0) ? null : new FilterSink(cPtr, false);
  }

/**
 * @param name unique name of a FilterSink in this FilterGraph. Should have been added with #addSink(FilterSink,String).

 * @throws PropertyNotFoundException if not in graph.
 */
  public FilterSink getSink(String name) {
    long cPtr = VideoJNI.FilterGraph_getSink__SWIG_1(swigCPtr, this, name);
    return (cPtr == 0) ? null : new FilterSink(cPtr, false);
  }

/**
 * Should this graph auto-convert audio or pictures into the formats

 * different filters require (rather than require the user to construct

 * a graph with all filters sets correctly).

 *

 * @param value whether to auto-convert with MediaPictureResampler or MediaAudioResampler objects.
 */
  public void setAutoConvert(FilterGraph.AutoConvertFlag value) {
    VideoJNI.FilterGraph_setAutoConvert(swigCPtr, this, value.swigValue());
  }

/**
 * @return does this graph auto convert MediaPicture and MediaRaw objects to different

 * dimensions/sample-rates/channels/etc. when

 * pulling them through the graph.
 */
  public FilterGraph.AutoConvertFlag getAutoConvert() {
    return FilterGraph.AutoConvertFlag.swigToEnum(VideoJNI.FilterGraph_getAutoConvert(swigCPtr, this));
  }

/**
 * Add a graph described by a string to a graph. For any Sinks or Sources

 * the caller must have called #addSource or #addSink before

 * this call.

 *

 * @param filterDescription The filter string to be parsed, in FFmpeg libavfilter format.

 * @throws RuntimeException if any inputs or outputs are open (i.e. each filter

 *   in the graph must either point to another filter on all inputs or outputs, or point to

 *   a FilterSink or FilterSource when done).
 */
  public void open(String filterDescription) {
    VideoJNI.FilterGraph_open(swigCPtr, this, filterDescription);
  }

  public String sendCommand(String target, String command, String arguments, int flags) {
    return VideoJNI.FilterGraph_sendCommand(swigCPtr, this, target, command, arguments, flags);
  }

/**
 * Queue a command for one or more filter instances.

 *

 * @param target the filter(s) to which the command should be sent

 *               "all" sends to all filters

 *               otherwise it can be a filter or filter instance name

 *               which will send the command to all matching filters.

 * @param command    the command to sent, for handling simplicity all commands must be alphanummeric only

 * @param arguments    the argument for the command

 * @param ts     time at which the command should be sent to the filter

 *

 * Note: As this executes commands after this function returns, no return code

 *       from the filter is provided, also AVFILTER_CMD_FLAG_ONE is not supported.
 */
  public void queueCommand(String target, String command, String arguments, int flags, double ts) {
    VideoJNI.FilterGraph_queueCommand(swigCPtr, this, target, command, arguments, flags, ts);
  }

  public String getDisplayString() {
    return VideoJNI.FilterGraph_getDisplayString(swigCPtr, this);
  }

  public FilterGraph.State getState() {
    return FilterGraph.State.swigToEnum(VideoJNI.FilterGraph_getState(swigCPtr, this));
  }

  /**
   * States a graph can be in.
   */
  public enum State {
  /**
   * Initialized but not yet opened. Properties and graph strings may still be set.
   */
    STATE_INITED,
  /**
   * Opened. Properites and graphs can no longer be set, but MediaRaw objects

   * can be processed.
   */
    STATE_OPENED,
  /**
   * An error occurred and this graph should be discarded.
   */
    STATE_ERROR,
  ;

    public final int swigValue() {
      return swigValue;
    }

    public static State swigToEnum(int swigValue) {
      State[] swigValues = State.class.getEnumConstants();
      if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue)
        return swigValues[swigValue];
      for (State swigEnum : swigValues)
        if (swigEnum.swigValue == swigValue)
          return swigEnum;
      throw new IllegalArgumentException("No enum " + State.class + " with value " + swigValue);
    }

    @SuppressWarnings("unused")
    private State() {
      this.swigValue = SwigNext.next++;
    }

    @SuppressWarnings("unused")
    private State(int swigValue) {
      this.swigValue = swigValue;
      SwigNext.next = swigValue+1;
    }

    @SuppressWarnings("unused")
    private State(State swigEnum) {
      this.swigValue = swigEnum.swigValue;
      SwigNext.next = this.swigValue+1;
    }

    private final int swigValue;

    private static class SwigNext {
      private static int next = 0;
    }
  }

  public enum AutoConvertFlag {
  /**
   * all automatic conversions enabled
   */
    AUTO_CONVERT_ALL(VideoJNI.FilterGraph_AUTO_CONVERT_ALL_get()),
  /**
   * all automatic conversions disabled
   */
    AUTO_CONVERT_NONE(VideoJNI.FilterGraph_AUTO_CONVERT_NONE_get()),
  ;

    public final int swigValue() {
      return swigValue;
    }

    public static AutoConvertFlag swigToEnum(int swigValue) {
      AutoConvertFlag[] swigValues = AutoConvertFlag.class.getEnumConstants();
      if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue)
        return swigValues[swigValue];
      for (AutoConvertFlag swigEnum : swigValues)
        if (swigEnum.swigValue == swigValue)
          return swigEnum;
      throw new IllegalArgumentException("No enum " + AutoConvertFlag.class + " with value " + swigValue);
    }

    @SuppressWarnings("unused")
    private AutoConvertFlag() {
      this.swigValue = SwigNext.next++;
    }

    @SuppressWarnings("unused")
    private AutoConvertFlag(int swigValue) {
      this.swigValue = swigValue;
      SwigNext.next = swigValue+1;
    }

    @SuppressWarnings("unused")
    private AutoConvertFlag(AutoConvertFlag swigEnum) {
      this.swigValue = swigEnum.swigValue;
      SwigNext.next = this.swigValue+1;
    }

    private final int swigValue;

    private static class SwigNext {
      private static int next = 0;
    }
  }

}


/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 2.0.6
 *
 * Do not make changes to this file unless you know what you are doing--modify
 * the SWIG interface file instead.
 * ----------------------------------------------------------------------------- */

package io.humble.video;
import io.humble.ferry.*;
/**
 * An index entry for a Stream.

 *

 * Some ContainerFormats can maintain index of where key-frames

 * (and other interesting frames) can be found in a byte-stream.

 * This is really helpful for implementing efficient seeking (for

 * example, you can find all index entries near a desired timestamp,

 * and you'll find the nearest key-frame).

 *

 *

 * We don't maintain a complete list of all ContainerFormats that support

 * index, but if they do, you can query the Stream#getNumIndexEntries()

 * method to find how many entires are in the index.  Some ContainerFormats can

 * parse the relevant Container message if an index is embedded in the

 * container (for example, the MOV and MP4 demuxer can do this).  Other

 * ContainerFormats can create an index automatically as they read the file,

 * even if an index is not embedded in the container (for example the FLV

 * demuxer does this).

 *

 *

 * @see Stream#findTimeStampEntryInIndex(int,int)

 * @see Stream#findTimeStampPositionInIndex(int,int)

 * @see Stream#getIndexEntry(int)

 * @see Stream#getNumIndexEntries()

 * @see Stream#getIndexEntries()
 */
public class IndexEntry extends RefCounted {
  // JNIHelper.swg: Start generated code
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>
  /**
   * This method is only here to use some references and remove
   * a Eclipse compiler warning.
   */
  @SuppressWarnings("unused")
  private void noop()
  {
    Buffer.make(null, 1);
  }

  private volatile long swigCPtr;

  /**
   * Internal Only.
   */
  protected IndexEntry(long cPtr, boolean cMemoryOwn) {
    super(VideoJNI.IndexEntry_SWIGUpcast(cPtr), cMemoryOwn);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.
   */
  protected IndexEntry(long cPtr, boolean cMemoryOwn,
      java.util.concurrent.atomic.AtomicLong ref)
  {
    super(VideoJNI.IndexEntry_SWIGUpcast(cPtr),
     cMemoryOwn, ref);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that obj is proxying for.
   *
   * @param obj The java proxy object for a native object.
   * @return The raw pointer obj is proxying for.
   */
  protected static long getCPtr(IndexEntry obj) {
    if (obj == null) return 0;
    return obj.getMyCPtr();
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that we're proxying for.
   *
   * @return The raw pointer we're proxying for.
   */
  protected long getMyCPtr() {
    if (swigCPtr == 0) throw new IllegalStateException("underlying native object already deleted");
    return swigCPtr;
  }

  /**
   * Create a new IndexEntry object that is actually referring to the
   * exact same underlying native object.
   *
   * @return the new Java object.
   */
  @Override
  public IndexEntry copyReference() {
    if (swigCPtr == 0)
      return null;
    else
      return new IndexEntry(swigCPtr, swigCMemOwn, getJavaRefCount());
  }

  /**
   * Compares two values, returning true if the underlying objects in native code are the same object.
   *
   * That means you can have two different Java objects, but when you do a comparison, you'll find out
   * they are the EXACT same object.
   *
   * @return True if the underlying native object is the same.  False otherwise.
   */
  public boolean equals(Object obj) {
    boolean equal = false;
    if (obj instanceof IndexEntry)
      equal = (((IndexEntry)obj).swigCPtr == this.swigCPtr);
    return equal;
  }

  /**
   * Get a hashable value for this object.
   *
   * @return the hashable value.
   */
  public int hashCode() {
     return (int)swigCPtr;
  }

  // <<<<<<<<<<<<<<<<<<<<<<<<<<<
  // JNIHelper.swg: End generated code

   /**
   * info about this entry.
   * @return information about this entry.
   */

  @Override
  public String toString()
  {
    StringBuilder result = new StringBuilder();

    result.append(this.getClass().getName()+"@"+hashCode()+"[");
    result.append("position:"+getPosition()+";");
    result.append("timestamp:"+getTimeStamp()+";");
    result.append("flags:"+getFlags()+";");
    result.append("size:"+getSize()+";");
    result.append("min-distance:"+getMinDistance()+";");
    result.append("]");
    return result.toString();
  }

/**
 * Create a new IndexEntry with the specified

 * values.

 *

 * @param position The value to be returned from #getPosition().

 * @param timeStamp The value to be returned from #getTimeStamp().

 * @param flags The value to be returned from #getFlags().

 * @param size The value to be returned from #getSize().

 * @param minDistance The value to be returned from #getMinDistance().
 */
  public static IndexEntry make(long position, long timeStamp, int flags, int size, int minDistance) {
    long cPtr = VideoJNI.IndexEntry_make(position, timeStamp, flags, size, minDistance);
    return (cPtr == 0) ? null : new IndexEntry(cPtr, false);
  }

/**
 * The position in bytes of the frame corresponding to this index entry

 * in the Container.

 * @return The byte-offset from start of the Container where the

 *   frame for this IndexEntry can be found.
 */
  public long getPosition() {
    return VideoJNI.IndexEntry_getPosition(swigCPtr, this);
  }

/**
 * The actual time stamp, in units of Stream#getTimeBase(), of the frame this entry points to.

 * @return The time stamp for this entry.
 */
  public long getTimeStamp() {
    return VideoJNI.IndexEntry_getTimeStamp(swigCPtr, this);
  }

/**
 * Flags set for this entry.  See the INDEX_FLAG* constants

 * above.

 * @return the flags.
 */
  public int getFlags() {
    return VideoJNI.IndexEntry_getFlags(swigCPtr, this);
  }

/**
 * The size of bytes of the frame this index entry points to.

 * @return The size in bytes.
 */
  public int getSize() {
    return VideoJNI.IndexEntry_getSize(swigCPtr, this);
  }

/**
 * Minimum number of index entries between this index entry

 * and the last keyframe in the index, used to avoid unneeded searching.

 * @return the minimum distance, in bytes.
 */
  public int getMinDistance() {
    return VideoJNI.IndexEntry_getMinDistance(swigCPtr, this);
  }

/**
 * Is this index entry pointing to a key frame.

 * Really shorthand for #getFlags() & #INDEX_FLAG_KEYFRAME.

 * @return True if this index entry is for a key frame.
 */
  public boolean isKeyFrame() {
    return VideoJNI.IndexEntry_isKeyFrame(swigCPtr, this);
  }

/**
 * A bit mask value that may be set in #getFlags.
 */
  public final static int INDEX_FLAG_KEYFRAME = VideoJNI.IndexEntry_INDEX_FLAG_KEYFRAME_get();
}


/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 2.0.6
 *
 * Do not make changes to this file unless you know what you are doing--modify
 * the SWIG interface file instead.
 * ----------------------------------------------------------------------------- */

package io.humble.video;
import io.humble.ferry.*;
/**
 * Takes a bit stream and filters bytes passed

 * in to add, remove, or modify the bit-stream.
 */
public class BitStreamFilter extends RefCounted {
  // JNIHelper.swg: Start generated code
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>
  /**
   * This method is only here to use some references and remove
   * a Eclipse compiler warning.
   */
  @SuppressWarnings("unused")
  private void noop()
  {
    Buffer.make(null, 1);
  }

  private volatile long swigCPtr;

  /**
   * Internal Only.
   */
  protected BitStreamFilter(long cPtr, boolean cMemoryOwn) {
    super(VideoJNI.BitStreamFilter_SWIGUpcast(cPtr), cMemoryOwn);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.
   */
  protected BitStreamFilter(long cPtr, boolean cMemoryOwn,
      java.util.concurrent.atomic.AtomicLong ref)
  {
    super(VideoJNI.BitStreamFilter_SWIGUpcast(cPtr),
     cMemoryOwn, ref);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that obj is proxying for.
   *
   * @param obj The java proxy object for a native object.
   * @return The raw pointer obj is proxying for.
   */
  protected static long getCPtr(BitStreamFilter obj) {
    if (obj == null) return 0;
    return obj.getMyCPtr();
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that we're proxying for.
   *
   * @return The raw pointer we're proxying for.
   */
  protected long getMyCPtr() {
    if (swigCPtr == 0) throw new IllegalStateException("underlying native object already deleted");
    return swigCPtr;
  }

  /**
   * Create a new BitStreamFilter object that is actually referring to the
   * exact same underlying native object.
   *
   * @return the new Java object.
   */
  @Override
  public BitStreamFilter copyReference() {
    if (swigCPtr == 0)
      return null;
    else
      return new BitStreamFilter(swigCPtr, swigCMemOwn, getJavaRefCount());
  }

  /**
   * Compares two values, returning true if the underlying objects in native code are the same object.
   *
   * That means you can have two different Java objects, but when you do a comparison, you'll find out
   * they are the EXACT same object.
   *
   * @return True if the underlying native object is the same.  False otherwise.
   */
  public boolean equals(Object obj) {
    boolean equal = false;
    if (obj instanceof BitStreamFilter)
      equal = (((BitStreamFilter)obj).swigCPtr == this.swigCPtr);
    return equal;
  }

  /**
   * Get a hashable value for this object.
   *
   * @return the hashable value.
   */
  public int hashCode() {
     return (int)swigCPtr;
  }

  // <<<<<<<<<<<<<<<<<<<<<<<<<<<
  // JNIHelper.swg: End generated code

  /**
   * info about this filter object
   * @return information about this object
   */

  @Override
  public String toString()
  {
    StringBuilder result = new StringBuilder();

    result.append(this.getClass().getName()+"@"+hashCode()+"[");
    result.append("name:"+getName()+";");
    result.append("]");
    return result.toString();
  }

/**
 * Create a filter given the name.

 *

 * @param filtername The name of the filter.

 *

 * @see BitStreamFilterType
 */
  public static BitStreamFilter make(String filtername) {
    long cPtr = VideoJNI.BitStreamFilter_make__SWIG_0(filtername);
    return (cPtr == 0) ? null : new BitStreamFilter(cPtr, false);
  }

/**
 * Create a filter given the type.

 *

 * @param type The type of the filter.

 *

 * @see BitStreamFilterType
 */
  public static BitStreamFilter make(BitStreamFilterType type) {
    long cPtr = VideoJNI.BitStreamFilter_make__SWIG_1(BitStreamFilterType.getCPtr(type), type);
    return (cPtr == 0) ? null : new BitStreamFilter(cPtr, false);
  }

/**
 * Get the type of this filter.
 */
  public BitStreamFilterType getType() {
    long cPtr = VideoJNI.BitStreamFilter_getType(swigCPtr, this);
    return (cPtr == 0) ? null : new BitStreamFilterType(cPtr, false);
  }

/**
 * Get the name of this filter.
 */
  public String getName() {
    return VideoJNI.BitStreamFilter_getName(swigCPtr, this);
  }

/**
 * Filter the input buffer into the output buffer.

 *

 * @param output The output buffer to copy filtered bytes to.

 * @param outputOffset The offset in output to copy data into.

 * @param input The input buffer to filter.

 * @param inputOffset The number of bytes into input to start filtering at.

 * @param inputSize The number of bytes (from inputOffset) to filter.

 * @param coder The Coder context belong to the Stream that this data will eventually get outputted to.

 * @param args String arguments for the filter call. See the FFmpeg documentation or source code.

 * @param isKey Does this data represent a key packet.

 *

 * @return The number of bytes copied into output once filtering is done.

 *

 * @throws InvalidArgument if any parameters are invalid.

 * @throws FfmpegException if the filtering fails for any reason.
 */
  public int filter(Buffer output, int outputOffset, Buffer input, int inputOffset, int inputSize, Coder coder, String args, boolean isKey) {
    return VideoJNI.BitStreamFilter_filter__SWIG_0(swigCPtr, this, Buffer.getCPtr(output), output, outputOffset, Buffer.getCPtr(input), input, inputOffset, inputSize, Coder.getCPtr(coder), coder, args, isKey);
  }

/**
 * Filters a packet in place (i.e. the prior contents will be replaced

 * with the filtered data).

 *

 * This method assumes packet.getCoder() is the coder that is being used

 * for outputting the packet to a stream. If this is not the case, use

 * the other filter mechanism and construct packets yourself.

 *

 * @param packet The packet to filter in place.

 * @param args Text arguments for the filter.

 *

 * @throws InvalidArgument if output is null.

 * @throws InvalidArgument if input is null or not complete.
 */
  public void filter(MediaPacket packet, String args) {
    VideoJNI.BitStreamFilter_filter__SWIG_1(swigCPtr, this, MediaPacket.getCPtr(packet), packet, args);
  }

}


/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 2.0.6
 *
 * Do not make changes to this file unless you know what you are doing--modify
 * the SWIG interface file instead.
 * ----------------------------------------------------------------------------- */

package io.humble.ferry;

/**
 * Allows Java code to get data from a native buffers, and optionally modify native memory directly.

 *

 * When accessing from Java, you can copy in and

 * out ranges of buffers.  You can do this by-copy

 * (which is safer but a little slower) or by-reference

 * where you directly access underlying C++/native

 * memory from Java.  Take special care if you decide

 * that native access is required.

 *

 *

 * When accessing from C++, you get direct access to

 * the underlying buffer.

 *

 *

 * To make an Buffer object that is not a Humble internal object,

 * pass in null for the RefCounted parameter.

 *

 *

 */
public class Buffer extends RefCounted {
  // Buffer.swg: Start generated code
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>

  private volatile long swigCPtr;

  /**
   *
   * DO NOT USE THIS CONSTRUCTOR - USE {@link #make(RefCounted,int)} INSTEAD.
   *
   *

   * Internal Only. Do not allocate this object using new.  Not part of public API.
   *

   *

   * Unfortunately this constructor is public because the internal
   * implementation needs it to be, but do not pass in values to this method
   * as you may end up crashing the virtual machine.
   *

   *
   * @param ignore1 ignore.
   * @param ignore2 ignore.
   *
   */
  public Buffer(long ignore1, boolean ignore2) {
    super(FerryJNI.Buffer_SWIGUpcast(ignore1), ignore2);
    swigCPtr = ignore1;
  }
  protected Buffer(long cPtr, boolean cMemoryOwn,
      java.util.concurrent.atomic.AtomicLong ref)
  {
    super(FerryJNI.Buffer_SWIGUpcast(cPtr),
     cMemoryOwn, ref);
    swigCPtr = cPtr;
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that obj is proxying for.
   *
   * @param obj The java proxy object for a native object.
   * @return The raw pointer obj is proxying for.
   */
  protected static long getCPtr(Buffer obj) {
    if (obj == null) return 0;
    return obj.getMyCPtr();
  }

  /**
   * Internal Only.  Not part of public API.
   *
   * Get the raw value of the native object that we're proxying for.
   *
   * @return The raw pointer we're proxying for.
   */
  protected long getMyCPtr() {
    if (swigCPtr == 0) throw new IllegalStateException("underlying native object already deleted");
    return swigCPtr;
  }

  /**
   * Releases ths instance of Buffer and frees any underlying
   * native memory.
   *

   * {@inheritDoc}
   *

   */
  @Override
  public void delete()
  {
    do {} while(false); // remove a warning
    super.delete();
  }

  /**
   * Create a new Buffer object that is actually referring to the
   * exact same underlying Native object.
   *
   * @return the new Java object.
   */
  @Override
  public Buffer copyReference() {
    if (swigCPtr == 0)
      return null;
    else
      return new Buffer(swigCPtr, swigCMemOwn, getJavaRefCount());
  }

  /**
   * Compares two values, returning true if the underlying objects in native code are the same object.
   *
   * That means you can have two different Java objects, but when you do a comparison, you'll find out
   * they are the EXACT same object.
   *
   * @return True if the underlying native object is the same.  False otherwise.
   */
  public boolean equals(Object obj) {
    boolean equal = false;
    if (obj instanceof Buffer)
      equal = (((Buffer)obj).swigCPtr == this.swigCPtr);
    return equal;
  }

  /**
   * Get a hashable value for this object.
   *
   * @return the hashable value.
   */
  public int hashCode() {
     return (int)swigCPtr;
  }

  private void validateArgs(Object array, int arrayLength,
      int arrayPos,
      int bufferSize,
      int bufferPos,
      int length)
  {
    if (arrayPos < 0)
      throw new IndexOutOfBoundsException();
    if (bufferPos < 0)
      throw new IndexOutOfBoundsException();
    if (length < 0)
      throw new IndexOutOfBoundsException();
    if (arrayPos+length > arrayLength)
      throw new IndexOutOfBoundsException();
    if (bufferPos + length > bufferSize)
      throw new IndexOutOfBoundsException();
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers bytes into this buffer from the given source array.
   * If there are more bytes to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no bytes are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which bytes are to be read.  Must be non null.
   * @param srcPos The offset within src of the first byte to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of bytes to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(byte[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer buffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (buffer == null)
        return;
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);

      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers bytes from this {@link Buffer} into the given
   * dest
   * array. If there are fewer bytes in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no bytes are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which bytes are to be written. Must be non null.
   * @param destPos The offset within dest of the first byte to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of bytes to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, byte[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer buffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (buffer == null)
        return;
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);

      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers shorts into this buffer from the given source array.
   * If there are more shorts to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no shorts are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which shorts are to be read.  Must be non null.
   * @param srcPos The offset within src of the first short to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of shorts to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(short[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.ShortBuffer buffer = bbuffer.asShortBuffer();
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);
      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers shorts from this {@link Buffer} into the given
   * dest
   * array. If there are fewer shorts in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no shorts are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which shorts are to be written. Must be non null.
   * @param destPos The offset within dest of the first short to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of shorts to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, short[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.ShortBuffer buffer = bbuffer.asShortBuffer();
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);
      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers ints into this buffer from the given source array.
   * If there are more ints to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no ints are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which ints are to be read.  Must be non null.
   * @param srcPos The offset within src of the first int to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of ints to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(int[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.IntBuffer buffer = bbuffer.asIntBuffer();
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);
      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers ints from this {@link Buffer} into the given
   * dest
   * array. If there are fewer ints in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no ints are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which ints are to be written. Must be non null.
   * @param destPos The offset within dest of the first int to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of ints to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, int[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.IntBuffer buffer = bbuffer.asIntBuffer();
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);
      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers longs into this buffer from the given source array.
   * If there are more longs to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no longs are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which longs are to be read.  Must be non null.
   * @param srcPos The offset within src of the first long to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of longs to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(long[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.LongBuffer buffer = bbuffer.asLongBuffer();
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);
      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers longs from this {@link Buffer} into the given
   * dest
   * array. If there are fewer longs in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no longs are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which longs are to be written. Must be non null.
   * @param destPos The offset within dest of the first long to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of longs to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, long[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.LongBuffer buffer = bbuffer.asLongBuffer();
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);
      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers doubles into this buffer from the given source array.
   * If there are more doubles to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no doubles are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which doubles are to be read.  Must be non null.
   * @param srcPos The offset within src of the first double to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of doubles to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(double[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.DoubleBuffer buffer = bbuffer.asDoubleBuffer();
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);
      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers doubles from this {@link Buffer} into the given
   * dest
   * array. If there are fewer doubles in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no doubles are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which doubles are to be written. Must be non null.
   * @param destPos The offset within dest of the first double to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of doubles to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, double[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.DoubleBuffer buffer = bbuffer.asDoubleBuffer();
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);
      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers floats into this buffer from the given source array.
   * If there are more floats to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no floats are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which floats are to be read.  Must be non null.
   * @param srcPos The offset within src of the first float to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of floats to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(float[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.FloatBuffer buffer = bbuffer.asFloatBuffer();
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);
      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers floats from this {@link Buffer} into the given
   * dest
   * array. If there are fewer floats in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no floats are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which floats are to be written. Must be non null.
   * @param destPos The offset within dest of the first float to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of floats to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, float[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.FloatBuffer buffer = bbuffer.asFloatBuffer();
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);
      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk put method.
   *

   * This method transfers chars into this buffer from the given source array.
   * If there are more chars to be copied from the array than there is
   * space remaining at the specified destination offset,
   * then no chars are transferred and a java.nio.BufferOverflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and copying the bytes over, but is more efficient in
   * the {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param src The array from which chars are to be read.  Must be non null.
   * @param srcPos The offset within src of the first char to be read;
   *   must be non-negative and less than src.length
   * @param destPos The offset in the Buffer where you want to copy
   *   data to.  Must be non-negative and less than getBufferSize()
   * @param length The number of chars to be read from src;
   *  must be non-negative and no larger than src.length - srcPos
   *
   * @throws NullPointerException if src is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *   mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient space
   *   in this {@link Buffer}.
   *
   */
  public void put(char[] src, int srcPos, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.CharBuffer buffer = bbuffer.asCharBuffer();
      buffer.clear();
      validateArgs(src, src.length, srcPos, buffer.limit(), destPos, length);
      buffer.position(destPos);
      buffer.put(src, srcPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Absolute bulk get method.
   *

   * This method transfers chars from this {@link Buffer} into the given
   * dest
   * array. If there are fewer chars in the {@link Buffer} starting
   * at position srcPos than are required
   * to satisfy the request, then no chars are
   * transferred and a BufferUnderflowException is thrown.
   *

   *

   * This method is equivalent to calling {@link #getByteBuffer(int, int)}
   * yourself and reading the bytes out, but is more efficient in the
   * {@link JNIMemoryManager.MemoryModel#NATIVE_BUFFERS} memory model.
   *

   *
   * @param srcPos The offset in the Buffer where you want to start
   *        copying data from.
   *        Must be non-negative and less than getBufferSize()
   * @param dest The array to which chars are to be written. Must be non null.
   * @param destPos The offset within dest of the first char to be
   *        written; must be non-negative and less than dest.length
   * @param length The number of chars to be copied into dest; must be
   *        non-negative and no larger than dest.length - destPos
   *
   * @throws NullPointerException if dest is null.
   * @throws IndexOutOfBoundsException if the preconditions on the arguments
   *         mentioned above are not honored.
   * @throws java.nio.BufferOverflowException if there is insufficient data in this
   *         {@link Buffer} to satisfy the request.
   *
   */
  public void get(int srcPos, char[] dest, int destPos, int length)
  {
    java.util.concurrent.atomic.AtomicReference<JNIReference> ref =
      new java.util.concurrent.atomic.AtomicReference<JNIReference>();
    java.nio.ByteBuffer bbuffer = this.getByteBuffer(0, this.getBufferSize(),
        ref);

    try
    {
      if (bbuffer == null)
        return;
      java.nio.CharBuffer buffer = bbuffer.asCharBuffer();
      validateArgs(dest, dest.length, destPos, buffer.limit(), srcPos, length);
      buffer.position(srcPos);
      buffer.get(dest, destPos, length);
      return;
    }
    finally
    {
      if (ref.get() != null)
        ref.get().delete();
    }
  }

  /**
   * Returns up to length bytes, starting at offset in the underlying
   * buffer we're managing.
   *
   *

   *
   * The buffer position, mark are initialized to zero and limit
   * is set to the maximum capacity of this buffer.  For some
   * Buffer contents, the actual usable data in this buffer will
   * be less that the limit.
   *
   *

   *

   * If you want to control exactly when the underlying memory
   * beyind the returned {@link java.nio.ByteBuffer} is released,
   * use {@link #getByteBuffer(int, int, java.util.concurrent.atomic.AtomicReference)}.
   *

   * @see #getByteBuffer(int, int, java.util.concurrent.atomic.AtomicReference)
   */
  public java.nio.ByteBuffer getByteBuffer(int offset, int length)
  {
    return getByteBuffer(offset, length, null);
  }

    /**
     * Returns up to length bytes, starting at offset in the underlying
     * buffer we're managing, and also passed back a {@link JNIReference}
     * that can optionally be used by the caller to free the underlying
     * native memory.
     *
     *

     *
     * The buffer position, mark are initialized to zero and limit
     * is set to the maximum capacity of this buffer.  For some
     * Buffer contents, the actual usable data in this buffer will
     * be less that the limit.
     *
     *

     *

     *
     * If you use this method you are accessing the direct native
     * memory associated with this buffer.  That means changes you make
     * to this buffer are immediately reflected in the underlying
     * memory.
     *
     *

     *

     *
     * Once you call this method,
     * the underlying native memory allocated will not be released until
     * all references to the returned ByteBuffer are no longer reachable and
     * at least one call to {@link JNIMemoryManager#gc()} has been
     * performed.  You can force the memory to be collect earlier
     * by using the {@link JNIReference} value returned when you
     * call this method.
     *

     *  The {@link JNIMemoryManager#gc()} is called whenever
     * Humble Video tries to allocate new memory for any Humble interface,
     * so normally you don't need to care about this.  If for some
     * reason no other Humble object is ever allocated, every
     * Humble object has
     * a finalizer as well that will do the right thing.
     *
     *

     *

     *
     * You can also start up
     * a separate thread to do continuously do Ferry garabage
     * collections by calling
     * {@link JNIMemoryManager#startCollectionThread()}.  This thread
     * will only wake up when it has work to do, so the overhead
     * is very low.  We don't turn it on by default since in
     * 99.999% of cases you don't need to worry about it.
     *
     *

     *
     * @param offset The offset (in bytes) into the buffer managed by
     *   this Buffer
     * @param length The requested length (in bytes) you want to access.
     *   The buffer returned may actually be longer than length.
     * @param referenceReturn If non null, on exit
     *   calling {@link java.util.concurrent.atomic.AtomicReference#get()}
     *   on this value will return a {@link JNIReference} you can use
     *   for explicitly de-allocating the underlying native store
     *   of the {@link java.nio.ByteBuffer}.  Call
     *   {@link JNIReference#delete()} to do that.  Warning:
     *   if you do call {@link JNIReference#delete()} on the
     *   value returned in this parameter, then the returned byte buffer
     *   will be immediately invalid.
     * @return A java.nio.ByteBuffer that directly accesses
     *   the native memory this Buffer manages, or null if
     *   error.
     */
  public java.nio.ByteBuffer getByteBuffer(int offset, int length,
      java.util.concurrent.atomic.AtomicReference<JNIReference> referenceReturn)
  {
    java.nio.ByteBuffer retval = this.java_getByteBuffer(offset, length);
    if (retval != null)
    {
      // increment the ref count of this class to reflect the
      // byte buffer
      java.util.concurrent.atomic.AtomicLong refCount =
        this.getJavaRefCount();
      refCount.incrementAndGet();

      // and use the byte buffer as the reference to track
      JNIReference ref = JNIReference.createNonFerryReference(
          this,
          retval, swigCPtr, refCount);
      if (referenceReturn != null)
        referenceReturn.set(ref);

      // and tell Java this byte buffer is in native order
      retval.order(java.nio.ByteOrder.nativeOrder());
      retval.position(0);
      retval.mark();
      retval.limit(this.getBufferSize());
    }
    return retval;
  }

  /**
   * Prints the same as {@link Object#toString()} but appends
   * the maximum number of bytes that will fit in this
   * {@link Buffer}, the type of the {@link Buffer}, and the maximum
   * size in units of {@link Buffer.Type} that will fit in the
   * {@link Buffer}.
   * {@inheritDoc}
   */
  @Override
  public String toString()
  {
    final StringBuilder builder = new StringBuilder();
    builder.append(super.toString());
    builder.append("[");
    builder.append("bytes=").append(getBufferSize()).append(";");
    builder.append("type=").append(getType()).append(";");
    builder.append("size=").append(getSize()).append(";");
    builder.append("]");
    return builder.toString();
  }

  // <<<<<<<<<<<<<<<<<<<<<<<<<<<
  // Buffer.swg

/**
 * Get the current maximum number of bytes that can

 * be safely placed in this buffer.

 *

 * @return Maximum number of bytes this buffer can manage.
 */
  public int getBufferSize() {
    return FerryJNI.Buffer_getBufferSize(swigCPtr, this);
  }

/**
 * Allocate a new buffer of at least bufferSize.

 *

 * @param requestor An optional value telling the Buffer class what object requested it.  This is used for debugging memory leaks; it's a marker for the FERRY object (e.g. IPacket) that actually requested the buffer.  If you're not an FERRY object, pass in null here.

 * @param bufferSize The minimum buffer size you're requesting in bytes; a buffer with a larger size may be returned.

 *

 * @return A new buffer, or null on error.
 */
  public static Buffer make(RefCounted requestor, int bufferSize) {
    long cPtr = FerryJNI.Buffer_make__SWIG_0(RefCounted.getCPtr(requestor), requestor, bufferSize);
    return (cPtr == 0) ? null : new Buffer(cPtr, false);
  }

/**
 * Get the type this buffer was created as.

 *

 * A type is really just a hint.  Like

 * java.nio.ByteBuffer objects,

 * Buffer objects can be cast to and from any type.

 *

 * @return the type
 */
  public Buffer.Type getType() {
    return Buffer.Type.swigToEnum(FerryJNI.Buffer_getType(swigCPtr, this));
  }

/**
 * Reset the buffer type to a new type.

 *

 * This method does not do any data conversion, it

 * just changes the reported type (so changing from

 * Type#BUFFER_UINT8 to Type#BUFFER_SINT16

 * is really just a "cast" operation).

 *

 * @param type the type to set to.
 */
  public void setType(Buffer.Type type) {
    FerryJNI.Buffer_setType(swigCPtr, this, type.swigValue());
  }

/**
 * Returns the size, in bytes, of elements of given Type.

 *

 * @return the size in bytes.
 */
  public static int getTypeSize(Buffer.Type type) {
    return FerryJNI.Buffer_getTypeSize(type.swigValue());
  }

/**
 * Returns the size, in units of #getType() of

 * this buffer.

 *

 * @return number of items of type #getType() that

 *   will fit in this buffer.
 */
  public int getSize() {
    return FerryJNI.Buffer_getSize(swigCPtr, this);
  }

/**
 * Allocate a new buffer of at least bufferSize.

 *

 * @param requestor An optional value telling the Buffer class what object requested it.  This is used for debugging memory leaks; it's a marker for the FERRY object (e.g. IPacket) that actually requested the buffer.  If you're not an FERRY object, pass in null here.

 * @param type The type of buffer.

 * @param numElements The minimum number of elements of the specified

 *                    type you will put in this buffer.

 * @param zero If true, we will guarantee the buffer contains

 *             only zeros.  If false, we will not (it is

 *             faster to not, but then the buffer will have

 *             garbage-data in it).

 *

 * @return A new buffer, or null on error.
 */
  public static Buffer make(RefCounted requestor, Buffer.Type type, int numElements, boolean zero) {
    long cPtr = FerryJNI.Buffer_make__SWIG_1(RefCounted.getCPtr(requestor), requestor, type.swigValue(), numElements, zero);
    return (cPtr == 0) ? null : new Buffer(cPtr, false);
  }

  private java.nio.ByteBuffer java_getByteBuffer(int offset, int length) {
    return FerryJNI.Buffer_java_getByteBuffer(swigCPtr, this, offset, length);
  }

/**
 * Returns up to length bytes, starting at offset in the

 * underlying buffer we're managing.

 *

 * This method COPIES the data into the byte array being

 * returned..

 *

 * If you don't NEED the direct access that getByteBuffer

 * offers (and most programs can in fact take the performance

 * hit of the copy), we recommend you use this method.

 * It's much harder to accidentally leave native memory lying

 * around waiting for cleanup then.

 *

 *

 * @param offset The offset (in bytes) into the buffer managed by this Buffer

 * @param length The requested length (in bytes) you want to access.  The buffer returned may

 *   actually be longer than length.

 *

 * @return A copy of the data that is in this Buffer, or null

 *   if error.
 */
  public byte[] getByteArray(int offset, int length) {
    return FerryJNI.Buffer_getByteArray(swigCPtr, this, offset, length);
  }

/**
 * Allocate a new Buffer, and copy the data in buffer into

 * the new Buffer object.

 *

 * @param requestor An optional value telling the Buffer class

 *   what object requested it. This is used for debugging memory leaks;

 *   it's a marker for the FERRY object (e.g. IPacket) that actually

 *   requested the buffer. If you're not an FERRY object, pass in null here.

 * @param buffer A java byte buffer for the data containing the

 *   data you want to copy.

 * @param offset The starting offset in buffer where you want

 *   to start copying.

 * @param length The total number of bytes you want to copy from buffer.

 *

 * @return a new Buffer object with a copy of the data in buffer,

 *   or null on failure.
 */
  public static Buffer make(RefCounted requestor, byte[] buffer, int offset, int length) {
    long cPtr = FerryJNI.Buffer_make__SWIG_2(RefCounted.getCPtr(requestor), requestor, buffer, offset, length);
    return (cPtr == 0) ? null : new Buffer(cPtr, false);
  }

/**
 * Create a new Buffer object that uses the direct byte buffer

 * passed in by reference (i.e. it directly uses the bytes in

 * the direct byte buffer).

 *

 * @param requestor An optional value telling the Buffer class

 *   what object requested it. This is used for debugging memory leaks;

 *   it's a marker for the FERRY object (e.g. IPacket) that actually

 *   requested the buffer. If you're not an FERRY object, pass in null here.

 * @param directByteBuffer A direct java.nio.ByteBuffer object

 *   you want to use for your memory.  This must be a direct object --

 *   non direct objects will result in an JVM-dependent exception

 *   being thrown.

 * @param offset The starting offset in directByteBuffer where you want

 *   to start copying.

 * @param length The total number of bytes you want to copy from

 *   directByteBuffer.

 *

 * @return a new Buffer object that is using directByteBuffer

 *   behind the scenes, or null on failure.
 */
  public static Buffer make(RefCounted requestor, java.nio.ByteBuffer directByteBuffer, int offset, int length) {
    long cPtr = FerryJNI.Buffer_make__SWIG_3(RefCounted.getCPtr(requestor), requestor, directByteBuffer, offset, length);
    return (cPtr == 0) ? null : new Buffer(cPtr, false);
  }

  /**
   * Types of data that are in this buffer.
   */
  public enum Type {
    BUFFER_UINT8,
    BUFFER_SINT8,
    BUFFER_UINT16,
    BUFFER_SINT16,
    BUFFER_UINT32,
    BUFFER_SINT32,
    BUFFER_UINT64,
    BUFFER_SINT64,
    BUFFER_FLT32,
    BUFFER_DBL64,
    BUFFER_NB,
  ;

    public final int swigValue() {
      return swigValue;
    }

    public static Type swigToEnum(int swigValue) {
      Type[] swigValues = Type.class.getEnumConstants();
      if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue)
        return swigValues[swigValue];
      for (Type swigEnum : swigValues)
        if (swigEnum.swigValue == swigValue)
          return swigEnum;
      throw new IllegalArgumentException("No enum " + Type.class + " with value " + swigValue);
    }

    @SuppressWarnings("unused")
    private Type() {
      this.swigValue = SwigNext.next++;
    }

    @SuppressWarnings("unused")
    private Type(int swigValue) {
      this.swigValue = swigValue;
      SwigNext.next = swigValue+1;
    }

    @SuppressWarnings("unused")
    private Type(Type swigEnum) {
      this.swigValue = swigEnum.swigValue;
      SwigNext.next = this.swigValue+1;
    }

    private final int swigValue;

    private static class SwigNext {
      private static int next = 0;
    }
  }

}


package io.humble.video.javaxsound;

import java.nio.ByteBuffer;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Creates a connection to the Java Sound system, and allows
 * convenient playback of the output form a {@link MediaAudioConverter}.
 *

 * Caller must call {@link #dispose()} when done to drain the line and
 * release resources.
 *

 *

 * This class has no Humble dependencies per-see, but does
 * playback audio that comes out of a converter.
 *

 * @author aclarke
 *
 */
public class AudioFrame {

  static private final Logger log = LoggerFactory.getLogger(AudioFrame.class);

  private SourceDataLine mLine;

  /**
   * Create an audio frame with the default assumed format.
   * @return
   */
  public static AudioFrame make() {
    final AudioFormat audioFormat = new AudioFormat(22050,
        2*8,
        2,
        true,
        false);
    return make(audioFormat);
  }

  /**
   * Get a connection to the speaker, if available.
   * @param audioFormat The java audio format that we will use.
   * @return A new audio format, or null if we cannot create one.
   */
  public static AudioFrame make(final AudioFormat audioFormat) {
    try {
      return new AudioFrame(audioFormat);
    } catch (LineUnavailableException e) {
      log.error("Could not get audio data line: {}", e.getMessage());
      return null;
    }
  }

  /**
   * Get the audio format being used.
   * @return
   */
  public AudioFormat getFormat() {
    return mLine.getFormat();
  }

  private AudioFrame(final AudioFormat audioFormat) throws LineUnavailableException{
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
    mLine = (SourceDataLine) AudioSystem.getLine(info);
    /**
     * if that succeeded, try opening the line.
     */
    mLine.open(audioFormat);
    /**
     * And if that succeed, start the line.
     */
    mLine.start();
  }

  /**
   * Play the given bytes (in {@link #getFormat()} format on the device.
   * @param rawAudio a byte buffer where the data from {@link ByteBuffer#position()}
   *   to {@link ByteBuffer#limit()} will be written.
   */
  public void play(ByteBuffer rawAudio)
  {
    byte[] data = rawAudio.array();
    mLine.write(data, rawAudio.position(), rawAudio.limit());
  }

  /**
   * Drain the line and then close it.
   */
  public void dispose()
  {
    if (mLine != null)
    {
      /*
       * Wait for the line to finish playing
       */
      mLine.drain();
      /*
       * Close the line.
       */
      mLine.close();
      mLine=null;
    }
  }

}


/*******************************************************************************
 * Copyright (c) 2013, Art Clarke.  All rights reserved.
 *
 * This file is part of Humble-Video.
 *
 * Humble-Video is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Humble-Video is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Humble-Video.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/

package io.humble.video.awt;

import io.humble.video.MediaPicture;
import io.humble.video.MediaPictureResampler;
import io.humble.video.PixelFormat;

import java.awt.image.BufferedImage;

/** An abstract converter class from which specific converters can be
 * derived to do the actual conversions.  This class establishes if
 * the {@link MediaPicture} needs to be re-sampled, and
 * if so, creates appropriate {@link MediaPictureResampler} objects to do
 * that.
 *
 *  Note: Package Private
 */

abstract class AMediaPictureConverter implements MediaPictureConverter
{
  /** Re-sampler called when converting image to picture, may be null. */

  protected MediaPictureResampler mToPictureResampler = null;

  /** Re-sampler called when converting picture to image, may be null. */

  protected MediaPictureResampler mToImageResampler = null;

  /** The width of the pictures. */

  protected int mPictureWidth;

  /** The height of the pictures. */

  protected int mPictureHeight;

  /** The width of the images. */

  protected int mImageWidth;

  /** The height of the images. */

  protected int mImageHeight;

  // the recognized BufferedImage type

  final private PixelFormat.Type mPictureType;

  // the recognized BufferedImage type

  final private PixelFormat.Type mRequiredPictureType;

  // the recognized BufferedImage type

  final private int mImageType;

  // the description of this convert

  final private String mDescription;

  /**
   * Construct an abstract Converter.  This will create a
   * {@link MediaPictureResampler}
   * to change color-space or resize the picture as needed for the
   * conversions specified.
   *
   * @param pictureType the recognized {@link MediaPicture} type
   * @param requiredPictureType the picture type requred to translate to
   *        and from the BufferedImage
   * @param imageType the recognized {@link BufferedImage} type
   * @param pictureWidth the width of picture
   * @param pictureHeight the height of picture
   * @param imageWidth the width of image
   * @param imageHeight the height of image
   */

  public AMediaPictureConverter(
    PixelFormat.Type pictureType,
    PixelFormat.Type requiredPictureType,
    int imageType,
    int pictureWidth,
    int pictureHeight,
    int imageWidth,
    int imageHeight)
  {
    // by default there is no resample description

    String resampleDescription = "";

    // record the image and picture parameters

    mPictureType = pictureType;
    mRequiredPictureType = requiredPictureType;
    mImageType = imageType;
    mPictureWidth = pictureWidth;
    mPictureHeight = pictureHeight;
    mImageWidth = imageWidth;
    mImageHeight = imageHeight;

    // if the picture type is not the type or size required, create the
    // resamplers to fix that

    if (!mPictureType.equals(mRequiredPictureType)
      || (mPictureWidth != mImageWidth)
      || (mPictureHeight != mImageHeight))
    {

      mToImageResampler = MediaPictureResampler.make(
          mImageWidth, mImageHeight, mRequiredPictureType,
        mPictureWidth, mPictureHeight, mPictureType, 0);
      mToImageResampler.open();

      mToPictureResampler = MediaPictureResampler.make(
        mPictureWidth, mPictureHeight, mPictureType,
        mImageWidth, mImageHeight, mRequiredPictureType, 0);
      mToPictureResampler.open();

      resampleDescription = "Pictures will be resampled to and from " +
          mRequiredPictureType + " during translation.";
    }

    // construct the description of this converter

    mDescription = "A converter which translates [" +
      pictureWidth + "x" + pictureHeight + "] MediaPicture type " +
      pictureType + " to and from [" + imageWidth + "x" + imageHeight +
      "] BufferedImage type " + imageType + ".  " + resampleDescription;
  }

  /** {@inheritDoc} */

  public PixelFormat.Type getPictureType()
  {
    return mPictureType;
  }

  /**
   * Return the Type which matches the {@link
   * BufferedImage} type.
   *
   * @return the picture type which allows for image translation.
   */

  protected PixelFormat.Type getRequiredPictureType()
  {
    return mRequiredPictureType;
  }

  /** {@inheritDoc} */

  public int getImageType()
  {
    return mImageType;
  }

  /** {@inheritDoc} */

  public boolean willResample()
  {
    return null != mToPictureResampler && null != mToImageResampler;
  }

  /**
   * Re-sample a picture.
   *
   * @param picture1 the picture to re-sample
   * @param resampler the picture re-samper to use
   *
   * @throws RuntimeException if could not re-sample picture
   **/

  protected static MediaPicture resample(MediaPicture input,
    MediaPictureResampler resampler)
  {
    // create new picture object

    MediaPicture output = MediaPicture.make(
      resampler.getOutputWidth(),
      resampler.getOutputHeight(),
      resampler.getOutputFormat());
    return resample(output, input, resampler);
  }
  protected static MediaPicture resample(MediaPicture output, MediaPicture input, MediaPictureResampler resampler) {
    // resample

    resampler.resample(output,  input);

    // return the resample picture

    return output;

  }

  /**
   * Test that the passed image is valid and conforms to the
   * converters specifications.
   *
   * @param image the image to test
   *
   * @throws IllegalArgumentException if the passed {@link
   *         BufferedImage} is NULL;
   * @throws IllegalArgumentException if the passed {@link
   *         BufferedImage} is not the correct type. See {@link
   *         #getImageType}.
   */

  protected void validateImage(BufferedImage image)
  {
    // if the image is NULL, throw up

    if (image == null)
      throw new IllegalArgumentException("The passed image is NULL.");

    // if image is not the correct type, throw up

    if (image.getType() != getImageType())
      throw new IllegalArgumentException(
        "The passed image is of type #" + image.getType() +
        " but is required to be of BufferedImage type #" +
        getImageType() + ".");
  }

  /**
   * Test that the passed picture is valid and conforms to the
   * converters specifications.
   *
   * @param picture the picture to test
   *
   * @throws IllegalArgumentException if the passed {@link
   *         MediaPicture} is NULL;
   * @throws IllegalArgumentException if the passed {@link
   *         MediaPicture} is not complete.
   * @throws IllegalArgumentException if the passed {@link
   *         MediaPicture} is not the correct type.
   */

  protected void validatePicture(MediaPicture picture)
  {
    // if the picture is NULL, throw up

    if (picture == null)
      throw new IllegalArgumentException("The picture is NULL.");

    // if the picture is not complete, throw up

    if (!picture.isComplete())
      throw new IllegalArgumentException("The picture is not complete.");

    // if the picture is an invalid type throw up

    PixelFormat.Type type = picture.getFormat();
    if ((type != getPictureType()) && (willResample() &&
        type != mToImageResampler.getOutputFormat()))
      throw new IllegalArgumentException(
        "Picture is of type: " + type + ", but must be " +
        getPictureType() + (willResample()
          ? " or " + mToImageResampler.getOutputFormat()
          : "") +
        ".");
  }

  /** {@inheritDoc} */

  public String getDescription()
  {
    return mDescription;
  }

  /** Get a string representation of this converter. */

  public String toString()
  {
    return getDescription();
  }

  public void delete()
  {
    if (mToPictureResampler != null)
      mToPictureResampler.delete();
    mToPictureResampler = null;
    if (mToImageResampler != null)
      mToImageResampler.delete();
    mToImageResampler = null;
  }

}


/*******************************************************************************
 * Copyright (c) 2013, Art Clarke.  All rights reserved.
 *
 * This file is part of Humble-Video.
 *
 * Humble-Video is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Humble-Video is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Humble-Video.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/

package io.humble.ferry;

import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Proxy for {@link java.lang.Thread} that is called by Ferry native code.
 *

 * This class is called from native code to tell if a thread
 * is interrupted.  It only exposes the methods that are called
 * from the native code, and adds logging to aid in debugging.
 *

 *

 * If allows a global handler to be set.  This can be useful for
 * catching threads that are started from native code as there is no other
 * way to detect those and interrupt them.  If set, the global handler
 * will always be checked BEFORE the local thread allowing users to
 * always get a callback on each interrupt check if they want.
 *

 *

 * Do not change the name or location of this class without also
 * changing the JNIHelper.cpp code that refers to it.
 *

 * @author aclarke
 * @since 5.0
 */
public class JNIThreadProxy extends Thread
{
  /**
   * Interface that global interrupt handlers should use.
   * @author aclarke
   *
   */
  public interface Interruptable {
    /**
     * Called BEFORE native code calls {@link java.lang.Thread#interrupted()}.
     *

     * Please note that this method can be called from any thread
     * and it is the responsibility of the caller to ensure it is
     * thread safe.
     *

     *
     * @return true if the JNIThreadProxy should continue on an call {@link java.lang.Thread#interrupted()}.  false to stop
     *   processing now (and tell callers the thread is NOT interrupted).
     */
    public boolean preInterruptCheck();

    /**
     * Called AFTER native code calls {@link java.lang.Thread#interrupted()} and allows
     * the caller to override the returned value if desired.
     * @param interruptStatus The value returned by {@link Thread#interrupted()} on the current thread
     *
     * @return The value you actually want to return to native code.  Allows you to override the value returned.
     */
    public boolean postInterruptCheck(boolean interruptStatus);
  }
  private static final AtomicReference<Interruptable> mGlobalHandler = new AtomicReference<JNIThreadProxy.Interruptable>();

  private static final Logger log = LoggerFactory
      .getLogger(JNIThreadProxy.class);

  private static final ThreadLocal<JNIThreadProxy> mThreads = new ThreadLocal<JNIThreadProxy>();
  private final Thread mThread;
  private JNIThreadProxy(Thread thread)
  {
    mThread = thread;
  }

  /**
   * Gets the current global interrupt handler
   * @return The handler, or null if not set.
   */
  public static Interruptable getGlobalInterruptHandler()
  {
    return mGlobalHandler.get();
  }
  /**
   * Set a new global interrupt handler.
   * @param handler The new handler to use, or null to disable.
   * @return The previous handler, or null if none is set.
   */
  public static Interruptable setGlobalInterruptable(Interruptable handler)
  {
    return mGlobalHandler.getAndSet(handler);
  }
  /**
   * @see java.lang.Thread#currentThread
   * @return java.lang.Thread
   */
  public static Thread currentThread()
  {
    JNIThreadProxy retval = mThreads.get();
    if (retval == null) {
      retval = new JNIThreadProxy(Thread.currentThread());
      // store it in thread local storage
      mThreads.set(retval);
    }
    // hot function; do not call logging.
//    log.trace("currentThread: {}", retval.mThread);
    return retval;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean isInterrupted()
  {
    final Thread thread = mThreads.get().mThread;
    final Interruptable handler = getGlobalInterruptHandler();
    boolean retval = false;
    if (handler != null) {
      retval = handler.preInterruptCheck();
      if (!retval)
        return retval;
    }
    retval = thread.isInterrupted();
    if (handler != null) {
      retval = handler.postInterruptCheck(retval);
    }
    return retval;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void interrupt()
  {
    final Thread thread = mThreads.get().mThread;
    log.trace("interrupt (thread {})", thread);
    thread.interrupt();
    return;
  }
}