android.media.MediaCodec# configure ( ) 源码实例Demo

下面列出了android.media.MediaCodec# configure ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。


@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    @Nullable MediaCrypto crypto,
    float codecOperatingRate) {
  codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
  passthroughEnabled = codecInfo.passthrough;
  String codecMimeType = passthroughEnabled ? MimeTypes.AUDIO_RAW : codecInfo.codecMimeType;
  MediaFormat mediaFormat =
      getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
  codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
  if (passthroughEnabled) {
    // Store the input MIME type if we're using the passthrough codec.
    passthroughMediaFormat = mediaFormat;
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    passthroughMediaFormat = null;
  }
}
 

@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate) {
  String codecMimeType = codecInfo.codecMimeType;
  codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
  MediaFormat mediaFormat =
      getMediaFormat(
          format,
          codecMimeType,
          codecMaxValues,
          codecOperatingRate,
          deviceNeedsNoPostProcessWorkaround,
          tunnelingAudioSessionId);
  if (surface == null) {
    Assertions.checkState(shouldUseDummySurface(codecInfo));
    if (dummySurface == null) {
      dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
    }
    surface = dummySurface;
  }
  codec.configure(mediaFormat, surface, crypto, 0);
  if (Util.SDK_INT >= 23 && tunneling) {
    tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
  }
}
 
源代码3 项目: In77Camera   文件: MediaCodecUtils.java

@TargetApi(MIN_API_LEVEL_AUDIO)
public static int checkMediaCodecAudioEncoderSupport(){
    if(getApiLevel()<MIN_API_LEVEL_AUDIO){
        Log.d(TAG, "checkMediaCodecAudioEncoderSupport: Min API is 16");
        return CODEC_REQ_API_NOT_SATISFIED;
    }
    final MediaFormat audioFormat = MediaFormat.createAudioFormat(MIME_TYPE_AUDIO, TEST_SAMPLE_RATE, 1);
    audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
    audioFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_IN_MONO);
    audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, TEST_AUDIO_BIT_RATE);
    audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
    MediaCodec mediaCodec;
    try {
        mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE_AUDIO);
        mediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        mediaCodec.start();
        mediaCodec.stop();
        mediaCodec.release();
        mediaCodec = null;
    } catch (Exception ex) {
        Log.e(TAG, "Failed on creation of codec #", ex);
        return CODEC_ERROR;
    }
    return CODEC_SUPPORTED;
}
 

@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate) {
  codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  passthroughEnabled = codecInfo.passthrough;
  String codecMimeType = codecInfo.mimeType == null ? MimeTypes.AUDIO_RAW : codecInfo.mimeType;
  MediaFormat mediaFormat =
      getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
  codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
  if (passthroughEnabled) {
    // Store the input MIME type if we're using the passthrough codec.
    passthroughMediaFormat = mediaFormat;
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    passthroughMediaFormat = null;
  }
}
 

@Override
protected MediaCodec createMediaCodec() throws IOException {
    parseSps();

    MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
        format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_FULL);
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        format.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
    }

    format.setByteBuffer("csd-0", mCsd0);
    format.setByteBuffer("csd-1", mCsd1);

    if (DEBUG) {
        Log.d(TAG, "H264Decoder::createMediaCodec: " + format);
    }

    MediaCodec mediaCodec = MediaCodec.createDecoderByType(mMimeType);
    mediaCodec.configure(format, getSurface(), null, 0);
    mediaCodec.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
    mediaCodec.start();
    return mediaCodec;
}
 
源代码6 项目: deltachat-android   文件: AudioCodec.java

private MediaCodec createMediaCodec(Context context, int bufferSize) throws IOException {
  MediaCodec  mediaCodec  = MediaCodec.createEncoderByType("audio/mp4a-latm");
  MediaFormat mediaFormat = new MediaFormat();

  mediaFormat.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
  mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
  mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNELS);
  mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
  mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, Prefs.isHardCompressionEnabled(context)? BIT_RATE_WORSE : BIT_RATE_BALANCED);
  mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);

  try {
    mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
  } catch (Exception e) {
    Log.w(TAG, e);
    mediaCodec.release();
    throw new IOException(e);
  }

  return mediaCodec;
}
 

