/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.media.cts;

import static org.junit.Assert.assertNotNull;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo.VideoCapabilities;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.cts.R;
import android.opengl.EGL14;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.util.Pair;
import android.view.PixelCopy;
import android.view.PixelCopy.OnPixelCopyFinishedListener;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import androidx.test.rule.ActivityTestRule;

import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.MediaUtils;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;

@TargetApi(16)
public class DecodeAccuracyTestBase {

    protected Context mContext;
    protected Resources mResources;
    protected DecodeAccuracyTestActivity mActivity;
    protected TestHelper testHelper;

    @Rule
    public ActivityTestRule<DecodeAccuracyTestActivity> mActivityRule =
            new ActivityTestRule<>(DecodeAccuracyTestActivity.class);

    @Before
    public void setUp() throws Exception {
        mActivity = mActivityRule.getActivity();
        mContext = mActivity.getApplicationContext();
        mResources = mActivity.getResources();
        testHelper = new TestHelper(mContext, mActivity);
    }

    @After
    public void tearDown() throws Exception {
        mActivity = null;
        mResources = null;
        mContext = null;
        mActivityRule = null;
    }

    protected void bringActivityToFront() {
        Intent intent = new Intent(mContext, DecodeAccuracyTestActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        mActivity.startActivity(intent);
    }

    protected TestHelper getHelper() {
        return testHelper;
    }

    public static <T> T checkNotNull(T reference) {
        assertNotNull(reference);
        return reference;
    }

    public static <T> T checkNotNull(String msg, T reference) {
        assertNotNull(msg, reference);
        return reference;
    }

    /* Simple Player that decodes a local video file only. */
    @TargetApi(16)
    static class SimplePlayer {

        public static final long MIN_MS_PER_FRAME = TimeUnit.SECONDS.toMillis(1) / 5; // 5 FPS
        public static final long STARTUP_ALLOW_MS = TimeUnit.SECONDS.toMillis(1) ;
        public static final int END_OF_STREAM = -1;
        public static final int DEQUEUE_SUCCESS = 1;
        public static final int DEQUEUE_FAIL = 0;

        private static final String TAG = SimplePlayer.class.getSimpleName();
        private static final int NO_TRACK_INDEX = -3;
        private static final long DEQUEUE_TIMEOUT_US = 20;

        private final Context context;
        private final MediaExtractor extractor;
        private final String codecName;
        private MediaCodec decoder;
        private byte[] outputBytes;
        private boolean renderToSurface;
        private MediaCodecList mediaCodecList;
        private Surface surface;

        public SimplePlayer(Context context) {
            this(context, null);
        }

        public SimplePlayer(Context context, String codecName) {
            this.context = checkNotNull(context);
            this.codecName = codecName;
            this.extractor = new MediaExtractor();
            this.renderToSurface = false;
            this.surface = null;
        }

        /**
         * The function play the corresponding file for certain number of frames.
         *
         * @param surface is the surface view of decoder output.
         * @param videoFormat is the format of the video to extract and decode.
         * @param numOfTotalFrames is the number of Frame wish to play.
         * @param msPerFrameCap is the maximum msec per frame. No cap is set if value is less than 1.
         * @return {@link PlayerResult} that consists the result.
         */
        public PlayerResult decodeVideoFrames(
                Surface surface, VideoFormat videoFormat, int numOfTotalFrames, long msPerFrameCap,
                boolean releasePlayer) {
            this.surface = surface;
            PlayerResult playerResult;
            if (prepareVideoDecode(videoFormat)) {
                if (startDecoder()) {
                    final long timeout =
                            Math.max(MIN_MS_PER_FRAME, msPerFrameCap) * numOfTotalFrames + STARTUP_ALLOW_MS;
                    playerResult = decodeFramesAndPlay(numOfTotalFrames, timeout, msPerFrameCap);
                } else {
                    playerResult = PlayerResult.failToStart();
                }
            } else {
                playerResult = new PlayerResult();
            }
            if (releasePlayer) {
                release();
            }
            return new PlayerResult(playerResult);
        }

        public PlayerResult decodeVideoFrames(
                Surface surface, VideoFormat videoFormat, int numOfTotalFrames) {
            return decodeVideoFrames(surface, videoFormat, numOfTotalFrames, 0, false);
        }

        /**
         * The function sets up the extractor and video decoder with proper format.
         * This must be called before doing starting up the decoder.
         */
        private boolean prepareVideoDecode(VideoFormat videoFormat) {
            MediaFormat mediaFormat = prepareExtractor(videoFormat);
            if (mediaFormat == null) {
                return false;
            }
            configureVideoFormat(mediaFormat, videoFormat);
            setRenderToSurface(surface != null);
            return createDecoder(mediaFormat) && configureDecoder(surface, mediaFormat);
        }

        /**
         * Sets up the extractor and gets the {@link MediaFormat} of the track.
         */
        private MediaFormat prepareExtractor(VideoFormat videoFormat) {
            if (!setExtractorDataSource(videoFormat)) {
                return null;
            }
            final int trackNum = getFirstTrackIndexByType(videoFormat.getMediaFormat());
            if (trackNum == NO_TRACK_INDEX) {
                return null;
            }
            extractor.selectTrack(trackNum);
            return extractor.getTrackFormat(trackNum);
        }

        /**
         * The function decode video frames and display in a surface.
         *
         * @param numOfTotalFrames is the number of frames to be decoded.
         * @param timeOutMs is the time limit for decoding the frames.
         * @param msPerFrameCap is the maximum msec per frame. No cap is set if value is less than 1.
         * @return {@link PlayerResult} that consists the result.
         */
        private PlayerResult decodeFramesAndPlay(
                int numOfTotalFrames, long timeOutMs, long msPerFrameCap) {
            int numOfDecodedFrames = 0;
            long firstOutputTimeMs = 0;
            long lastFrameAt = 0;
            final long loopStart = SystemClock.elapsedRealtime();

            while (numOfDecodedFrames < numOfTotalFrames
                    && (SystemClock.elapsedRealtime() - loopStart < timeOutMs)) {
                try {
                    queueDecoderInputBuffer();
                } catch (IllegalStateException exception) {
                    Log.e(TAG, "IllegalStateException in queueDecoderInputBuffer", exception);
                    break;
                }
                try {
                    final int outputResult = dequeueDecoderOutputBuffer();
                    if (outputResult == SimplePlayer.END_OF_STREAM) {
                        break;
                    }
                    if (outputResult == SimplePlayer.DEQUEUE_SUCCESS) {
                        if (firstOutputTimeMs == 0) {
                            firstOutputTimeMs = SystemClock.elapsedRealtime();
                        }
                        if (msPerFrameCap > 0) {
                            // Slow down if cap is set and not reached.
                            final long delayMs =
                                    msPerFrameCap - (SystemClock.elapsedRealtime() - lastFrameAt);
                            if (lastFrameAt != 0 && delayMs > 0) {
                                final long threadDelayMs = 3; // In case of delay in thread.
                                if (delayMs > threadDelayMs) {
                                    try {
                                        Thread.sleep(delayMs - threadDelayMs);
                                    } catch (InterruptedException ex) { /* */}
                                }
                                while (SystemClock.elapsedRealtime() - lastFrameAt
                                        < msPerFrameCap) { /* */ }
                            }
                            lastFrameAt = SystemClock.elapsedRealtime();
                        }
                        numOfDecodedFrames++;
                    }
                } catch (IllegalStateException exception) {
                    Log.e(TAG, "IllegalStateException in dequeueDecoderOutputBuffer", exception);
                }
            }
            // NB: totalTime measures from "first output" instead of
            // "first INPUT", so does not include first frame latency
            // and therefore does not tell us if the timeout expired
            final long totalTime = SystemClock.elapsedRealtime() - firstOutputTimeMs;
            return new PlayerResult(true, true, numOfTotalFrames == numOfDecodedFrames, totalTime);
        }

        /**
         * Queues the input buffer with the media file one buffer at a time.
         *
         * @return true if success, fail otherwise.
         */
        private boolean queueDecoderInputBuffer() {
            ByteBuffer inputBuffer;
            final ByteBuffer[] inputBufferArray = decoder.getInputBuffers();
            final int inputBufferIndex = decoder.dequeueInputBuffer(DEQUEUE_TIMEOUT_US);
            if (inputBufferIndex >= 0) {
                if (ApiLevelUtil.isBefore(Build.VERSION_CODES.LOLLIPOP)) {
                    inputBuffer = inputBufferArray[inputBufferIndex];
                } else {
                    inputBuffer = decoder.getInputBuffer(inputBufferIndex);
                }
                final int sampleSize = extractor.readSampleData(inputBuffer, 0);
                if (sampleSize > 0) {
                    decoder.queueInputBuffer(
                            inputBufferIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                    extractor.advance();
                }
                return true;
            }
            return false;
        }

        /**
         * Dequeues the output buffer.
         * For video decoder, renders to surface if provided.
         * For audio decoder, gets the bytes from the output buffer.
         *
         * @return an integer indicating its status (fail, success, or end of stream).
         */
        private int dequeueDecoderOutputBuffer() {
            final BufferInfo info = new BufferInfo();
            final int decoderStatus = decoder.dequeueOutputBuffer(info, DEQUEUE_TIMEOUT_US);
            if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                return END_OF_STREAM;
            }
            if (decoderStatus >= 0) {
                // For JELLY_BEAN_MR2- devices, when rendering to a surface,
                // info.size seems to always return 0 even if
                // the decoder successfully decoded the frame.
                if (info.size <= 0 && ApiLevelUtil.isAtLeast(Build.VERSION_CODES.JELLY_BEAN_MR2)) {
                    return DEQUEUE_FAIL;
                }
                if (!renderToSurface) {
                    ByteBuffer outputBuffer;
                    if (ApiLevelUtil.isBefore(Build.VERSION_CODES.LOLLIPOP)) {
                        outputBuffer = decoder.getOutputBuffers()[decoderStatus];
                    } else {
                        outputBuffer = decoder.getOutputBuffer(decoderStatus);
                    }
                    outputBytes = new byte[info.size];
                    outputBuffer.get(outputBytes);
                    outputBuffer.clear();
                }
                decoder.releaseOutputBuffer(decoderStatus, renderToSurface);
                return DEQUEUE_SUCCESS;
            }
            return DEQUEUE_FAIL;
        }

        public void release() {
            decoderRelease();
            extractorRelease();
        }

        private boolean setExtractorDataSource(VideoFormat videoFormat) {
            checkNotNull(videoFormat);
            try {
                final AssetFileDescriptor afd = videoFormat.getAssetFileDescriptor(context);
                extractor.setDataSource(
                        afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                afd.close();
            } catch (IOException exception) {
                Log.e(TAG, "IOException in setDataSource", exception);
                return false;
            }
            return true;
        }

        /**
         * Creates a decoder based on conditions.
         *
         * <p>If codec name is provided, {@link MediaCodec#createByCodecName(String)} is used.
         * If codec name is not provided, {@link MediaCodecList#findDecoderForFormat(MediaFormat)}
         * is preferred on LOLLIPOP and up for finding out the codec name that
         * supports the media format.
         * For OS older than LOLLIPOP, {@link MediaCodec#createDecoderByType(String)} is used.
         */
        private boolean createDecoder(MediaFormat mediaFormat) {
            try {
                if (codecName != null) {
                    decoder = MediaCodec.createByCodecName(codecName);
                } else if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.LOLLIPOP)) {
                    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
                        // On LOLLIPOP, format must not contain a frame rate.
                        mediaFormat.setString(MediaFormat.KEY_FRAME_RATE, null);
                    }
                    if (mediaCodecList == null) {
                        mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
                    }
                    decoder = MediaCodec.createByCodecName(
                            mediaCodecList.findDecoderForFormat(mediaFormat));
                } else {
                    decoder = MediaCodec.createDecoderByType(
                            mediaFormat.getString(MediaFormat.KEY_MIME));
                }
            } catch (Exception exception) {
                Log.e(TAG, "Exception during decoder creation", exception);
                decoderRelease();
                return false;
            }
            return true;
        }

