/*
 * Copyright (C) 2014 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 com.android.cts.media.R;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;

import android.opengl.GLES20;
import javax.microedition.khronos.opengles.GL10;

import java.io.IOException;
import java.lang.System;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
import java.util.Vector;
import java.util.zip.CRC32;

public class AdaptivePlaybackTest extends MediaPlayerTestBase {
    private static final String TAG = "AdaptivePlaybackTest";
    private boolean sanity = false;
    private static final int MIN_FRAMES_BEFORE_DRC = 2;

    public Iterable<Codec> H264(CodecFactory factory) {
        return factory.createCodecList(
                mContext,
                MediaFormat.MIMETYPE_VIDEO_AVC,
                "OMX.google.h264.decoder",
                R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
                R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
    }

    public Iterable<Codec> HEVC(CodecFactory factory) {
        return factory.createCodecList(
                mContext,
                MediaFormat.MIMETYPE_VIDEO_HEVC,
                "OMX.google.hevc.decoder",
                R.raw.video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz,
                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz);
    }

    public Iterable<Codec> H263(CodecFactory factory) {
        return factory.createCodecList(
                mContext,
                MediaFormat.MIMETYPE_VIDEO_H263,
                "OMX.google.h263.decoder",
                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
                R.raw.video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz);
    }

    public Iterable<Codec> Mpeg4(CodecFactory factory) {
        return factory.createCodecList(
                mContext,
                MediaFormat.MIMETYPE_VIDEO_MPEG4,
                "OMX.google.mpeg4.decoder",

                R.raw.video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz,
                R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
    }

    public Iterable<Codec> VP8(CodecFactory factory) {
        return factory.createCodecList(
                mContext,
                MediaFormat.MIMETYPE_VIDEO_VP8,
                "OMX.google.vp8.decoder",
                R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
                R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
    }

    public Iterable<Codec> VP9(CodecFactory factory) {
        return factory.createCodecList(
                mContext,
                MediaFormat.MIMETYPE_VIDEO_VP9,
                "OMX.google.vp9.decoder",
                R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
                R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz);
    }

    CodecFactory ALL = new CodecFactory();
    CodecFactory SW  = new SWCodecFactory();
    CodecFactory HW  = new HWCodecFactory();

    public Iterable<Codec> H264()  { return H264(ALL);  }
    public Iterable<Codec> HEVC()  { return HEVC(ALL);  }
    public Iterable<Codec> VP8()   { return VP8(ALL);   }
    public Iterable<Codec> VP9()   { return VP9(ALL);   }
    public Iterable<Codec> Mpeg4() { return Mpeg4(ALL); }
    public Iterable<Codec> H263()  { return H263(ALL);  }

    public Iterable<Codec> AllCodecs() {
        return chain(H264(ALL), HEVC(ALL), VP8(ALL), VP9(ALL), Mpeg4(ALL), H263(ALL));
    }

    public Iterable<Codec> SWCodecs() {
        return chain(H264(SW), HEVC(SW), VP8(SW), VP9(SW), Mpeg4(SW), H263(SW));
    }

    public Iterable<Codec> HWCodecs() {
        return chain(H264(HW), HEVC(HW), VP8(HW), VP9(HW), Mpeg4(HW), H263(HW));
    }

    /* tests for adaptive codecs */
    Test adaptiveEarlyEos     = new EarlyEosTest().adaptive();
    Test adaptiveEosFlushSeek = new EosFlushSeekTest().adaptive();
    Test adaptiveSkipAhead    = new AdaptiveSkipTest(true /* forward */);
    Test adaptiveSkipBack     = new AdaptiveSkipTest(false /* forward */);

    /* DRC tests for adaptive codecs */
    Test adaptiveReconfigDrc      = new ReconfigDrcTest().adaptive();
    Test adaptiveSmallReconfigDrc = new ReconfigDrcTest().adaptiveSmall();
    Test adaptiveDrc      = new AdaptiveDrcTest(); /* adaptive */
    Test adaptiveSmallDrc = new AdaptiveDrcTest().adaptiveSmall();

    /* tests for regular codecs */
    Test earlyEos          = new EarlyEosTest();
    Test eosFlushSeek      = new EosFlushSeekTest();
    Test flushConfigureDrc = new ReconfigDrcTest();

    Test[] allTests = {
        adaptiveEarlyEos,
        adaptiveEosFlushSeek,
        adaptiveSkipAhead,
        adaptiveSkipBack,
        adaptiveReconfigDrc,
        adaptiveSmallReconfigDrc,
        adaptiveDrc,
        adaptiveSmallDrc,
        earlyEos,
        eosFlushSeek,
        flushConfigureDrc,
    };

    /* helpers to run sets of tests */
    public void runEOS() { ex(AllCodecs(), new Test[] {
        adaptiveEarlyEos,
        adaptiveEosFlushSeek,
        adaptiveReconfigDrc,
        adaptiveSmallReconfigDrc,
        earlyEos,
        eosFlushSeek,
        flushConfigureDrc,
    }); }

    public void runAll() { ex(AllCodecs(), allTests); }
    public void runSW()  { ex(SWCodecs(),  allTests); }
    public void runHW()  { ex(HWCodecs(),  allTests); }

    public void sanityAll() { sanity = true; try { runAll(); } finally { sanity = false; } }
    public void sanitySW()  { sanity = true; try { runSW();  } finally { sanity = false; } }
    public void sanityHW()  { sanity = true; try { runHW();  } finally { sanity = false; } }

    public void runH264()  { ex(H264(),  allTests); }
    public void runHEVC()  { ex(HEVC(),  allTests); }
    public void runVP8()   { ex(VP8(),   allTests); }
    public void runVP9()   { ex(VP9(),   allTests); }
    public void runMpeg4() { ex(Mpeg4(), allTests); }
    public void runH263()  { ex(H263(),  allTests); }

    public void onlyH264HW()  { ex(H264(HW),  allTests); }
    public void onlyHEVCHW()  { ex(HEVC(HW),  allTests); }
    public void onlyVP8HW()   { ex(VP8(HW),   allTests); }
    public void onlyVP9HW()   { ex(VP9(HW),   allTests); }
    public void onlyMpeg4HW() { ex(Mpeg4(HW), allTests); }
    public void onlyH263HW()  { ex(H263(HW),  allTests); }

    public void onlyH264SW()  { ex(H264(SW),  allTests); }
    public void onlyHEVCSW()  { ex(HEVC(SW),  allTests); }
    public void onlyVP8SW()   { ex(VP8(SW),   allTests); }
    public void onlyVP9SW()   { ex(VP9(SW),   allTests); }
    public void onlyMpeg4SW() { ex(Mpeg4(SW), allTests); }
    public void onlyH263SW()  { ex(H263(SW),  allTests); }

    public void bytebuffer() { ex(H264(SW), new EarlyEosTest().byteBuffer()); }
    public void texture() { ex(H264(HW), new EarlyEosTest().texture()); }

    /* inidividual tests */
    public void testH264_adaptiveEarlyEos()  { ex(H264(),  adaptiveEarlyEos); }
    public void testHEVC_adaptiveEarlyEos()  { ex(HEVC(),  adaptiveEarlyEos); }
    public void testVP8_adaptiveEarlyEos()   { ex(VP8(),   adaptiveEarlyEos); }
    public void testVP9_adaptiveEarlyEos()   { ex(VP9(),   adaptiveEarlyEos); }
    public void testMpeg4_adaptiveEarlyEos() { ex(Mpeg4(), adaptiveEarlyEos); }
    public void testH263_adaptiveEarlyEos()  { ex(H263(),  adaptiveEarlyEos); }

    public void testH264_adaptiveEosFlushSeek()  { ex(H264(),  adaptiveEosFlushSeek); }
    public void testHEVC_adaptiveEosFlushSeek()  { ex(HEVC(),  adaptiveEosFlushSeek); }
    public void testVP8_adaptiveEosFlushSeek()   { ex(VP8(),   adaptiveEosFlushSeek); }
    public void testVP9_adaptiveEosFlushSeek()   { ex(VP9(),   adaptiveEosFlushSeek); }
    public void testMpeg4_adaptiveEosFlushSeek() { ex(Mpeg4(), adaptiveEosFlushSeek); }
    public void testH263_adaptiveEosFlushSeek()  { ex(H263(),  adaptiveEosFlushSeek); }

    public void testH264_adaptiveSkipAhead()  { ex(H264(),  adaptiveSkipAhead); }
    public void testHEVC_adaptiveSkipAhead()  { ex(HEVC(),  adaptiveSkipAhead); }
    public void testVP8_adaptiveSkipAhead()   { ex(VP8(),   adaptiveSkipAhead); }
    public void testVP9_adaptiveSkipAhead()   { ex(VP9(),   adaptiveSkipAhead); }
    public void testMpeg4_adaptiveSkipAhead() { ex(Mpeg4(), adaptiveSkipAhead); }
    public void testH263_adaptiveSkipAhead()  { ex(H263(),  adaptiveSkipAhead); }

    public void testH264_adaptiveSkipBack()  { ex(H264(),  adaptiveSkipBack); }
    public void testHEVC_adaptiveSkipBack()  { ex(HEVC(),  adaptiveSkipBack); }
    public void testVP8_adaptiveSkipBack()   { ex(VP8(),   adaptiveSkipBack); }
    public void testVP9_adaptiveSkipBack()   { ex(VP9(),   adaptiveSkipBack); }
    public void testMpeg4_adaptiveSkipBack() { ex(Mpeg4(), adaptiveSkipBack); }
    public void testH263_adaptiveSkipBack()  { ex(H263(),  adaptiveSkipBack); }

    public void testH264_adaptiveReconfigDrc()  { ex(H264(),  adaptiveReconfigDrc); }
    public void testHEVC_adaptiveReconfigDrc()  { ex(HEVC(),  adaptiveReconfigDrc); }
    public void testVP8_adaptiveReconfigDrc()   { ex(VP8(),   adaptiveReconfigDrc); }
    public void testVP9_adaptiveReconfigDrc()   { ex(VP9(),   adaptiveReconfigDrc); }
    public void testMpeg4_adaptiveReconfigDrc() { ex(Mpeg4(), adaptiveReconfigDrc); }
    public void testH263_adaptiveReconfigDrc()  { ex(H263(),  adaptiveReconfigDrc); }

    public void testH264_adaptiveSmallReconfigDrc()  { ex(H264(),  adaptiveSmallReconfigDrc); }
    public void testHEVC_adaptiveSmallReconfigDrc()  { ex(HEVC(),  adaptiveSmallReconfigDrc); }
    public void testVP8_adaptiveSmallReconfigDrc()   { ex(VP8(),   adaptiveSmallReconfigDrc); }
    public void testVP9_adaptiveSmallReconfigDrc()   { ex(VP9(),   adaptiveSmallReconfigDrc); }
    public void testMpeg4_adaptiveSmallReconfigDrc() { ex(Mpeg4(), adaptiveSmallReconfigDrc); }
    public void testH263_adaptiveSmallReconfigDrc()  { ex(H263(),  adaptiveSmallReconfigDrc); }

    public void testH264_adaptiveDrc() { ex(H264(), adaptiveDrc); }
    public void testHEVC_adaptiveDrc() { ex(HEVC(), adaptiveDrc); }
    public void testVP8_adaptiveDrc()  { ex(VP8(),  adaptiveDrc); }
    public void testVP9_adaptiveDrc()  { ex(VP9(),  adaptiveDrc); }
    public void testMpeg4_adaptiveDrc() { ex(Mpeg4(), adaptiveDrc); }
    public void testH263_adaptiveDrc() { ex(H263(), adaptiveDrc); }

    public void testH264_adaptiveDrcEarlyEos() { ex(H264(), new AdaptiveDrcEarlyEosTest()); }
    public void testHEVC_adaptiveDrcEarlyEos() { ex(HEVC(), new AdaptiveDrcEarlyEosTest()); }
    public void testVP8_adaptiveDrcEarlyEos()  { ex(VP8(),  new AdaptiveDrcEarlyEosTest()); }
    public void testVP9_adaptiveDrcEarlyEos()  { ex(VP9(),  new AdaptiveDrcEarlyEosTest()); }

    public void testH264_adaptiveSmallDrc()  { ex(H264(),  adaptiveSmallDrc); }
    public void testHEVC_adaptiveSmallDrc()  { ex(HEVC(),  adaptiveSmallDrc); }
    public void testVP8_adaptiveSmallDrc()   { ex(VP8(),   adaptiveSmallDrc); }
    public void testVP9_adaptiveSmallDrc()   { ex(VP9(),   adaptiveSmallDrc); }

    public void testH264_earlyEos()  { ex(H264(),  earlyEos); }
    public void testHEVC_earlyEos()  { ex(HEVC(),  earlyEos); }
    public void testVP8_earlyEos()   { ex(VP8(),   earlyEos); }
    public void testVP9_earlyEos()   { ex(VP9(),   earlyEos); }
    public void testMpeg4_earlyEos() { ex(Mpeg4(), earlyEos); }
    public void testH263_earlyEos()  { ex(H263(),  earlyEos); }

    public void testH264_eosFlushSeek()  { ex(H264(),  eosFlushSeek); }
    public void testHEVC_eosFlushSeek()  { ex(HEVC(),  eosFlushSeek); }
    public void testVP8_eosFlushSeek()   { ex(VP8(),   eosFlushSeek); }
    public void testVP9_eosFlushSeek()   { ex(VP9(),   eosFlushSeek); }
    public void testMpeg4_eosFlushSeek() { ex(Mpeg4(), eosFlushSeek); }
    public void testH263_eosFlushSeek()  { ex(H263(),  eosFlushSeek); }

    public void testH264_flushConfigureDrc()  { ex(H264(),  flushConfigureDrc); }
    public void testHEVC_flushConfigureDrc()  { ex(HEVC(),  flushConfigureDrc); }
    public void testVP8_flushConfigureDrc()   { ex(VP8(),   flushConfigureDrc); }
    public void testVP9_flushConfigureDrc()   { ex(VP9(),   flushConfigureDrc); }
    public void testMpeg4_flushConfigureDrc() { ex(Mpeg4(), flushConfigureDrc); }
    public void testH263_flushConfigureDrc()  { ex(H263(),  flushConfigureDrc); }

    /* only use unchecked exceptions to allow brief test methods */
    private void ex(Iterable<Codec> codecList, Test test) {
        ex(codecList, new Test[] { test } );
    }

    private void ex(Iterable<Codec> codecList, Test[] testList) {
        if (codecList == null) {
            Log.i(TAG, "CodecList was empty. Skipping test.");
            return;
        }

        TestList tests = new TestList();
        for (Codec c : codecList) {
            for (Test test : testList) {
                if (test.isValid(c)) {
                    test.addTests(tests, c);
                }
            }
        }
        try {
            tests.run();
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    /* need an inner class to have access to the activity */
    abstract class ActivityTest extends Test {
        TestSurface mNullSurface = new ActivitySurface(null);
        protected TestSurface getSurface() {
            if (mUseSurface) {
                return new ActivitySurface(getActivity().getSurfaceHolder().getSurface());
            } else if (mUseSurfaceTexture) {
                return new DecoderSurface(1280, 720, mCRC);
            }
            return mNullSurface;
        }
    }

    static final int NUM_FRAMES = 50;

    /**
     * Queue some frames with an EOS on the last one.  Test that we have decoded as many
     * frames as we queued.  This tests the EOS handling of the codec to see if all queued
     * (and out-of-order) frames are actually decoded and returned.
     *
     * Also test flushing prior to sending CSD, and immediately after sending CSD.
     */
    class EarlyEosTest extends ActivityTest {
        // using bitfields to create a directed state graph that terminates at FLUSH_NEVER
        static final int FLUSH_BEFORE_CSD = (1 << 1);
        static final int FLUSH_AFTER_CSD = (1 << 0);
        static final int FLUSH_NEVER = 0;

        public boolean isValid(Codec c) {
            return getFormat(c) != null;
        }
        public void addTests(TestList tests, final Codec c) {
            int state = FLUSH_BEFORE_CSD;
            for (int i = NUM_FRAMES / 2; i > 0; --i, state >>= 1) {
                final int queuedFrames = i;
                final int earlyFlushMode = state;
                tests.add(
                    new Step("testing early EOS at " + queuedFrames, this, c) {
                        public void run() {
                            Decoder decoder = new Decoder(c.name);
                            try {
                                MediaFormat fmt = stepFormat();
                                MediaFormat configFmt = fmt;
                                if (earlyFlushMode == FLUSH_BEFORE_CSD) {
                                    // flush before CSD requires not submitting CSD with configure
                                    configFmt = Media.removeCSD(fmt);
                                }
                                decoder.configureAndStart(configFmt, stepSurface());
                                if (earlyFlushMode != FLUSH_NEVER) {
                                    decoder.flush();
                                    // We must always queue CSD after a flush that is potentially
                                    // before we receive output format has changed.  This should
                                    // work even after we receive the format change.
                                    decoder.queueCSD(fmt);
                                }
                                int decodedFrames = -decoder.queueInputBufferRange(
                                        stepMedia(),
                                        0 /* startFrame */,
                                        queuedFrames,
                                        true /* sendEos */,
                                        true /* waitForEos */);
                                if (decodedFrames <= 0) {
                                    Log.w(TAG, "Did not receive EOS -- negating frame count");
                                }
                                decoder.stop();
                                if (decodedFrames != queuedFrames) {
                                    warn("decoded " + decodedFrames + " frames out of " +
                                            queuedFrames + " queued");
                                }
                            } finally {
                                warn(decoder.getWarnings());
                                decoder.releaseQuietly();
                            }
                        }
                    });
                if (sanity) {
                    i >>= 1;
                }
            }
        }
    };

    /**
     * Similar to EarlyEosTest, but we keep the component alive and running in between the steps.
     * This is how seeking should be done if all frames must be outputted.  This also tests that
     * PTS can be repeated after flush.
     */
    class EosFlushSeekTest extends ActivityTest {
        Decoder mDecoder; // test state
        public boolean isValid(Codec c) {
            return getFormat(c) != null;
        }
        public void addTests(TestList tests, final Codec c) {
            tests.add(
                new Step("testing EOS & flush before seek - init", this, c) {
                    public void run() {
                        mDecoder = new Decoder(c.name);
                        mDecoder.configureAndStart(stepFormat(), stepSurface());
                    }});

            for (int i = NUM_FRAMES; i > 0; i--) {
                final int queuedFrames = i;
                tests.add(
                    new Step("testing EOS & flush before seeking after " + queuedFrames +
                            " frames", this, c) {
                        public void run() {
                            int decodedFrames = -mDecoder.queueInputBufferRange(
                                    stepMedia(),
                                    0 /* startFrame */,
                                    queuedFrames,
                                    true /* sendEos */,
                                    true /* waitForEos */);
                            if (decodedFrames != queuedFrames) {
                                warn("decoded " + decodedFrames + " frames out of " +
                                        queuedFrames + " queued");
                            }
                            warn(mDecoder.getWarnings());
                            mDecoder.clearWarnings();
                            mDecoder.flush();
                        }
                    });
                if (sanity) {
                    i >>= 1;
                }
            }

            tests.add(
                new Step("testing EOS & flush before seek - finally", this, c) {
                    public void run() {
                        try {
                            mDecoder.stop();
                        } finally {
                            mDecoder.release();
                        }
                    }});
        }
    };

    /**
     * Similar to EosFlushSeekTest, but we change the media size between the steps.
     * This is how dynamic resolution switching can be done on codecs that do not support
     * adaptive playback.
     */
    class ReconfigDrcTest extends ActivityTest {
        Decoder mDecoder;  // test state
        public boolean isValid(Codec c) {
            return getFormat(c) != null && c.mediaList.length > 1;
        }
        public void addTests(TestList tests, final Codec c) {
            tests.add(
                new Step("testing DRC with reconfigure - init", this, c) {
                    public void run() {
                        mDecoder = new Decoder(c.name);
                    }});

            for (int i = NUM_FRAMES, ix = 0; i > 0; i--, ix++) {
                final int queuedFrames = i;
                final int mediaIx = ix % c.mediaList.length;
                tests.add(
                    new Step("testing DRC with reconfigure after " + queuedFrames + " frames",
                            this, c, mediaIx) {
                        public void run() {
                            try {
                                mDecoder.configureAndStart(stepFormat(), stepSurface());
                                int decodedFrames = -mDecoder.queueInputBufferRange(
                                        stepMedia(),
                                        0 /* startFrame */,
                                        queuedFrames,
                                        true /* sendEos */,
                                        true /* waitForEos */);
                                if (decodedFrames != queuedFrames) {
                                    warn("decoded " + decodedFrames + " frames out of " +
                                            queuedFrames + " queued");
                                }
                                warn(mDecoder.getWarnings());
                                mDecoder.clearWarnings();
                                mDecoder.flush();
                            } finally {
                                mDecoder.stop();
                            }
                        }
                    });
                if (sanity) {
                    i >>= 1;
                }
            }
            tests.add(
                new Step("testing DRC with reconfigure - finally", this, c) {
                    public void run() {
                        mDecoder.release();
                    }});
        }
    };

    /* ADAPTIVE-ONLY TESTS - only run on codecs that support adaptive playback */

    /**
     * Test dynamic resolution change support.  Queue various sized media segments
     * with different resolutions, verify that all queued frames were decoded.  Here
     * PTS will grow between segments.
     */
    class AdaptiveDrcTest extends ActivityTest {
        Decoder mDecoder;
        int mAdjustTimeUs;
        int mDecodedFrames;
        int mQueuedFrames;

        public AdaptiveDrcTest() {
            super();
            adaptive();
        }
        public boolean isValid(Codec c) {
            checkAdaptiveFormat();
            return c.adaptive && c.mediaList.length > 1;
        }
        public void addTests(TestList tests, final Codec c) {
            tests.add(
                new Step("testing DRC with no reconfigure - init", this, c) {
                    public void run() throws Throwable {
                        // FIXME wait 2 seconds to allow system to free up previous codecs
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {}
                        mDecoder = new Decoder(c.name);
                        mDecoder.configureAndStart(stepFormat(), stepSurface());
                        mAdjustTimeUs = 0;
                        mDecodedFrames = 0;
                        mQueuedFrames = 0;
                    }});

            for (int i = NUM_FRAMES, ix = 0; i >= MIN_FRAMES_BEFORE_DRC; i--, ix++) {
                final int mediaIx = ix % c.mediaList.length;
                final int segmentSize = i;
                tests.add(
                    new Step("testing DRC with no reconfigure after " + i + " frames",
                            this, c, mediaIx) {
                        public void run() throws Throwable {
                            mQueuedFrames += segmentSize;
                            boolean lastSequence = segmentSize == MIN_FRAMES_BEFORE_DRC;
                            if (sanity) {
                                lastSequence = (segmentSize >> 1) <= MIN_FRAMES_BEFORE_DRC;
                            }
                            int frames = mDecoder.queueInputBufferRange(
                                    stepMedia(),
                                    0 /* startFrame */,
                                    segmentSize,
                                    lastSequence /* sendEos */,
                                    lastSequence /* expectEos */,
                                    mAdjustTimeUs);
                            if (lastSequence && frames >= 0) {
                                warn("did not receive EOS, received " + frames + " frames");
                            } else if (!lastSequence && frames < 0) {
                                warn("received EOS, received " + (-frames) + " frames");
                            }
                            warn(mDecoder.getWarnings());
                            mDecoder.clearWarnings();

                            mDecodedFrames += Math.abs(frames);
                            mAdjustTimeUs += 1 + stepMedia().getTimestampRangeValue(
                                    0, segmentSize, Media.RANGE_END);
                        }});
                if (sanity) {
                    i >>= 1;
                }
            }
            tests.add(
                new Step("testing DRC with no reconfigure - init", this, c) {
                    public void run() throws Throwable {
                        if (mDecodedFrames != mQueuedFrames) {
                            warn("decoded " + mDecodedFrames + " frames out of " +
                                    mQueuedFrames + " queued");
                        }
                        try {
                            mDecoder.stop();
                        } finally {
                            mDecoder.release();
                        }
                    }
                });
        }
    };

    /**
     * Queue EOS shortly after a dynamic resolution change.  Test that all frames were
     * decoded.
     */
    class AdaptiveDrcEarlyEosTest extends ActivityTest {
        public AdaptiveDrcEarlyEosTest() {
            super();
            adaptive();
        }
        public boolean isValid(Codec c) {
            checkAdaptiveFormat();
            return c.adaptive && c.mediaList.length > 1;
        }
        public Step testStep(final Codec c, final int framesBeforeDrc,
                final int framesBeforeEos) {
            return new Step("testing DRC with no reconfigure after " + framesBeforeDrc +
                    " frames and subsequent EOS after " + framesBeforeEos + " frames",
                    this, c) {
                public void run() throws Throwable {
                    Decoder decoder = new Decoder(c.name);
                    int queuedFrames = framesBeforeDrc + framesBeforeEos;
                    int framesA = 0;
                    int framesB = 0;
                    try {
                        decoder.configureAndStart(stepFormat(), stepSurface());
                        Media media = c.mediaList[0];

                        framesA = decoder.queueInputBufferRange(
                                media,
                                0 /* startFrame */,
                                framesBeforeDrc,
                                false /* sendEos */,
                                false /* expectEos */);
                        if (framesA < 0) {
                            warn("received unexpected EOS, received " + (-framesA) + " frames");
                        }
                        long adjustTimeUs = 1 + media.getTimestampRangeValue(
                                0, framesBeforeDrc, Media.RANGE_END);

                        media = c.mediaList[1];
                        framesB = decoder.queueInputBufferRange(
                                media,
                                0 /* startFrame */,
                                framesBeforeEos,
                                true /* sendEos */,
                                true /* expectEos */,
                                adjustTimeUs);
                        if (framesB >= 0) {
                            warn("did not receive EOS, received " + (-framesB) + " frames");
                        }
                        decoder.stop();
                        warn(decoder.getWarnings());
                    } finally {
                        int decodedFrames = Math.abs(framesA) + Math.abs(framesB);
                        if (decodedFrames != queuedFrames) {
                            warn("decoded " + decodedFrames + " frames out of " + queuedFrames +
                                    " queued");
                        }
                        decoder.release();
                    }
                }
            };
        }
        public void addTests(TestList tests, Codec c) {
            for (int drcFrame = 6; drcFrame >= MIN_FRAMES_BEFORE_DRC; drcFrame--) {
                for (int eosFrame = 6; eosFrame >= 1; eosFrame--) {
                    tests.add(testStep(c, drcFrame, eosFrame));
                }
            }
        }
    };

    /**
     * Similar to AdaptiveDrcTest, but tests that PTS can change at adaptive boundaries both
     * forward and backward without the need to flush.
     */
    class AdaptiveSkipTest extends ActivityTest {
        boolean forward;
        public AdaptiveSkipTest(boolean fwd) {
            forward = fwd;
            adaptive();
        }
        public boolean isValid(Codec c) {
            checkAdaptiveFormat();
            return c.adaptive;
        }
        Decoder mDecoder;
        int mAdjustTimeUs = 0;
        int mDecodedFrames = 0;
        int mQueuedFrames = 0;
        public void addTests(TestList tests, final Codec c) {
            tests.add(
                new Step("testing flushless skipping - init", this, c) {
                    public void run() throws Throwable {
                        mDecoder = new Decoder(c.name);
                        mDecoder.configureAndStart(stepFormat(), stepSurface());
                        mAdjustTimeUs = 0;
                        mDecodedFrames = 0;
                        mQueuedFrames = 0;
                    }});

            for (int i = 2, ix = 0; i <= NUM_FRAMES; i++, ix++) {
                final int mediaIx = ix % c.mediaList.length;
                final int segmentSize = i;
                final boolean lastSequence;
                if (sanity) {
                    lastSequence = (segmentSize << 1) + 1 > NUM_FRAMES;
                } else {
                    lastSequence = segmentSize >= NUM_FRAMES;
                }
                tests.add(
                    new Step("testing flushless skipping " + (forward ? "forward" : "backward") +
                            " after " + i + " frames", this, c) {
                        public void run() throws Throwable {
                            int frames = mDecoder.queueInputBufferRange(
                                stepMedia(),
                                0 /* startFrame */,
                                segmentSize,
                                lastSequence /* sendEos */,
                                lastSequence /* expectEos */,
                                mAdjustTimeUs);
                            if (lastSequence && frames >= 0) {
                                warn("did not receive EOS, received " + frames + " frames");
                            } else if (!lastSequence && frames < 0) {
                                warn("received unexpected EOS, received " + (-frames) + " frames");
                            }
                            warn(mDecoder.getWarnings());
                            mDecoder.clearWarnings();

                            mQueuedFrames += segmentSize;
                            mDecodedFrames += Math.abs(frames);
                            if (forward) {
                                mAdjustTimeUs += 10000000 + stepMedia().getTimestampRangeValue(
                                        0, segmentSize, Media.RANGE_DURATION);
                            }
                        }});
                if (sanity) {
                    i <<= 1;
                }
            }

            tests.add(
                new Step("testing flushless skipping - finally", this, c) {
                    public void run() throws Throwable {
                        if (mDecodedFrames != mQueuedFrames) {
                            warn("decoded " + mDecodedFrames + " frames out of " + mQueuedFrames +
                                    " queued");
                        }
                        try {
                            mDecoder.stop();
                        } finally {
                            mDecoder.release();
                        }
                    }});
        }
    };

    // not yet used
    static long checksum(ByteBuffer buf, int size, CRC32 crc) {
        assertTrue(size >= 0);
        assertTrue(size <= buf.capacity());
        crc.reset();
        if (buf.hasArray()) {
            crc.update(buf.array(), buf.arrayOffset(), size);
        } else {
           int pos = buf.position();
           buf.rewind();
           final int rdsize = Math.min(4096, size);
           byte bb[] = new byte[rdsize];
           int chk;
           for (int i = 0; i < size; i += chk) {
                chk = Math.min(rdsize, size - i);
                buf.get(bb, 0, chk);
                crc.update(bb, 0, chk);
            }
            buf.position(pos);
        }
        return crc.getValue();
    }

    CRC32 mCRC;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mCRC = new CRC32();
    }

    /* ====================================================================== */
    /*                              UTILITY FUNCTIONS                         */
    /* ====================================================================== */
    public static String collectionString(Collection<?> c) {
        StringBuilder res = new StringBuilder("[");
        boolean subsequent = false;
        for (Object o: c) {
            if (subsequent) {
                res.append(", ");
            }
            res.append(o);
            subsequent = true;
        }
        return res.append("]").toString();
    }

    static String byteBufferToString(ByteBuffer buf, int start, int len) {
        int oldPosition = buf.position();
        buf.position(start);
        int strlen = 2; // {}
        boolean ellipsis = len < buf.limit();
        if (ellipsis) {
            strlen += 3; // ...
        } else {
            len = buf.limit();
        }
        strlen += 3 * len - (len > 0 ? 1 : 0); // XX,XX
        char[] res = new char[strlen];
        res[0] = '{';
        res[strlen - 1] = '}';
        if (ellipsis) {
            res[strlen - 2] = res[strlen - 3] = res[strlen - 4] = '.';
        }
        for (int i = 1; i < len; i++) {
            res[i * 3] = ',';
        }
        for (int i = 0; i < len; i++) {
            byte b = buf.get();
            int d = (b >> 4) & 15;
            res[i * 3 + 1] = (char)(d + (d > 9 ? 'a' - 10 : '0'));
            d = (b & 15);
            res[i * 3 + 2] = (char)(d + (d > 9 ? 'a' - 10 : '0'));
        }
        buf.position(oldPosition);
        return new String(res);
    }

    static <E> Iterable<E> chain(Iterable<E> ... iterables) {
        /* simple chainer using ArrayList */
        ArrayList<E> items = new ArrayList<E>();
        for (Iterable<E> it: iterables) {
            for (E el: it) {
                items.add(el);
            }
        }
        return items;
    }

    class Decoder implements MediaCodec.OnFrameRenderedListener {
        private final static String TAG = "AdaptiveDecoder";
        final long kTimeOutUs = 5000;
        final long kCSDTimeOutUs = 1000000;
        MediaCodec mCodec;
        ByteBuffer[] mInputBuffers;
        ByteBuffer[] mOutputBuffers;
        TestSurface mSurface;
        boolean mDoChecksum;
        boolean mQueuedEos;
        ArrayList<Long> mTimeStamps;
        ArrayList<String> mWarnings;
        Vector<Long> mRenderedTimeStamps; // using Vector as it is implicitly synchronized
        long mLastRenderNanoTime;
        int mFramesNotifiedRendered;

        public Decoder(String codecName) {
            MediaCodec codec = null;
            try {
                codec = MediaCodec.createByCodecName(codecName);
            } catch (Exception e) {
                throw new RuntimeException("couldn't create codec " + codecName, e);
            }
            Log.i(TAG, "using codec: " + codec.getName());
            mCodec = codec;
            mDoChecksum = false;
            mQueuedEos = false;
            mTimeStamps = new ArrayList<Long>();
            mWarnings = new ArrayList<String>();
            mRenderedTimeStamps = new Vector<Long>();
            mLastRenderNanoTime = System.nanoTime();
            mFramesNotifiedRendered = 0;

            codec.setOnFrameRenderedListener(this, null);
        }

        public void onFrameRendered(MediaCodec codec, long presentationTimeUs, long nanoTime) {
            final long NSECS_IN_1SEC = 1000000000;
            if (!mRenderedTimeStamps.remove(presentationTimeUs)) {
                warn("invalid timestamp " + presentationTimeUs + ", queued " +
                        collectionString(mRenderedTimeStamps));
            }
            assert nanoTime > mLastRenderNanoTime;
            mLastRenderNanoTime = nanoTime;
            ++mFramesNotifiedRendered;
            assert nanoTime > System.nanoTime() - NSECS_IN_1SEC;
        }

        public String getName() {
            return mCodec.getName();
        }

        public Iterable<String> getWarnings() {
            return mWarnings;
        }

        private void warn(String warning) {
            mWarnings.add(warning);
            Log.w(TAG, warning);
        }

        public void clearWarnings() {
            mWarnings.clear();
        }

        public void configureAndStart(MediaFormat format, TestSurface surface) {
            mSurface = surface;
            Log.i(TAG, "configure(" + format + ", " + mSurface.getSurface() + ")");
            mCodec.configure(format, mSurface.getSurface(), null /* crypto */, 0 /* flags */);
            Log.i(TAG, "start");
            mCodec.start();

            // inject some minimal setOutputSurface test
            // TODO: change this test to also change the surface midstream
            try {
                mCodec.setOutputSurface(null);
                fail("should not be able to set surface to NULL");
            } catch (IllegalArgumentException e) {}
            mCodec.setOutputSurface(mSurface.getSurface());

            mInputBuffers = mCodec.getInputBuffers();
            mOutputBuffers = mCodec.getOutputBuffers();
            Log.i(TAG, "configured " + mInputBuffers.length + " input[" +
                  mInputBuffers[0].capacity() + "] and " +
                  mOutputBuffers.length + "output[" +
                  (mOutputBuffers[0] == null ? null : mOutputBuffers[0].capacity()) + "]");
            mQueuedEos = false;
            mRenderedTimeStamps.clear();
            mLastRenderNanoTime = System.nanoTime();
            mFramesNotifiedRendered = 0;
        }

        public void stop() {
            Log.i(TAG, "stop");
            mCodec.stop();
            // if we have queued 32 frames or more, at least one should have been notified
            // to have rendered.
            if (mRenderedTimeStamps.size() > 32 && mFramesNotifiedRendered == 0) {
                fail("rendered " + mRenderedTimeStamps.size() +
                        " frames, but none have been notified.");
            }
        }

        public void flush() {
            Log.i(TAG, "flush");
            mCodec.flush();
            mQueuedEos = false;
            mTimeStamps.clear();
        }

        public String dequeueAndReleaseOutputBuffer(MediaCodec.BufferInfo info) {
            int ix = mCodec.dequeueOutputBuffer(info, kTimeOutUs);
            if (ix == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                mOutputBuffers = mCodec.getOutputBuffers();
                Log.d(TAG, "output buffers have changed.");
                return null;
            } else if (ix == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                MediaFormat format = mCodec.getOutputFormat();
                Log.d(TAG, "output format has changed to " + format);
                int colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
                mDoChecksum = isRecognizedFormat(colorFormat);
                return null;
            } else if (ix < 0) {
                Log.v(TAG, "no output");
                return null;
            }
            /* create checksum */
            long sum = 0;


            Log.v(TAG, "dequeue #" + ix + " => { [" + info.size + "] flags=" + info.flags +
                    " @" + info.presentationTimeUs + "}");

            // we get a nonzero size for valid decoded frames
            boolean doRender = (info.size != 0);
            if (mSurface.getSurface() == null) {
                if (mDoChecksum) {
                    sum = checksum(mOutputBuffers[ix], info.size, mCRC);
                }
                mCodec.releaseOutputBuffer(ix, doRender);
            } else if (doRender) {
                // If using SurfaceTexture, as soon as we call releaseOutputBuffer, the
                // buffer will be forwarded to SurfaceTexture to convert to a texture.
                // The API doesn't guarantee that the texture will be available before
                // the call returns, so we need to wait for the onFrameAvailable callback
                // to fire.  If we don't wait, we risk dropping frames.
                mSurface.prepare();
                mCodec.releaseOutputBuffer(ix, doRender);
                mSurface.waitForDraw();
                if (mDoChecksum) {
                    sum = mSurface.checksum();
                }
            } else {
                mCodec.releaseOutputBuffer(ix, doRender);
            }

            if (doRender) {
                mRenderedTimeStamps.add(info.presentationTimeUs);
                if (!mTimeStamps.remove(info.presentationTimeUs)) {
                    warn("invalid timestamp " + info.presentationTimeUs + ", queued " +
                            collectionString(mTimeStamps));
                }
            }

            return String.format(Locale.US, "{pts=%d, flags=%x, data=0x%x}",
                                 info.presentationTimeUs, info.flags, sum);
        }

        /* returns true iff queued a frame */
        public boolean queueInputBuffer(Media media, int frameIx, boolean EOS) {
            return queueInputBuffer(media, frameIx, EOS, 0);
        }

        public boolean queueInputBuffer(Media media, int frameIx, boolean EOS, long adjustTimeUs) {
            if (mQueuedEos) {
                return false;
            }

            int ix = mCodec.dequeueInputBuffer(kTimeOutUs);

            if (ix < 0) {
                return false;
            }

            ByteBuffer buf = mInputBuffers[ix];
            Media.Frame frame = media.getFrame(frameIx);
            buf.clear();

            long presentationTimeUs = adjustTimeUs;
            int flags = 0;
            if (frame != null) {
                buf.put((ByteBuffer)frame.buf.clear());
                presentationTimeUs += frame.presentationTimeUs;
                flags = frame.flags;
            }

            if (EOS) {
                flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
                mQueuedEos = true;
            }

            mTimeStamps.add(presentationTimeUs);
            Log.v(TAG, "queue { [" + buf.position() + "]=" + byteBufferToString(buf, 0, 16) +
                    " flags=" + flags + " @" + presentationTimeUs + "} => #" + ix);
            mCodec.queueInputBuffer(
                    ix, 0 /* offset */, buf.position(), presentationTimeUs, flags);
            return true;
        }

        /* returns number of frames received multiplied by -1 if received EOS, 1 otherwise */
        public int queueInputBufferRange(
                Media media, int frameStartIx, int frameEndIx, boolean sendEosAtEnd,
                boolean waitForEos) {
            return queueInputBufferRange(media,frameStartIx,frameEndIx,sendEosAtEnd,waitForEos,0);
        }

        public void queueCSD(MediaFormat format) {
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            for (int csdIx = 0; ; ++csdIx) {
                ByteBuffer csdBuf = format.getByteBuffer("csd-" + csdIx);
                if (csdBuf == null) {
                    break;
                }

                int ix = mCodec.dequeueInputBuffer(kCSDTimeOutUs);
                if (ix < 0) {
                    fail("Could not dequeue input buffer for CSD #" + csdIx);
                    return;
                }

                ByteBuffer buf = mInputBuffers[ix];
                buf.clear();
                buf.put((ByteBuffer)csdBuf.clear());
                Log.v(TAG, "queue-CSD { [" + buf.position() + "]=" +
                        byteBufferToString(buf, 0, 16) + "} => #" + ix);
                mCodec.queueInputBuffer(
                        ix, 0 /* offset */, buf.position(), 0 /* timeUs */,
                        MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
            }
        }

        public int queueInputBufferRange(
                Media media, int frameStartIx, int frameEndIx, boolean sendEosAtEnd,
                boolean waitForEos, long adjustTimeUs) {
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            int frameIx = frameStartIx;
            int numFramesDecoded = 0;
            boolean sawOutputEos = false;
            int deadDecoderCounter = 0;
            ArrayList<String> frames = new ArrayList<String>();
            while ((waitForEos && !sawOutputEos) || frameIx < frameEndIx) {
                if (frameIx < frameEndIx) {
                    if (queueInputBuffer(
                            media,
                            frameIx,
                            sendEosAtEnd && (frameIx + 1 == frameEndIx),
                            adjustTimeUs)) {
                        frameIx++;
                    }
                }

                String buf = dequeueAndReleaseOutputBuffer(info);
                if (buf != null) {
                    // Some decoders output a 0-sized buffer at the end. Disregard those.
                    if (info.size > 0) {
                        deadDecoderCounter = 0;
                        numFramesDecoded++;
                    }

                    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                        Log.d(TAG, "saw output EOS.");
                        sawOutputEos = true;
                    }
                }
                if (++deadDecoderCounter >= 100) {
                    warn("have not received an output frame for a while");
                    break;
                }
            }

            if (numFramesDecoded < frameEndIx - frameStartIx - 16) {
                fail("Queued " + (frameEndIx - frameStartIx) + " frames but only received " +
                        numFramesDecoded);
            }
            return (sawOutputEos ? -1 : 1) * numFramesDecoded;
        }

        void release() {
            Log.i(TAG, "release");
            mCodec.release();
            mSurface.release();
            mInputBuffers = null;
            mOutputBuffers = null;
            mCodec = null;
            mSurface = null;
        }

        // don't fail on exceptions in release()
        void releaseQuietly() {
            try {
                Log.i(TAG, "release");
                mCodec.release();
            } catch (Throwable e) {
                Log.e(TAG, "Exception while releasing codec", e);
            }
            mSurface.release();
            mInputBuffers = null;
            mOutputBuffers = null;
            mCodec = null;
            mSurface = null;
        }
    };

    /* from EncodeDecodeTest */
    private static boolean isRecognizedFormat(int colorFormat) {
        switch (colorFormat) {
            // these are the formats we know how to handle for this test
            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
            case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
            case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
                return true;
            default:
                return false;
        }
    }

    private int countFrames(
            String codecName, MediaCodecInfo codecInfo, Media media, int eosframe, TestSurface s)
            throws Exception {
        Decoder codec = new Decoder(codecName);
        codec.configureAndStart(media.getFormat(), s /* surface */);

        int numframes = codec.queueInputBufferRange(
                media, 0, eosframe, true /* sendEos */, true /* waitForEos */);
        if (numframes >= 0) {
            Log.w(TAG, "Did not receive EOS");
        } else {
            numframes *= -1;
        }

        codec.stop();
        codec.release();
        return numframes;
    }
}