/**
 * @param media_extractor
 * @param trackIndex
 * @return
 */
protected MediaCodec internalStartVideo(final MediaExtractor media_extractor, final int trackIndex) {
	if (DEBUG) Log.v(TAG, "internalStartVideo:");
	MediaCodec codec = null;
	if (trackIndex >= 0) {
        final MediaFormat format = media_extractor.getTrackFormat(trackIndex);
        final String mime = format.getString(MediaFormat.KEY_MIME);
		try {
			codec = MediaCodec.createDecoderByType(mime);
			codec.configure(format, mOutputSurface, null, 0);
	        codec.start();
		} catch (final IOException e) {
			Log.w(TAG, e);
			codec = null;
		}
    	if (DEBUG) Log.v(TAG, "internalStartVideo:codec started");
	}
	return codec;
}
 

/**
 * Creates an encoder for the given format using the specified codec, taking input from a
 * surface.
 *
 * <p>The surface to use as input is stored in the given reference.
 *
 * @param codecName of the codec to use
 * @param format of the stream to be produced
 * @param surfaceReference to store the surface to use as input
 */
private MediaCodec createVideoEncoder(
        String codecName,
        MediaFormat format,
        AtomicReference<Surface> surfaceReference) {
    try {
        MediaCodec encoder = MediaCodec.createByCodecName(codecName);
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        // Must be called before start() is.
        surfaceReference.set(encoder.createInputSurface());
        encoder.start();
        return encoder;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
 
源代码9 项目: K-Sonic   文件: MediaCodecAudioRenderer.java

@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
    MediaCrypto crypto) {
  codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
  if (passthroughEnabled) {
    // Override the MIME type used to configure the codec if we are using a passthrough decoder.
    passthroughMediaFormat = format.getFrameworkMediaFormatV16();
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, MimeTypes.AUDIO_RAW);
    codec.configure(passthroughMediaFormat, null, crypto, 0);
    passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  } else {
    codec.configure(format.getFrameworkMediaFormatV16(), null, crypto, 0);
    passthroughMediaFormat = null;
  }
}
 

private @NonNull
MediaCodec createVideoEncoder(
        final @NonNull MediaCodecInfo codecInfo,
        final @NonNull MediaFormat format,
        final @NonNull AtomicReference<Surface> surfaceReference) throws IOException {
    final MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
    encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    // Must be called before start()
    surfaceReference.set(encoder.createInputSurface());
    encoder.start();
    return encoder;
}
 
源代码11 项目: ScreenCapture   文件: BaseEncoder.java

/**
 * Must call in a worker handler thread!
 */
@Override
public void prepare() throws IOException {
    if (Looper.myLooper() == null
            || Looper.myLooper() == Looper.getMainLooper()) {
        throw new IllegalStateException("should run in a HandlerThread");
    }
    if (mEncoder != null) {
        throw new IllegalStateException("prepared!");
    }
    MediaFormat format = createMediaFormat();
    Log.d("Encoder", "Create media format: " + format);

    String mimeType = format.getString(MediaFormat.KEY_MIME);
    final MediaCodec encoder = createEncoder(mimeType);
    try {
        if (this.mCallback != null) {
            // NOTE: MediaCodec maybe crash on some devices due to null callback
            encoder.setCallback(mCodecCallback);
        }
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        onEncoderConfigured(encoder);
        encoder.start();
    } catch (MediaCodec.CodecException e) {
        Log.e("Encoder", "Configure codec failure!\n  with format" + format, e);
        throw e;
    }
    mEncoder = encoder;
}
 

