// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.media;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaCodec.CryptoInfo;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.view.Surface;

import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.MainDex;
import org.chromium.base.annotations.NativeMethods;

import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.Queue;

/**
 * A MediaCodec wrapper for adapting the API and catching exceptions.
 */
@JNINamespace("media")
@MainDex
class MediaCodecBridge {
    private static final String TAG = "MediaCodecBridge";

    // After a flush(), dequeueOutputBuffer() can often produce empty presentation timestamps
    // for several frames. As a result, the player may find that the time does not increase
    // after decoding a frame. To detect this, we check whether the presentation timestamp from
    // dequeueOutputBuffer() is larger than input_timestamp - MAX_PRESENTATION_TIMESTAMP_SHIFT_US
    // after a flush. And we set the presentation timestamp from dequeueOutputBuffer() to be
    // non-decreasing for the remaining frames.
    private static final long MAX_PRESENTATION_TIMESTAMP_SHIFT_US = 100000;

    // We use only one output audio format (PCM16) that has 2 bytes per sample
    private static final int PCM16_BYTES_PER_SAMPLE = 2;

    private static final int MEDIA_CODEC_UNKNOWN_CIPHER_MODE = -1;

    // TODO(qinmin): Use MediaFormat constants when part of the public API.
    private static final String KEY_CROP_LEFT = "crop-left";
    private static final String KEY_CROP_RIGHT = "crop-right";
    private static final String KEY_CROP_BOTTOM = "crop-bottom";
    private static final String KEY_CROP_TOP = "crop-top";

    protected MediaCodec mMediaCodec;
    private @BitrateAdjuster.Type int mBitrateAdjuster;

    // The maximum input size this codec was configured with.
    private int mMaxInputSize;

    // To support both the synchronous and asynchronous version of MediaCodec
    // (since we need to work on <M devices), we implement async support as a
    // layer under synchronous API calls and provide a callback signal for when
    // work (new input, new output, errors, or format changes) is available.
    //
    // Once the callback has been set on MediaCodec, these variables must only
    // be accessed from synchronized(this) blocks since MediaCodecCallback may
    // execute on an arbitrary thread.
    private boolean mUseAsyncApi;
    private Queue<GetOutputFormatResult> mPendingFormat;
    private GetOutputFormatResult mCurrentFormat;
    private boolean mPendingError;
    private boolean mPendingStart;
    private long mNativeMediaCodecBridge;
    private int mSequenceCounter;
    private Queue<DequeueInputResult> mPendingInputBuffers;
    private Queue<DequeueOutputResult> mPendingOutputBuffers;

    // Set by tests which don't have a Java MessagePump to ensure the MediaCodec
    // callbacks are actually delivered. Always null in production.
    private static HandlerThread sCallbackHandlerThread;
    private static Handler sCallbackHandler;

    private static class DequeueInputResult {
        private final int mStatus;
        private final int mIndex;

        private DequeueInputResult(int status, int index) {
            mStatus = status;
            mIndex = index;
        }

        @CalledByNative("DequeueInputResult")
        private int status() {
            return mStatus;
        }

        @CalledByNative("DequeueInputResult")
        private int index() {
            return mIndex;
        }
    }

    private static class DequeueOutputResult {
        private final int mStatus;
        private final int mIndex;
        private final int mFlags;
        private final int mOffset;
        private final long mPresentationTimeMicroseconds;
        private final int mNumBytes;

        private DequeueOutputResult(int status, int index, int flags, int offset,
                long presentationTimeMicroseconds, int numBytes) {
            mStatus = status;
            mIndex = index;
            mFlags = flags;
            mOffset = offset;
            mPresentationTimeMicroseconds = presentationTimeMicroseconds;
            mNumBytes = numBytes;
        }

        @CalledByNative("DequeueOutputResult")
        private int status() {
            return mStatus;
        }

        @CalledByNative("DequeueOutputResult")
        private int index() {
            return mIndex;
        }

        @CalledByNative("DequeueOutputResult")
        private int flags() {
            return mFlags;
        }

        @CalledByNative("DequeueOutputResult")
        private int offset() {
            return mOffset;
        }

        @CalledByNative("DequeueOutputResult")
        private long presentationTimeMicroseconds() {
            return mPresentationTimeMicroseconds;
        }

        @CalledByNative("DequeueOutputResult")
        private int numBytes() {
            return mNumBytes;
        }
    }

