/*
 *  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);
          textureListener.setSize(width, height);
          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;
    if (textureListener != null) {
      textureListener.setSize(width, 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 VideoSink {
    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
    // onFrame().
    @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;
      }
    }

    public void setSize(int width, int height) {
      surfaceTextureHelper.setTextureSize(width, height);
    }

    // Callback from |surfaceTextureHelper|. May be called on an arbitrary thread.
    @Override
    public void onFrame(VideoFrame frame) {
      synchronized (newFrameLock) {
        if (renderedBuffer != null) {
          Logging.e(TAG, "Unexpected onFrame() 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 = frame.getBuffer();
        buffer.retain();
        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 onFrame() in progress is done.
      // Therefore, the call must be outside any synchronized statement that is also used in the
      // onFrame() 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 (textureListener != null) {
            textureListener.setSize(width, height);
          }

          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;
  }
}