/* ====================================================================== */
/*                             Video Media Asset                          */
/* ====================================================================== */
class Media {
    private final static String TAG = "AdaptiveMedia";
    private MediaFormat mFormat;
    private MediaFormat mAdaptiveFormat;
    static class Frame {
        long presentationTimeUs;
        int flags;
        ByteBuffer buf;
        public Frame(long _pts, int _flags, ByteBuffer _buf) {
            presentationTimeUs = _pts;
            flags = _flags;
            buf = _buf;
        }
    };
    private Frame[] mFrames;

    public Frame getFrame(int ix) {
        /* this works even on short sample as frame is allocated as null */
        if (ix >= 0 && ix < mFrames.length) {
            return mFrames[ix];
        }
        return null;
    }
    private Media(MediaFormat format, MediaFormat adaptiveFormat, int numFrames) {
        /* need separate copies of format as once we add adaptive flags to
           MediaFormat, we cannot remove them */
        mFormat = format;
        mAdaptiveFormat = adaptiveFormat;
        mFrames = new Frame[numFrames];
    }

    public MediaFormat getFormat() {
        return mFormat;
    }

    public static MediaFormat removeCSD(MediaFormat orig) {
        MediaFormat copy = MediaFormat.createVideoFormat(
                orig.getString(orig.KEY_MIME),
                orig.getInteger(orig.KEY_WIDTH), orig.getInteger(orig.KEY_HEIGHT));
        for (String k : new String[] {
                orig.KEY_FRAME_RATE, orig.KEY_MAX_WIDTH, orig.KEY_MAX_HEIGHT,
                orig.KEY_MAX_INPUT_SIZE
        }) {
            if (orig.containsKey(k)) {
                try {
                    copy.setInteger(k, orig.getInteger(k));
                } catch (ClassCastException e) {
                    try {
                        copy.setFloat(k, orig.getFloat(k));
                    } catch (ClassCastException e2) {
                        // Could not copy value. Don't fail here, as having non-standard
                        // value types for defined keys is permissible by the media API
                        // for optional keys.
                    }
                }
            }
        }
        return copy;
    }