    /** A wrapper around a MediaFormat. */
    private static class GetOutputFormatResult {
        private final int mStatus;
        // May be null if mStatus is not MediaCodecStatus.OK.
        private final MediaFormat mFormat;

        private GetOutputFormatResult(int status, MediaFormat format) {
            mStatus = status;
            mFormat = format;
        }

        private boolean formatHasCropValues() {
            return mFormat.containsKey(KEY_CROP_RIGHT) && mFormat.containsKey(KEY_CROP_LEFT)
                    && mFormat.containsKey(KEY_CROP_BOTTOM) && mFormat.containsKey(KEY_CROP_TOP);
        }

        @CalledByNative("GetOutputFormatResult")
        private int status() {
            return mStatus;
        }

        @CalledByNative("GetOutputFormatResult")
        private int width() {
            return formatHasCropValues()
                    ? mFormat.getInteger(KEY_CROP_RIGHT) - mFormat.getInteger(KEY_CROP_LEFT) + 1
                    : mFormat.getInteger(MediaFormat.KEY_WIDTH);
        }

        @CalledByNative("GetOutputFormatResult")
        private int height() {
            return formatHasCropValues()
                    ? mFormat.getInteger(KEY_CROP_BOTTOM) - mFormat.getInteger(KEY_CROP_TOP) + 1
                    : mFormat.getInteger(MediaFormat.KEY_HEIGHT);
        }

        @CalledByNative("GetOutputFormatResult")
        private int sampleRate() {
            return mFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
        }

        @CalledByNative("GetOutputFormatResult")
        private int channelCount() {
            return mFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
        }
    }

    // Warning: This class may execute on an arbitrary thread for the lifetime
    // of the MediaCodec. The MediaCodecBridge methods it calls are synchronized
    // to avoid race conditions.
    @TargetApi(Build.VERSION_CODES.M)
    class MediaCodecCallback extends MediaCodec.Callback {
        private MediaCodecBridge mMediaCodecBridge;
        MediaCodecCallback(MediaCodecBridge bridge) {
            mMediaCodecBridge = bridge;
        }

        @Override
        public void onError(MediaCodec codec, MediaCodec.CodecException e) {
            // TODO(dalecurtis): We may want to drop transient errors here.
            Log.e(TAG, "MediaCodec.onError: %s", e.getDiagnosticInfo());
            mMediaCodecBridge.onError(e);
        }

        @Override
        public void onInputBufferAvailable(MediaCodec codec, int index) {
            mMediaCodecBridge.onInputBufferAvailable(index);
        }

        @Override
        public void onOutputBufferAvailable(
                MediaCodec codec, int index, MediaCodec.BufferInfo info) {
            mMediaCodecBridge.onOutputBufferAvailable(index, info);
        }

