/*
 * Copyright (C) 2019 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.mediav2.common.cts;

import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing;
import static android.media.MediaCodecInfo.CodecProfileLevel.*;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.Context;
import android.hardware.display.DisplayManager;
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.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Pair;
import android.view.Display;
import android.view.Surface;

import androidx.test.platform.app.InstrumentationRegistry;

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

import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;

/**
 * This class comprises of routines that are generic to media codec component trying and testing.
 * <p>
 * A media codec component essentially processes input data to generate output data. The
 * component uses a set of input and output buffers. At a simplistic level, the client requests
 * (or receive) an empty input buffer, fills it up with data and sends it to the codec for
 * processing. The codec uses up the data and transforms it into one of its empty output
 * buffers. Finally, the client asks (or receive) a filled output buffer, consume its contents and
 * release it back to the codec.
 * <p>
 * The type of data that a component receives and sends is dependent on the component. For
 * instance video encoders expect raw yuv/rgb data and send compressed data. A video decoder
 * receives compressed access-unit and sends reconstructed yuv. But the processes surrounding
 * this enqueue and dequeue remain common to all components. Operations like configure, requesting
 * the component for an empty input buffer, feeding the component a filled input buffer,
 * requesting the component for an output buffer, releasing the processed output buffer, Sending
 * state transition commands, waiting on component to send all outputs, closing the component and
 * releasing the resources, ... remain more or less identical to all components. The routines
 * that manage these generic processes are maintained by this class. Not only the methods that
 * are responsible for component trying but also methods that test its functionality are covered
 * here. A video component is expected to give same number of outputs as inputs. The output
 * buffer timestamps of an audio component or a decoder component is expected to be strictly
 * increasing. The routines that enforce these generic rules of all components at all times are
 * part of this class. Besides these, mediaType specific constants, helper utilities to test
 * specific components or mediaTypes are covered here.
 * <p>
 * enqueueInput and dequeueOutput are routines responsible for filling the input buffer and
 * handing the received output buffer respectively. These shall be component specific, hence they
 * are abstract methods. Any client intending to use this class shall implement these methods
 * basing on the component under test.
 * <p>
 * In simple terms, the CodecTestBase is a wrapper class comprising generic routines for
 * component trying and testing.
 */