        private boolean configureDecoder(Surface surface, MediaFormat mediaFormat) {
            try {
                decoder.configure(mediaFormat, surface, null, 0);
            } catch (Exception exception) {
                Log.e(TAG, "Exception during decoder configuration", exception);
                try {
                    decoder.reset();
                } catch (Exception resetException) {
                    Log.e(TAG, "Exception during decoder reset", resetException);
                }
                decoderRelease();
                return false;
            }
            return true;
        }

        private void setRenderToSurface(boolean render) {
            this.renderToSurface = render;
        }

        private boolean startDecoder() {
            try {
                decoder.start();
            } catch (Exception exception) {
                Log.e(TAG, "Exception during decoder start", exception);
                decoder.reset();
                decoderRelease();
                return false;
            }
            return true;
        }

        private void decoderRelease() {
            if (decoder == null) {
                return;
            }
            try {
                decoder.stop();
            } catch (IllegalStateException exception) {
                decoder.reset();
                // IllegalStateException happens when decoder fail to start.
                Log.e(TAG, "IllegalStateException during decoder stop", exception);
            } finally {
                try {
                    decoder.release();
                } catch (IllegalStateException exception) {
                    Log.e(TAG, "IllegalStateException during decoder release", exception);
                }
                decoder = null;
            }
        }

        private void extractorRelease() {
            if (extractor == null) {
                return;
            }
            try {
                extractor.release();
            } catch (IllegalStateException exception) {
                Log.e(TAG, "IllegalStateException during extractor release", exception);
            }
        }