    public MediaFormat getAdaptiveFormat(int width, int height) {
        mAdaptiveFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, width);
        mAdaptiveFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, height);
        return mAdaptiveFormat;
    }

    public String getMime() {
        return mFormat.getString(MediaFormat.KEY_MIME);
    }

    public int getWidth() {
        return mFormat.getInteger(MediaFormat.KEY_WIDTH);
    }

    public int getHeight() {
        return mFormat.getInteger(MediaFormat.KEY_HEIGHT);
    }

    public final static int RANGE_START = 0;
    public final static int RANGE_END = 1;
    public final static int RANGE_DURATION = 2;

    public long getTimestampRangeValue(int frameStartIx, int frameEndIx, int kind) {
        long min = Long.MAX_VALUE, max = Long.MIN_VALUE;
        for (int frameIx = frameStartIx; frameIx < frameEndIx; frameIx++) {
            Frame frame = getFrame(frameIx);
            if (frame != null) {
                if (min > frame.presentationTimeUs) {
                    min = frame.presentationTimeUs;
                }
                if (max < frame.presentationTimeUs) {
                    max = frame.presentationTimeUs;
                }
            }
        }
        if (kind == RANGE_START) {
            return min;
        } else if (kind == RANGE_END) {
            return max;
        } else if (kind == RANGE_DURATION) {
            return max - min;
        } else {
            throw new IllegalArgumentException("kind is not valid: " + kind);
        }
    }

    public static Media read(Context context, int video, int numFrames)
            throws java.io.IOException {
        MediaExtractor extractor = new MediaExtractor();
        AssetFileDescriptor testFd = context.getResources().openRawResourceFd(video);
        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
                testFd.getLength());

        Media media = new Media(
                extractor.getTrackFormat(0), extractor.getTrackFormat(0), numFrames);
        extractor.selectTrack(0);

        Log.i(TAG, "format=" + media.getFormat());
        ArrayList<ByteBuffer> csds = new ArrayList<ByteBuffer>();
        for (String tag: new String[] { "csd-0", "csd-1" }) {
            if (media.getFormat().containsKey(tag)) {
                ByteBuffer csd = media.getFormat().getByteBuffer(tag);
                Log.i(TAG, tag + "=" + AdaptivePlaybackTest.byteBufferToString(csd, 0, 16));
                csds.add(csd);
            }
        }

        ByteBuffer readBuf = ByteBuffer.allocate(200000);
        for (int ix = 0; ix < numFrames; ix++) {
            int sampleSize = extractor.readSampleData(readBuf, 0 /* offset */);

            if (sampleSize < 0) {
                throw new IllegalArgumentException("media is too short at " + ix + " frames");
            } else {
                readBuf.position(0).limit(sampleSize);
                for (ByteBuffer csd: csds) {
                    sampleSize += csd.capacity();
                }
                ByteBuffer buf = ByteBuffer.allocate(sampleSize);
                for (ByteBuffer csd: csds) {
                    csd.clear();
                    buf.put(csd);
                    csd.clear();
                    Log.i(TAG, "csd[" + csd.capacity() + "]");
                }
                Log.i(TAG, "frame-" + ix + "[" + sampleSize + "]");
                csds.clear();
                buf.put(readBuf);
                media.mFrames[ix] = new Frame(
                    extractor.getSampleTime(),
                    extractor.getSampleFlags(),
                    buf);
                extractor.advance();
            }
        }
        extractor.release();
        testFd.close();
        return media;
    }
}