public abstract class CodecTestBase {
    public static final boolean IS_Q = ApiLevelUtil.getApiLevel() == Build.VERSION_CODES.Q;
    public static final boolean IS_AT_LEAST_R = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
    public static final boolean IS_AT_LEAST_T =
            ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU);
    //TODO(b/248315681) Remove codenameEquals() check once devices return correct version for U
    public static final boolean IS_AT_LEAST_U = ApiLevelUtil.isAfter(Build.VERSION_CODES.TIRAMISU)
            || ApiLevelUtil.codenameEquals("UpsideDownCake");
    public static final boolean IS_BEFORE_U = !IS_AT_LEAST_U;
    public static final boolean FIRST_SDK_IS_AT_LEAST_T =
            ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU);
    public static final boolean VNDK_IS_AT_LEAST_T =
            SystemProperties.getInt("ro.vndk.version", Build.VERSION_CODES.CUR_DEVELOPMENT)
                    >= Build.VERSION_CODES.TIRAMISU;
    public static final boolean IS_HDR_EDITING_SUPPORTED;
    private static final String LOG_TAG = CodecTestBase.class.getSimpleName();

    public static final ArrayList<String> HDR_INFO_IN_BITSTREAM_CODECS = new ArrayList<>();
    public static final String HDR_STATIC_INFO =
            "00 d0 84 80 3e c2 33 c4 86 4c 1d b8 0b 13 3d 42 40 a0 0f 32 00 10 27 df 0d";
    public static final String HDR_STATIC_INCORRECT_INFO =
            "00 d0 84 80 3e c2 33 c4 86 10 27 d0 07 13 3d 42 40 a0 0f 32 00 10 27 df 0d";
    public static final HashMap<Integer, String> HDR_DYNAMIC_INFO = new HashMap<>();
    public static final HashMap<Integer, String> HDR_DYNAMIC_INCORRECT_INFO = new HashMap<>();
    public static final String CODEC_PREFIX_KEY = "codec-prefix";
    public static final String MEDIA_TYPE_PREFIX_KEY = "media-type-prefix";
    public static final String MIME_SEL_KEY = "mime-sel";
    public static final Map<String, String> CODEC_SEL_KEY_MIME_MAP = new HashMap<>();
    public static final Map<String, String> DEFAULT_ENCODERS = new HashMap<>();
    public static final Map<String, String> DEFAULT_DECODERS = new HashMap<>();
    public static final HashMap<String, int[]> PROFILE_MAP = new HashMap<>();
    public static final HashMap<String, int[]> PROFILE_SDR_MAP = new HashMap<>();
    public static final HashMap<String, int[]> PROFILE_HLG_MAP = new HashMap<>();
    public static final HashMap<String, int[]> PROFILE_HDR10_MAP = new HashMap<>();
    public static final HashMap<String, int[]> PROFILE_HDR10_PLUS_MAP = new HashMap<>();
    public static final HashMap<String, int[]> PROFILE_HDR_MAP = new HashMap<>();
    public static final boolean ENABLE_LOGS = false;
    public static final int PER_TEST_TIMEOUT_LARGE_TEST_MS = 300000;
    public static final int PER_TEST_TIMEOUT_SMALL_TEST_MS = 60000;
    public static final int UNSPECIFIED = 0;
    // Maintain Timeouts in sync with their counterpart in NativeMediaCommon.h
    // block at most 5ms while looking for io buffers
    public static final long Q_DEQ_TIMEOUT_US = 5000;
    // max poll counter before test aborts and returns error
    public static final int RETRY_LIMIT = 100;
    public static final String INVALID_CODEC = "unknown.codec_";
    static final int[] MPEG2_PROFILES = new int[]{MPEG2ProfileSimple, MPEG2ProfileMain,
            MPEG2Profile422, MPEG2ProfileSNR, MPEG2ProfileSpatial, MPEG2ProfileHigh};
    static final int[] MPEG4_PROFILES = new int[]{MPEG4ProfileSimple, MPEG4ProfileSimpleScalable,
            MPEG4ProfileCore, MPEG4ProfileMain, MPEG4ProfileNbit, MPEG4ProfileScalableTexture,
            MPEG4ProfileSimpleFace, MPEG4ProfileSimpleFBA, MPEG4ProfileBasicAnimated,
            MPEG4ProfileHybrid, MPEG4ProfileAdvancedRealTime, MPEG4ProfileCoreScalable,
            MPEG4ProfileAdvancedCoding, MPEG4ProfileAdvancedCore, MPEG4ProfileAdvancedScalable,
            MPEG4ProfileAdvancedSimple};
    static final int[] H263_PROFILES = new int[]{H263ProfileBaseline, H263ProfileH320Coding,
            H263ProfileBackwardCompatible, H263ProfileISWV2, H263ProfileISWV3,
            H263ProfileHighCompression, H263ProfileInternet, H263ProfileInterlace,
            H263ProfileHighLatency};
    static final int[] VP8_PROFILES = new int[]{VP8ProfileMain};
    static final int[] AVC_SDR_PROFILES = new int[]{AVCProfileBaseline, AVCProfileMain,
            AVCProfileExtended, AVCProfileHigh, AVCProfileConstrainedBaseline,
            AVCProfileConstrainedHigh};
    static final int[] AVC_HLG_PROFILES = new int[]{AVCProfileHigh10};
    static final int[] AVC_HDR_PROFILES = AVC_HLG_PROFILES;
    static final int[] AVC_PROFILES = combine(AVC_SDR_PROFILES, AVC_HDR_PROFILES);
    static final int[] VP9_SDR_PROFILES = new int[]{VP9Profile0};
    static final int[] VP9_HLG_PROFILES = new int[]{VP9Profile2};
    static final int[] VP9_HDR10_PROFILES = new int[]{VP9Profile2HDR};
    static final int[] VP9_HDR10_PLUS_PROFILES = new int[]{VP9Profile2HDR10Plus};
    static final int[] VP9_HDR_PROFILES =
            combine(VP9_HLG_PROFILES, combine(VP9_HDR10_PROFILES, VP9_HDR10_PLUS_PROFILES));
    static final int[] VP9_PROFILES = combine(VP9_SDR_PROFILES, VP9_HDR_PROFILES);
    static final int[] HEVC_SDR_PROFILES = new int[]{HEVCProfileMain, HEVCProfileMainStill};
    static final int[] HEVC_HLG_PROFILES = new int[]{HEVCProfileMain10};
    static final int[] HEVC_HDR10_PROFILES = new int[]{HEVCProfileMain10HDR10};
    static final int[] HEVC_HDR10_PLUS_PROFILES = new int[]{HEVCProfileMain10HDR10Plus};
    static final int[] HEVC_HDR_PROFILES =
            combine(HEVC_HLG_PROFILES, combine(HEVC_HDR10_PROFILES, HEVC_HDR10_PLUS_PROFILES));
    static final int[] HEVC_PROFILES = combine(HEVC_SDR_PROFILES, HEVC_HDR_PROFILES);
    static final int[] AV1_SDR_PROFILES = new int[]{AV1ProfileMain8};
    static final int[] AV1_HLG_PROFILES = new int[]{AV1ProfileMain10};
    static final int[] AV1_HDR10_PROFILES = new int[]{AV1ProfileMain10HDR10};
    static final int[] AV1_HDR10_PLUS_PROFILES = new int[]{AV1ProfileMain10HDR10Plus};
    static final int[] AV1_HDR_PROFILES =
            combine(AV1_HLG_PROFILES, combine(AV1_HDR10_PROFILES, AV1_HDR10_PLUS_PROFILES));
    static final int[] AV1_PROFILES = combine(AV1_SDR_PROFILES, AV1_HDR_PROFILES);
    static final int[] AAC_PROFILES = new int[]{AACObjectMain, AACObjectLC, AACObjectSSR,
            AACObjectLTP, AACObjectHE, AACObjectScalable, AACObjectERLC, AACObjectERScalable,
            AACObjectLD, AACObjectELD, AACObjectXHE};
    public static final Context CONTEXT =
            InstrumentationRegistry.getInstrumentation().getTargetContext();
    public static String mimeSelKeys;
    public static String codecPrefix;
    public static String mediaTypePrefix;

    public enum SupportClass {
        CODEC_ALL, // All codecs must support
        CODEC_ANY, // At least one codec must support
        CODEC_DEFAULT, // Default codec must support
        CODEC_OPTIONAL; // Codec support is optional

        public static String toString(SupportClass supportRequirements) {
            switch (supportRequirements) {
                case CODEC_ALL:
                    return "CODEC_ALL";
                case CODEC_ANY:
                    return "CODEC_ANY";
                case CODEC_DEFAULT:
                    return "CODEC_DEFAULT";
                case CODEC_OPTIONAL:
                    return "CODEC_OPTIONAL";
                default:
                    return "Unknown support class";
            }
        }
    }

    public enum ComponentClass {
        ALL,
        SOFTWARE,
        HARDWARE;

        public static String toString(ComponentClass selectSwitch) {
            switch (selectSwitch) {
                case ALL:
                    return "all";
                case SOFTWARE:
                    return "software only";
                case HARDWARE:
                    return "hardware accelerated";
                default:
                    return "Unknown select switch";
            }
        }
    }

    public CodecTestBase(String encoder, String mime, String allTestParams) {
        mCodecName = encoder;
        mMime = mime;
        mAllTestParams = allTestParams;
        mAsyncHandle = new CodecAsyncHandler();
        mIsAudio = mMime.startsWith("audio/");
        mIsVideo = mMime.startsWith("video/");
    }

    protected final String mCodecName;
    protected final String mMime;
    protected final String mAllTestParams;  // logging

    protected final boolean mIsAudio;
    protected final boolean mIsVideo;
    protected final CodecAsyncHandler mAsyncHandle;
    protected boolean mIsCodecInAsyncMode;
    protected boolean mSawInputEOS;
    protected boolean mSawOutputEOS;
    protected boolean mSignalEOSWithLastFrame;
    protected int mInputCount;
    protected int mOutputCount;
    protected long mPrevOutputPts;
    protected boolean mSignalledOutFormatChanged;
    protected MediaFormat mOutFormat;

    protected StringBuilder mTestConfig = new StringBuilder();
    protected StringBuilder mTestEnv = new StringBuilder();

    protected boolean mSaveToMem;
    protected OutputManager mOutputBuff;

    protected MediaCodec mCodec;
    protected Surface mSurface;
    // NOTE: mSurface is a place holder of current Surface used by the CodecTestBase.
    // This doesn't own the handle. The ownership with instances that manage
    // SurfaceView or TextureView, ... They hold the responsibility of calling release().
    protected CodecTestActivity mActivity;

    public static final MediaCodecList MEDIA_CODEC_LIST_ALL;
    public static final MediaCodecList MEDIA_CODEC_LIST_REGULAR;
    static {
        MEDIA_CODEC_LIST_ALL = new MediaCodecList(MediaCodecList.ALL_CODECS);
        MEDIA_CODEC_LIST_REGULAR = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        IS_HDR_EDITING_SUPPORTED = isHDREditingSupported();
        CODEC_SEL_KEY_MIME_MAP.put("vp8", MediaFormat.MIMETYPE_VIDEO_VP8);
        CODEC_SEL_KEY_MIME_MAP.put("vp9", MediaFormat.MIMETYPE_VIDEO_VP9);
        CODEC_SEL_KEY_MIME_MAP.put("av1", MediaFormat.MIMETYPE_VIDEO_AV1);
        CODEC_SEL_KEY_MIME_MAP.put("avc", MediaFormat.MIMETYPE_VIDEO_AVC);
        CODEC_SEL_KEY_MIME_MAP.put("hevc", MediaFormat.MIMETYPE_VIDEO_HEVC);
        CODEC_SEL_KEY_MIME_MAP.put("mpeg4", MediaFormat.MIMETYPE_VIDEO_MPEG4);
        CODEC_SEL_KEY_MIME_MAP.put("h263", MediaFormat.MIMETYPE_VIDEO_H263);
        CODEC_SEL_KEY_MIME_MAP.put("mpeg2", MediaFormat.MIMETYPE_VIDEO_MPEG2);
        CODEC_SEL_KEY_MIME_MAP.put("vraw", MediaFormat.MIMETYPE_VIDEO_RAW);
        CODEC_SEL_KEY_MIME_MAP.put("amrnb", MediaFormat.MIMETYPE_AUDIO_AMR_NB);
        CODEC_SEL_KEY_MIME_MAP.put("amrwb", MediaFormat.MIMETYPE_AUDIO_AMR_WB);
        CODEC_SEL_KEY_MIME_MAP.put("mp3", MediaFormat.MIMETYPE_AUDIO_MPEG);
        CODEC_SEL_KEY_MIME_MAP.put("aac", MediaFormat.MIMETYPE_AUDIO_AAC);
        CODEC_SEL_KEY_MIME_MAP.put("vorbis", MediaFormat.MIMETYPE_AUDIO_VORBIS);
        CODEC_SEL_KEY_MIME_MAP.put("opus", MediaFormat.MIMETYPE_AUDIO_OPUS);
        CODEC_SEL_KEY_MIME_MAP.put("g711alaw", MediaFormat.MIMETYPE_AUDIO_G711_ALAW);
        CODEC_SEL_KEY_MIME_MAP.put("g711mlaw", MediaFormat.MIMETYPE_AUDIO_G711_MLAW);
        CODEC_SEL_KEY_MIME_MAP.put("araw", MediaFormat.MIMETYPE_AUDIO_RAW);
        CODEC_SEL_KEY_MIME_MAP.put("flac", MediaFormat.MIMETYPE_AUDIO_FLAC);
        CODEC_SEL_KEY_MIME_MAP.put("gsm", MediaFormat.MIMETYPE_AUDIO_MSGSM);

        android.os.Bundle args = InstrumentationRegistry.getArguments();
        mimeSelKeys = args.getString(MIME_SEL_KEY);
        codecPrefix = args.getString(CODEC_PREFIX_KEY);
        mediaTypePrefix = args.getString(MEDIA_TYPE_PREFIX_KEY);

        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_AVC, AVC_SDR_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_SDR_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_H263, H263_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_MPEG2, MPEG2_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_MPEG4, MPEG4_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP8, VP8_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_SDR_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_SDR_PROFILES);
        PROFILE_SDR_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC, AAC_PROFILES);

        PROFILE_HLG_MAP.put(MediaFormat.MIMETYPE_VIDEO_AVC, AVC_HLG_PROFILES);
        PROFILE_HLG_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_HLG_PROFILES);
        PROFILE_HLG_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_HLG_PROFILES);
        PROFILE_HLG_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_HLG_PROFILES);

        PROFILE_HDR10_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_HDR10_PROFILES);
        PROFILE_HDR10_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_HDR10_PROFILES);
        PROFILE_HDR10_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_HDR10_PROFILES);

        PROFILE_HDR10_PLUS_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_HDR10_PLUS_PROFILES);
        PROFILE_HDR10_PLUS_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_HDR10_PLUS_PROFILES);
        PROFILE_HDR10_PLUS_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_HDR10_PLUS_PROFILES);

        PROFILE_HDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_AVC, AVC_HDR_PROFILES);
        PROFILE_HDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_HDR_PROFILES);
        PROFILE_HDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_HDR_PROFILES);
        PROFILE_HDR_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_HDR_PROFILES);

        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_AVC, AVC_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, HEVC_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_H263, H263_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_MPEG2, MPEG2_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_MPEG4, MPEG4_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP8, VP8_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, VP9_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, AV1_PROFILES);
        PROFILE_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC, AAC_PROFILES);

        HDR_INFO_IN_BITSTREAM_CODECS.add(MediaFormat.MIMETYPE_VIDEO_AV1);
        HDR_INFO_IN_BITSTREAM_CODECS.add(MediaFormat.MIMETYPE_VIDEO_AVC);
        HDR_INFO_IN_BITSTREAM_CODECS.add(MediaFormat.MIMETYPE_VIDEO_HEVC);

        HDR_DYNAMIC_INFO.put(0, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0a 00 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 00");
        HDR_DYNAMIC_INFO.put(4, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0a 00 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 00");
        HDR_DYNAMIC_INFO.put(12, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0e 80 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 00");
        HDR_DYNAMIC_INFO.put(22, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0e 80 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 00");

        HDR_DYNAMIC_INCORRECT_INFO.put(0, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0a 00 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 00");
        HDR_DYNAMIC_INCORRECT_INFO.put(4, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0a 00 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 01");
        HDR_DYNAMIC_INCORRECT_INFO.put(12, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0e 80 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 02");
        HDR_DYNAMIC_INCORRECT_INFO.put(22, "b5 00 3c 00 01 04 00 40  00 0c 80 4e 20 27 10 00"
                + "0e 80 00 24 08 00 00 28  00 00 50 00 28 c8 00 c9"
                + "90 02 aa 58 05 ca d0 0c  0a f8 16 83 18 9c 18 00"
                + "40 78 13 64 d5 7c 2e 2c  c3 59 de 79 6e c3 c2 03");
    }

    static int[] combine(int[] first, int[] second) {
        int[] result = Arrays.copyOf(first, first.length + second.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }

    public static boolean isMediaTypeLossless(String mediaType) {
        if (mediaType.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) return true;
        if (mediaType.equals(MediaFormat.MIMETYPE_AUDIO_RAW)) return true;
        return false;
    }

    // some media types decode a pre-roll amount before playback. This would mean that decoding
    // after seeking may not return the exact same values as would be obtained by decoding the
    // stream straight through
    public static boolean isMediaTypeOutputUnAffectedBySeek(String mediaType) {
        if (mediaType.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) return true;
        if (mediaType.equals(MediaFormat.MIMETYPE_AUDIO_RAW)) return true;
        if (mediaType.startsWith("video/")) return true;
        return false;
    }

    public static boolean hasDecoder(String mime) {
        return CodecTestBase.selectCodecs(mime, null, null, false).size() != 0;
    }

    public static boolean hasEncoder(String mime) {
        return CodecTestBase.selectCodecs(mime, null, null, true).size() != 0;
    }

    public static void checkFormatSupport(String codecName, String mime, boolean isEncoder,
            ArrayList<MediaFormat> formats, String[] features, SupportClass supportRequirements)
            throws IOException {
        if (!areFormatsSupported(codecName, mime, formats)) {
            switch (supportRequirements) {
                case CODEC_ALL:
                    fail("format(s) not supported by codec: " + codecName + " for mime : " + mime
                            + " formats: " + formats);
                    break;
                case CODEC_ANY:
                    if (selectCodecs(mime, formats, features, isEncoder).isEmpty()) {
                        fail("format(s) not supported by any component for mime : " + mime
                                + " formats: " + formats);
                    }
                    break;
                case CODEC_DEFAULT:
                    if (isDefaultCodec(codecName, mime, isEncoder)) {
                        fail("format(s) not supported by default codec : " + codecName
                                + "for mime : " + mime + " formats: " + formats);
                    }
                    break;
                case CODEC_OPTIONAL:
                default:
                    // the later assumeTrue() ensures we skip the test for unsupported codecs
                    break;
            }
            Assume.assumeTrue("format(s) not supported by codec: " + codecName + " for mime : "
                    + mime, false);
        }
    }

    public static boolean isFeatureSupported(String name, String mime, String feature)
            throws IOException {
        MediaCodec codec = MediaCodec.createByCodecName(name);
        MediaCodecInfo.CodecCapabilities codecCapabilities =
                codec.getCodecInfo().getCapabilitiesForType(mime);
        boolean isSupported = codecCapabilities.isFeatureSupported(feature);
        codec.release();
        return isSupported;
    }

    public static boolean isHDREditingSupported() {
        for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_REGULAR.getCodecInfos()) {
            if (!codecInfo.isEncoder()) {
                continue;
            }
            for (String mediaType : codecInfo.getSupportedTypes()) {
                CodecCapabilities caps = codecInfo.getCapabilitiesForType(mediaType);
                if (caps != null && caps.isFeatureSupported(FEATURE_HdrEditing)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean doesAnyFormatHaveHDRProfile(String mime, ArrayList<MediaFormat> formats) {
        int[] profileArray = PROFILE_HDR_MAP.get(mime);
        if (profileArray != null) {
            for (MediaFormat format : formats) {
                assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
                int profile = format.getInteger(MediaFormat.KEY_PROFILE, -1);
                if (IntStream.of(profileArray).anyMatch(x -> x == profile)) return true;
            }
        }
        return false;
    }

    public static boolean doesCodecSupportHDRProfile(String codecName, String mediaType) {
        int[] hdrProfiles = PROFILE_HDR_MAP.get(mediaType);
        if (hdrProfiles == null) {
            return false;
        }
        for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_REGULAR.getCodecInfos()) {
            if (!codecName.equals(codecInfo.getName())) {
                continue;
            }
            CodecCapabilities caps = codecInfo.getCapabilitiesForType(mediaType);
            if (caps == null) {
                return false;
            }
            for (CodecProfileLevel pl : caps.profileLevels) {
                if (IntStream.of(hdrProfiles).anyMatch(x -> x == pl.profile)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static boolean canDisplaySupportHDRContent() {
        DisplayManager displayManager = CONTEXT.getSystemService(DisplayManager.class);
        return displayManager.getDisplay(Display.DEFAULT_DISPLAY).getHdrCapabilities()
                .getSupportedHdrTypes().length != 0;
    }

    public static boolean areFormatsSupported(String name, String mime,
            ArrayList<MediaFormat> formats) throws IOException {
        MediaCodec codec = MediaCodec.createByCodecName(name);
        MediaCodecInfo.CodecCapabilities codecCapabilities =
                codec.getCodecInfo().getCapabilitiesForType(mime);
        boolean isSupported = true;
        if (formats != null) {
            for (int i = 0; i < formats.size() && isSupported; i++) {
                isSupported = codecCapabilities.isFormatSupported(formats.get(i));
            }
        }
        codec.release();
        return isSupported;
    }

    public static boolean hasSupportForColorFormat(String name, String mime, int colorFormat)
            throws IOException {
        MediaCodec codec = MediaCodec.createByCodecName(name);
        MediaCodecInfo.CodecCapabilities cap =
                codec.getCodecInfo().getCapabilitiesForType(mime);
        boolean hasSupport = false;
        for (int c : cap.colorFormats) {
            if (c == colorFormat) {
                hasSupport = true;
                break;
            }
        }
        codec.release();
        return hasSupport;
    }

    public static boolean isDefaultCodec(String codecName, String mime, boolean isEncoder)
            throws IOException {
        Map<String, String> mDefaultCodecs = isEncoder ? DEFAULT_ENCODERS : DEFAULT_DECODERS;
        if (mDefaultCodecs.containsKey(mime)) {
            return mDefaultCodecs.get(mime).equalsIgnoreCase(codecName);
        }
        MediaCodec codec = isEncoder ? MediaCodec.createEncoderByType(mime)
                : MediaCodec.createDecoderByType(mime);
        boolean isDefault = codec.getName().equalsIgnoreCase(codecName);
        mDefaultCodecs.put(mime, codec.getName());
        codec.release();
        return isDefault;
    }

    public static boolean isVendorCodec(String codecName) {
        for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_ALL.getCodecInfos()) {
            if (codecName.equals(codecInfo.getName())) {
                return codecInfo.isVendor();
            }
        }
        return false;
    }

    public static boolean isSoftwareCodec(String codecName) {
        for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_ALL.getCodecInfos()) {
            if (codecName.equals(codecInfo.getName())) {
                return codecInfo.isSoftwareOnly();
            }
        }
        return false;
    }

    public static boolean isHardwareAcceleratedCodec(String codecName) {
        for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_ALL.getCodecInfos()) {
            if (codecName.equals(codecInfo.getName())) {
                return codecInfo.isHardwareAccelerated();
            }
        }
        return false;
    }

    protected static String paramToString(Object[] param) {
        StringBuilder paramStr = new StringBuilder("[  ");
        for (int j = 0; j < param.length - 1; j++) {
            Object o = param[j];
            if (o == null) {
                paramStr.append("null, ");
            } else if (o instanceof String[]) {
                int length = Math.min(((String[]) o).length, 3);
                paramStr.append("{");
                for (int i = 0; i < length; i++) {
                    paramStr.append(((String[]) o)[i]).append(", ");
                }
                paramStr.delete(paramStr.length() - 2, paramStr.length())
                        .append(length == ((String[]) o).length ? "}, " : ", ... }, ");
            } else if (o instanceof int[]) {
                paramStr.append("{");
                for (int i = 0; i < ((int[]) o).length; i++) {
                    paramStr.append(((int[]) o)[i]).append(", ");
                }
                paramStr.delete(paramStr.length() - 2, paramStr.length()).append("}, ");
            } else if (o instanceof Map) {
                int length = 0;
                paramStr.append("{ ");
                Map map = (Map) o;
                for (Object key : map.keySet()) {
                    paramStr.append(key).append(" = ").append(map.get(key)).append(", ");
                    length++;
                    if (length > 1) break;
                }
                paramStr.delete(paramStr.length() - 2, paramStr.length())
                        .append(length == map.size() ? "}, " : ", ... }, ");
            } else if (o instanceof EncoderConfigParams[]) {
                int length = Math.min(((EncoderConfigParams[]) o).length, 3);
                paramStr.append("{");
                for (int i = 0; i < ((EncoderConfigParams[]) o).length; i++) {
                    paramStr.append(((EncoderConfigParams[]) o)[i]).append(", ");
                }
                paramStr.delete(paramStr.length() - 2, paramStr.length())
                        .append(length == ((EncoderConfigParams[]) o).length ? "}, " : ", ... }, ");
            } else paramStr.append(o).append(", ");
        }
        paramStr.delete(paramStr.length() - 2, paramStr.length()).append("  ]");
        return paramStr.toString();
    }

    public static ArrayList<String> compileRequiredMimeList(boolean isEncoder, boolean needAudio,
            boolean needVideo) {
        Set<String> list = new HashSet<>();
        if (!isEncoder) {
            if (MediaUtils.hasAudioOutput() && needAudio) {
                // sec 5.1.2
                list.add(MediaFormat.MIMETYPE_AUDIO_AAC);
                list.add(MediaFormat.MIMETYPE_AUDIO_FLAC);
                list.add(MediaFormat.MIMETYPE_AUDIO_MPEG);
                list.add(MediaFormat.MIMETYPE_AUDIO_VORBIS);
                list.add(MediaFormat.MIMETYPE_AUDIO_RAW);
                list.add(MediaFormat.MIMETYPE_AUDIO_OPUS);
            }
            if (MediaUtils.isHandheld() || MediaUtils.isTablet() || MediaUtils.isTv()
                    || MediaUtils.isAutomotive()) {
                // sec 2.2.2, 2.3.2, 2.5.2
                if (needAudio) {
                    list.add(MediaFormat.MIMETYPE_AUDIO_AAC);
                }
                if (needVideo) {
                    list.add(MediaFormat.MIMETYPE_VIDEO_AVC);
                    list.add(MediaFormat.MIMETYPE_VIDEO_MPEG4);
                    list.add(MediaFormat.MIMETYPE_VIDEO_H263);
                    list.add(MediaFormat.MIMETYPE_VIDEO_VP8);
                    list.add(MediaFormat.MIMETYPE_VIDEO_VP9);
                }
            }
            if (MediaUtils.isHandheld() || MediaUtils.isTablet()) {
                // sec 2.2.2
                if (needAudio) {
                    list.add(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
                    list.add(MediaFormat.MIMETYPE_AUDIO_AMR_WB);
                }
                if (needVideo) {
                    list.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
                    if (IS_AT_LEAST_U) {
                        list.add(MediaFormat.MIMETYPE_VIDEO_AV1);
                    }
                }
            }
            if (MediaUtils.isTv() && needVideo) {
                // sec 2.3.2
                list.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
                list.add(MediaFormat.MIMETYPE_VIDEO_MPEG2);
            }
        } else {
            if (MediaUtils.hasMicrophone() && needAudio) {
                // sec 5.1.1
                // TODO(b/154423550)
                // list.add(MediaFormat.MIMETYPE_AUDIO_RAW);
                list.add(MediaFormat.MIMETYPE_AUDIO_FLAC);
                list.add(MediaFormat.MIMETYPE_AUDIO_OPUS);
            }
            if (MediaUtils.isHandheld() || MediaUtils.isTablet() || MediaUtils.isTv()
                    || MediaUtils.isAutomotive()) {
                // sec 2.2.2, 2.3.2, 2.5.2
                if (needAudio) {
                    list.add(MediaFormat.MIMETYPE_AUDIO_AAC);
                }
                if (needVideo) {
                    list.add(MediaFormat.MIMETYPE_VIDEO_AVC);
                    list.add(MediaFormat.MIMETYPE_VIDEO_VP8);
                }
            }
            if ((MediaUtils.isHandheld() || MediaUtils.isTablet()) && needAudio) {
                // sec 2.2.2
                list.add(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
                list.add(MediaFormat.MIMETYPE_AUDIO_AMR_WB);
            }
        }
        return new ArrayList<>(list);
    }

    private static ArrayList<String> compileCompleteTestMimeList(boolean isEncoder,
            boolean needAudio, boolean needVideo) {
        ArrayList<String> mimes = new ArrayList<>();
        if (mimeSelKeys == null) {
            ArrayList<String> cddRequiredMimeList =
                    compileRequiredMimeList(isEncoder, needAudio, needVideo);
            MediaCodecInfo[] codecInfos = MEDIA_CODEC_LIST_REGULAR.getCodecInfos();
            for (MediaCodecInfo codecInfo : codecInfos) {
                if (codecInfo.isEncoder() != isEncoder) continue;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) continue;
                String[] types = codecInfo.getSupportedTypes();
                for (String type : types) {
                    if (mediaTypePrefix != null && !type.startsWith(mediaTypePrefix)) {
                        continue;
                    }
                    if (!needAudio && type.startsWith("audio/")) continue;
                    if (!needVideo && type.startsWith("video/")) continue;
                    if (!mimes.contains(type)) {
                        mimes.add(type);
                    }
                }
            }
            if (mediaTypePrefix != null) {
                return mimes;
            }
            // feature_video_output is not exposed to package manager. Testing for video output
            // ports, such as VGA, HDMI, DisplayPort, or a wireless port for display is also not
            // direct.
            /* sec 5.2: device implementations include an embedded screen display with the
            diagonal length of at least 2.5 inches or include a video output port or declare the
            support of a camera */
            if (isEncoder && needVideo
                    && (MediaUtils.hasCamera() || MediaUtils.getScreenSizeInInches() >= 2.5)
                    && !mimes.contains(MediaFormat.MIMETYPE_VIDEO_AVC)
                    && !mimes.contains(MediaFormat.MIMETYPE_VIDEO_VP8)) {
                // Add required cdd mimes here so that respective codec tests fail.
                mimes.add(MediaFormat.MIMETYPE_VIDEO_AVC);
                mimes.add(MediaFormat.MIMETYPE_VIDEO_VP8);
                Log.e(LOG_TAG, "device must support at least one of VP8 or AVC video encoders");
            }
            for (String mime : cddRequiredMimeList) {
                if (!mimes.contains(mime)) {
                    // Add required cdd mimes here so that respective codec tests fail.
                    mimes.add(mime);
                    Log.e(LOG_TAG, "no codec found for mime " + mime + " as required by cdd");
                }
            }
        } else {
            for (Map.Entry<String, String> entry : CODEC_SEL_KEY_MIME_MAP.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (mimeSelKeys.contains(key) && !mimes.contains(value)) mimes.add(value);
            }
        }
        return mimes;
    }

    public static List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList,
            boolean isEncoder, boolean needAudio, boolean needVideo, boolean mustTestAllCodecs) {
        return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo,
                mustTestAllCodecs, ComponentClass.ALL);
    }

    public static List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList,
            boolean isEncoder, boolean needAudio, boolean needVideo, boolean mustTestAllCodecs,
            ComponentClass selectSwitch) {
        ArrayList<String> mimes = compileCompleteTestMimeList(isEncoder, needAudio, needVideo);
        ArrayList<String> cddRequiredMimeList =
                compileRequiredMimeList(isEncoder, needAudio, needVideo);
        final List<Object[]> argsList = new ArrayList<>();
        int argLength = exhaustiveArgsList.get(0).length;
        for (String mime : mimes) {
            ArrayList<String> totalListOfCodecs =
                    selectCodecs(mime, null, null, isEncoder, selectSwitch);
            ArrayList<String> listOfCodecs = new ArrayList<>();
            if (codecPrefix != null) {
                for (String codec : totalListOfCodecs) {
                    if (codec.startsWith(codecPrefix)) {
                        listOfCodecs.add(codec);
                    }
                }
            } else {
                listOfCodecs = totalListOfCodecs;
            }
            if (mustTestAllCodecs && listOfCodecs.size() == 0 && codecPrefix == null) {
                listOfCodecs.add(INVALID_CODEC + mime);
            }
            boolean miss = true;
            for (Object[] arg : exhaustiveArgsList) {
                if (mime.equals(arg[0])) {
                    for (String codec : listOfCodecs) {
                        Object[] argUpdate = new Object[argLength + 2];
                        argUpdate[0] = codec;
                        System.arraycopy(arg, 0, argUpdate, 1, argLength);
                        argUpdate[argLength + 1] = paramToString(argUpdate);
                        argsList.add(argUpdate);
                    }
                    miss = false;
                }
            }
            if (miss && mustTestAllCodecs) {
                if (!cddRequiredMimeList.contains(mime)) {
                    Log.w(LOG_TAG, "no test vectors available for optional mime type " + mime);
                    continue;
                }
                for (String codec : listOfCodecs) {
                    Object[] argUpdate = new Object[argLength + 2];
                    argUpdate[0] = codec;
                    argUpdate[1] = mime;
                    System.arraycopy(exhaustiveArgsList.get(0), 1, argUpdate, 2, argLength - 1);
                    argUpdate[argLength + 1] = paramToString(argUpdate);
                    argsList.add(argUpdate);
                }
            }
        }
        return argsList;
    }

    public static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
            String[] features, boolean isEncoder) {
        return selectCodecs(mime, formats, features, isEncoder, ComponentClass.ALL);
    }

    public static ArrayList<String> selectCodecs(String mime, ArrayList<MediaFormat> formats,
            String[] features, boolean isEncoder, ComponentClass selectSwitch) {
        MediaCodecInfo[] codecInfos = MEDIA_CODEC_LIST_REGULAR.getCodecInfos();
        ArrayList<String> listOfCodecs = new ArrayList<>();
        for (MediaCodecInfo codecInfo : codecInfos) {
            if (codecInfo.isEncoder() != isEncoder) continue;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) continue;
            if (selectSwitch == ComponentClass.HARDWARE && !codecInfo.isHardwareAccelerated()) {
                continue;
            } else if (selectSwitch == ComponentClass.SOFTWARE && !codecInfo.isSoftwareOnly()) {
                continue;
            }
            String[] types = codecInfo.getSupportedTypes();
            for (String type : types) {
                if (type.equalsIgnoreCase(mime)) {
                    boolean isOk = true;
                    MediaCodecInfo.CodecCapabilities codecCapabilities =
                            codecInfo.getCapabilitiesForType(type);
                    if (formats != null) {
                        for (MediaFormat format : formats) {
                            if (!codecCapabilities.isFormatSupported(format)) {
                                isOk = false;
                                break;
                            }
                        }
                    }
                    if (features != null) {
                        for (String feature : features) {
                            if (!codecCapabilities.isFeatureSupported(feature)) {
                                isOk = false;
                                break;
                            }
                        }
                    }
                    if (isOk) listOfCodecs.add(codecInfo.getName());
                }
            }
        }
        return listOfCodecs;
    }

    public static int getWidth(MediaFormat format) {
        int width = format.getInteger(MediaFormat.KEY_WIDTH, -1);
        if (format.containsKey("crop-left") && format.containsKey("crop-right")) {
            width = format.getInteger("crop-right") + 1 - format.getInteger("crop-left");
        }
        return width;
    }

    public static int getHeight(MediaFormat format) {
        int height = format.getInteger(MediaFormat.KEY_HEIGHT, -1);
        if (format.containsKey("crop-top") && format.containsKey("crop-bottom")) {
            height = format.getInteger("crop-bottom") + 1 - format.getInteger("crop-top");
        }
        return height;
    }

    public static byte[] loadByteArrayFromString(final String str) {
        if (str == null) {
            return null;
        }
        Pattern pattern = Pattern.compile("[0-9a-fA-F]{2}");
        Matcher matcher = pattern.matcher(str);
        // allocate a large enough byte array first
        byte[] tempArray = new byte[str.length() / 2];
        int i = 0;
        while (matcher.find()) {
            tempArray[i++] = (byte) Integer.parseInt(matcher.group(), 16);
        }
        return Arrays.copyOfRange(tempArray, 0, i);
    }

    protected abstract void enqueueInput(int bufferIndex) throws IOException;

    protected abstract void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info);

    @Rule
    public final TestName mTestName = new TestName();

    @Before
    public void setUpCodecTestBase() {
        mTestConfig.setLength(0);
        mTestConfig.append("\n##################       Test Details        ####################\n");
        mTestConfig.append("Test Name :- ").append(mTestName.getMethodName()).append("\n");
        mTestConfig.append("Test Parameters :- ").append(mAllTestParams).append("\n");
        if (mCodecName != null && mCodecName.startsWith(INVALID_CODEC)) {
            fail("no valid component available for current test \n" + mTestConfig);
        }
    }

    @After
    public void tearDownCodecTestBase() {
        mSurface = null;
        if (mActivity != null) {
            mActivity.finish();
            mActivity = null;
        }
        if (mCodec != null) {
            mCodec.release();
            mCodec = null;
        }
    }

    protected void configureCodec(MediaFormat format, boolean isAsync,
            boolean signalEOSWithLastFrame, boolean isEncoder) {
        resetContext(isAsync, signalEOSWithLastFrame);
        mAsyncHandle.setCallBack(mCodec, isAsync);
        // signalEOS flag has nothing to do with configure. We are using this flag to try all
        // available configure apis
        if (signalEOSWithLastFrame) {
            mCodec.configure(format, mSurface, null,
                    isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0);
        } else {
            mCodec.configure(format, mSurface, isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0,
                    null);
        }
        mTestEnv.setLength(0);
        mTestEnv.append("###################      Test Environment       #####################\n");
        mTestEnv.append(String.format("Component under test :- %s \n", mCodecName));
        mTestEnv.append("Format under test :- ").append(format).append("\n");
        mTestEnv.append(String.format("Component operating in :- %s mode \n",
                (isAsync ? "asynchronous" : "synchronous")));
        mTestEnv.append(String.format("Component received input eos :- %s \n",
                (signalEOSWithLastFrame ? "with full buffer" : "with empty buffer")));
        if (ENABLE_LOGS) {
            Log.v(LOG_TAG, "codec configured");
        }
    }

    public OutputManager getOutputManager() {
        return mOutputBuff;
    }

    public MediaFormat getOutputFormat() {
        return mIsCodecInAsyncMode ? mAsyncHandle.getOutputFormat() : mOutFormat;
    }

    protected void flushCodec() {
        mCodec.flush();
        // TODO(b/147576107): is it ok to clearQueues right away or wait for some signal
        mAsyncHandle.clearQueues();
        mSawInputEOS = false;
        mSawOutputEOS = false;
        mInputCount = 0;
        mOutputCount = 0;
        mPrevOutputPts = Long.MIN_VALUE;
        if (ENABLE_LOGS) {
            Log.v(LOG_TAG, "codec flushed");
        }
    }

    protected void reConfigureCodec(MediaFormat format, boolean isAsync,
            boolean signalEOSWithLastFrame, boolean isEncoder) {
        /* TODO(b/147348711) */
        if (false) mCodec.stop();
        else mCodec.reset();
        configureCodec(format, isAsync, signalEOSWithLastFrame, isEncoder);
    }

    protected void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
        mAsyncHandle.resetContext();
        mIsCodecInAsyncMode = isAsync;
        mSawInputEOS = false;
        mSawOutputEOS = false;
        mSignalEOSWithLastFrame = signalEOSWithLastFrame;
        mInputCount = 0;
        mOutputCount = 0;
        mPrevOutputPts = Long.MIN_VALUE;
        mSignalledOutFormatChanged = false;
    }

    protected void enqueueEOS(int bufferIndex) {
        if (!mSawInputEOS) {
            mCodec.queueInputBuffer(bufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
            mSawInputEOS = true;
            if (ENABLE_LOGS) {
                Log.v(LOG_TAG, "Queued End of Stream");
            }
        }
    }

    protected void doWork(int frameLimit) throws InterruptedException, IOException {
        int frameCount = 0;
        if (mIsCodecInAsyncMode) {
            // dequeue output after inputEOS is expected to be done in waitForAllOutputs()
            while (!mAsyncHandle.hasSeenError() && !mSawInputEOS && frameCount < frameLimit) {
                Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
                if (element != null) {
                    int bufferID = element.first;
                    MediaCodec.BufferInfo info = element.second;
                    if (info != null) {
                        // <id, info> corresponds to output callback. Handle it accordingly
                        dequeueOutput(bufferID, info);
                    } else {
                        // <id, null> corresponds to input callback. Handle it accordingly
                        enqueueInput(bufferID);
                        frameCount++;
                    }
                }
            }
        } else {
            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
            // dequeue output after inputEOS is expected to be done in waitForAllOutputs()
            while (!mSawInputEOS && frameCount < frameLimit) {
                int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
                if (outputBufferId >= 0) {
                    dequeueOutput(outputBufferId, outInfo);
                } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    mOutFormat = mCodec.getOutputFormat();
                    mSignalledOutFormatChanged = true;
                }
                int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
                if (inputBufferId != -1) {
                    enqueueInput(inputBufferId);
                    frameCount++;
                }
            }
        }
    }

    protected void queueEOS() throws InterruptedException {
        if (mIsCodecInAsyncMode) {
            while (!mAsyncHandle.hasSeenError() && !mSawInputEOS) {
                Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getWork();
                if (element != null) {
                    int bufferID = element.first;
                    MediaCodec.BufferInfo info = element.second;
                    if (info != null) {
                        dequeueOutput(bufferID, info);
                    } else {
                        enqueueEOS(element.first);
                    }
                }
            }
        } else {
            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
            while (!mSawInputEOS) {
                int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
                if (outputBufferId >= 0) {
                    dequeueOutput(outputBufferId, outInfo);
                } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    mOutFormat = mCodec.getOutputFormat();
                    mSignalledOutFormatChanged = true;
                }
                int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US);
                if (inputBufferId != -1) {
                    enqueueEOS(inputBufferId);
                }
            }
        }
    }

    protected void waitForAllOutputs() throws InterruptedException {
        if (mIsCodecInAsyncMode) {
            while (!mAsyncHandle.hasSeenError() && !mSawOutputEOS) {
                Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getOutput();
                if (element != null) {
                    dequeueOutput(element.first, element.second);
                }
            }
        } else {
            MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo();
            while (!mSawOutputEOS) {
                int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US);
                if (outputBufferId >= 0) {
                    dequeueOutput(outputBufferId, outInfo);
                } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    mOutFormat = mCodec.getOutputFormat();
                    mSignalledOutFormatChanged = true;
                }
            }
        }
        validateTestState();
    }

    void validateTestState() {
        assertFalse("Encountered error in async mode. \n" + mTestConfig + mTestEnv
                + mAsyncHandle.getErrMsg(), mAsyncHandle.hasSeenError());
        if (mInputCount > 0) {
            assertTrue(String.format("fed %d input frames, received no output frames \n",
                    mInputCount) + mTestConfig + mTestEnv, mOutputCount > 0);
        }
        /*if (mInputCount == 0 && mInputCount != mOutputCount) {
            String msg = String.format("The number of output frames received is not same as number "
                            + "of input frames queued. Output count is %d, Input count is %d \n",
                    mOutputCount, mInputCount);
            // check the pts lists to see what frames are dropped, the below call is needed to
            // get useful error messages
            boolean unused = mOutputBuff.isOutPtsListIdenticalToInpPtsList(true);
            fail(msg + mTestConfig + mTestEnv + mOutputBuff.getErrMsg());
        }*/
    }

    protected void insertHdrDynamicInfo(byte[] info) {
        final Bundle params = new Bundle();
        params.putByteArray(MediaFormat.KEY_HDR10_PLUS_INFO, info);
        mCodec.setParameters(params);
    }

    public boolean isFormatSimilar(MediaFormat inpFormat, MediaFormat outFormat) {
        if (inpFormat == null || outFormat == null) return false;
        String inpMime = inpFormat.getString(MediaFormat.KEY_MIME);
        String outMime = outFormat.getString(MediaFormat.KEY_MIME);
        // not comparing input and output mimes because for a codec, mime is raw on one side and
        // encoded type on the other
        if (outMime.startsWith("audio/")) {
            return (inpFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT, -1)
                    == outFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT, -2))
                    && (inpFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE, -1)
                    == outFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE, -2))
                    && inpMime.startsWith("audio/");
        } else if (outMime.startsWith("video/")) {
            return getWidth(inpFormat) == getWidth(outFormat)
                    && getHeight(inpFormat) == getHeight(outFormat) && inpMime.startsWith("video/");
        }
        return true;
    }

    protected PersistableBundle validateMetrics(String codec) {
        PersistableBundle metrics = mCodec.getMetrics();
        assertNotNull("error! MediaCodec.getMetrics() returns null \n" + mTestConfig + mTestEnv,
                metrics);
        assertEquals("error! metrics#MetricsConstants.CODEC is not as expected \n" + mTestConfig
                + mTestEnv, metrics.getString(MediaCodec.MetricsConstants.CODEC), codec);
        assertEquals("error! metrics#MetricsConstants.MODE is not as expected \n" + mTestConfig
                        + mTestEnv, mIsAudio ? MediaCodec.MetricsConstants.MODE_AUDIO :
                        MediaCodec.MetricsConstants.MODE_VIDEO,
                metrics.getString(MediaCodec.MetricsConstants.MODE));
        return metrics;
    }

    protected PersistableBundle validateMetrics(String codec, MediaFormat format) {
        PersistableBundle metrics = validateMetrics(codec);
        if (mIsVideo) {
            assertEquals("error! metrics#MetricsConstants.WIDTH is not as expected\n" + mTestConfig
                            + mTestEnv, metrics.getInt(MediaCodec.MetricsConstants.WIDTH),
                    getWidth(format));
            assertEquals("error! metrics#MetricsConstants.HEIGHT is not as expected\n" + mTestConfig
                            + mTestEnv, metrics.getInt(MediaCodec.MetricsConstants.HEIGHT),
                    getHeight(format));
        }
        assertEquals("error! metrics#MetricsConstants.SECURE is not as expected\n" + mTestConfig
                + mTestEnv, 0, metrics.getInt(MediaCodec.MetricsConstants.SECURE));
        return metrics;
    }

    public void validateColorAspects(MediaFormat fmt, int range, int standard, int transfer) {
        int colorRange = fmt.getInteger(MediaFormat.KEY_COLOR_RANGE, UNSPECIFIED);
        int colorStandard = fmt.getInteger(MediaFormat.KEY_COLOR_STANDARD, UNSPECIFIED);
        int colorTransfer = fmt.getInteger(MediaFormat.KEY_COLOR_TRANSFER, UNSPECIFIED);
        if (range > UNSPECIFIED) {
            assertEquals("error! color range mismatch \n" + mTestConfig + mTestEnv, range,
                    colorRange);
        }
        if (standard > UNSPECIFIED) {
            assertEquals("error! color standard mismatch \n" + mTestConfig + mTestEnv, standard,
                    colorStandard);
        }
        if (transfer > UNSPECIFIED) {
            assertEquals("error! color transfer mismatch \n" + mTestConfig + mTestEnv, transfer,
                    colorTransfer);
        }
    }

    protected void validateHDRInfo(MediaFormat fmt, String hdrInfoKey, ByteBuffer hdrInfoRef) {
        ByteBuffer hdrInfo = fmt.getByteBuffer(hdrInfoKey, null);
        assertNotNull("error! no " + hdrInfoKey + " present in format : " + fmt + "\n "
                + mTestConfig + mTestEnv, hdrInfo);
        if (!hdrInfoRef.equals(hdrInfo)) {
            StringBuilder msg = new StringBuilder(
                    "###################       Error Details         #####################\n");
            byte[] ref = new byte[hdrInfoRef.capacity()];
            hdrInfoRef.get(ref);
            hdrInfoRef.rewind();
            byte[] test = new byte[hdrInfo.capacity()];
            hdrInfo.get(test);
            hdrInfo.rewind();
            msg.append("ref info :- \n");
            for (byte b : ref) {
                msg.append(String.format("%2x ", b));
            }
            msg.append("\ntest info :- \n");
            for (byte b : test) {
                msg.append(String.format("%2x ", b));
            }
            fail("error! mismatch seen between ref and test info of " + hdrInfoKey + "\n"
                    + mTestConfig + mTestEnv + msg);
        }
    }

    protected void setUpSurface(CodecTestActivity activity) throws InterruptedException {
        activity.waitTillSurfaceIsCreated();
        mSurface = activity.getSurface();
        assertNotNull("Surface created is null \n" + mTestConfig + mTestEnv, mSurface);
        assertTrue("Surface created is invalid \n" + mTestConfig + mTestEnv, mSurface.isValid());
    }
}