private static @NonNull
MediaCodec createAudioEncoder(final @NonNull MediaCodecInfo codecInfo, final @NonNull MediaFormat format) throws IOException {
    final MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
    encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
    encoder.start();
    return encoder;
}
 
源代码13 项目: SoloPi   文件: BaseEncoder.java

/**
 * Must call in a worker handler thread!
 */
@Override
public void prepare() throws IOException {
    if (Looper.myLooper() == null
            || Looper.myLooper() == Looper.getMainLooper()) {
        throw new IllegalStateException("should run in a HandlerThread");
    }
    if (mEncoder != null) {
        throw new IllegalStateException("prepared!");
    }
    MediaFormat format = createMediaFormat();
    LogUtil.i("Encoder", "Create media format: " + format);

    String mimeType = format.getString(MediaFormat.KEY_MIME);
    final MediaCodec encoder = createEncoder(mimeType);
    try {
        if (this.mCallback != null) {
            // NOTE: MediaCodec maybe crash on some devices due to null callback
            encoder.setCallback( mCodecCallback);
        }
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        onEncoderConfigured(encoder);
        encoder.start();
    } catch (MediaCodec.CodecException e) {
        LogUtil.e("Encoder", "Configure codec failure!\n  with format" + format, e);
        throw e;
    }
    mEncoder = encoder;
}
 

/**
 * Creates a decoder for the given format, which outputs to the given surface.
 *
 * @param inputFormat the format of the stream to decode
 * @param surface into which to decode the frames
 */