/* ====================================================================== */
/*                      Codec, CodecList and CodecFactory                 */
/* ====================================================================== */
class Codec {
    private final static String TAG = "AdaptiveCodec";

    public String name;
    public CodecCapabilities capabilities;
    public Media[] mediaList;
    public boolean adaptive;
    public Codec(String n, CodecCapabilities c, Media[] m) {
        name = n;
        capabilities = c;
        mediaList = m;

        if (capabilities == null) {
            adaptive = false;
        } else {
            Log.w(TAG, "checking capabilities of " + name + " for " + mediaList[0].getMime());
            adaptive = capabilities.isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback);
        }
    }
}

class CodecList extends ArrayList<Codec> { };

/* all codecs of mime, plus named codec if exists */
class CodecFamily extends CodecList {
    private final static String TAG = "AdaptiveCodecFamily";
    private static final int NUM_FRAMES = AdaptivePlaybackTest.NUM_FRAMES;

    public CodecFamily(Context context, String mime, String explicitCodecName, int ... resources) {
        try {
            /* read all media */
            Media[] mediaList = new Media[resources.length];
            for (int i = 0; i < resources.length; i++) {
                Log.v(TAG, "reading media " + resources[i]);
                Media media = Media.read(context, resources[i], NUM_FRAMES);
                assert media.getMime().equals(mime):
                        "test stream " + resources[i] + " has " + media.getMime() +
                        " mime type instead of " + mime;

                /* assuming the first timestamp is the smallest */
                long firstPTS = media.getFrame(0).presentationTimeUs;
                long smallestPTS = media.getTimestampRangeValue(0, NUM_FRAMES, Media.RANGE_START);

                assert firstPTS == smallestPTS:
                        "first frame timestamp (" + firstPTS + ") is not smallest (" +
                        smallestPTS + ")";

                mediaList[i] = media;
            }

            /* enumerate codecs */
            MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
            for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
                if (codecInfo.isEncoder()) {
                    continue;
                }
                for (String type : codecInfo.getSupportedTypes()) {
                    if (type.equals(mime)) {
                        /* mark the explicitly named codec as included */
                        if (codecInfo.getName().equals(explicitCodecName)) {
                            explicitCodecName = null;
                        }
                        add(new Codec(
                                codecInfo.getName(),
                                codecInfo.getCapabilitiesForType(mime),
                                mediaList));
                        break;
                    }
                }
            }

            /* test if the explicitly named codec is present on the system */
            if (explicitCodecName != null) {
                MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
                if (codec != null) {
                    codec.release();
                    add(new Codec(explicitCodecName, null, mediaList));
                }
            }
        } catch (Throwable t) {
            Log.wtf("Constructor failed", t);
            throw new RuntimeException("constructor failed", t);
        }
    }
}

