/*
 *  Copyright 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.webrtc;

import android.graphics.SurfaceTexture;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.os.Build;
import android.os.SystemClock;
import android.view.Surface;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.webrtc.EglBase;
import org.webrtc.VideoFrame;

// Java-side of peerconnection.cc:MediaCodecVideoDecoder.
// This class is an implementation detail of the Java PeerConnection API.
@SuppressWarnings("deprecation")
public class MediaCodecVideoDecoder {
  // This class is constructed, operated, and destroyed by its C++ incarnation,
  // so the class and its methods have non-public visibility.  The API this
  // class exposes aims to mimic the webrtc::VideoDecoder API as closely as
  // possibly to minimize the amount of translation work necessary.

  private static final String TAG = "MediaCodecVideoDecoder";
  private static final long MAX_DECODE_TIME_MS = 200;

  // TODO(magjed): Use MediaFormat constants when part of the public API.
  private static final String FORMAT_KEY_STRIDE = "stride";
  private static final String FORMAT_KEY_SLICE_HEIGHT = "slice-height";
  private static final String FORMAT_KEY_CROP_LEFT = "crop-left";
  private static final String FORMAT_KEY_CROP_RIGHT = "crop-right";
  private static final String FORMAT_KEY_CROP_TOP = "crop-top";
  private static final String FORMAT_KEY_CROP_BOTTOM = "crop-bottom";

  // Tracks webrtc::VideoCodecType.
  public enum VideoCodecType {
    VIDEO_CODEC_UNKNOWN,
    VIDEO_CODEC_VP8,
    VIDEO_CODEC_VP9,
    VIDEO_CODEC_H264;

    @CalledByNative("VideoCodecType")
    static VideoCodecType fromNativeIndex(int nativeIndex) {
      return values()[nativeIndex];
    }
  }

  // Timeout for input buffer dequeue.
  private static final int DEQUEUE_INPUT_TIMEOUT = 500000;
  // Timeout for codec releasing.
  private static final int MEDIA_CODEC_RELEASE_TIMEOUT_MS = 5000;
  // Max number of output buffers queued before starting to drop decoded frames.
  private static final int MAX_QUEUED_OUTPUTBUFFERS = 3;
  // Active running decoder instance. Set in initDecode() (called from native code)
  // and reset to null in release() call.
  @Nullable private static MediaCodecVideoDecoder runningInstance = null;
  @Nullable private static MediaCodecVideoDecoderErrorCallback errorCallback = null;
  private static int codecErrors = 0;
  // List of disabled codec types - can be set from application.
  private static Set<String> hwDecoderDisabledTypes = new HashSet<String>();

  @Nullable private Thread mediaCodecThread;
  @Nullable private MediaCodec mediaCodec;
  private ByteBuffer[] inputBuffers;
  private ByteBuffer[] outputBuffers;
  private static final String VP8_MIME_TYPE = "video/x-vnd.on2.vp8";
  private static final String VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
  private static final String H264_MIME_TYPE = "video/avc";
  // List of supported HW VP8 decoders.
  private static final String[] supportedVp8HwCodecPrefixes() {
    ArrayList<String> supportedPrefixes = new ArrayList<String>();
    supportedPrefixes.add("OMX.qcom.");
    supportedPrefixes.add("OMX.Nvidia.");
    supportedPrefixes.add("OMX.Exynos.");
    supportedPrefixes.add("OMX.Intel.");
    if (PeerConnectionFactory.fieldTrialsFindFullName("WebRTC-MediaTekVP8").equals("Enabled")
        && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      supportedPrefixes.add("OMX.MTK.");
    }
    return supportedPrefixes.toArray(new String[supportedPrefixes.size()]);
  }
  // List of supported HW VP9 decoders.
  private static final String[] supportedVp9HwCodecPrefixes = {"OMX.qcom.", "OMX.Exynos."};
  // List of supported HW H.264 decoders.
  private static final String[] supportedH264HwCodecPrefixes() {
    ArrayList<String> supportedPrefixes = new ArrayList<String>();
    supportedPrefixes.add("OMX.qcom.");
    supportedPrefixes.add("OMX.Intel.");
    supportedPrefixes.add("OMX.Exynos.");
    if (PeerConnectionFactory.fieldTrialsFindFullName("WebRTC-MediaTekH264").equals("Enabled")
        && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
      supportedPrefixes.add("OMX.MTK.");
    }
    return supportedPrefixes.toArray(new String[supportedPrefixes.size()]);
  }

  // List of supported HW H.264 high profile decoders.
  private static final String supportedQcomH264HighProfileHwCodecPrefix = "OMX.qcom.";
  private static final String supportedExynosH264HighProfileHwCodecPrefix = "OMX.Exynos.";
  private static final String supportedMediaTekH264HighProfileHwCodecPrefix = "OMX.MTK.";

  // NV12 color format supported by QCOM codec, but not declared in MediaCodec -
  // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
  private static final int COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka = 0x7FA30C01;
  private static final int COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka = 0x7FA30C02;
  private static final int COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03;
  private static final int COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04;
  // Allowable color formats supported by codec - in order of preference.
  private static final List<Integer> supportedColorList = Arrays.asList(
      CodecCapabilities.COLOR_FormatYUV420Planar, CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
      CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
      COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka, COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka,
      COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka,
      COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m);

  private int colorFormat;
  private int width;
  private int height;
  private int stride;
  private int sliceHeight;
  private boolean hasDecodedFirstFrame;
  private final Queue<TimeStamps> decodeStartTimeMs = new ArrayDeque<TimeStamps>();
  private boolean useSurface;

  // The below variables are only used when decoding to a Surface.
  @Nullable private TextureListener textureListener;
  private int droppedFrames;
  @Nullable private Surface surface = null;
  private final Queue<DecodedOutputBuffer> dequeuedSurfaceOutputBuffers =
      new ArrayDeque<DecodedOutputBuffer>();

  // MediaCodec error handler - invoked when critical error happens which may prevent
  // further use of media codec API. Now it means that one of media codec instances
  // is hanging and can no longer be used in the next call.
  public static interface MediaCodecVideoDecoderErrorCallback {
    void onMediaCodecVideoDecoderCriticalError(int codecErrors);
  }

  public static void setErrorCallback(MediaCodecVideoDecoderErrorCallback errorCallback) {
    Logging.d(TAG, "Set error callback");
    MediaCodecVideoDecoder.errorCallback = errorCallback;
  }

  // Functions to disable HW decoding - can be called from applications for platforms
  // which have known HW decoding problems.
  public static void disableVp8HwCodec() {
    Logging.w(TAG, "VP8 decoding is disabled by application.");
    hwDecoderDisabledTypes.add(VP8_MIME_TYPE);
  }

  public static void disableVp9HwCodec() {
    Logging.w(TAG, "VP9 decoding is disabled by application.");
    hwDecoderDisabledTypes.add(VP9_MIME_TYPE);
  }

  public static void disableH264HwCodec() {
    Logging.w(TAG, "H.264 decoding is disabled by application.");
    hwDecoderDisabledTypes.add(H264_MIME_TYPE);
  }

  // Functions to query if HW decoding is supported.
  @CalledByNativeUnchecked
  public static boolean isVp8HwSupported() {
    return !hwDecoderDisabledTypes.contains(VP8_MIME_TYPE)
        && (findDecoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes()) != null);
  }

  @CalledByNativeUnchecked
  public static boolean isVp9HwSupported() {
    return !hwDecoderDisabledTypes.contains(VP9_MIME_TYPE)
        && (findDecoder(VP9_MIME_TYPE, supportedVp9HwCodecPrefixes) != null);
  }

  @CalledByNativeUnchecked
  public static boolean isH264HwSupported() {
    return !hwDecoderDisabledTypes.contains(H264_MIME_TYPE)
        && (findDecoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes()) != null);
  }

  @CalledByNative
  public static boolean isH264HighProfileHwSupported() {
    if (hwDecoderDisabledTypes.contains(H264_MIME_TYPE)) {
      return false;
    }
    // Support H.264 HP decoding on QCOM chips for Android L and above.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
        && findDecoder(H264_MIME_TYPE, new String[] {supportedQcomH264HighProfileHwCodecPrefix})
            != null) {
      return true;
    }
    // Support H.264 HP decoding on Exynos chips for Android M and above.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && findDecoder(H264_MIME_TYPE, new String[] {supportedExynosH264HighProfileHwCodecPrefix})
            != null) {
      return true;
    }
    // Support H.264 HP decoding on MediaTek chips for Android O_MR1 and above
    if (PeerConnectionFactory.fieldTrialsFindFullName("WebRTC-MediaTekH264").equals("Enabled")
        && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
        && findDecoder(H264_MIME_TYPE, new String[] {supportedMediaTekH264HighProfileHwCodecPrefix})
            != null) {
      return true;
    }
    return false;
  }

  public static void printStackTrace() {
    if (runningInstance != null && runningInstance.mediaCodecThread != null) {
      StackTraceElement[] mediaCodecStackTraces = runningInstance.mediaCodecThread.getStackTrace();
      if (mediaCodecStackTraces.length > 0) {
        Logging.d(TAG, "MediaCodecVideoDecoder stacks trace:");
        for (StackTraceElement stackTrace : mediaCodecStackTraces) {
          Logging.d(TAG, stackTrace.toString());
        }
      }
    }
  }

  // Helper struct for findDecoder() below.
  private static class DecoderProperties {
    public DecoderProperties(String codecName, int colorFormat) {
      this.codecName = codecName;
      this.colorFormat = colorFormat;
    }
    public final String codecName; // OpenMax component name for VP8 codec.
    public final int colorFormat; // Color format supported by codec.
  }

  private static @Nullable DecoderProperties findDecoder(
      String mime, String[] supportedCodecPrefixes) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
      return null; // MediaCodec.setParameters is missing.
    }
    Logging.d(TAG, "Trying to find HW decoder for mime " + mime);
    for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) {
      MediaCodecInfo info = null;
      try {
        info = MediaCodecList.getCodecInfoAt(i);
      } catch (IllegalArgumentException e) {
        Logging.e(TAG, "Cannot retrieve decoder codec info", e);
      }
      if (info == null || info.isEncoder()) {
        continue;
      }
      String name = null;
      for (String mimeType : info.getSupportedTypes()) {
        if (mimeType.equals(mime)) {
          name = info.getName();
          break;
        }
      }
      if (name == null) {
        continue; // No HW support in this codec; try the next one.
      }
      Logging.d(TAG, "Found candidate decoder " + name);

      // Check if this is supported decoder.
      boolean supportedCodec = false;
      for (String codecPrefix : supportedCodecPrefixes) {
        if (name.startsWith(codecPrefix)) {
          supportedCodec = true;
          break;
        }
      }
      if (!supportedCodec) {
        continue;
      }

      // Check if codec supports either yuv420 or nv12.
      CodecCapabilities capabilities;
      try {
        capabilities = info.getCapabilitiesForType(mime);
      } catch (IllegalArgumentException e) {
        Logging.e(TAG, "Cannot retrieve decoder capabilities", e);
        continue;
      }
      for (int colorFormat : capabilities.colorFormats) {
        Logging.v(TAG, "   Color: 0x" + Integer.toHexString(colorFormat));
      }
      for (int supportedColorFormat : supportedColorList) {
        for (int codecColorFormat : capabilities.colorFormats) {
          if (codecColorFormat == supportedColorFormat) {
            // Found supported HW decoder.
            Logging.d(TAG, "Found target decoder " + name + ". Color: 0x"
                    + Integer.toHexString(codecColorFormat));
            return new DecoderProperties(name, codecColorFormat);
          }
        }
      }
    }
    Logging.d(TAG, "No HW decoder found for mime " + mime);
    return null; // No HW decoder.
  }

  @CalledByNative
  MediaCodecVideoDecoder() {}

  private void checkOnMediaCodecThread() throws IllegalStateException {
    if (mediaCodecThread.getId() != Thread.currentThread().getId()) {
      throw new IllegalStateException("MediaCodecVideoDecoder previously operated on "
          + mediaCodecThread + " but is now called on " + Thread.currentThread());
    }
  }

  // Pass null in |eglContext| to configure the codec for ByteBuffer output.
  @CalledByNativeUnchecked
  private boolean initDecode(
      VideoCodecType type, int width, int height, @Nullable EglBase.Context eglContext) {
    if (mediaCodecThread != null) {
      throw new RuntimeException("initDecode: Forgot to release()?");
    }

    String mime = null;
    useSurface = (eglContext != null);
    String[] supportedCodecPrefixes = null;
    if (type == VideoCodecType.VIDEO_CODEC_VP8) {
      mime = VP8_MIME_TYPE;
      supportedCodecPrefixes = supportedVp8HwCodecPrefixes();
    } else if (type == VideoCodecType.VIDEO_CODEC_VP9) {
      mime = VP9_MIME_TYPE;
      supportedCodecPrefixes = supportedVp9HwCodecPrefixes;
    } else if (type == VideoCodecType.VIDEO_CODEC_H264) {
      mime = H264_MIME_TYPE;
      supportedCodecPrefixes = supportedH264HwCodecPrefixes();
    } else {
      throw new RuntimeException("initDecode: Non-supported codec " + type);
    }
    DecoderProperties properties = findDecoder(mime, supportedCodecPrefixes);
    if (properties == null) {
      throw new RuntimeException("Cannot find HW decoder for " + type);
    }

    Logging.d(TAG, "Java initDecode: " + type + " : " + width + " x " + height + ". Color: 0x"
            + Integer.toHexString(properties.colorFormat) + ". Use Surface: " + useSurface);

    runningInstance = this; // Decoder is now running and can be queried for stack traces.
    mediaCodecThread = Thread.currentThread();
    try {
      this.width = width;
      this.height = height;
      stride = width;
      sliceHeight = height;

      if (useSurface) {
        @Nullable
        final SurfaceTextureHelper surfaceTextureHelper =
            SurfaceTextureHelper.create("Decoder SurfaceTextureHelper", eglContext);
        if (surfaceTextureHelper != null) {
          textureListener = new TextureListener(surfaceTextureHelper);
          surface = new Surface(surfaceTextureHelper.getSurfaceTexture());
        }
      }

      MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
      if (!useSurface) {
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
      }
      Logging.d(TAG, "  Format: " + format);
      mediaCodec = MediaCodecVideoEncoder.createByCodecName(properties.codecName);
      if (mediaCodec == null) {
        Logging.e(TAG, "Can not create media decoder");
        return false;
      }
      mediaCodec.configure(format, surface, null, 0);
      mediaCodec.start();

      colorFormat = properties.colorFormat;
      outputBuffers = mediaCodec.getOutputBuffers();
      inputBuffers = mediaCodec.getInputBuffers();
      decodeStartTimeMs.clear();
      hasDecodedFirstFrame = false;
      dequeuedSurfaceOutputBuffers.clear();
      droppedFrames = 0;
      Logging.d(TAG,
          "Input buffers: " + inputBuffers.length + ". Output buffers: " + outputBuffers.length);
      return true;
    } catch (IllegalStateException e) {
      Logging.e(TAG, "initDecode failed", e);
      return false;
    }
  }

  // Resets the decoder so it can start decoding frames with new resolution.
  // Flushes MediaCodec and clears decoder output buffers.
  @CalledByNativeUnchecked
  private void reset(int width, int height) {
    if (mediaCodecThread == null || mediaCodec == null) {
      throw new RuntimeException("Incorrect reset call for non-initialized decoder.");
    }
    Logging.d(TAG, "Java reset: " + width + " x " + height);

    mediaCodec.flush();

    this.width = width;
    this.height = height;
    decodeStartTimeMs.clear();
    dequeuedSurfaceOutputBuffers.clear();
    hasDecodedFirstFrame = false;
    droppedFrames = 0;
  }

  @CalledByNativeUnchecked
  private void release() {
    Logging.d(TAG, "Java releaseDecoder. Total number of dropped frames: " + droppedFrames);
    checkOnMediaCodecThread();

    // Run Mediacodec stop() and release() on separate thread since sometime
    // Mediacodec.stop() may hang.
    final CountDownLatch releaseDone = new CountDownLatch(1);

    Runnable runMediaCodecRelease = new Runnable() {
      @Override
      public void run() {
        try {
          Logging.d(TAG, "Java releaseDecoder on release thread");
          mediaCodec.stop();
          mediaCodec.release();
          Logging.d(TAG, "Java releaseDecoder on release thread done");
        } catch (Exception e) {
          Logging.e(TAG, "Media decoder release failed", e);
        }
        releaseDone.countDown();
      }
    };
    new Thread(runMediaCodecRelease).start();

    if (!ThreadUtils.awaitUninterruptibly(releaseDone, MEDIA_CODEC_RELEASE_TIMEOUT_MS)) {
      Logging.e(TAG, "Media decoder release timeout");
      codecErrors++;
      if (errorCallback != null) {
        Logging.e(TAG, "Invoke codec error callback. Errors: " + codecErrors);
        errorCallback.onMediaCodecVideoDecoderCriticalError(codecErrors);
      }
    }

    mediaCodec = null;
    mediaCodecThread = null;
    runningInstance = null;
    if (useSurface) {
      surface.release();
      surface = null;
      textureListener.release();
    }
    Logging.d(TAG, "Java releaseDecoder done");
  }

  // Dequeue an input buffer and return its index, -1 if no input buffer is
  // available, or -2 if the codec is no longer operative.
  @CalledByNativeUnchecked
  private int dequeueInputBuffer() {
    checkOnMediaCodecThread();
    try {
      return mediaCodec.dequeueInputBuffer(DEQUEUE_INPUT_TIMEOUT);
    } catch (IllegalStateException e) {
      Logging.e(TAG, "dequeueIntputBuffer failed", e);
      return -2;
    }
  }

  @CalledByNativeUnchecked
  private boolean queueInputBuffer(int inputBufferIndex, int size, long presentationTimeStamUs,
      long timeStampMs, long ntpTimeStamp) {
    checkOnMediaCodecThread();
    try {
      inputBuffers[inputBufferIndex].position(0);
      inputBuffers[inputBufferIndex].limit(size);
      decodeStartTimeMs.add(
          new TimeStamps(SystemClock.elapsedRealtime(), timeStampMs, ntpTimeStamp));
      mediaCodec.queueInputBuffer(inputBufferIndex, 0, size, presentationTimeStamUs, 0);
      return true;
    } catch (IllegalStateException e) {
      Logging.e(TAG, "decode failed", e);
      return false;
    }
  }

  private static class TimeStamps {
    public TimeStamps(long decodeStartTimeMs, long timeStampMs, long ntpTimeStampMs) {
      this.decodeStartTimeMs = decodeStartTimeMs;
      this.timeStampMs = timeStampMs;
      this.ntpTimeStampMs = ntpTimeStampMs;
    }
    // Time when this frame was queued for decoding.
    private final long decodeStartTimeMs;
    // Only used for bookkeeping in Java. Stores C++ inputImage._timeStamp value for input frame.
    private final long timeStampMs;
    // Only used for bookkeeping in Java. Stores C++ inputImage.ntp_time_ms_ value for input frame.
    private final long ntpTimeStampMs;
  }

  // Helper struct for dequeueOutputBuffer() below.
  private static class DecodedOutputBuffer {
    public DecodedOutputBuffer(int index, int offset, int size, long presentationTimeStampMs,
        long timeStampMs, long ntpTimeStampMs, long decodeTime, long endDecodeTime) {
      this.index = index;
      this.offset = offset;
      this.size = size;
      this.presentationTimeStampMs = presentationTimeStampMs;
      this.timeStampMs = timeStampMs;
      this.ntpTimeStampMs = ntpTimeStampMs;
      this.decodeTimeMs = decodeTime;
      this.endDecodeTimeMs = endDecodeTime;
    }

    private final int index;
    private final int offset;
    private final int size;
    // Presentation timestamp returned in dequeueOutputBuffer call.
    private final long presentationTimeStampMs;
    // C++ inputImage._timeStamp value for output frame.
    private final long timeStampMs;
    // C++ inputImage.ntp_time_ms_ value for output frame.
    private final long ntpTimeStampMs;
    // Number of ms it took to decode this frame.
    private final long decodeTimeMs;
    // System time when this frame decoding finished.
    private final long endDecodeTimeMs;

    @CalledByNative("DecodedOutputBuffer")
    int getIndex() {
      return index;
    }

    @CalledByNative("DecodedOutputBuffer")
    int getOffset() {
      return offset;
    }

    @CalledByNative("DecodedOutputBuffer")
    int getSize() {
      return size;
    }

    @CalledByNative("DecodedOutputBuffer")
    long getPresentationTimestampMs() {
      return presentationTimeStampMs;
    }

    @CalledByNative("DecodedOutputBuffer")
    long getTimestampMs() {
      return timeStampMs;
    }

    @CalledByNative("DecodedOutputBuffer")
    long getNtpTimestampMs() {
      return ntpTimeStampMs;
    }

    @CalledByNative("DecodedOutputBuffer")
    long getDecodeTimeMs() {
      return decodeTimeMs;
    }
  }

  // Helper struct for dequeueTextureBuffer() below.
  private static class DecodedTextureBuffer {
    private final VideoFrame.Buffer videoFrameBuffer;
    // Presentation timestamp returned in dequeueOutputBuffer call.
    private final long presentationTimeStampMs;
    // C++ inputImage._timeStamp value for output frame.
    private final long timeStampMs;
    // C++ inputImage.ntp_time_ms_ value for output frame.
    private final long ntpTimeStampMs;
    // Number of ms it took to decode this frame.
    private final long decodeTimeMs;
    // Interval from when the frame finished decoding until this buffer has been created.
    // Since there is only one texture, this interval depend on the time from when
    // a frame is decoded and provided to C++ and until that frame is returned to the MediaCodec
    // so that the texture can be updated with the next decoded frame.
    private final long frameDelayMs;

    // A DecodedTextureBuffer with zero |textureID| has special meaning and represents a frame
    // that was dropped.
    public DecodedTextureBuffer(VideoFrame.Buffer videoFrameBuffer, long presentationTimeStampMs,
        long timeStampMs, long ntpTimeStampMs, long decodeTimeMs, long frameDelay) {
      this.videoFrameBuffer = videoFrameBuffer;
      this.presentationTimeStampMs = presentationTimeStampMs;
      this.timeStampMs = timeStampMs;
      this.ntpTimeStampMs = ntpTimeStampMs;
      this.decodeTimeMs = decodeTimeMs;
      this.frameDelayMs = frameDelay;
    }

    @CalledByNative("DecodedTextureBuffer")
    VideoFrame.Buffer getVideoFrameBuffer() {
      return videoFrameBuffer;
    }

    @CalledByNative("DecodedTextureBuffer")
    long getPresentationTimestampMs() {
      return presentationTimeStampMs;
    }

    @CalledByNative("DecodedTextureBuffer")
    long getTimeStampMs() {
      return timeStampMs;
    }

    @CalledByNative("DecodedTextureBuffer")
    long getNtpTimestampMs() {
      return ntpTimeStampMs;
    }

    @CalledByNative("DecodedTextureBuffer")
    long getDecodeTimeMs() {
      return decodeTimeMs;
    }

    @CalledByNative("DecodedTextureBuffer")
    long getFrameDelayMs() {
      return frameDelayMs;
    }
  }

  // Poll based texture listener.
  private class TextureListener implements SurfaceTextureHelper.OnTextureFrameAvailableListener {
    private final SurfaceTextureHelper surfaceTextureHelper;
    // |newFrameLock| is used to synchronize arrival of new frames with wait()/notifyAll().
    private final Object newFrameLock = new Object();
    // |bufferToRender| is non-null when waiting for transition between addBufferToRender() to
    // onTextureFrameAvailable().
    @Nullable private DecodedOutputBuffer bufferToRender;
    @Nullable private DecodedTextureBuffer renderedBuffer;

    public TextureListener(SurfaceTextureHelper surfaceTextureHelper) {
      this.surfaceTextureHelper = surfaceTextureHelper;
      surfaceTextureHelper.startListening(this);
    }

    public void addBufferToRender(DecodedOutputBuffer buffer) {
      if (bufferToRender != null) {
        Logging.e(TAG, "Unexpected addBufferToRender() called while waiting for a texture.");
        throw new IllegalStateException("Waiting for a texture.");
      }
      bufferToRender = buffer;
    }

    public boolean isWaitingForTexture() {
      synchronized (newFrameLock) {
        return bufferToRender != null;
      }
    }

    // Callback from |surfaceTextureHelper|. May be called on an arbitrary thread.
    @Override
    public void onTextureFrameAvailable(
        int oesTextureId, float[] transformMatrix, long timestampNs) {
      synchronized (newFrameLock) {
        if (renderedBuffer != null) {
          Logging.e(
              TAG, "Unexpected onTextureFrameAvailable() called while already holding a texture.");
          throw new IllegalStateException("Already holding a texture.");
        }
        // |timestampNs| is always zero on some Android versions.
        final VideoFrame.Buffer buffer = surfaceTextureHelper.createTextureBuffer(
            width, height, RendererCommon.convertMatrixToAndroidGraphicsMatrix(transformMatrix));
        renderedBuffer = new DecodedTextureBuffer(buffer, bufferToRender.presentationTimeStampMs,
            bufferToRender.timeStampMs, bufferToRender.ntpTimeStampMs, bufferToRender.decodeTimeMs,
            SystemClock.elapsedRealtime() - bufferToRender.endDecodeTimeMs);
        bufferToRender = null;
        newFrameLock.notifyAll();
      }
    }

    // Dequeues and returns a DecodedTextureBuffer if available, or null otherwise.
    @Nullable
    @SuppressWarnings("WaitNotInLoop")
    public DecodedTextureBuffer dequeueTextureBuffer(int timeoutMs) {
      synchronized (newFrameLock) {
        if (renderedBuffer == null && timeoutMs > 0 && isWaitingForTexture()) {
          try {
            newFrameLock.wait(timeoutMs);
          } catch (InterruptedException e) {
            // Restore the interrupted status by reinterrupting the thread.
            Thread.currentThread().interrupt();
          }
        }
        DecodedTextureBuffer returnedBuffer = renderedBuffer;
        renderedBuffer = null;
        return returnedBuffer;
      }
    }

    public void release() {
      // SurfaceTextureHelper.stopListening() will block until any onTextureFrameAvailable() in
      // progress is done. Therefore, the call must be outside any synchronized
      // statement that is also used in the onTextureFrameAvailable() above to avoid deadlocks.
      surfaceTextureHelper.stopListening();
      synchronized (newFrameLock) {
        if (renderedBuffer != null) {
          renderedBuffer.getVideoFrameBuffer().release();
          renderedBuffer = null;
        }
      }
      surfaceTextureHelper.dispose();
    }
  }

  // Returns null if no decoded buffer is available, and otherwise a DecodedByteBuffer.
  // Throws IllegalStateException if call is made on the wrong thread, if color format changes to an
  // unsupported format, or if |mediaCodec| is not in the Executing state. Throws CodecException
  // upon codec error.
  @CalledByNativeUnchecked
  private @Nullable DecodedOutputBuffer dequeueOutputBuffer(int dequeueTimeoutMs) {
    checkOnMediaCodecThread();
    if (decodeStartTimeMs.isEmpty()) {
      return null;
    }
    // Drain the decoder until receiving a decoded buffer or hitting
    // MediaCodec.INFO_TRY_AGAIN_LATER.
    final MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
    while (true) {
      final int result =
          mediaCodec.dequeueOutputBuffer(info, TimeUnit.MILLISECONDS.toMicros(dequeueTimeoutMs));
      switch (result) {
        case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
          outputBuffers = mediaCodec.getOutputBuffers();
          Logging.d(TAG, "Decoder output buffers changed: " + outputBuffers.length);
          if (hasDecodedFirstFrame) {
            throw new RuntimeException("Unexpected output buffer change event.");
          }
          break;
        case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
          MediaFormat format = mediaCodec.getOutputFormat();
          Logging.d(TAG, "Decoder format changed: " + format.toString());
          final int newWidth;
          final int newHeight;
          if (format.containsKey(FORMAT_KEY_CROP_LEFT) && format.containsKey(FORMAT_KEY_CROP_RIGHT)
              && format.containsKey(FORMAT_KEY_CROP_BOTTOM)
              && format.containsKey(FORMAT_KEY_CROP_TOP)) {
            newWidth = 1 + format.getInteger(FORMAT_KEY_CROP_RIGHT)
                - format.getInteger(FORMAT_KEY_CROP_LEFT);
            newHeight = 1 + format.getInteger(FORMAT_KEY_CROP_BOTTOM)
                - format.getInteger(FORMAT_KEY_CROP_TOP);
          } else {
            newWidth = format.getInteger(MediaFormat.KEY_WIDTH);
            newHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
          }
          if (hasDecodedFirstFrame && (newWidth != width || newHeight != height)) {
            throw new RuntimeException("Unexpected size change. Configured " + width + "*" + height
                + ". New " + newWidth + "*" + newHeight);
          }
          width = newWidth;
          height = newHeight;

          if (!useSurface && format.containsKey(MediaFormat.KEY_COLOR_FORMAT)) {
            colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
            Logging.d(TAG, "Color: 0x" + Integer.toHexString(colorFormat));
            if (!supportedColorList.contains(colorFormat)) {
              throw new IllegalStateException("Non supported color format: " + colorFormat);
            }
          }
          if (format.containsKey(FORMAT_KEY_STRIDE)) {
            stride = format.getInteger(FORMAT_KEY_STRIDE);
          }
          if (format.containsKey(FORMAT_KEY_SLICE_HEIGHT)) {
            sliceHeight = format.getInteger(FORMAT_KEY_SLICE_HEIGHT);
          }
          Logging.d(TAG, "Frame stride and slice height: " + stride + " x " + sliceHeight);
          stride = Math.max(width, stride);
          sliceHeight = Math.max(height, sliceHeight);
          break;
        case MediaCodec.INFO_TRY_AGAIN_LATER:
          return null;
        default:
          hasDecodedFirstFrame = true;
          TimeStamps timeStamps = decodeStartTimeMs.remove();
          long decodeTimeMs = SystemClock.elapsedRealtime() - timeStamps.decodeStartTimeMs;
          if (decodeTimeMs > MAX_DECODE_TIME_MS) {
            Logging.e(TAG, "Very high decode time: " + decodeTimeMs + "ms"
                    + ". Q size: " + decodeStartTimeMs.size()
                    + ". Might be caused by resuming H264 decoding after a pause.");
            decodeTimeMs = MAX_DECODE_TIME_MS;
          }
          return new DecodedOutputBuffer(result, info.offset, info.size,
              TimeUnit.MICROSECONDS.toMillis(info.presentationTimeUs), timeStamps.timeStampMs,
              timeStamps.ntpTimeStampMs, decodeTimeMs, SystemClock.elapsedRealtime());
      }
    }
  }

  // Returns null if no decoded buffer is available, and otherwise a DecodedTextureBuffer.
  // Throws IllegalStateException if call is made on the wrong thread, if color format changes to an
  // unsupported format, or if |mediaCodec| is not in the Executing state. Throws CodecException
  // upon codec error. If |dequeueTimeoutMs| > 0, the oldest decoded frame will be dropped if
  // a frame can't be returned.
  @CalledByNativeUnchecked
  private @Nullable DecodedTextureBuffer dequeueTextureBuffer(int dequeueTimeoutMs) {
    checkOnMediaCodecThread();
    if (!useSurface) {
      throw new IllegalStateException("dequeueTexture() called for byte buffer decoding.");
    }
    DecodedOutputBuffer outputBuffer = dequeueOutputBuffer(dequeueTimeoutMs);
    if (outputBuffer != null) {
      dequeuedSurfaceOutputBuffers.add(outputBuffer);
    }

    MaybeRenderDecodedTextureBuffer();
    // Check if there is texture ready now by waiting max |dequeueTimeoutMs|.
    DecodedTextureBuffer renderedBuffer = textureListener.dequeueTextureBuffer(dequeueTimeoutMs);
    if (renderedBuffer != null) {
      MaybeRenderDecodedTextureBuffer();
      return renderedBuffer;
    }

    if ((dequeuedSurfaceOutputBuffers.size()
                >= Math.min(MAX_QUEUED_OUTPUTBUFFERS, outputBuffers.length)
            || (dequeueTimeoutMs > 0 && !dequeuedSurfaceOutputBuffers.isEmpty()))) {
      ++droppedFrames;
      // Drop the oldest frame still in dequeuedSurfaceOutputBuffers.
      // The oldest frame is owned by |textureListener| and can't be dropped since
      // mediaCodec.releaseOutputBuffer has already been called.
      final DecodedOutputBuffer droppedFrame = dequeuedSurfaceOutputBuffers.remove();
      if (dequeueTimeoutMs > 0) {
        // TODO(perkj): Re-add the below log when VideoRenderGUI has been removed or fixed to
        // return the one and only texture even if it does not render.
        Logging.w(TAG, "Draining decoder. Dropping frame with TS: "
                + droppedFrame.presentationTimeStampMs + ". Total number of dropped frames: "
                + droppedFrames);
      } else {
        Logging.w(TAG, "Too many output buffers " + dequeuedSurfaceOutputBuffers.size()
                + ". Dropping frame with TS: " + droppedFrame.presentationTimeStampMs
                + ". Total number of dropped frames: " + droppedFrames);
      }

      mediaCodec.releaseOutputBuffer(droppedFrame.index, false /* render */);
      return new DecodedTextureBuffer(null /* videoFrameBuffer */,
          droppedFrame.presentationTimeStampMs, droppedFrame.timeStampMs,
          droppedFrame.ntpTimeStampMs, droppedFrame.decodeTimeMs,
          SystemClock.elapsedRealtime() - droppedFrame.endDecodeTimeMs);
    }
    return null;
  }

  private void MaybeRenderDecodedTextureBuffer() {
    if (dequeuedSurfaceOutputBuffers.isEmpty() || textureListener.isWaitingForTexture()) {
      return;
    }
    // Get the first frame in the queue and render to the decoder output surface.
    final DecodedOutputBuffer buffer = dequeuedSurfaceOutputBuffers.remove();
    textureListener.addBufferToRender(buffer);
    mediaCodec.releaseOutputBuffer(buffer.index, true /* render */);
  }

  // Release a dequeued output byte buffer back to the codec for re-use. Should only be called for
  // non-surface decoding.
  // Throws IllegalStateException if the call is made on the wrong thread, if codec is configured
  // for surface decoding, or if |mediaCodec| is not in the Executing state. Throws
  // MediaCodec.CodecException upon codec error.
  @CalledByNativeUnchecked
  private void returnDecodedOutputBuffer(int index)
      throws IllegalStateException, MediaCodec.CodecException {
    checkOnMediaCodecThread();
    if (useSurface) {
      throw new IllegalStateException("returnDecodedOutputBuffer() called for surface decoding.");
    }
    mediaCodec.releaseOutputBuffer(index, false /* render */);
  }

  @CalledByNative
  ByteBuffer[] getInputBuffers() {
    return inputBuffers;
  }

  @CalledByNative
  ByteBuffer[] getOutputBuffers() {
    return outputBuffers;
  }

  @CalledByNative
  int getColorFormat() {
    return colorFormat;
  }

  @CalledByNative
  int getWidth() {
    return width;
  }

  @CalledByNative
  int getHeight() {
    return height;
  }

  @CalledByNative
  int getStride() {
    return stride;
  }

  @CalledByNative
  int getSliceHeight() {
    return sliceHeight;
  }
}