        @Override
        public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
            mMediaCodecBridge.onOutputFormatChanged(format);
        }
    };

    MediaCodecBridge(
            MediaCodec mediaCodec, @BitrateAdjuster.Type int bitrateAdjuster, boolean useAsyncApi) {
        assert mediaCodec != null;
        mMediaCodec = mediaCodec;
        mBitrateAdjuster = bitrateAdjuster;
        mUseAsyncApi = useAsyncApi;

        if (!mUseAsyncApi) return;

        enableAsyncApi();
        prepareAsyncApiForRestart();
    }

    // There's a Lollipop version of the setCallback() API, so we could enable
    // it there, but since it's likely to be more stable in later SDK versions
    // and our tests require their own Handler to pump the callbacks, we limit
    // support to Marshmallow only.
    @TargetApi(Build.VERSION_CODES.M)
    private void enableAsyncApi() {
        mPendingError = false;
        mPendingFormat = new LinkedList<GetOutputFormatResult>();
        mPendingInputBuffers = new LinkedList<DequeueInputResult>();
        mPendingOutputBuffers = new LinkedList<DequeueOutputResult>();
        mMediaCodec.setCallback(new MediaCodecCallback(this), sCallbackHandler);
    }

    // The methods below are all synchronized because we may receive callbacks
    // from the MediaCodecCallback on a different thread; especially in the
    // testing case where we create a separate HandlerThread.

    private synchronized void prepareAsyncApiForRestart() {
        mPendingFormat.clear();
        mPendingInputBuffers.clear();
        mPendingOutputBuffers.clear();
        mPendingStart = true;
        mCurrentFormat = null;
        ++mSequenceCounter;
    }

    @CalledByNative
    private synchronized void setBuffersAvailableListener(long nativeMediaCodecBridge) {
        mNativeMediaCodecBridge = nativeMediaCodecBridge;

        // If any buffers or errors occurred before this, trigger the callback now.
        if (!mPendingInputBuffers.isEmpty() || !mPendingOutputBuffers.isEmpty() || mPendingError) {
            notifyBuffersAvailable();
        }
    }

    private synchronized void notifyBuffersAvailable() {
        if (mNativeMediaCodecBridge != 0) {
            MediaCodecBridgeJni.get().onBuffersAvailable(
                    mNativeMediaCodecBridge, MediaCodecBridge.this);
        }
    }

    public synchronized void onError(MediaCodec.CodecException e) {
        mPendingError = true;
        mPendingInputBuffers.clear();
        mPendingOutputBuffers.clear();
        notifyBuffersAvailable();
    }

    public synchronized void onInputBufferAvailable(int index) {
        if (mPendingStart) return;

        mPendingInputBuffers.add(new DequeueInputResult(MediaCodecStatus.OK, index));
        notifyBuffersAvailable();
    }

    public synchronized void onOutputBufferAvailable(int index, MediaCodec.BufferInfo info) {
        // Drop buffers that come in during a flush.
        if (mPendingStart) return;

        mPendingOutputBuffers.add(new DequeueOutputResult(MediaCodecStatus.OK, index, info.flags,
                info.offset, info.presentationTimeUs, info.size));
        notifyBuffersAvailable();
    }

    public synchronized void onOutputFormatChanged(MediaFormat format) {
        mPendingOutputBuffers.add(
                new DequeueOutputResult(MediaCodecStatus.OUTPUT_FORMAT_CHANGED, -1, 0, 0, 0, 0));
        mPendingFormat.add(new GetOutputFormatResult(MediaCodecStatus.OK, format));
        notifyBuffersAvailable();
    }

    public synchronized void onPendingStartComplete(int sequenceCounter) {
        // Ignore events from the past.
        if (mSequenceCounter != sequenceCounter) return;
        mPendingStart = false;
    }

    @CalledByNative
    void release() {
        if (mUseAsyncApi) {
            // Disconnect from the native code to ensure we don't issue calls
            // into it after its destruction.
            synchronized (this) {
                mNativeMediaCodecBridge = 0;
            }
        }
        try {
            String codecName = mMediaCodec.getName();
            // This logging is to help us identify hung MediaCodecs in crash reports.
            Log.w(TAG, "Releasing: %s", codecName);
            mMediaCodec.release();
            Log.w(TAG, "Codec released");
        } catch (IllegalStateException e) {
            // The MediaCodec is stuck in a bad state, possibly due to losing
            // the surface.
            Log.e(TAG, "Cannot release media codec", e);
        }
        mMediaCodec = null;
    }

    // TODO(sanfin): Move this to constructor or builder.
    @SuppressWarnings("deprecation")
    boolean start() {
        try {
            if (mUseAsyncApi) {
                synchronized (this) {
                    if (mPendingError) return false;

                    class CompletePendingStartTask implements Runnable {
                        private int mThisSequence;
                        CompletePendingStartTask(int sequence) {
                            mThisSequence = sequence;
                        }

                        @Override
                        public void run() {
                            onPendingStartComplete(mThisSequence);
                        }
                    };

                    // Ensure any pending indices are ignored until after start
                    // by trampolining through the handler/looper that the
                    // notifications are coming from.
                    Handler h = sCallbackHandler == null ? new Handler(Looper.getMainLooper())
                                                         : sCallbackHandler;
                    h.post(new CompletePendingStartTask(mSequenceCounter));
                }
            }

            mMediaCodec.start();
        } catch (IllegalStateException e) {
            Log.e(TAG, "Cannot start the media codec", e);
            return false;
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Cannot start the media codec", e);
            return false;
        }
        return true;
    }

    @CalledByNative
    private DequeueInputResult dequeueInputBuffer(long timeoutUs) {
        if (mUseAsyncApi) {
            synchronized (this) {
                if (mPendingError) return new DequeueInputResult(MediaCodecStatus.ERROR, -1);
                if (mPendingStart || mPendingInputBuffers.isEmpty()) {
                    return new DequeueInputResult(MediaCodecStatus.TRY_AGAIN_LATER, -1);
                }
                return mPendingInputBuffers.remove();
            }
        }

        int status = MediaCodecStatus.ERROR;
        int index = -1;
        try {
            int indexOrStatus = mMediaCodec.dequeueInputBuffer(timeoutUs);
            if (indexOrStatus >= 0) { // index!
                status = MediaCodecStatus.OK;
                index = indexOrStatus;
            } else if (indexOrStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
                status = MediaCodecStatus.TRY_AGAIN_LATER;
            } else {
                Log.e(TAG, "Unexpected index_or_status: %d", indexOrStatus);
                assert false;
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to dequeue input buffer", e);
        }
        return new DequeueInputResult(status, index);
    }

    @CalledByNative
    private int flush() {
        try {
            mMediaCodec.flush();

            // MediaCodec.flush() invalidates all returned indices, but there
            // may be some unhandled callbacks when using the async API. When
            // we call prepareAsyncApiForRestart() it will set mPendingStart,
            // start() will then post a task through the callback handler which
            // clears mPendingStart to start accepting new buffers.
            if (mUseAsyncApi) {
                prepareAsyncApiForRestart();
                if (!start()) return MediaCodecStatus.ERROR;
            }
        } catch (Exception e) {
            Log.e(TAG, "Failed to flush MediaCodec", e);
            return MediaCodecStatus.ERROR;
        }
        return MediaCodecStatus.OK;
    }

    @CalledByNative
    private void stop() {
        try {
            mMediaCodec.stop();

            // MediaCodec.stop() invalidates all returned indices.
            if (mUseAsyncApi) prepareAsyncApiForRestart();
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to stop MediaCodec", e);
        }
    }

    @CalledByNative
    private String getName() {
        String codecName = "unknown";
        try {
            codecName = mMediaCodec.getName();
        } catch (IllegalStateException e) {
            Log.e(TAG, "Cannot get codec name", e);
        }
        return codecName;
    }

    @CalledByNative
    private GetOutputFormatResult getOutputFormat() {
        if (mUseAsyncApi && mCurrentFormat != null) return mCurrentFormat;

        MediaFormat format = null;
        int status = MediaCodecStatus.OK;
        try {
            format = mMediaCodec.getOutputFormat();
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to get output format", e);
            status = MediaCodecStatus.ERROR;
        }
        return new GetOutputFormatResult(status, format);
    }

    /** Returns null if MediaCodec throws IllegalStateException. */
    @CalledByNative
    private ByteBuffer getInputBuffer(int index) {
        if (mUseAsyncApi) {
            synchronized (this) {
                if (mPendingError) return null;
            }
        }
        try {
            return mMediaCodec.getInputBuffer(index);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to get input buffer", e);
            return null;
        }
    }

    /** Returns null if MediaCodec throws IllegalStateException. */
    @CalledByNative
    protected ByteBuffer getOutputBuffer(int index) {
        try {
            return mMediaCodec.getOutputBuffer(index);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to get output buffer", e);
            return null;
        }
    }

    @CalledByNative
    private int queueInputBuffer(
            int index, int offset, int size, long presentationTimeUs, int flags) {
        try {
            mMediaCodec.queueInputBuffer(index, offset, size, presentationTimeUs, flags);
        } catch (Exception e) {
            Log.e(TAG, "Failed to queue input buffer", e);
            return MediaCodecStatus.ERROR;
        }
        return MediaCodecStatus.OK;
    }

    @CalledByNative
    private void setVideoBitrate(int bps, int frameRate) {
        int targetBps = BitrateAdjuster.getTargetBitrate(mBitrateAdjuster, bps, frameRate);
        Bundle b = new Bundle();
        b.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, targetBps);
        try {
            mMediaCodec.setParameters(b);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to set MediaCodec parameters", e);
        }
        Log.v(TAG, "setVideoBitrate: input %dbps@%d, targetBps %d", bps, frameRate, targetBps);
    }

    @CalledByNative
    private void requestKeyFrameSoon() {
        Bundle b = new Bundle();
        b.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
        try {
            mMediaCodec.setParameters(b);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to set MediaCodec parameters", e);
        }
    }

    // Incoming |native| values are as defined in media/base/encryption_scheme.h. Translated values
    // are from MediaCodec. At present, these values are in sync. Returns
    // MEDIA_CODEC_UNKNOWN_CIPHER_MODE in the case of unknown incoming value.
    private int translateEncryptionSchemeValue(int nativeValue) {
        switch (nativeValue) {
            case EncryptionScheme.UNENCRYPTED:
                return MediaCodec.CRYPTO_MODE_UNENCRYPTED;
            case EncryptionScheme.CENC:
                return MediaCodec.CRYPTO_MODE_AES_CTR;
            case EncryptionScheme.CBCS:
                return MediaCodec.CRYPTO_MODE_AES_CBC;
            default:
                Log.e(TAG, "Unsupported cipher mode: %d", nativeValue);
                return MEDIA_CODEC_UNKNOWN_CIPHER_MODE;
        }
    }

    @SuppressLint("WrongConstant") // False positive on logging statement.
    @CalledByNative
    private int queueSecureInputBuffer(int index, int offset, byte[] iv, byte[] keyId,
            int[] numBytesOfClearData, int[] numBytesOfEncryptedData, int numSubSamples,
            int cipherMode, int patternEncrypt, int patternSkip, long presentationTimeUs) {
        try {
            cipherMode = translateEncryptionSchemeValue(cipherMode);
            if (cipherMode == MEDIA_CODEC_UNKNOWN_CIPHER_MODE) {
                return MediaCodecStatus.ERROR;
            }
            boolean usesCbcs = cipherMode == MediaCodec.CRYPTO_MODE_AES_CBC;
            if (usesCbcs && !MediaCodecUtil.platformSupportsCbcsEncryption(Build.VERSION.SDK_INT)) {
                Log.e(TAG, "Encryption scheme 'cbcs' not supported on this platform.");
                return MediaCodecStatus.ERROR;
            }
            CryptoInfo cryptoInfo = new CryptoInfo();
            cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncryptedData, keyId, iv,
                    cipherMode);
            if (patternEncrypt != 0 && patternSkip != 0) {
                if (usesCbcs) {
                    // Above platform check ensured that setting the pattern is indeed supported.
                    MediaCodecUtil.setPatternIfSupported(cryptoInfo, patternEncrypt, patternSkip);
                } else {
                    Log.e(TAG, "Pattern encryption only supported for 'cbcs' scheme (CBC mode).");
                    return MediaCodecStatus.ERROR;
                }
            }
            mMediaCodec.queueSecureInputBuffer(index, offset, cryptoInfo, presentationTimeUs, 0);
        } catch (MediaCodec.CryptoException e) {
            if (e.getErrorCode() == MediaCodec.CryptoException.ERROR_NO_KEY) {
                Log.d(TAG, "Failed to queue secure input buffer: CryptoException.ERROR_NO_KEY");
                return MediaCodecStatus.NO_KEY;
            }
            Log.e(TAG, "Failed to queue secure input buffer. Error code %d", e.getErrorCode(), e);
            return MediaCodecStatus.ERROR;
        } catch (IllegalArgumentException e) {
            // IllegalArgumentException can occur when release() is called on the MediaCrypto
            // object, but the MediaCodecBridge is unaware of the change.
            Log.e(TAG, "Failed to queue secure input buffer.", e);
            return MediaCodecStatus.ERROR;
        } catch (IllegalStateException e) {
            Log.e(TAG, "Failed to queue secure input buffer.", e);
            return MediaCodecStatus.ERROR;
        }
        return MediaCodecStatus.OK;
    }

    @CalledByNative
    protected void releaseOutputBuffer(int index, boolean render) {
        try {
            mMediaCodec.releaseOutputBuffer(index, render);
        } catch (IllegalStateException e) {
            // TODO(qinmin): May need to report the error to the caller. crbug.com/356498.
            Log.e(TAG, "Failed to release output buffer", e);
        }
    }

    @SuppressWarnings("deprecation")
    @CalledByNative
    private DequeueOutputResult dequeueOutputBuffer(long timeoutUs) {
        if (mUseAsyncApi) {
            synchronized (this) {
                if (mPendingError) {
                    return new DequeueOutputResult(MediaCodecStatus.ERROR, -1, 0, 0, 0, 0);
                }
                if (mPendingOutputBuffers.isEmpty()) {
                    return new DequeueOutputResult(
                            MediaCodecStatus.TRY_AGAIN_LATER, -1, 0, 0, 0, 0);
                }
                if (mPendingOutputBuffers.peek().status()
                        == MediaCodecStatus.OUTPUT_FORMAT_CHANGED) {
                    assert !mPendingFormat.isEmpty();
                    mCurrentFormat = mPendingFormat.remove();
                }
                return mPendingOutputBuffers.remove();
            }
        }

        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        int status = MediaCodecStatus.ERROR;
        int index = -1;
        try {
            int indexOrStatus = dequeueOutputBufferInternal(info, timeoutUs);

            if (indexOrStatus >= 0) { // index!
                status = MediaCodecStatus.OK;
                index = indexOrStatus;
            } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                status = MediaCodecStatus.OUTPUT_BUFFERS_CHANGED;
            } else if (indexOrStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                status = MediaCodecStatus.OUTPUT_FORMAT_CHANGED;
                MediaFormat newFormat = mMediaCodec.getOutputFormat();
            } else if (indexOrStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
                status = MediaCodecStatus.TRY_AGAIN_LATER;
            } else {
                Log.e(TAG, "Unexpected index_or_status: %d", indexOrStatus);
                assert false;
            }
        } catch (IllegalStateException e) {
            status = MediaCodecStatus.ERROR;
            Log.e(TAG, "Failed to dequeue output buffer", e);
        }

        return new DequeueOutputResult(
                status, index, info.flags, info.offset, info.presentationTimeUs, info.size);
    }

    protected int dequeueOutputBufferInternal(MediaCodec.BufferInfo info, long timeoutUs) {
        return mMediaCodec.dequeueOutputBuffer(info, timeoutUs);
    }

    // TODO(sanfin): Move this out of MediaCodecBridge.
    boolean configureVideo(MediaFormat format, Surface surface, MediaCrypto crypto, int flags) {
        try {
            mMediaCodec.configure(format, surface, crypto, flags);
            if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
                mMaxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                return true;
            }
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Cannot configure the video codec, wrong format or surface", e);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Cannot configure the video codec", e);
        } catch (MediaCodec.CryptoException e) {
            Log.e(TAG, "Cannot configure the video codec: DRM error", e);
        } catch (Exception e) {
            Log.e(TAG, "Cannot configure the video codec", e);
        }
        return false;
    }

    @TargetApi(Build.VERSION_CODES.M)
    @CalledByNative
    private boolean setSurface(Surface surface) {
        try {
            mMediaCodec.setOutputSurface(surface);
        } catch (IllegalArgumentException | IllegalStateException e) {
            Log.e(TAG, "Cannot set output surface", e);
            return false;
        }
        return true;
    }

    // TODO(sanfin): Move this out of MediaCodecBridge.
    boolean configureAudio(MediaFormat format, MediaCrypto crypto, int flags) {
        try {
            mMediaCodec.configure(format, null, crypto, flags);
            return true;
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Cannot configure the audio codec", e);
        } catch (IllegalStateException e) {
            Log.e(TAG, "Cannot configure the audio codec", e);
        } catch (MediaCodec.CryptoException e) {
            Log.e(TAG, "Cannot configure the audio codec: DRM error", e);
        } catch (Exception e) {
            Log.e(TAG, "Cannot configure the audio codec", e);
        }
        return false;
    }

    @SuppressWarnings("deprecation")
    private int getAudioFormat(int channelCount) {
        switch (channelCount) {
            case 1:
                return AudioFormat.CHANNEL_OUT_MONO;
            case 2:
                return AudioFormat.CHANNEL_OUT_STEREO;
            case 4:
                return AudioFormat.CHANNEL_OUT_QUAD;
            case 6:
                return AudioFormat.CHANNEL_OUT_5POINT1;
            case 8:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    return AudioFormat.CHANNEL_OUT_7POINT1_SURROUND;
                } else {
                    return AudioFormat.CHANNEL_OUT_7POINT1;
                }
            default:
                return AudioFormat.CHANNEL_OUT_DEFAULT;
        }
    }

    @CalledByNative
    private int getMaxInputSize() {
        return mMaxInputSize;
    }

    @CalledByNative
    private static void createCallbackHandlerForTesting() {
        if (sCallbackHandlerThread != null) return;

        sCallbackHandlerThread = new HandlerThread("TestCallbackThread");
        sCallbackHandlerThread.start();
        sCallbackHandler = new Handler(sCallbackHandlerThread.getLooper());
    }

    @NativeMethods
    interface Natives {
        void onBuffersAvailable(long nativeMediaCodecBridge, MediaCodecBridge caller);
    }
}
