public void open(VirtualInputFile input) {

    close();

    this.input = input;

    container = IContainer.make();
    format = IContainerFormat.make();
    packet = IPacket.make();

    // open the input video file
    int success = container.open(input, format, true, true);
    /*		int success = -1;

    		try {
    			RandomAccessFile f = new RandomAccessFile("j:/grey.avi", "r");
    			success = container.open(f, Type.READ, format);

    		} catch (FileNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    */

    if (success < 0) {

      throw new RuntimeException(
          "XUGGLER DECODER: could not open input: " + input.getLocation().getDecodedURL());
    }

    for (int streamIndex = 0; streamIndex < container.getNumStreams(); streamIndex++) {

      IStreamCoder coder = container.getStream(streamIndex).getStreamCoder();

      switch (coder.getCodecType()) {
        case CODEC_TYPE_VIDEO:
          {
            videoStream = coder;
            videoStreamIndex = streamIndex;
            break;
          }
        case CODEC_TYPE_AUDIO:
          {
            audioStream = coder;
            audioStreamIndex = streamIndex;
            break;
          }
        default:
          {
            break;
          }
      }
    }

    setDecodeMode(DecodeMode.NORMAL);
  }
  public void decode() {

    int success = videoStream.open();
    if (success < 0) {

      throw new RuntimeException(
          "XUGGLER DECODER: could not open video decoder for container: "
              + input.getLocation().getDecodedURL());
    }

    IAudioSamples decodeSamples = null;

    if (audioStream != null) {

      success = audioStream.open();
      if (success < 0) {

        throw new RuntimeException(
            "XUGGLER DECODER: could not open audio decoder for container: "
                + input.getLocation().getDecodedURL());
      }

      decodeSamples = IAudioSamples.make(1024, audioStream.getChannels());
    }

    IVideoPicture decodePicture =
        IVideoPicture.make(
            videoStream.getPixelType(), videoStream.getWidth(), videoStream.getHeight());

    while (container.readNextPacket(packet) >= 0 && decodeMode != DecodeMode.STOP) {

      /** Find out if this stream has a starting timestamp */
      IStream stream = container.getStream(packet.getStreamIndex());
      long tsOffset = 0;
      if (stream.getStartTime() != Global.NO_PTS
          && stream.getStartTime() > 0
          && stream.getTimeBase() != null) {
        IRational defTimeBase = IRational.make(1, (int) Global.DEFAULT_PTS_PER_SECOND);
        tsOffset = defTimeBase.rescale(stream.getStartTime(), stream.getTimeBase());
      }

      /*
       * Now we have a packet, let's see if it belongs to our video stream
       */
      if (packet.getStreamIndex() == videoStreamIndex) {

        int offset = 0;
        while (offset < packet.getSize()) {
          /*
           * Now, we decode the video, checking for any errors.
           *
           */
          int bytesDecoded = videoStream.decodeVideo(decodePicture, packet, offset);
          if (bytesDecoded < 0) {

            throw new RuntimeException(
                "XUGGLER: error decoding video in: " + input.getLocation().getDecodedURL());
          }

          if (decodePicture.getTimeStamp() != Global.NO_PTS) {

            decodePicture.setTimeStamp(decodePicture.getTimeStamp() - tsOffset);
          }

          offset += bytesDecoded;
          /*
           * Some decoders will consume data in a packet, but will not be able to construct
           * a full video picture yet.  Therefore you should always check if you
           * got a complete picture from the decoder
           */
          if (decodePicture.isComplete()) {

            decodedPicture(decodePicture);
          }
        }

      } else if (audioStream != null
          && packet.getStreamIndex() == audioStreamIndex
          && decodeMode != DecodeMode.IGNORE_AUDIO) {

        /*
         * A packet can actually contain multiple sets of samples (or frames of samples
         * in audio-decoding speak).  So, we may need to call decode audio multiple
         * times at different offsets in the packet's data.  We capture that here.
         */
        int offset = 0;

        /*
         * Keep going until we've processed all data
         */
        while (offset < packet.getSize()) {
          int bytesDecoded = audioStream.decodeAudio(decodeSamples, packet, offset);
          if (bytesDecoded < 0) {
            break;
            // throw new RuntimeException("XUGGLER: got error decoding audio in: " +
            // inputVideoFile);

          }

          if (decodeSamples.getTimeStamp() != Global.NO_PTS) {

            decodeSamples.setTimeStamp(decodeSamples.getTimeStamp() - tsOffset);
          }

          offset += bytesDecoded;
          /*
           * Some decoder will consume data in a packet, but will not be able to construct
           * a full set of samples yet.  Therefore you should always check if you
           * got a complete set of samples from the decoder
           */
          if (decodeSamples.isComplete()) {

            decodedAudioSamples(decodeSamples);
          }
        }

      } else {

        /*
         * This packet isn't part of our video stream, so we just
         * silently drop it.
         */
        continue;
      }
    }
  }