        private static void configureVideoFormat(MediaFormat mediaFormat, VideoFormat videoFormat) {
            checkNotNull(mediaFormat);
            checkNotNull(videoFormat);
            videoFormat.setMimeType(mediaFormat.getString(MediaFormat.KEY_MIME));
            videoFormat.setWidth(mediaFormat.getInteger(MediaFormat.KEY_WIDTH));
            videoFormat.setHeight(mediaFormat.getInteger(MediaFormat.KEY_HEIGHT));
            mediaFormat.setInteger(MediaFormat.KEY_WIDTH, videoFormat.getWidth());
            mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, videoFormat.getHeight());
            if (ApiLevelUtil.isBefore(Build.VERSION_CODES.KITKAT)) {
                return;
            }
            // Set KEY_MAX_WIDTH and KEY_MAX_HEIGHT when isAbrEnabled() is set.
            if (videoFormat.isAbrEnabled()) {
                try {
                    // Check for max resolution supported by the codec.
                    final MediaCodec decoder = MediaUtils.getDecoder(mediaFormat);
                    final VideoCapabilities videoCapabilities = MediaUtils.getVideoCapabilities(
                            decoder.getName(), videoFormat.getMimeType());
                    decoder.release();
                    final int maxWidth = videoCapabilities.getSupportedWidths().getUpper();
                    final int maxHeight =
                            videoCapabilities.getSupportedHeightsFor(maxWidth).getUpper();
                    if (maxWidth >= videoFormat.getWidth() && maxHeight >= videoFormat.getHeight()) {
                        mediaFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, maxWidth);
                        mediaFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, maxHeight);
                        return;
                    }
                } catch (NullPointerException exception) { /* */ }
                // Set max width/height to current size if can't get codec's max supported
                // width/height or max is not greater than the current size.
                mediaFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, videoFormat.getWidth());
                mediaFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, videoFormat.getHeight());
            }
        }

        /**
         * The function returns the first track found based on the media type.
         */
        private int getFirstTrackIndexByType(String format) {
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                MediaFormat trackMediaFormat = extractor.getTrackFormat(i);
                if (trackMediaFormat.getString(MediaFormat.KEY_MIME).startsWith(format + "/")) {
                    return i;
                }
            }
            Log.e(TAG, "couldn't get a " + format + " track");
            return NO_TRACK_INDEX;
        }

        /**
         * Stores the result from SimplePlayer.
         */
        public static final class PlayerResult {

            public static final int UNSET = -1;
            private final boolean configureSuccess;
            private final boolean startSuccess;
            private final boolean decodeSuccess;
            private final long totalTime;

            public PlayerResult(
                    boolean configureSuccess, boolean startSuccess,
                    boolean decodeSuccess, long totalTime) {
                this.configureSuccess = configureSuccess;
                this.startSuccess = startSuccess;
                this.decodeSuccess = decodeSuccess;
                this.totalTime = totalTime;
            }

            public PlayerResult(PlayerResult playerResult) {
                this(playerResult.configureSuccess, playerResult.startSuccess,
                        playerResult.decodeSuccess, playerResult.totalTime);
            }

            public PlayerResult() {
                // Dummy PlayerResult.
                this(false, false, false, UNSET);
            }

            public static PlayerResult failToStart() {
                return new PlayerResult(true, false, false, UNSET);
            }

            public String getFailureMessage() {
                if (!configureSuccess) {
                    return "Failed to configure decoder.";
                } else if (!startSuccess) {
                    return "Failed to start decoder.";
                } else if (!decodeSuccess) {
                    return "Failed to decode the expected number of frames.";
                } else {
                    return "Failed to finish decoding.";
                }
            }

            public boolean isConfigureSuccess() {
                return configureSuccess;
            }

            public boolean isSuccess() {
                return configureSuccess && startSuccess && decodeSuccess && getTotalTime() != UNSET;
            }

            public long getTotalTime() {
                return totalTime;
            }

        }

    }

    /* Utility class for collecting common test case functionality. */
    class TestHelper {

        private final String TAG =  TestHelper.class.getSimpleName();

        private final Context context;
        private final Handler handler;
        private final Activity activity;

        public TestHelper(Context context, Activity activity) {
            this.context = checkNotNull(context);
            this.handler = new Handler(Looper.getMainLooper());
            this.activity = activity;
        }

        public Bitmap generateBitmapFromImageResourceId(int resourceId) {
            return BitmapFactory.decodeStream(context.getResources().openRawResource(resourceId));
        }

        public Context getContext() {
            return context;
        }

        public void rotateOrientation() {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    final int orientation = context.getResources().getConfiguration().orientation;
                    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    } else {
                        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    }
                }
            });
        }

        public void unsetOrientation() {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
                }
            });
        }

        public void generateView(View view) {
            RelativeLayout relativeLayout =
                    (RelativeLayout) activity.findViewById(R.id.attach_view);
            ViewGenerator viewGenerator = new ViewGenerator(relativeLayout, view);
            handler.post(viewGenerator);
        }

        public void cleanUpView(View view) {
            ViewCleaner viewCleaner = new ViewCleaner(view);
            handler.post(viewCleaner);
        }

        public Bitmap generateBitmapFromVideoViewSnapshot(VideoViewSnapshot snapshot) {
            handler.post(snapshot);
            synchronized (snapshot.getSyncObject()) {
                try {
                    snapshot.getSyncObject().wait(snapshot.SNAPSHOT_TIMEOUT_MS + 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Log.e(TAG, "Unable to finish generateBitmapFromVideoViewSnapshot().");
                    return null;
                }
            }
            if (!snapshot.isBitmapReady()) {
                Log.e(TAG, "Time out in generateBitmapFromVideoViewSnapshot().");
                return null;
            }
            return snapshot.getBitmap();
        }

        private class ViewGenerator implements Runnable {

            private final View view;
            private final RelativeLayout relativeLayout;

            public ViewGenerator(RelativeLayout relativeLayout, View view) {
                this.view = checkNotNull(view);
                this.relativeLayout = checkNotNull(relativeLayout);
            }

            @Override
            public void run() {
                if (view.getParent() != null) {
                    ((ViewGroup) view.getParent()).removeView(view);
                }
                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                        VideoViewFactory.VIEW_WIDTH, VideoViewFactory.VIEW_HEIGHT);
                view.setLayoutParams(params);
                relativeLayout.addView(view);
            }

        }

        private class ViewCleaner implements Runnable {

            private final View view;

            public ViewCleaner(View view) {
                this.view = checkNotNull(view);
            }

            @Override
            public void run() {
                if (view.getParent() != null) {
                    ((ViewGroup) view.getParent()).removeView(view);
                }
            }

        }

    }

}

/* Factory for manipulating a {@link View}. */
abstract class VideoViewFactory {

    public static final long VIEW_WAITTIME_MS = TimeUnit.SECONDS.toMillis(1);
    public static final long DEFAULT_VIEW_AVAILABLE_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(3);
    public static final int VIEW_WIDTH = 480;
    public static final int VIEW_HEIGHT = 360;

    public VideoViewFactory() {}

    public abstract void release();

    public abstract String getName();

    public abstract View createView(Context context);

    public void waitForViewIsAvailable() throws Exception {
        waitForViewIsAvailable(DEFAULT_VIEW_AVAILABLE_TIMEOUT_MS);
    };

    public abstract void waitForViewIsAvailable(long timeOutMs) throws Exception;

    public abstract Surface getSurface();

    public abstract VideoViewSnapshot getVideoViewSnapshot();

    public boolean hasLooper() {
        return Looper.myLooper() != null;
    }

}

/* Factory for building a {@link TextureView}. */
@TargetApi(16)
class TextureViewFactory extends VideoViewFactory implements TextureView.SurfaceTextureListener {

    private static final String TAG = TextureViewFactory.class.getSimpleName();
    private static final String NAME = "TextureView";

    private final Object syncToken = new Object();
    private TextureView textureView;

    public TextureViewFactory() {}

    @Override
    public TextureView createView(Context context) {
        Log.i(TAG, "Creating a " + NAME);
        textureView = DecodeAccuracyTestBase.checkNotNull(new TextureView(context));
        textureView.setSurfaceTextureListener(this);
        return textureView;
    }