/* named codec if exists */
class CodecByName extends CodecList {
    public CodecByName(Context context, String mime, String codecName, int ... resources) {
        for (Codec c: new CodecFamily(context, mime, codecName, resources)) {
            if (c.name.equals(codecName)) {
                add(c);
            }
        }
    }
}

/* all codecs of mime, except named codec if exists */
class CodecFamilyExcept extends CodecList {
    public CodecFamilyExcept(
            Context context, String mime, String exceptCodecName, int ... resources) {
        for (Codec c: new CodecFamily(context, mime, null, resources)) {
            if (!c.name.equals(exceptCodecName)) {
                add(c);
            }
        }
    }
}

class CodecFactory {
    protected boolean hasCodec(String codecName) {
        MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS);
        for (MediaCodecInfo info : list.getCodecInfos()) {
            if (codecName.equals(info.getName())) {
                return true;
            }
        }
        return false;
    }

    public CodecList createCodecList(
            Context context, String mime, String googleCodecName, int ...resources) {
        if (!hasCodec(googleCodecName)) {
            return null;
        }
        return new CodecFamily(context, mime, googleCodecName, resources);
    }
}

class SWCodecFactory extends CodecFactory {
    public CodecList createCodecList(
            Context context, String mime, String googleCodecName, int ...resources) {
        if (!hasCodec(googleCodecName)) {
            return null;
        }
        return new CodecByName(context, mime, googleCodecName, resources);
    }
}