private MediaCodec createVideoDecoder(
        MediaCodecList mcl, MediaFormat inputFormat, Surface surface){
    try {
        MediaCodec decoder = MediaCodec.createByCodecName(mcl.findDecoderForFormat(inputFormat));
        decoder.configure(inputFormat, surface, null, 0);
        decoder.start();
        return decoder;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
 

@Override
protected void configureCodec(
    MediaCodecInfo codecInfo,
    MediaCodec codec,
    Format format,
    MediaCrypto crypto,
    float codecOperatingRate)
    throws DecoderQueryException {
  codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
  MediaFormat mediaFormat =
      getMediaFormat(
          format,
          codecMaxValues,
          codecOperatingRate,
          deviceNeedsAutoFrcWorkaround,
          tunnelingAudioSessionId);
  if (surface == null) {
    Assertions.checkState(shouldUseDummySurface(codecInfo));
    if (dummySurface == null) {
      dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
    }
    surface = dummySurface;
  }
  codec.configure(mediaFormat, surface, crypto, 0);
  if (Util.SDK_INT >= 23 && tunneling) {
    tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
  }
}
 
源代码16 项目: MusicPlus   文件: VideoMuxer.java

private MediaCodec createACCAudioDecoder() throws IOException {
	MediaCodec	codec = MediaCodec.createEncoderByType(AUDIO_MIME);
	MediaFormat format = new MediaFormat();
	format.setString(MediaFormat.KEY_MIME, AUDIO_MIME);
	format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
	format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
	format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
	format.setInteger(MediaFormat.KEY_AAC_PROFILE,
			MediaCodecInfo.CodecProfileLevel.AACObjectLC);
	codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
	return codec;
}
 

public boolean configure(SurfaceView surfaceView, int width, int height) {
    mSurfaceView = surfaceView;
    Log.d(TAG, "configure " + "width" + width + "height" + height + mSurfaceView.toString());

    MediaFormat format = new MediaFormat();
    format.setString(MediaFormat.KEY_MIME, "video/x-vnd.on2.vp8");
    format.setInteger(MediaFormat.KEY_WIDTH, width);
    format.setInteger(MediaFormat.KEY_HEIGHT, height);

    Surface surface = mSurfaceView.getHolder().getSurface();
    Log.d(TAG, "Surface " + surface.isValid());
    MediaCodec codec;
    try {
        codec = MediaCodec.createDecoderByType("video/x-vnd.on2.vp8");
        // SW VP8 decoder
        // codec = MediaCodec.createByCodecName("OMX.google.vpx.decoder");
        // Nexus10 HW VP8 decoder
        // codec = MediaCodec.createByCodecName("OMX.Exynos.VP8.Decoder");
    } catch (Exception e) {
        // TODO(dwkang): replace this instanceof/throw with a narrower catch clause
        // once the SDK advances.
        if (e instanceof IOException) {
            Log.e(TAG, "Failed to create MediaCodec for VP8.", e);
            return false;
        }
        throw new RuntimeException(e);
    }

    codec.configure(format, surface, null, 0);
    mCodecState = new CodecState(this, format, codec);
    initMediaCodecView();
    return true;
}
 
源代码18 项目: ssj   文件: AudioDecoder.java

/**
 * Decodes audio file into a raw file. This method accepts audio file formats with valid
 * headers (like .mp3, .mp4, and .wav).
 * @param filepath Path of the file to decode.
 * @return Decoded raw audio file.
 * @throws IOException when file cannot be read.
 */
private File decode(String filepath) throws IOException
{
	// Set selected audio file as a source.
	MediaExtractor extractor = new MediaExtractor();
	extractor.setDataSource(filepath);

	// Get audio format.
	MediaFormat format = extractor.getTrackFormat(0);
	String mime = format.getString(MediaFormat.KEY_MIME);

	// Cache necessary audio attributes.
	sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
	channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);

	// Create and configure decoder based on audio format.
	MediaCodec decoder = MediaCodec.createDecoderByType(mime);
	decoder.configure(format, null, null, 0);
	decoder.start();

	// Create input/output buffers.
	ByteBuffer[] inputBuffers = decoder.getInputBuffers();
	ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
	MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
	extractor.selectTrack(0);

	File dst = new File(FileCons.SSJ_EXTERNAL_STORAGE + File.separator + "output.raw");
	FileOutputStream f = new FileOutputStream(dst);

	boolean endOfStreamReached = false;

	while (true)
	{
		if (!endOfStreamReached)
		{
			int inputBufferIndex = decoder.dequeueInputBuffer(10 * 1000);
			if (inputBufferIndex >= 0)
			{
				ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
				int sampleSize = extractor.readSampleData(inputBuffer, 0);
				if (sampleSize < 0)
				{
					// Pass empty buffer and the end of stream flag to the codec.
					decoder.queueInputBuffer(inputBufferIndex, 0, 0,
											 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
					endOfStreamReached = true;
				}
				else
				{
					// Pass data-filled buffer to the decoder.
					decoder.queueInputBuffer(inputBufferIndex, 0, sampleSize,
											 extractor.getSampleTime(), 0);
					extractor.advance();
				}
			}
		}

		int outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 10 * 1000);
		if (outputBufferIndex >= 0)
		{
			ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
			byte[] data = new byte[bufferInfo.size];
			outputBuffer.get(data);
			outputBuffer.clear();

			if (data.length > 0)
			{
				f.write(data, 0, data.length);
			}
			decoder.releaseOutputBuffer(outputBufferIndex, false);

			if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
			{
				endOfStreamReached = true;
			}
		}
		else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
		{
			outputBuffers = decoder.getOutputBuffers();
		}

		if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
		{
			return dst;
		}
	}
}
 

static void extractThumbnails(final @NonNull MediaInput input,
                              final int thumbnailCount,
                              final int thumbnailResolution,
                              final @NonNull Callback callback)
{
  MediaExtractor extractor     = null;
  MediaCodec     decoder       = null;
  OutputSurface  outputSurface = null;
  try {
    extractor = input.createExtractor();
    MediaFormat mediaFormat = null;
    for (int index = 0; index < extractor.getTrackCount(); ++index) {
      if (extractor.getTrackFormat(index).getString(MediaFormat.KEY_MIME).startsWith("video/")) {
        extractor.selectTrack(index);
        mediaFormat = extractor.getTrackFormat(index);
        break;
      }
    }
    if (mediaFormat != null) {
      final String mime     = mediaFormat.getString(MediaFormat.KEY_MIME);
      final int    rotation = mediaFormat.containsKey(MediaFormat.KEY_ROTATION) ? mediaFormat.getInteger(MediaFormat.KEY_ROTATION) : 0;
      final int    width    = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
      final int    height   = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
      final int    outputWidth;
      final int    outputHeight;

      if (width < height) {
        outputWidth  = thumbnailResolution;
        outputHeight = height * outputWidth / width;
      } else {
        outputHeight = thumbnailResolution;
        outputWidth  = width * outputHeight / height;
      }

      final int outputWidthRotated;
      final int outputHeightRotated;

      if ((rotation % 180 == 90)) {
        //noinspection SuspiciousNameCombination
        outputWidthRotated = outputHeight;
        //noinspection SuspiciousNameCombination
        outputHeightRotated = outputWidth;
      } else {
        outputWidthRotated  = outputWidth;
        outputHeightRotated = outputHeight;
      }

      Log.i(TAG, "video: " + width + "x" + height + " " + rotation);
      Log.i(TAG, "output: " + outputWidthRotated + "x" + outputHeightRotated);

      outputSurface = new OutputSurface(outputWidthRotated, outputHeightRotated, true);

      decoder = MediaCodec.createDecoderByType(mime);
      decoder.configure(mediaFormat, outputSurface.getSurface(), null, 0);
      decoder.start();

      long duration = 0;

      if (mediaFormat.containsKey(MediaFormat.KEY_DURATION)) {
        duration = mediaFormat.getLong(MediaFormat.KEY_DURATION);
      } else {
        Log.w(TAG, "Video is missing duration!");
      }

      callback.durationKnown(duration);

      doExtract(extractor, decoder, outputSurface, outputWidthRotated, outputHeightRotated, duration, thumbnailCount, callback);
    }
  } catch (IOException | TranscodingException e) {
    Log.w(TAG, e);
    callback.failed();
  } finally {
    if (outputSurface != null) {
      outputSurface.release();
    }
    if (decoder != null) {
      decoder.stop();
      decoder.release();
    }
    if (extractor != null) {
      extractor.release();
    }
  }
}
 
源代码20 项目: VIA-AI   文件: MediaPlayerGrabber.java

private void decodeFrames(final MediaCodec decoder, MediaExtractor extractor, MediaFormat mediaFormat) {
    boolean sawInputEOS = false;
    sawOutputEOS = false;
    decoder.configure(mediaFormat, null, null, 0);
    decoder.start();

    if(!Helper.isUpperThanAPI21()) {
        inputByteBuffers = decoder.getInputBuffers();
        outputByteBuffers = decoder.getOutputBuffers();
    }

    while (!sawOutputEOS && !stopDecode) {
        if (!sawInputEOS) {
            int inputBufferId = decoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
            if (inputBufferId >= 0) {
                ByteBuffer inputBuffer = null;
                if (Helper.isUpperThanAPI21()) {
                    inputBuffer = decoder.getInputBuffer(inputBufferId);
                } else {
                    inputBuffer = inputByteBuffers[inputBufferId];
                }

                int sampleSize = extractor.readSampleData(inputBuffer, 0);
                if (sampleSize < 0) {
                    decoder.queueInputBuffer(inputBufferId, 0, 0, 0L, 0);
                    sawInputEOS = false;
                    extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
                } else {
                    long presentationTimeUs = extractor.getSampleTime();
                    decoder.queueInputBuffer(inputBufferId, 0, sampleSize, presentationTimeUs, 0);
                    extractor.advance();
                }
            }

        }

        if(displayThread==null) {
            displayThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (!sawOutputEOS && !stopDisplay) {
                        frameDisplay(decoder);
                    }
                }
            });
            displayThread.start();
        }
    }

}