    @Override
    public void release() {
        textureView = null;
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public Surface getSurface() {
        return new Surface(textureView.getSurfaceTexture());
    }

    @Override
    public TextureViewSnapshot getVideoViewSnapshot() {
        return new TextureViewSnapshot(textureView);
    }

    @Override
    public void waitForViewIsAvailable(long timeOutMs) throws Exception {
        final long start = SystemClock.elapsedRealtime();
        while (SystemClock.elapsedRealtime() - start < timeOutMs && !textureView.isAvailable()) {
            synchronized (syncToken) {
                try {
                    syncToken.wait(VIEW_WAITTIME_MS);
                } catch (InterruptedException e) {
                    Log.e(TAG, "Exception occurred when attaching a TextureView to a window.", e);
                    throw new InterruptedException(e.getMessage());
                }
            }
        }
        if (!textureView.isAvailable()) {
            throw new InterruptedException("Taking too long to attach a TextureView to a window.");
        }
        Log.i(TAG, NAME + " is available.");
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
        synchronized (syncToken) {
            syncToken.notify();
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(
            SurfaceTexture surfaceTexture, int width, int height) {}

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}

}

/**
 * Factory for building a {@link SurfaceView}
 */
@TargetApi(24)
class SurfaceViewFactory extends VideoViewFactory implements SurfaceHolder.Callback {

    private static final String TAG = SurfaceViewFactory.class.getSimpleName();
    private static final String NAME = "SurfaceView";
    private final Object syncToken = new Object();

    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;

    public SurfaceViewFactory() {}

    @Override
    public void release() {
        surfaceView = null;
        surfaceHolder = null;
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public View createView(Context context) {
        Log.i(TAG, "Creating a " + NAME);
        if (!super.hasLooper()) {
            Looper.prepare();
        }
        surfaceView = new SurfaceView(context);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        return surfaceView;
    }

    @Override
    public void waitForViewIsAvailable(long timeOutMs) throws Exception {
        final long start = SystemClock.elapsedRealtime();
        while (SystemClock.elapsedRealtime() - start < timeOutMs && !getSurface().isValid()) {
            synchronized (syncToken) {
                try {
                    syncToken.wait(VIEW_WAITTIME_MS);
                } catch (InterruptedException e) {
                    Log.e(TAG, "Exception occurred when attaching a SurfaceView to a window.", e);
                    throw new InterruptedException(e.getMessage());
                }
            }
        }
        if (!getSurface().isValid()) {
            throw new InterruptedException("Taking too long to attach a SurfaceView to a window.");
        }
        Log.i(TAG, NAME + " is available.");
    }

    @Override
    public Surface getSurface() {
        return surfaceHolder == null ? null : surfaceHolder.getSurface();
    }

    @Override
    public VideoViewSnapshot getVideoViewSnapshot() {
        return new SurfaceViewSnapshot(surfaceView, VIEW_WIDTH, VIEW_HEIGHT);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        synchronized (syncToken) {
            syncToken.notify();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {}

}

/**
 * Factory for building EGL and GLES that could render to GLSurfaceView.
 * {@link GLSurfaceView} {@link EGL10} {@link GLES20}.
 */
@TargetApi(16)
class GLSurfaceViewFactory extends VideoViewFactory {

    private static final String TAG = GLSurfaceViewFactory.class.getSimpleName();
    private static final String NAME = "GLSurfaceView";

    private final Object surfaceSyncToken = new Object();

    private GLSurfaceViewThread glSurfaceViewThread;
    private boolean byteBufferIsReady = false;

    public GLSurfaceViewFactory() {}

    @Override
    public void release() {
        glSurfaceViewThread.release();
        glSurfaceViewThread = null;
    }

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public View createView(Context context) {
        Log.i(TAG, "Creating a " + NAME);
        // Do all GL rendering in the GL thread.
        glSurfaceViewThread = new GLSurfaceViewThread();
        glSurfaceViewThread.start();
        // No necessary view to display, return null.
        return null;
    }

    @Override
    public void waitForViewIsAvailable(long timeOutMs) throws Exception {
        final long start = SystemClock.elapsedRealtime();
        while (SystemClock.elapsedRealtime() - start < timeOutMs
                && glSurfaceViewThread.getSurface() == null) {
            synchronized (surfaceSyncToken) {
                try {
                    surfaceSyncToken.wait(VIEW_WAITTIME_MS);
                } catch (InterruptedException e) {
                    Log.e(TAG, "Exception occurred when waiting for the surface from"
                            + " GLSurfaceView to become available.", e);
                    throw new InterruptedException(e.getMessage());
                }
            }
        }
        if (glSurfaceViewThread.getSurface() == null) {
            throw new InterruptedException("Taking too long for the surface from"
                    + " GLSurfaceView to become available.");
        }
        Log.i(TAG, NAME + " is available.");
    }

    @Override
    public Surface getSurface() {
        return glSurfaceViewThread.getSurface();
    }

    @Override
    public VideoViewSnapshot getVideoViewSnapshot() {
        return new GLSurfaceViewSnapshot(this, VIEW_WIDTH, VIEW_HEIGHT);
    }

    public boolean byteBufferIsReady() {
        return byteBufferIsReady;
    }

    public ByteBuffer getByteBuffer() {
        return glSurfaceViewThread.getByteBuffer();
    }

    /* Does all GL operations. */
    private class GLSurfaceViewThread extends Thread
            implements SurfaceTexture.OnFrameAvailableListener {

        private static final int FLOAT_SIZE_BYTES = 4;
        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
        private FloatBuffer triangleVertices;
        private float[] textureTransform = new float[16];

        private float[] triangleVerticesData = {
            // X, Y, Z, U, V
            -1f, -1f,  0f,  0f,  1f,
             1f, -1f,  0f,  1f,  1f,
            -1f,  1f,  0f,  0f,  0f,
             1f,  1f,  0f,  1f,  0f,
        };
        // Make the top-left corner corresponds to texture coordinate
        // (0, 0). This complies with the transformation matrix obtained from
        // SurfaceTexture.getTransformMatrix.

        private static final String VERTEX_SHADER =
                "attribute vec4 aPosition;\n"
                + "attribute vec4 aTextureCoord;\n"
                + "uniform mat4 uTextureTransform;\n"
                + "varying vec2 vTextureCoord;\n"
                + "void main() {\n"
                + "    gl_Position = aPosition;\n"
                + "    vTextureCoord = (uTextureTransform * aTextureCoord).xy;\n"
                + "}\n";

        private static final String FRAGMENT_SHADER =
                "#extension GL_OES_EGL_image_external : require\n"
                + "precision mediump float;\n"      // highp here doesn't seem to matter
                + "varying vec2 vTextureCoord;\n"
                + "uniform samplerExternalOES sTexture;\n"
                + "void main() {\n"
                + "    gl_FragColor = texture2D(sTexture, vTextureCoord);\n"
                + "}\n";

        private int glProgram;
        private int textureID = -1;
        private int aPositionHandle;
        private int aTextureHandle;
        private int uTextureTransformHandle;
        private EGLDisplay eglDisplay = null;
        private EGLContext eglContext = null;
        private EGLSurface eglSurface = null;
        private EGL10 egl10;
        private Surface surface = null;
        private SurfaceTexture surfaceTexture;
        private ByteBuffer byteBuffer;
        private Looper looper;

        public GLSurfaceViewThread() {}

        @Override
        public void run() {
            Looper.prepare();
            looper = Looper.myLooper();
            triangleVertices = ByteBuffer
                    .allocateDirect(triangleVerticesData.length * FLOAT_SIZE_BYTES)
                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
            triangleVertices.put(triangleVerticesData).position(0);

            eglSetup();
            makeCurrent();
            eglSurfaceCreated();

            surfaceTexture = new SurfaceTexture(getTextureId());
            surfaceTexture.setOnFrameAvailableListener(this);
            surface = new Surface(surfaceTexture);
            synchronized (surfaceSyncToken) {
                surfaceSyncToken.notify();
            }
            // Store pixels from surface
            byteBuffer = ByteBuffer.allocateDirect(VIEW_WIDTH * VIEW_HEIGHT * 4);
            byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
            Looper.loop();
        }

        @Override
        public void onFrameAvailable(SurfaceTexture st) {
            checkGlError("before updateTexImage");
            surfaceTexture.updateTexImage();
            st.getTransformMatrix(textureTransform);
            drawFrame();
            saveFrame();
        }

        /* Prepares EGL to use GLES 2.0 context and a surface that supports pbuffer. */
        public void eglSetup() {
            egl10 = (EGL10) EGLContext.getEGL();
            eglDisplay = egl10.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
            if (eglDisplay == EGL10.EGL_NO_DISPLAY) {
                throw new RuntimeException("unable to get egl10 display");
            }
            int[] version = new int[2];
            if (!egl10.eglInitialize(eglDisplay, version)) {
                eglDisplay = null;
                throw new RuntimeException("unable to initialize egl10");
            }
            // Configure EGL for pbuffer and OpenGL ES 2.0, 24-bit RGB.
            int[] configAttribs = {
                EGL10.EGL_RED_SIZE, 8,
                EGL10.EGL_GREEN_SIZE, 8,
                EGL10.EGL_BLUE_SIZE, 8,
                EGL10.EGL_ALPHA_SIZE, 8,
                EGL10.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
                EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
                EGL10.EGL_NONE
            };
            EGLConfig[] configs = new EGLConfig[1];
            int[] numConfigs = new int[1];
            if (!egl10.eglChooseConfig(
                    eglDisplay, configAttribs, configs, configs.length, numConfigs)) {
                throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
            }
            // Configure EGL context for OpenGL ES 2.0.
            int[] contextAttribs = {
                EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL10.EGL_NONE
            };
            eglContext = egl10.eglCreateContext(
                    eglDisplay, configs[0], EGL10.EGL_NO_CONTEXT, contextAttribs);
            checkEglError("eglCreateContext");
            if (eglContext == null) {
                throw new RuntimeException("null context");
            }
            // Create a pbuffer surface.
            int[] surfaceAttribs = {
                EGL10.EGL_WIDTH, VIEW_WIDTH,
                EGL10.EGL_HEIGHT, VIEW_HEIGHT,
                EGL10.EGL_NONE
            };
            eglSurface = egl10.eglCreatePbufferSurface(eglDisplay, configs[0], surfaceAttribs);
            checkEglError("eglCreatePbufferSurface");
            if (eglSurface == null) {
                throw new RuntimeException("surface was null");
            }
        }

        public void release() {
            looper.quit();
            if (eglDisplay != EGL10.EGL_NO_DISPLAY) {
                egl10.eglMakeCurrent(eglDisplay,
                        EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
                egl10.eglDestroySurface(eglDisplay, eglSurface);
                egl10.eglDestroyContext(eglDisplay, eglContext);
                egl10.eglTerminate(eglDisplay);
            }
            eglDisplay = EGL10.EGL_NO_DISPLAY;
            eglContext = EGL10.EGL_NO_CONTEXT;
            eglSurface = EGL10.EGL_NO_SURFACE;
            surface.release();
            surfaceTexture.release();
            byteBufferIsReady = false;
            byteBuffer =  null;
        }

        /* Makes our EGL context and surface current. */
        public void makeCurrent() {
            if (!egl10.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
                throw new RuntimeException("eglMakeCurrent failed");
            }
            checkEglError("eglMakeCurrent");
        }

        /* Call this after the EGL Surface is created and made current. */
        public void eglSurfaceCreated() {
            glProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
            if (glProgram == 0) {
                throw new RuntimeException("failed creating program");
            }
            aPositionHandle = GLES20.glGetAttribLocation(glProgram, "aPosition");
            checkLocation(aPositionHandle, "aPosition");
            aTextureHandle = GLES20.glGetAttribLocation(glProgram, "aTextureCoord");
            checkLocation(aTextureHandle, "aTextureCoord");
            uTextureTransformHandle = GLES20.glGetUniformLocation(glProgram, "uTextureTransform");
            checkLocation(uTextureTransformHandle, "uTextureTransform");

            int[] textures = new int[1];
            GLES20.glGenTextures(1, textures, 0);
            checkGlError("glGenTextures");
            textureID = textures[0];
            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureID);
            checkGlError("glBindTexture");

            GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
                    GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
                    GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
                    GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
                    GLES20.GL_CLAMP_TO_EDGE);
            checkGlError("glTexParameter");
        }

        public void drawFrame() {
            GLES20.glUseProgram(glProgram);
            checkGlError("glUseProgram");
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            checkGlError("glActiveTexture");
            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureID);
            checkGlError("glBindTexture");

            triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
            GLES20.glVertexAttribPointer(aPositionHandle, 3, GLES20.GL_FLOAT, false,
                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
            checkGlError("glVertexAttribPointer aPositionHandle");
            GLES20.glEnableVertexAttribArray(aPositionHandle);
            checkGlError("glEnableVertexAttribArray aPositionHandle");

            triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
            GLES20.glVertexAttribPointer(aTextureHandle, 2, GLES20.GL_FLOAT, false,
                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
            checkGlError("glVertexAttribPointer aTextureHandle");
            GLES20.glEnableVertexAttribArray(aTextureHandle);
            checkGlError("glEnableVertexAttribArray aTextureHandle");

            GLES20.glUniformMatrix4fv(uTextureTransformHandle, 1, false, textureTransform, 0);
            checkGlError("glUniformMatrix uTextureTransformHandle");

            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
            checkGlError("glDrawArrays");
            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
        }

        /* Reads the pixels to a ByteBuffer. */
        public void saveFrame() {
            byteBufferIsReady = false;
            byteBuffer.clear();
            GLES20.glReadPixels(0, 0, VIEW_WIDTH, VIEW_HEIGHT, GLES20.GL_RGBA,
                    GLES20.GL_UNSIGNED_BYTE, byteBuffer);
            byteBufferIsReady = true;
        }

        public int getTextureId() {
            return textureID;
        }

        public Surface getSurface() {
            return surface;
        }

        public ByteBuffer getByteBuffer() {
            return byteBuffer;
        }

        private int loadShader(int shaderType, String source) {
            int shader = GLES20.glCreateShader(shaderType);
            checkGlError("glCreateShader type=" + shaderType);
            GLES20.glShaderSource(shader, source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);

            if (compiled[0] == 0) {
                Log.e(TAG, "Could not compile shader " + shaderType + ":");
                Log.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
            return shader;
        }

        private int createProgram(String vertexSource, String fragmentSource) {
            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
            if (vertexShader == 0) {
                return 0;
            }
            int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
            if (pixelShader == 0) {
                return 0;
            }
            int program = GLES20.glCreateProgram();
            if (program == 0) {
                Log.e(TAG, "Could not create program");
            }
            GLES20.glAttachShader(program, vertexShader);
            checkGlError("glAttachShader");
            GLES20.glAttachShader(program, pixelShader);
            checkGlError("glAttachShader");
            GLES20.glLinkProgram(program);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);

            if (linkStatus[0] != GLES20.GL_TRUE) {
                Log.e(TAG, "Could not link program: ");
                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
            return program;
        }

        private void checkEglError(String msg) {
            int error;
            if ((error = egl10.eglGetError()) != EGL10.EGL_SUCCESS) {
                throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
            }
        }

        public void checkGlError(String op) {
            int error;
            if ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
                Log.e(TAG, op + ": glError " + error);
                throw new RuntimeException(op + ": glError " + error);
            }
        }

        public void checkLocation(int location, String label) {
            if (location < 0) {
                throw new RuntimeException("Unable to locate '" + label + "' in program");
            }
        }
    }

}

/* Definition of a VideoViewSnapshot and a runnable to get a bitmap from a view. */
abstract class VideoViewSnapshot implements Runnable {

    public static final long SNAPSHOT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(30);
    public static final long SLEEP_TIME_MS = 30;
    public static final Object SYNC_TOKEN = new Object();

    public abstract Bitmap getBitmap();

    public abstract boolean isBitmapReady();

    public abstract Object getSyncObject();

}

/* Runnable to get a bitmap from a texture view on the UI thread via a handler.
 * This class is to be used together with
 * {@link TestHelper#generateBitmapFromVideoViewSnapshot(VideoViewSnapshot)}
 */
class TextureViewSnapshot extends VideoViewSnapshot {

    private final TextureView tv;
    private Bitmap bitmap = null;

    public TextureViewSnapshot(TextureView tv) {
        this.tv = DecodeAccuracyTestBase.checkNotNull(tv);
    }

    @Override
    public void run() {
        bitmap = null;
        bitmap = tv.getBitmap();
        synchronized (SYNC_TOKEN) {
            SYNC_TOKEN.notify();
        }
    }

    @Override
    public Bitmap getBitmap() {
        return bitmap;
    }

    @Override
    public boolean isBitmapReady() {
        return bitmap != null;
    }

    @Override
    public Object getSyncObject() {
        return SYNC_TOKEN;
    }

}

/**
 * Method to get bitmap of a {@link SurfaceView}.
 * Note that PixelCopy does not have to be called in a runnable.
 * This class is to be used together with
 * {@link TestHelper#generateBitmapFromVideoViewSnapshot(VideoViewSnapshot)}
 */
class SurfaceViewSnapshot extends VideoViewSnapshot  {

    private static final String TAG = SurfaceViewSnapshot.class.getSimpleName();
    private static final int PIXELCOPY_TIMEOUT_MS = 1000;
    private static final int INITIAL_STATE = -1;

    private final SurfaceView surfaceView;
    private final int width;
    private final int height;

    private Bitmap bitmap;
    private int copyResult;

    public SurfaceViewSnapshot(SurfaceView surfaceView, int width, int height) {
        this.surfaceView = surfaceView;
        this.width = width;
        this.height = height;
        this.copyResult = INITIAL_STATE;
        this.bitmap = null;
    }

    @Override
    public void run() {
        final long start = SystemClock.elapsedRealtime();
        copyResult = INITIAL_STATE;
        final SynchronousPixelCopy copyHelper = new SynchronousPixelCopy();
        bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        try {
            // Wait for PixelCopy to finish.
            while ((copyResult = copyHelper.request(surfaceView, bitmap)) != PixelCopy.SUCCESS
                    && (SystemClock.elapsedRealtime() - start) < SNAPSHOT_TIMEOUT_MS) {
                Thread.sleep(SLEEP_TIME_MS);
            }
        } catch (InterruptedException e) {
            Log.e(TAG, "Pixel Copy is stopped/interrupted before it finishes.", e);
            bitmap = null;
        } finally {
            copyHelper.release();
            synchronized (SYNC_TOKEN) {
                SYNC_TOKEN.notify();
            }
        }
    }

    @Override
    public Bitmap getBitmap() {
        return bitmap;
    }

    @Override
    public boolean isBitmapReady() {
        return bitmap != null && copyResult == PixelCopy.SUCCESS;
    }

    @Override
    public Object getSyncObject() {
        return SYNC_TOKEN;
    }

    private static class SynchronousPixelCopy implements OnPixelCopyFinishedListener {

        private final Handler handler;
        private final HandlerThread thread;

        private int status = INITIAL_STATE;

        public SynchronousPixelCopy() {
            this.thread = new HandlerThread("PixelCopyHelper");
            thread.start();
            this.handler = new Handler(thread.getLooper());
        }

        public void release() {
            if (thread.isAlive()) {
                thread.quit();
            }
        }

        public int request(SurfaceView source, Bitmap dest) {
            synchronized (this) {
                try {
                    PixelCopy.request(source, dest, this, handler);
                    return getResultLocked();
                } catch (Exception e) {
                    Log.e(TAG, "Exception occurred when copying a SurfaceView.", e);
                    return -1;
                }
            }
        }

        private int getResultLocked() {
            try {
                this.wait(PIXELCOPY_TIMEOUT_MS);
            } catch (InterruptedException e) { /* PixelCopy request didn't complete within 1s */ }
            return status;
        }

        @Override
        public void onPixelCopyFinished(int copyResult) {
            synchronized (this) {
                status = copyResult;
                this.notify();
            }
        }

    }

}

/**
 * Runnable to get a bitmap from a GLSurfaceView on the UI thread via a handler.
 * Note, because of how the bitmap is captured in GLSurfaceView,
 * this method does not have to be a runnable.
  * This class is to be used together with
 * {@link TestHelper#generateBitmapFromVideoViewSnapshot(VideoViewSnapshot)}
 */
class GLSurfaceViewSnapshot extends VideoViewSnapshot {

    private static final String TAG = GLSurfaceViewSnapshot.class.getSimpleName();

    private final GLSurfaceViewFactory glSurfaceViewFactory;
    private final int width;
    private final int height;

    private Bitmap bitmap = null;
    private boolean bitmapIsReady = false;

    public GLSurfaceViewSnapshot(GLSurfaceViewFactory glSurfaceViewFactory, int width, int height) {
        this.glSurfaceViewFactory = DecodeAccuracyTestBase.checkNotNull(glSurfaceViewFactory);
        this.width = width;
        this.height = height;
    }

    @Override
    public void run() {
        bitmapIsReady = false;
        bitmap = null;
        try {
            waitForByteBuffer();
        } catch (InterruptedException exception) {
            Log.e(TAG, exception.getMessage());
            bitmap = null;
            notifyObject();
            return;
        }
        try {
            final ByteBuffer byteBuffer = glSurfaceViewFactory.getByteBuffer();
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            byteBuffer.rewind();
            bitmap.copyPixelsFromBuffer(byteBuffer);
            bitmapIsReady = true;
            byteBuffer.clear();
        } catch (NullPointerException exception) {
            Log.e(TAG, "glSurfaceViewFactory or byteBuffer may have been released", exception);
            bitmap = null;
        } finally {
            notifyObject();
        }
    }

    @Override
    public Bitmap getBitmap() {
        return bitmap;
    }

    @Override
    public boolean isBitmapReady() {
        return bitmapIsReady;
    }

    @Override
    public Object getSyncObject() {
        return SYNC_TOKEN;
    }

    private void notifyObject() {
        synchronized (SYNC_TOKEN) {
            SYNC_TOKEN.notify();
        }
    }

    private void waitForByteBuffer() throws InterruptedException {
        // Wait for byte buffer to be ready.
        final long start = SystemClock.elapsedRealtime();
        while (SystemClock.elapsedRealtime() - start < SNAPSHOT_TIMEOUT_MS) {
            if (glSurfaceViewFactory.byteBufferIsReady()) {
                return;
            }
            Thread.sleep(SLEEP_TIME_MS);
        }
        throw new InterruptedException("Taking too long to read pixels into a ByteBuffer.");
    }

}

/* Stores information of a video file. */
class VideoFormat {

    public static final String STRING_UNSET = "UNSET";
    public static final int INT_UNSET = -1;

    private final String filename;

    private String mimeType = STRING_UNSET;
    private int width = INT_UNSET;
    private int height = INT_UNSET;
    private int maxWidth = INT_UNSET;
    private int maxHeight = INT_UNSET;
    private FilenameParser filenameParser;

    public VideoFormat(String filename) {
        this.filename = filename;
    }

    public VideoFormat(VideoFormat videoFormat) {
        this(videoFormat.filename);
    }

    private FilenameParser getParsedName() {
        if (filenameParser == null) {
            filenameParser = new FilenameParser(filename);
        }
        return filenameParser;
    }

    public String getMediaFormat() {
        return "video";
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    public String getMimeType() {
        if (mimeType.equals(STRING_UNSET)) {
            return getParsedName().getMimeType();
        }
        return mimeType;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setMaxWidth(int maxWidth) {
        this.maxWidth = maxWidth;
    }

    public int getWidth() {
        if (width == INT_UNSET) {
            return getParsedName().getWidth();
        }
        return width;
    }

    public int getMaxWidth() {
        return maxWidth;
    }

    public int getOriginalWidth() {
        return getParsedName().getWidth();
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setMaxHeight(int maxHeight) {
        this.maxHeight = maxHeight;
    }

    public int getHeight() {
        if (height == INT_UNSET) {
            return getParsedName().getHeight();
        }
        return height;
    }

    public int getMaxHeight() {
        return maxHeight;
    }

    public int getOriginalHeight() {
        return getParsedName().getHeight();
    }

    public boolean isAbrEnabled() {
        return false;
    }

    public String getOriginalSize() {
        if (width == INT_UNSET || height == INT_UNSET) {
            return getParsedName().getSize();
        }
        return width + "x" + height;
    }

    public String getDescription() {
        return getParsedName().getDescription();
    }

    public String toPrettyString() {
        return getParsedName().toPrettyString();
    }

    public AssetFileDescriptor getAssetFileDescriptor(Context context) {
        try {
            return context.getAssets().openFd(filename);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

/* File parser for filenames with format of {description}-{mimeType}_{size}_{framerate}.{format} */
class FilenameParser {

    static final String VP9 = "vp9";
    static final String H264 = "h264";

    private final String filename;

    private String codec = VideoFormat.STRING_UNSET;
    private String description = VideoFormat.STRING_UNSET;
    private int width = VideoFormat.INT_UNSET;
    private int height = VideoFormat.INT_UNSET;

    FilenameParser(String filename) {
        this.filename = filename;
        parseFilename(filename);
    }

    public String getCodec() {
        return codec;
    }

    public String getMimeType() {
        switch (codec) {
            case H264:
                return MimeTypes.VIDEO_H264;
            case VP9:
                return MimeTypes.VIDEO_VP9;
            default:
                return null;
        }
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public String getSize() {
        return width + "x" + height;
    }

    public String getDescription() {
        return description;
    }

    String toPrettyString() {
        if (codec != null) {
            return codec.toUpperCase() + " " + getSize();
        }
        return filename;
    }

    private void parseFilename(String filename) {
        final String descriptionDelimiter = "-";
        final String infoDelimiter = "_";
        final String sizeDelimiter = "x";
        try {
            this.description = filename.split(descriptionDelimiter)[0];
            final String[] fileInfo = filename.split(descriptionDelimiter)[1].split(infoDelimiter);
            this.codec = fileInfo[0];
            this.width = Integer.parseInt(fileInfo[1].split(sizeDelimiter)[0]);
            this.height = Integer.parseInt(fileInfo[1].split(sizeDelimiter)[1]);
        } catch (Exception exception) { /* Filename format does not match. */ }
    }

}

/**
 * Compares bitmaps to determine if they are similar.
 *
 * <p>To determine greatest pixel difference we transform each pixel into the
 * CIE L*a*b* color space. The euclidean distance formula is used to determine pixel differences.
 */
class BitmapCompare {

    private static final int RED = 0;
    private static final int GREEN = 1;
    private static final int BLUE = 2;
    private static final int X = 0;
    private static final int Y = 1;
    private static final int Z = 2;

    private BitmapCompare() {}

    /**
     * Produces greatest pixel between two bitmaps. Used to determine bitmap similarity.
     *
     * @param bitmap1 A bitmap to compare to bitmap2.
     * @param bitmap2 A bitmap to compare to bitmap1.
     * @return A {@link Difference} with an integer describing the greatest pixel difference,
     *     using {@link Integer#MAX_VALUE} for completely different bitmaps, and an optional
     *     {@link Pair<Integer, Integer>} of the (col, row) pixel coordinate where it was first found.
     */
    @TargetApi(12)
    public static Difference computeDifference(Bitmap bitmap1, Bitmap bitmap2) {
        if (bitmap1 == null || bitmap2 == null) {
            return new Difference(Integer.MAX_VALUE);
        }
        if (bitmap1.equals(bitmap2) || bitmap1.sameAs(bitmap2)) {
            return new Difference(0);
        }
        if (bitmap1.getHeight() != bitmap2.getHeight() || bitmap1.getWidth() != bitmap2.getWidth()) {
            return new Difference(Integer.MAX_VALUE);
        }
        // Convert all pixels to CIE L*a*b* color space so we can do a direct color comparison using
        // euclidean distance formula.
        final double[][] pixels1 = convertRgbToCieLab(bitmap1);
        final double[][] pixels2 = convertRgbToCieLab(bitmap2);
        int greatestDifference = 0;
        int greatestDifferenceIndex = -1;
        for (int i = 0; i < pixels1.length; i++) {
            final int difference = euclideanDistance(pixels1[i], pixels2[i]);
            if (difference > greatestDifference) {
                greatestDifference = difference;
                greatestDifferenceIndex = i;
            }
        }
        return new Difference(greatestDifference, Pair.create(
            greatestDifferenceIndex % bitmap1.getWidth(),
            greatestDifferenceIndex / bitmap1.getHeight()));
    }

    @SuppressLint("UseSparseArrays")
    private static double[][] convertRgbToCieLab(Bitmap bitmap) {
        final HashMap<Integer, double[]> pixelTransformCache = new HashMap<>();
        final double[][] result = new double[bitmap.getHeight() * bitmap.getWidth()][3];
        final int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()];
        bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
        for (int i = 0; i < pixels.length; i++) {
            final double[] transformedColor = pixelTransformCache.get(pixels[i]);
            if (transformedColor != null) {
                result[i] = transformedColor;
            } else {
                result[i] = convertXyzToCieLab(convertRgbToXyz(pixels[i]));
                pixelTransformCache.put(pixels[i], result[i]);
            }
        }
        return result;
    }

    /**
     * Conversion from RGB to XYZ based algorithm as defined by:
     * http://www.easyrgb.com/index.php?X=MATH&H=02#text2
     *
     * <p><pre>{@code
     *   var_R = ( R / 255 )        //R from 0 to 255
     *   var_G = ( G / 255 )        //G from 0 to 255
     *   var_B = ( B / 255 )        //B from 0 to 255
     *
     *   if ( var_R > 0.04045 ) var_R = ( ( var_R + 0.055 ) / 1.055 ) ^ 2.4
     *   else                   var_R = var_R / 12.92
     *   if ( var_G > 0.04045 ) var_G = ( ( var_G + 0.055 ) / 1.055 ) ^ 2.4
     *   else                   var_G = var_G / 12.92
     *   if ( var_B > 0.04045 ) var_B = ( ( var_B + 0.055 ) / 1.055 ) ^ 2.4
     *   else                   var_B = var_B / 12.92
     *
     *   var_R = var_R * 100
     *   var_G = var_G * 100
     *   var_B = var_B * 100
     *
     *   // Observer. = 2°, Illuminant = D65
     *   X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
     *   Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
     *   Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
     * }</pre>
     *
     * @param rgbColor A packed int made up of 4 bytes: alpha, red, green, blue.
     * @return An array of doubles where each value is a component of the XYZ color space.
     */
    private static double[] convertRgbToXyz(int rgbColor) {
        final double[] comp = {Color.red(rgbColor), Color.green(rgbColor), Color.blue(rgbColor)};
        for (int i = 0; i < comp.length; i++) {
            comp[i] /= 255.0;
            if (comp[i] > 0.04045) {
                comp[i] = Math.pow((comp[i] + 0.055) / 1.055, 2.4);
            } else {
                comp[i] /= 12.92;
            }
            comp[i] *= 100;
        }
        final double x = (comp[RED] * 0.4124) + (comp[GREEN] * 0.3576) + (comp[BLUE] * 0.1805);
        final double y = (comp[RED] * 0.2126) + (comp[GREEN] * 0.7152) + (comp[BLUE] * 0.0722);
        final double z = (comp[RED] * 0.0193) + (comp[GREEN] * 0.1192) + (comp[BLUE] * 0.9505);
        return new double[] {x, y, z};
    }

    /**
     * Conversion from XYZ to CIE-L*a*b* based algorithm as defined by:
     * http://www.easyrgb.com/index.php?X=MATH&H=07#text7
     *
     * <p><pre>
     * {@code
     *   var_X = X / ref_X          //ref_X =  95.047   Observer= 2°, Illuminant= D65
     *   var_Y = Y / ref_Y          //ref_Y = 100.000
     *   var_Z = Z / ref_Z          //ref_Z = 108.883
     *
     *   if ( var_X > 0.008856 ) var_X = var_X ^ ( 1/3 )
     *   else                    var_X = ( 7.787 * var_X ) + ( 16 / 116 )
     *   if ( var_Y > 0.008856 ) var_Y = var_Y ^ ( 1/3 )
     *   else                    var_Y = ( 7.787 * var_Y ) + ( 16 / 116 )
     *   if ( var_Z > 0.008856 ) var_Z = var_Z ^ ( 1/3 )
     *   else                    var_Z = ( 7.787 * var_Z ) + ( 16 / 116 )
     *
     *   CIE-L* = ( 116 * var_Y ) - 16
     *   CIE-a* = 500 * ( var_X - var_Y )
     *   CIE-b* = 200 * ( var_Y - var_Z )
     * }
     * </pre>
     *
     * @param comp An array of doubles where each value is a component of the XYZ color space.
     * @return An array of doubles where each value is a component of the CIE-L*a*b* color space.
     */
    private static double[] convertXyzToCieLab(double[] comp) {
        comp[X] /= 95.047;
        comp[Y] /= 100.0;
        comp[Z] /= 108.883;
        for (int i = 0; i < comp.length; i++) {
            if (comp[i] > 0.008856) {
                comp[i] = Math.pow(comp[i], (1.0 / 3.0));
            } else {
                comp[i] = (7.787 * comp[i]) + (16.0 / 116.0);
            }
        }
        final double l = (116 * comp[Y]) - 16;
        final double a = 500 * (comp[X] - comp[Y]);
        final double b = 200 * (comp[Y] - comp[Z]);
        return new double[] {l, a, b};
    }

    private static int euclideanDistance(double[] p1, double[] p2) {
        if (p1.length != p2.length) {
            return Integer.MAX_VALUE;
        }
        double result = 0;
        for (int i = 0; i < p1.length; i++) {
            result += Math.pow(p1[i] - p2[i], 2);
        }
        return (int) Math.round(Math.sqrt(result));
    }

    /**
     * Crops the border of the array representing an image by hBorderSize
     * pixels on the left and right borders, and by vBorderSize pixels on the
     * top and bottom borders (so the width is 2 * hBorderSize smaller and
     * the height is 2 * vBorderSize smaller), then scales the image up to
     * match the original size using bilinear interpolation.
     */
    private static Bitmap shrinkAndScaleBilinear(
            Bitmap input, double hBorderSize, double vBorderSize) {

        int width = input.getWidth();
        int height = input.getHeight();

        // Compute the proper step sizes
        double xInc = ((double) width - 1 - hBorderSize * 2) / (double) (width - 1);
        double yInc = ((double) height - 1 - vBorderSize * 2) / (double) (height - 1);

        // Read the input bitmap into RGB arrays.
        int[] inputPixels = new int[width * height];
        input.getPixels(inputPixels, 0, width, 0, 0, width, height);
        int[][] inputRgb = new int[width * height][3];
        for (int i = 0; i < width * height; ++i) {
            inputRgb[i][0] = Color.red(inputPixels[i]);
            inputRgb[i][1] = Color.green(inputPixels[i]);
            inputRgb[i][2] = Color.blue(inputPixels[i]);
        }
        inputPixels = null;

        // Prepare the output buffer.
        int[] outputPixels = new int[width * height];

        // Start the iteration. The first y coordinate is vBorderSize.
        double y = vBorderSize;
        for (int yIndex = 0; yIndex < height; ++yIndex) {
            // The first x coordinate is hBorderSize.
            double x = hBorderSize;
            for (int xIndex = 0; xIndex < width; ++xIndex) {
                // Determine the square of interest.
                int left = (int)x;    // This is floor(x).
                int top = (int)y;     // This is floor(y).
                int right = left + 1;
                int bottom = top + 1;

                // (u, v) is the fractional part of (x, y).
                double u = x - (double)left;
                double v = y - (double)top;

                // Precompute necessary products to save time.
                double p00 = (1.0 - u) * (1.0 - v);
                double p01 = (1.0 - u) * v;
                double p10 = u * (1.0 - v);
                double p11 = u * v;

                // Clamp the indices to prevent out-of-bound that may be caused
                // by round-off error.
                if (left >= width) left = width - 1;
                if (top >= height) top = height - 1;
                if (right >= width) right = width - 1;
                if (bottom >= height) bottom = height - 1;

                // Sample RGB values from the four corners.
                int[] rgb00 = inputRgb[top * width + left];
                int[] rgb01 = inputRgb[bottom * width + left];
                int[] rgb10 = inputRgb[top * width + right];
                int[] rgb11 = inputRgb[bottom * width + right];

                // Interpolate each component of RGB separately.
                int[] mixedColor = new int[3];
                for (int k = 0; k < 3; ++k) {
                    mixedColor[k] = (int)Math.round(
                            p00 * (double) rgb00[k] + p01 * (double) rgb01[k]
                            + p10 * (double) rgb10[k] + p11 * (double) rgb11[k]);
                }
                // Convert RGB to bitmap Color format and store.
                outputPixels[yIndex * width + xIndex] = Color.rgb(
                        mixedColor[0], mixedColor[1], mixedColor[2]);
                x += xInc;
            }
            y += yInc;
        }
        // Assemble the output buffer into a Bitmap object.
        return Bitmap.createBitmap(outputPixels, width, height, input.getConfig());
    }

    /**
     * Calls computeDifference on multiple cropped-and-scaled versions of
     * bitmap2.
     */
    @TargetApi(12)
    public static Difference computeMinimumDifference(
            Bitmap bitmap1, Bitmap bitmap2, Pair<Double, Double>[] borderCrops) {

        // Compute the difference with the original image (bitmap2) first.
        Difference minDiff = computeDifference(bitmap1, bitmap2);
        // Then go through the list of borderCrops.
        for (Pair<Double, Double> borderCrop : borderCrops) {
            // Compute the difference between bitmap1 and a transformed
            // version of bitmap2.
            Bitmap bitmap2s = shrinkAndScaleBilinear(bitmap2, borderCrop.first, borderCrop.second);
            Difference d = computeDifference(bitmap1, bitmap2s);
            // Keep the minimum difference.
            if (d.greatestPixelDifference < minDiff.greatestPixelDifference) {
                minDiff = d;
                minDiff.bestMatchBorderCrop = borderCrop;
            }
        }
        return minDiff;
    }

    /**
     * Calls computeMinimumDifference on a default list of borderCrop.
     */
    @TargetApi(12)
    public static Difference computeMinimumDifference(
            Bitmap bitmap1, Bitmap bitmap2, int trueWidth, int trueHeight) {

        double hBorder = (double) bitmap1.getWidth() / (double) trueWidth;
        double vBorder = (double) bitmap1.getHeight() / (double) trueHeight;
        double hBorderH = 0.5 * hBorder; // Half-texel horizontal border
        double vBorderH = 0.5 * vBorder; // Half-texel vertical border
        return computeMinimumDifference(
                bitmap1,
                bitmap2,
                new Pair[] {
                    Pair.create(hBorderH, 0.0),
                    Pair.create(hBorderH, vBorderH),
                    Pair.create(0.0, vBorderH),
                    Pair.create(hBorder, 0.0),
                    Pair.create(hBorder, vBorder),
                    Pair.create(0.0, vBorder)
                });
        // This default list of borderCrop comes from the behavior of
        // GLConsumer.computeTransformMatrix().
    }

    /* Describes the difference between two {@link Bitmap} instances. */
    public static final class Difference {

        public final int greatestPixelDifference;
        public final Pair<Integer, Integer> greatestPixelDifferenceCoordinates;
        public Pair<Double, Double> bestMatchBorderCrop;

        private Difference(int greatestPixelDifference) {
            this(greatestPixelDifference, null, Pair.create(0.0, 0.0));
        }

        private Difference(
                int greatestPixelDifference,
                Pair<Integer, Integer> greatestPixelDifferenceCoordinates) {
            this(greatestPixelDifference, greatestPixelDifferenceCoordinates,
                    Pair.create(0.0, 0.0));
        }

        private Difference(
                int greatestPixelDifference,
                Pair<Integer, Integer> greatestPixelDifferenceCoordinates,
                Pair<Double, Double> bestMatchBorderCrop) {
            this.greatestPixelDifference = greatestPixelDifference;
            this.greatestPixelDifferenceCoordinates = greatestPixelDifferenceCoordinates;
            this.bestMatchBorderCrop = bestMatchBorderCrop;
        }
    }

}

/* Wrapper for MIME types. */
final class MimeTypes {

    private MimeTypes() {}

    public static final String VIDEO_VP9 = "video/x-vnd.on2.vp9";
    public static final String VIDEO_H264 = "video/avc";

    public static boolean isVideo(String mimeType) {
        return mimeType.startsWith("video");
    }

}