class HWCodecFactory extends CodecFactory {
    public CodecList createCodecList(
            Context context, String mime, String googleCodecName, int ...resources) {
        if (!hasCodec(googleCodecName)) {
            return null;
        }
        return new CodecFamilyExcept(context, mime, googleCodecName, resources);
    }
}

/* ====================================================================== */
/*                  Test Steps, Test (Case)s, and Test List               */
/* ====================================================================== */
class StepRunner implements Runnable {
    public StepRunner(Step s) {
        mStep = s;
        mThrowed = null;
    }
    public void run() {
        try {
            mStep.run();
        } catch (Throwable e) {
            mThrowed = e;
        }
    }
    public void throwThrowed() throws Throwable {
        if (mThrowed != null) {
            throw mThrowed;
        }
    }
    private Throwable mThrowed;
    private Step mStep;
}

class TestList extends ArrayList<Step> {
    private final static String TAG = "AdaptiveTestList";
    public void run() throws Throwable {
        Throwable res = null;
        for (Step step: this) {
            try {
                Log.i(TAG, step.getDescription());
                if (step.stepSurface().needsToRunInSeparateThread()) {
                    StepRunner runner = new StepRunner(step);
                    Thread th = new Thread(runner, "stepWrapper");
                    th.start();
                    th.join();
                    runner.throwThrowed();
                } else {
                    step.run();
                }
            } catch (Throwable e) {
                Log.e(TAG, "while " + step.getDescription(), e);
                res = e;
                mFailedSteps++;
            } finally {
                mWarnings += step.getWarnings();
            }
        }
        if (res != null) {
            throw new RuntimeException(
                mFailedSteps + " failed steps, " + mWarnings + " warnings",
                res);
        }
    }
    public int getWarnings() {
        return mWarnings;
    }
    public int getFailures() {
        return mFailedSteps;
    }
    private int mFailedSteps;
    private int mWarnings;
}

abstract class Test {
    public static final int FORMAT_ADAPTIVE_LARGEST = 1;
    public static final int FORMAT_ADAPTIVE_FIRST = 2;
    public static final int FORMAT_REGULAR = 3;

    protected int mFormatType;
    protected boolean mUseSurface;
    protected boolean mUseSurfaceTexture;

    public Test() {
        mFormatType = FORMAT_REGULAR;
        mUseSurface = true;
        mUseSurfaceTexture = false;
    }

    public Test adaptive() {
        mFormatType = FORMAT_ADAPTIVE_LARGEST;
        return this;
    }

    public Test adaptiveSmall() {
        mFormatType = FORMAT_ADAPTIVE_FIRST;
        return this;
    }

    public Test byteBuffer() {
        mUseSurface = false;
        mUseSurfaceTexture = false;
        return this;
    }

    public Test texture() {
        mUseSurface = false;
        mUseSurfaceTexture = true;
        return this;
    }

    public void checkAdaptiveFormat() {
        assert mFormatType != FORMAT_REGULAR:
                "must be used with adaptive format";
    }

    abstract protected TestSurface getSurface();

    /* TRICKY: format is updated in each test run as we are actually reusing the
       same 2 MediaFormat objects returned from MediaExtractor.  Therefore,
       format must be explicitly obtained in each test step.

       returns null if codec does not support the format.
       */
    protected MediaFormat getFormat(Codec c) {
        return getFormat(c, 0);
    }

    protected MediaFormat getFormat(Codec c, int i) {
        MediaFormat format = null;
        if (mFormatType == FORMAT_REGULAR) {
            format = c.mediaList[i].getFormat();
        } else if (mFormatType == FORMAT_ADAPTIVE_FIRST && c.adaptive) {
            format = c.mediaList[i].getAdaptiveFormat(
                c.mediaList[i].getWidth(), c.mediaList[i].getHeight());
        } else if (mFormatType == FORMAT_ADAPTIVE_LARGEST && c.adaptive) {
            /* update adaptive format to max size used */
            format = c.mediaList[i].getAdaptiveFormat(0, 0);
            for (Media media : c.mediaList) {
                /* get the largest width, and the largest height independently */
                if (media.getWidth() > format.getInteger(MediaFormat.KEY_MAX_WIDTH)) {
                    format.setInteger(MediaFormat.KEY_MAX_WIDTH, media.getWidth());
                }
                if (media.getHeight() > format.getInteger(MediaFormat.KEY_MAX_HEIGHT)) {
                    format.setInteger(MediaFormat.KEY_MAX_HEIGHT, media.getHeight());
                }
            }
        }
        return format;
    }

    public boolean isValid(Codec c) { return true; }
    public abstract void addTests(TestList tests, Codec c);
}

abstract class Step {
    private static final String TAG = "AdaptiveStep";

    public Step(String title, Test instance, Codec codec, Media media) {
        mTest = instance;
        mCodec = codec;
        mMedia = media;
        mDescription = title + " on " + stepSurface().getSurface() + " using " +
            mCodec.name + " and " + stepFormat();
    }
    public Step(String title, Test instance, Codec codec, int mediaIx) {
        this(title, instance, codec, codec.mediaList[mediaIx]);
    }
    public Step(String title, Test instance, Codec codec) {
        this(title, instance, codec, 0);
    }
    public Step(String description) {
        mDescription = description;
    }
    public Step() { }

    public abstract void run() throws Throwable;

    private String mDescription;
    private Test mTest;
    private Codec mCodec;
    private Media mMedia;
    private int mWarnings;

    /* TRICKY: use non-standard getter names so that we don't conflict with the getters
       in the Test classes, as most test Steps are defined as anonymous classes inside
       the test classes. */
    public MediaFormat stepFormat() {
        int ix = Arrays.asList(mCodec.mediaList).indexOf(mMedia);
        return mTest.getFormat(mCodec, ix);
    }

    public TestSurface stepSurface() {
        return mTest.getSurface();
    }

    public Media  stepMedia()       { return mMedia; }

    public String getDescription() { return mDescription; }
    public int    getWarnings()    { return mWarnings; }

    public void warn(String message) {
        Log.e(TAG, "WARNING: " + message + " in " + getDescription());
        mWarnings++;
    }
    public void warn(String message, Throwable t) {
        Log.e(TAG, "WARNING: " + message + " in " + getDescription(), t);
        mWarnings++;
    }
    public void warn(Iterable<String> warnings) {
        for (String warning: warnings) {
            warn(warning);
        }
    }
}

interface TestSurface {
    public Surface getSurface();
    public long checksum();
    public void release();
    public void prepare();         // prepare surface prior to render
    public void waitForDraw();     // wait for rendering to take place
    public boolean needsToRunInSeparateThread();
}

class DecoderSurface extends OutputSurface implements TestSurface {
    private ByteBuffer mBuf;
    int mWidth;
    int mHeight;
    CRC32 mCRC;

    public DecoderSurface(int width, int height, CRC32 crc) {
        super(width, height);
        mWidth = width;
        mHeight = height;
        mCRC = crc;
        mBuf = ByteBuffer.allocateDirect(4 * width * height);
    }

    public void prepare() {
        makeCurrent();
    }

    public void waitForDraw() {
        awaitNewImage();
        drawImage();
    }

    public long checksum() {
        mBuf.position(0);
        GLES20.glReadPixels(0, 0, mWidth, mHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, mBuf);
        mBuf.position(0);
        return AdaptivePlaybackTest.checksum(mBuf, mBuf.capacity(), mCRC);
    }

    public void release() {
        super.release();
        mBuf = null;
    }

    public boolean needsToRunInSeparateThread() {
        return true;
    }
}

class ActivitySurface implements TestSurface {
    private Surface mSurface;
    public ActivitySurface(Surface s) {
        mSurface = s;
    }
    public Surface getSurface() {
        return mSurface;
    }
    public void prepare() { }
    public void waitForDraw() { }
    public long checksum() {
        return 0;
    }
    public void release() {
        // don't release activity surface, as it is reusable
    }
    public boolean needsToRunInSeparateThread() {
        return false;
    }
}

