/*
 * 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.cts;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaMuxer;
import android.util.Log;

import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

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

/**
 * MuxerTestHelper breaks a media file to elements that a muxer can use to rebuild its clone.
 * While testing muxer, if the test doesn't use MediaCodecs class to generate elementary
 * stream, but uses MediaExtractor, this class will be handy
 */
class MuxerTestHelper {
    private static final String LOG_TAG = MuxerTestHelper.class.getSimpleName();
    private static final boolean ENABLE_LOGS = false;
    // Stts values within 0.1ms(100us) difference are fudged to save too
    // many stts entries in MPEG4Writer.
    static final int STTS_TOLERANCE_US = 100;
    private String mSrcPath;
    private String mMime;
    private int mTrackCount;
    private ArrayList<MediaFormat> mFormat = new ArrayList<>();
    private ByteBuffer mBuff;
    private ArrayList<ArrayList<MediaCodec.BufferInfo>> mBufferInfo;
    private HashMap<Integer, Integer> mInpIndexMap = new HashMap<>();
    private ArrayList<Integer> mTrackIdxOrder = new ArrayList<>();
    private int mFrameLimit;
    // combineMedias() uses local version of this variable
    private HashMap<Integer, Integer> mOutIndexMap = new HashMap<>();
    private boolean mRemoveCSD;

    private void splitMediaToMuxerParameters() throws IOException {
        // Set up MediaExtractor to read from the source.
        MediaExtractor extractor = new MediaExtractor();
        extractor.setDataSource(mSrcPath);

        // Set up MediaFormat
        int index = 0;
        for (int trackID = 0; trackID < extractor.getTrackCount(); trackID++) {
            extractor.selectTrack(trackID);
            MediaFormat format = extractor.getTrackFormat(trackID);
            if (mRemoveCSD) {
                for (int i = 0; ; ++i) {
                    String csdKey = "csd-" + i;
                    if (format.containsKey(csdKey)) {
                        format.removeKey(csdKey);
                    } else {
                        break;
                    }
                }
            }
            if (mMime == null) {
                mTrackCount++;
                mFormat.add(format);
                mInpIndexMap.put(trackID, index++);
            } else {
                String mime = format.getString(MediaFormat.KEY_MIME);
                if (mime != null && mime.equals(mMime)) {
                    mTrackCount++;
                    mFormat.add(format);
                    mInpIndexMap.put(trackID, index);
                    break;
                } else {
                    extractor.unselectTrack(trackID);
                }
            }
        }

        if (0 == mTrackCount) {
            extractor.release();
            throw new IllegalArgumentException("could not find usable track in file " + mSrcPath);
        }

        // Set up location for elementary stream
        File file = new File(mSrcPath);
        int bufferSize = (int) file.length();
        bufferSize = ((bufferSize + 127) >> 7) << 7;
        // Ideally, Sum of return values of extractor.readSampleData(...) should not exceed
        // source file size. But in case of Vorbis, aosp extractor appends an additional 4 bytes to
        // the data at every readSampleData() call. bufferSize <<= 1 empirically large enough to
        // hold the excess 4 bytes per read call
        bufferSize <<= 1;
        mBuff = ByteBuffer.allocate(bufferSize);

        // Set up space for bufferInfo of all samples of all tracks
        mBufferInfo = new ArrayList<>(mTrackCount);
        for (index = 0; index < mTrackCount; index++) {
            mBufferInfo.add(new ArrayList<MediaCodec.BufferInfo>());
        }

        // Let MediaExtractor do its thing
        boolean sawEOS = false;
        int frameCount = 0;
        int offset = 0;
        while (!sawEOS && frameCount < mFrameLimit) {
            int trackID;
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            bufferInfo.offset = offset;
            bufferInfo.size = extractor.readSampleData(mBuff, offset);

            if (bufferInfo.size < 0) {
                sawEOS = true;
            } else {
                bufferInfo.presentationTimeUs = extractor.getSampleTime();
                bufferInfo.flags = extractor.getSampleFlags();
                trackID = extractor.getSampleTrackIndex();
                mTrackIdxOrder.add(trackID);
                mBufferInfo.get(mInpIndexMap.get(trackID)).add(bufferInfo);
                extractor.advance();
                frameCount++;
            }
            offset += bufferInfo.size;
        }
        extractor.release();
    }

    void registerTrack(MediaMuxer muxer) {
        for (int trackID = 0; trackID < mTrackCount; trackID++) {
            int dstIndex = muxer.addTrack(mFormat.get(trackID));
            mOutIndexMap.put(trackID, dstIndex);
        }
    }

    void insertSampleData(MediaMuxer muxer) {
        // write all registered tracks in interleaved order
        int[] frameCount = new int[mTrackCount];
        for (int i = 0; i < mTrackIdxOrder.size(); i++) {
            int trackID = mTrackIdxOrder.get(i);
            int index = mInpIndexMap.get(trackID);
            MediaCodec.BufferInfo bufferInfo = mBufferInfo.get(index).get(frameCount[index]);
            muxer.writeSampleData(mOutIndexMap.get(index), mBuff, bufferInfo);
            frameCount[index]++;
            if (ENABLE_LOGS) {
                Log.v(LOG_TAG, "Track: " + index + " Timestamp: " + bufferInfo.presentationTimeUs);
            }
        }
        if (ENABLE_LOGS) {
            Log.v(LOG_TAG, "Total samples: " + mTrackIdxOrder.size());
        }
    }

    void muxMedia(MediaMuxer muxer) {
        registerTrack(muxer);
        muxer.start();
        insertSampleData(muxer);
        muxer.stop();
    }

    void combineMedias(MediaMuxer muxer, Object o, int[] repeater) {
        if (o == null || getClass() != o.getClass())
            throw new IllegalArgumentException("Invalid Object handle");
        if (null == repeater || repeater.length < 2)
            throw new IllegalArgumentException("Invalid Parameter, repeater");
        MuxerTestHelper that = (MuxerTestHelper) o;

        // add tracks
        int totalTracksToAdd = repeater[0] * this.mTrackCount + repeater[1] * that.mTrackCount;
        int[] outIndexMap = new int[totalTracksToAdd];
        MuxerTestHelper[] group = {this, that};
        for (int k = 0, idx = 0; k < group.length; k++) {
            for (int j = 0; j < repeater[k]; j++) {
                for (MediaFormat format : group[k].mFormat) {
                    outIndexMap[idx++] = muxer.addTrack(format);
                }
            }
        }

        // mux samples
        // write all registered tracks in planar order viz all samples of a track A then all
        // samples of track B, ...
        muxer.start();
        for (int k = 0, idx = 0; k < group.length; k++) {
            for (int j = 0; j < repeater[k]; j++) {
                for (int i = 0; i < group[k].mTrackCount; i++) {
                    ArrayList<MediaCodec.BufferInfo> bufInfos = group[k].mBufferInfo.get(i);
                    for (int p = 0; p < bufInfos.size(); p++) {
                        MediaCodec.BufferInfo bufInfo = bufInfos.get(p);
                        muxer.writeSampleData(outIndexMap[idx], group[k].mBuff, bufInfo);
                        if (ENABLE_LOGS) {
                            Log.v(LOG_TAG, "Track: " + outIndexMap[idx] + " Timestamp: " +
                                    bufInfo.presentationTimeUs);
                        }
                    }
                    idx++;
                }
            }
        }
        muxer.stop();
    }

    MuxerTestHelper(String srcPath, String mime, int frameLimit, boolean aRemoveCSD) throws IOException {
        mSrcPath = srcPath;
        mMime = mime;
        if (frameLimit < 0) frameLimit = Integer.MAX_VALUE;
        mFrameLimit = frameLimit;
        mRemoveCSD = aRemoveCSD;
        splitMediaToMuxerParameters();
    }

    MuxerTestHelper(String srcPath, String mime) throws IOException {
        this(srcPath, mime, -1, false);
    }

    MuxerTestHelper(String srcPath, int frameLimit) throws IOException {
        this(srcPath, null, frameLimit, false);
    }

    MuxerTestHelper(String srcPath, boolean aRemoveCSD) throws IOException {
        this(srcPath, null, -1, aRemoveCSD);
    }

    MuxerTestHelper(String srcPath) throws IOException {
        this(srcPath, null, -1, false);
    }

    int getTrackCount() {
        return mTrackCount;
    }

    // offset pts of samples from index sampleOffset till the end by tsOffset
    void offsetTimeStamp(int trackID, long tsOffset, int sampleOffset) {
        if (trackID < mTrackCount) {
            for (int i = sampleOffset; i < mBufferInfo.get(trackID).size(); i++) {
                MediaCodec.BufferInfo bufferInfo = mBufferInfo.get(trackID).get(i);
                bufferInfo.presentationTimeUs += tsOffset;
            }
        }
    }

    // returns true if 'this' stream is a subset of 'o'. That is all tracks in current media
    // stream are present in ref media stream
    boolean isSubsetOf(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MuxerTestHelper that = (MuxerTestHelper) o;
        int MAX_SAMPLE_SIZE = 4 * 1024 * 1024;
        byte[] refBuffer = new byte[MAX_SAMPLE_SIZE];
        byte[] testBuffer = new byte[MAX_SAMPLE_SIZE];
        for (int i = 0; i < mTrackCount; i++) {
            MediaFormat thisFormat = mFormat.get(i);
            String thisMime = thisFormat.getString(MediaFormat.KEY_MIME);
            int j = 0;
            for (; j < that.mTrackCount; j++) {
                MediaFormat thatFormat = that.mFormat.get(j);
                String thatMime = thatFormat.getString(MediaFormat.KEY_MIME);
                if (thisMime != null && thisMime.equals(thatMime)) {
                    if (!ExtractorTest.isCSDIdentical(thisFormat, thatFormat)) continue;
                    if (mBufferInfo.get(i).size() == that.mBufferInfo.get(j).size()) {
                        long tolerance = thisMime.startsWith("video/") ? STTS_TOLERANCE_US : 0;
                        // TODO(b/157008437) - muxed file pts is +1us of target pts
                        tolerance += 1; // rounding error
                        int k = 0;
                        for (; k < mBufferInfo.get(i).size(); k++) {
                            MediaCodec.BufferInfo thisInfo = mBufferInfo.get(i).get(k);
                            MediaCodec.BufferInfo thatInfo = that.mBufferInfo.get(j).get(k);
                            if (thisInfo.flags != thatInfo.flags) {
                                break;
                            }
                            if (thisInfo.size != thatInfo.size) {
                                break;
                            } else {
                                mBuff.position(thisInfo.offset);
                                mBuff.get(refBuffer, 0, thisInfo.size);
                                that.mBuff.position(thatInfo.offset);
                                that.mBuff.get(testBuffer, 0, thatInfo.size);
                                int count = 0;
                                for (; count < thisInfo.size; count++) {
                                    if (refBuffer[count] != testBuffer[count]) {
                                        break;
                                    }
                                }
                                if (count != thisInfo.size) break;
                            }
                            if (Math.abs(
                                    thisInfo.presentationTimeUs - thatInfo.presentationTimeUs) >
                                    tolerance) {
                                break;
                            }
                        }
                        // all samples are identical. successful match found. move to next track
                        if (k == mBufferInfo.get(i).size()) break;
                    } else {
                        if (ENABLE_LOGS) {
                            Log.d(LOG_TAG, "Mime matched but sample count different." +
                                    " Total Samples ref/test: " + mBufferInfo.get(i).size() + '/' +
                                    that.mBufferInfo.get(j).size());
                        }
                    }
                }
            }
            mBuff.position(0);
            that.mBuff.position(0);
            if (j == that.mTrackCount) {
                if (ENABLE_LOGS) {
                    Log.d(LOG_TAG, "For track: " + thisMime + " Couldn't find a match ");
                }
                return false;
            }
        }
        return true;
    }
}

@RunWith(Enclosed.class)
public class MuxerTest {
    // duplicate definitions of hide fields of MediaMuxer.OutputFormat.
    private static final int MUXER_OUTPUT_FIRST = 0;
    private static final int MUXER_OUTPUT_LAST = MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG;

    private static final String MUX_SEL_KEY = "mux-sel";
    private static String selector;
    private static boolean[] muxSelector = new boolean[MUXER_OUTPUT_LAST + 1];
    private static HashMap<Integer, String> formatStringPair = new HashMap<>();

    static {
        android.os.Bundle args = InstrumentationRegistry.getArguments();
        final String defSel = "mp4;webm;3gp;ogg";
        selector = (null == args.getString(MUX_SEL_KEY)) ? defSel : args.getString(MUX_SEL_KEY);

        createFormatStringPair();
        for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; format++) {
            muxSelector[format] = selector.contains(formatStringPair.get(format));
        }
    }

    static private void createFormatStringPair() {
        formatStringPair.put(MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "mp4");
        formatStringPair.put(MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM, "webm");
        formatStringPair.put(MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP, "3gp");
        formatStringPair.put(MediaMuxer.OutputFormat.MUXER_OUTPUT_HEIF, "heif");
        formatStringPair.put(MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG, "ogg");
    }

    static private boolean shouldRunTest(int format) {
        return muxSelector[format];
    }

    /**
     * Tests MediaMuxer API that are dependent on MediaMuxer.OutputFormat. setLocation,
     * setOrientationHint are dependent on the mime type and OutputFormat. Legality of these APIs
     * are tested in this class.
     */
    @SmallTest
    @RunWith(Parameterized.class)
    public static class TestApi {
        private int mOutFormat;
        private String mSrcFile;
        private String mInpPath;
        private String mOutPath;
        private static final float annapurnaLat = 28.59f;
        private static final float annapurnaLong = 83.82f;
        private static final float TOLERANCE = 0.0002f;
        private static final int currRotation = 180;

        static {
            System.loadLibrary("ctsmediav2muxer_jni");
        }

        @Before
        public void prologue() throws IOException {
            mInpPath = WorkDir.getMediaDirString() + mSrcFile;
            mOutPath = File.createTempFile("tmp", ".out").getAbsolutePath();
        }

        @After
        public void epilogue() {
            new File(mOutPath).delete();
        }

        @Parameterized.Parameters(name = "{index}({2})")
        public static Collection<Object[]> input() {
            return Arrays.asList(new Object[][]{
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "bbb_cif_768kbps_30fps_avc.mp4",
                            "mp4"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM, "bbb_cif_768kbps_30fps_vp9.mkv",
                            "webm"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP, "bbb_cif_768kbps_30fps_h263.mp4",
                            "3gpp"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG, "bbb_stereo_48kHz_192kbps_opus.ogg",
                            "ogg"},
            });
        }

        public TestApi(int outFormat, String srcFile, String testName) {
            mOutFormat = outFormat;
            mSrcFile = srcFile;
        }

        private native boolean nativeTestSetLocation(int format, String srcPath, String outPath);

        private native boolean nativeTestSetOrientationHint(int format, String srcPath,
                String outPath);

        private void verifyLocationInFile(String fileName) {
            if (mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 &&
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) return;
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            retriever.setDataSource(fileName);

            // parsing String location and recover the location information in floats
            // Make sure the tolerance is very small - due to rounding errors.

            // Get the position of the -/+ sign in location String, which indicates
            // the beginning of the longitude.
            String loc = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
            assertTrue(loc != null);
            int minusIndex = loc.lastIndexOf('-');
            int plusIndex = loc.lastIndexOf('+');

            assertTrue("+ or - is not found or found only at the beginning [" + loc + "]",
                    (minusIndex > 0 || plusIndex > 0));
            int index = Math.max(minusIndex, plusIndex);

            float latitude = Float.parseFloat(loc.substring(0, index - 1));
            int lastIndex = loc.lastIndexOf('/', index);
            if (lastIndex == -1) {
                lastIndex = loc.length();
            }
            float longitude = Float.parseFloat(loc.substring(index, lastIndex - 1));
            assertTrue("Incorrect latitude: " + latitude + " [" + loc + "]",
                    Math.abs(latitude - annapurnaLat) <= TOLERANCE);
            assertTrue("Incorrect longitude: " + longitude + " [" + loc + "]",
                    Math.abs(longitude - annapurnaLong) <= TOLERANCE);
            retriever.release();
        }

        private void verifyOrientation(String fileName) {
            if (mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 &&
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) return;
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            retriever.setDataSource(fileName);

            String testDegrees = retriever.extractMetadata(
                    MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
            assertTrue(testDegrees != null);
            assertEquals("Different degrees " + currRotation + " and " + testDegrees,
                    currRotation, Integer.parseInt(testDegrees));
            retriever.release();
        }

        @Test
        public void testSetLocation() throws IOException {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            MediaMuxer muxer = new MediaMuxer(mOutPath, mOutFormat);
            try {
                boolean isGeoDataSupported = false;
                final float tooFarNorth = 90.5f;
                final float tooFarWest = -180.5f;
                final float tooFarSouth = -90.5f;
                final float tooFarEast = 180.5f;
                final float atlanticLat = 14.59f;
                final float atlanticLong = 28.67f;

                try {
                    muxer.setLocation(tooFarNorth, atlanticLong);
                    fail("setLocation succeeded with bad argument: [" + tooFarNorth + "," +
                            atlanticLong + "]");
                } catch (Exception e) {
                    // expected
                }
                try {
                    muxer.setLocation(tooFarSouth, atlanticLong);
                    fail("setLocation succeeded with bad argument: [" + tooFarSouth + "," +
                            atlanticLong + "]");
                } catch (Exception e) {
                    // expected
                }
                try {
                    muxer.setLocation(atlanticLat, tooFarWest);
                    fail("setLocation succeeded with bad argument: [" + atlanticLat + "," +
                            tooFarWest + "]");
                } catch (Exception e) {
                    // expected
                }
                try {
                    muxer.setLocation(atlanticLat, tooFarEast);
                    fail("setLocation succeeded with bad argument: [" + atlanticLat + "," +
                            tooFarEast + "]");
                } catch (Exception e) {
                    // expected
                }
                try {
                    muxer.setLocation(tooFarNorth, tooFarWest);
                    fail("setLocation succeeded with bad argument: [" + tooFarNorth + "," +
                            tooFarWest + "]");
                } catch (Exception e) {
                    // expected
                }
                try {
                    muxer.setLocation(atlanticLat, atlanticLong);
                    isGeoDataSupported = true;
                } catch (Exception e) {
                    // can happen
                }

                if (isGeoDataSupported) {
                    try {
                        muxer.setLocation(annapurnaLat, annapurnaLong);
                    } catch (IllegalArgumentException e) {
                        fail(e.getMessage());
                    }
                } else {
                    assertTrue(mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 &&
                            mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
                }

                MuxerTestHelper mediaInfo = new MuxerTestHelper(mInpPath, 60);
                mediaInfo.registerTrack(muxer);
                muxer.start();
                // after start
                try {
                    muxer.setLocation(0.0f, 0.0f);
                    fail("SetLocation succeeded after muxer.start()");
                } catch (IllegalStateException e) {
                    // Exception
                }
                mediaInfo.insertSampleData(muxer);
                muxer.stop();
                // after stop
                try {
                    muxer.setLocation(annapurnaLat, annapurnaLong);
                    fail("setLocation() succeeded after muxer.stop()");
                } catch (IllegalStateException e) {
                    // expected
                }
                muxer.release();
                // after release
                try {
                    muxer.setLocation(annapurnaLat, annapurnaLong);
                    fail("setLocation() succeeded after muxer.release()");
                } catch (IllegalStateException e) {
                    // expected
                }
                verifyLocationInFile(mOutPath);
            } finally {
                muxer.release();
            }
        }

        @Test
        public void testSetOrientationHint() throws IOException {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            MediaMuxer muxer = new MediaMuxer(mOutPath, mOutFormat);
            try {
                boolean isOrientationSupported = false;
                final int[] badRotation = {360, 45, -90};
                final int oldRotation = 90;

                for (int degree : badRotation) {
                    try {
                        muxer.setOrientationHint(degree);
                        fail("setOrientationHint() succeeded with bad argument :" + degree);
                    } catch (Exception e) {
                        // expected
                    }
                }
                try {
                    muxer.setOrientationHint(oldRotation);
                    isOrientationSupported = true;
                } catch (Exception e) {
                    // can happen
                }
                if (isOrientationSupported) {
                    try {
                        muxer.setOrientationHint(currRotation);
                    } catch (IllegalArgumentException e) {
                        fail(e.getMessage());
                    }
                } else {
                    assertTrue(mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 &&
                            mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
                }

                MuxerTestHelper mediaInfo = new MuxerTestHelper(mInpPath, 60);
                mediaInfo.registerTrack(muxer);
                muxer.start();
                // after start
                try {
                    muxer.setOrientationHint(0);
                    fail("setOrientationHint succeeded after muxer.start()");
                } catch (IllegalStateException e) {
                    // Exception
                }
                mediaInfo.insertSampleData(muxer);
                muxer.stop();
                // after stop
                try {
                    muxer.setOrientationHint(currRotation);
                    fail("setOrientationHint() succeeded after muxer.stop()");
                } catch (IllegalStateException e) {
                    // expected
                }
                muxer.release();
                // after release
                try {
                    muxer.setOrientationHint(currRotation);
                    fail("setOrientationHint() succeeded after muxer.release()");
                } catch (IllegalStateException e) {
                    // expected
                }
                verifyOrientation(mOutPath);
            } finally {
                muxer.release();
            }
        }

        @Test
        public void testSetLocationNative() {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            assertTrue(nativeTestSetLocation(mOutFormat, mInpPath, mOutPath));
            verifyLocationInFile(mOutPath);
        }

        @Test
        public void testSetOrientationHintNative() {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            assertTrue(nativeTestSetOrientationHint(mOutFormat, mInpPath, mOutPath));
            verifyOrientation(mOutPath);
        }
    }

    /**
     * Tests muxing multiple Video/Audio Tracks
     */
    @LargeTest
    @RunWith(Parameterized.class)
    public static class TestMultiTrack {
        private int mOutFormat;
        private String mSrcFileA;
        private String mSrcFileB;
        private String mInpPathA;
        private String mInpPathB;
        private String mRefPath;
        private String mOutPath;

        static {
            System.loadLibrary("ctsmediav2muxer_jni");
        }

        @Before
        public void prologue() throws IOException {
            mInpPathA = WorkDir.getMediaDirString() + mSrcFileA;
            mInpPathB = WorkDir.getMediaDirString() + mSrcFileB;
            mRefPath = File.createTempFile("ref", ".out").getAbsolutePath();
            mOutPath = File.createTempFile("tmp", ".out").getAbsolutePath();
        }

        @After
        public void epilogue() {
            new File(mRefPath).delete();
            new File(mOutPath).delete();
        }

        @Parameterized.Parameters(name = "{index}({3})")
        public static Collection<Object[]> input() {
            return Arrays.asList(new Object[][]{
                    // audio, video are 3 sec
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "bbb_cif_768kbps_30fps_mpeg4" +
                            ".mkv", "bbb_stereo_48kHz_192kbps_aac.mp4", "mp4"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM, "bbb_cif_768kbps_30fps_vp9.mkv"
                            , "bbb_stereo_48kHz_192kbps_vorbis.ogg", "webm"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP, "bbb_cif_768kbps_30fps_h263.mp4"
                            , "bbb_mono_16kHz_20kbps_amrwb.amr", "3gpp"},

                    // audio 3 sec, video 10 sec
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "bbb_qcif_512kbps_30fps_avc" +
                            ".mp4", "bbb_stereo_48kHz_192kbps_aac.mp4", "mp4"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM, "bbb_qcif_512kbps_30fps_vp9.webm"
                            , "bbb_stereo_48kHz_192kbps_vorbis.ogg", "webm"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP, "bbb_qcif_512kbps_30fps_h263.3gp"
                            , "bbb_mono_16kHz_20kbps_amrwb.amr", "3gpp"},

                    // audio 10 sec, video 3 sec
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "bbb_cif_768kbps_30fps_mpeg4" +
                            ".mkv", "bbb_stereo_48kHz_128kbps_aac.mp4", "mp4"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM, "bbb_cif_768kbps_30fps_vp9.mkv"
                            , "bbb_stereo_48kHz_128kbps_vorbis.ogg", "webm"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP, "bbb_cif_768kbps_30fps_h263.mp4"
                            , "bbb_mono_8kHz_8kbps_amrnb.3gp", "3gpp"},
            });
        }

        public TestMultiTrack(int outFormat, String srcFileA, String srcFileB, String testName) {
            mOutFormat = outFormat;
            mSrcFileA = srcFileA;
            mSrcFileB = srcFileB;
        }

        private native boolean nativeTestMultiTrack(int format, String fileA, String fileB,
                String fileR, String fileO);

        @Test
        public void testMultiTrack() throws IOException {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            Assume.assumeTrue("TODO(b/146423022)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
            // number of times to repeat {mSrcFileA, mSrcFileB} in Output
            final int[][] numTracks = {{2, 0}, {0, 2}, {1, 2}, {2, 1}};

            MuxerTestHelper mediaInfoA = new MuxerTestHelper(mInpPathA);
            MuxerTestHelper mediaInfoB = new MuxerTestHelper(mInpPathB);
            assertEquals("error! unexpected track count", 1, mediaInfoA.getTrackCount());
            assertEquals("error! unexpected track count", 1, mediaInfoB.getTrackCount());

            // prepare reference
            RandomAccessFile refFile = new RandomAccessFile(mRefPath, "rws");
            MediaMuxer muxer = new MediaMuxer(refFile.getFD(), mOutFormat);
            MuxerTestHelper refInfo = null;
            String msg = String.format("testMultiTrack: inputs: %s %s, fmt: %d ", mSrcFileA,
                    mSrcFileB, mOutFormat);
            try {
                mediaInfoA.combineMedias(muxer, mediaInfoB, new int[]{1, 1});
                refInfo = new MuxerTestHelper(mRefPath);
                if (!mediaInfoA.isSubsetOf(refInfo) || !mediaInfoB.isSubsetOf(refInfo)) {
                    fail(msg + "error ! muxing src A and src B failed");
                }
            } catch (Exception e) {
                if (mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
                    fail(msg + "error ! muxing src A and src B failed");
                }
            } finally {
                muxer.release();
                refFile.close();
            }

            // test multi-track
            for (int[] numTrack : numTracks) {
                RandomAccessFile outFile = new RandomAccessFile(mOutPath, "rws");
                muxer = new MediaMuxer(outFile.getFD(), mOutFormat);
                try {
                    mediaInfoA.combineMedias(muxer, mediaInfoB, numTrack);
                    MuxerTestHelper outInfo = new MuxerTestHelper(mOutPath);
                    if (!outInfo.isSubsetOf(refInfo)) {
                        fail(msg + " error ! muxing src A: " + numTrack[0] + " src B: " +
                                numTrack[1] + "failed");
                    }
                } catch (Exception e) {
                    if (mOutFormat == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) {
                        fail(msg + " error ! muxing src A: " + numTrack[0] + " src B: " +
                                numTrack[1] + "failed");
                    }
                } finally {
                    muxer.release();
                    outFile.close();
                }
            }
        }

        @Test
        public void testMultiTrackNative() {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            Assume.assumeTrue("TODO(b/146423022)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
            assertTrue(nativeTestMultiTrack(mOutFormat, mInpPathA, mInpPathB, mRefPath, mOutPath));
        }
    }

    /**
     * Add an offset to the presentation time of samples of a track. Mux with the added offset,
     * validate by re-extracting the muxer output file and compare with original.
     */
    @LargeTest
    @RunWith(Parameterized.class)
    public static class TestOffsetPts {
        private String mSrcFile;
        private int mOutFormat;
        private int[] mOffsetIndices;
        private String mInpPath;
        private String mOutPath;

        static {
            System.loadLibrary("ctsmediav2muxer_jni");
        }

        @Before
        public void prologue() throws IOException {
            mInpPath = WorkDir.getMediaDirString() + mSrcFile;
            mOutPath = File.createTempFile("tmp", ".out").getAbsolutePath();
        }

        @After
        public void epilogue() {
            new File(mOutPath).delete();
        }

        @Parameterized.Parameters(name = "{index}({3})")
        public static Collection<Object[]> input() {
            return Arrays.asList(new Object[][]{
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
                            "bbb_cif_768kbps_30fps_hevc_stereo_48kHz_192kbps_aac.mp4",
                            new int[]{0}, "mp4"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM,
                            "bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.webm",
                            new int[]{0}, "webm"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP,
                            "bbb_cif_768kbps_30fps_mpeg4_mono_16kHz_20kbps_amrwb.3gp",
                            new int[]{0}, "3gpp"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG, "bbb_stereo_48kHz_192kbps_opus.ogg",
                            new int[]{10}, "ogg"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4, "bbb_cif_768kbps_30fps_avc.mp4",
                            new int[]{6, 50, 77}, "mp4"},
                    {MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM, "bbb_cif_768kbps_30fps_vp9.mkv",
                            new int[]{8, 44}, "webm"},
            });
        }

        public TestOffsetPts(int outFormat, String file, int[] offsetIndices, String testName) {
            mOutFormat = outFormat;
            mSrcFile = file;
            mOffsetIndices = offsetIndices;
        }

        private native boolean nativeTestOffsetPts(int format, String srcFile, String dstFile,
                int[] offsetIndices);

        @Test
        public void testOffsetPresentationTime() throws IOException {
            final int OFFSET_TS = 111000;
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            Assume.assumeTrue("TODO(b/148978457)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            Assume.assumeTrue("TODO(b/148978457)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
            Assume.assumeTrue("TODO(b/146423022)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
            Assume.assumeTrue("TODO(b/146421018)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
            assertTrue(OFFSET_TS > MuxerTestHelper.STTS_TOLERANCE_US);
            MuxerTestHelper mediaInfo = new MuxerTestHelper(mInpPath);
            for (int trackID = 0; trackID < mediaInfo.getTrackCount(); trackID++) {
                for (int i = 0; i < mOffsetIndices.length; i++) {
                    mediaInfo.offsetTimeStamp(trackID, OFFSET_TS, mOffsetIndices[i]);
                }
                MediaMuxer muxer = new MediaMuxer(mOutPath, mOutFormat);
                mediaInfo.muxMedia(muxer);
                muxer.release();
                MuxerTestHelper outInfo = new MuxerTestHelper(mOutPath);
                if (!outInfo.isSubsetOf(mediaInfo)) {
                    String msg = String.format(
                            "testOffsetPresentationTime: inp: %s, fmt: %d, trackID %d", mSrcFile,
                            mOutFormat, trackID);
                    fail(msg + "error! output != input");
                }
                for (int i = mOffsetIndices.length - 1; i >= 0; i--) {
                    mediaInfo.offsetTimeStamp(trackID, -OFFSET_TS, mOffsetIndices[i]);
                }
            }
        }

        @Test
        public void testOffsetPresentationTimeNative() {
            Assume.assumeTrue(shouldRunTest(mOutFormat));
            Assume.assumeTrue("TODO(b/148978457)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            Assume.assumeTrue("TODO(b/148978457)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
            Assume.assumeTrue("TODO(b/146423022)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
            Assume.assumeTrue("TODO(b/146421018)",
                    mOutFormat != MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
            assertTrue(nativeTestOffsetPts(mOutFormat, mInpPath, mOutPath, mOffsetIndices));
        }
    }

    /**
     * Audio, Video Codecs support a variety of file-types/container formats. For example,
     * AAC-LC supports MPEG4, 3GPP. Vorbis supports OGG and WEBM. H.263 supports 3GPP and WEBM.
     * This test takes the output of a codec and muxes it in to all possible container formats.
     * The results are checked for inconsistencies with the requirements of CDD.
     */
    @LargeTest
    @RunWith(Parameterized.class)
    public static class TestSimpleMux {
        private final List<String> codecListforTypeMp4 =
                Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
                        MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
                        MediaFormat.MIMETYPE_AUDIO_AAC);
        private final List<String> codecListforTypeWebm =
                Arrays.asList(MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
                        MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
        private final List<String> codecListforType3gp =
                Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
                        MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_AUDIO_AAC,
                        MediaFormat.MIMETYPE_AUDIO_AMR_NB, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
        private final List<String> codecListforTypeOgg =
                Arrays.asList(MediaFormat.MIMETYPE_AUDIO_OPUS);
        private String mMime;
        private String mSrcFile;
        private String mInpPath;
        private String mOutPath;

        static {
            System.loadLibrary("ctsmediav2muxer_jni");
        }

        public TestSimpleMux(String mime, String srcFile) {
            mMime = mime;
            mSrcFile = srcFile;
        }

        @Before
        public void prologue() throws IOException {
            mInpPath = WorkDir.getMediaDirString() + mSrcFile;
            mOutPath = File.createTempFile("tmp", ".out").getAbsolutePath();
        }

        @After
        public void epilogue() {
            new File(mOutPath).delete();
        }

        private boolean isCodecContainerPairValid(int format) {
            boolean result = false;
            if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
                result = codecListforTypeMp4.contains(mMime) || mMime.startsWith("application/");
            else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) {
                return codecListforTypeWebm.contains(mMime);
            } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
                result = codecListforType3gp.contains(mMime);
            } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
                result = codecListforTypeOgg.contains(mMime);
            }
            return result;
        }

        private boolean doesCodecRequireCSD(String aMime) {
            return (aMime == MediaFormat.MIMETYPE_VIDEO_AVC ||
                    aMime == MediaFormat.MIMETYPE_VIDEO_HEVC ||
                    aMime == MediaFormat.MIMETYPE_VIDEO_MPEG4 ||
                    aMime == MediaFormat.MIMETYPE_AUDIO_AAC);

        }

        private native boolean nativeTestSimpleMux(String srcPath, String outPath, String mime,
                String selector);

        @Parameterized.Parameters(name = "{index}({0})")
        public static Collection<Object[]> input() {
            return Arrays.asList(new Object[][]{
                    // Video Codecs
                    {MediaFormat.MIMETYPE_VIDEO_H263,
                            "bbb_cif_768kbps_30fps_h263_mono_8kHz_12kbps_amrnb.3gp"},
                    {MediaFormat.MIMETYPE_VIDEO_AVC,
                            "bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_vorbis.mp4"},
                    {MediaFormat.MIMETYPE_VIDEO_HEVC,
                            "bbb_cif_768kbps_30fps_hevc_stereo_48kHz_192kbps_opus.mp4"},
                    {MediaFormat.MIMETYPE_VIDEO_MPEG4,
                            "bbb_cif_768kbps_30fps_mpeg4_mono_16kHz_20kbps_amrwb.3gp"},
                    {MediaFormat.MIMETYPE_VIDEO_VP8,
                            "bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.webm"},
                    {MediaFormat.MIMETYPE_VIDEO_VP9,
                            "bbb_cif_768kbps_30fps_vp9_stereo_48kHz_192kbps_opus.webm"},
                    // Audio Codecs
                    {MediaFormat.MIMETYPE_AUDIO_AAC,
                            "bbb_stereo_48kHz_128kbps_aac.mp4"},
                    {MediaFormat.MIMETYPE_AUDIO_AMR_NB,
                            "bbb_cif_768kbps_30fps_h263_mono_8kHz_12kbps_amrnb.3gp"},
                    {MediaFormat.MIMETYPE_AUDIO_AMR_WB,
                            "bbb_cif_768kbps_30fps_mpeg4_mono_16kHz_20kbps_amrwb.3gp"},
                    {MediaFormat.MIMETYPE_AUDIO_OPUS,
                            "bbb_cif_768kbps_30fps_vp9_stereo_48kHz_192kbps_opus.webm"},
                    {MediaFormat.MIMETYPE_AUDIO_VORBIS,
                            "bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.webm"},
                    // Metadata
                    {"application/gyro",
                            "video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz_metadata_gyro_non_compliant.3gp"},
                    {"application/gyro",
                            "video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz_metadata_gyro_compliant.3gp"},
            });
        }

        @Test
        public void testSimpleMux() throws IOException {
            Assume.assumeTrue("TODO(b/146421018)",
                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_OPUS));
            Assume.assumeTrue("TODO(b/146923287)",
                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
            MuxerTestHelper mediaInfo = new MuxerTestHelper(mInpPath, mMime);
            assertEquals("error! unexpected track count", 1, mediaInfo.getTrackCount());
            for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; format++) {
                if (!shouldRunTest(format)) continue;
                // TODO(b/146923551)
                if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) continue;
                String msg = String.format("testSimpleMux: inp: %s, mime: %s, fmt: %d ", mSrcFile,
                        mMime, format);
                MediaMuxer muxer = new MediaMuxer(mOutPath, format);
                try {
                    mediaInfo.muxMedia(muxer);
                    MuxerTestHelper outInfo = new MuxerTestHelper(mOutPath);
                    if (!mediaInfo.isSubsetOf(outInfo)) {
                        fail(msg + "error! output != clone(input)");
                    }
                } catch (Exception e) {
                    if (isCodecContainerPairValid(format)) {
                        fail(msg + "error! incompatible mime and output format");
                    }
                } finally {
                    muxer.release();
                }
            }
        }

        /* Does MediaMuxer throw IllegalStateException on missing codec specific data when required.
         * Check if relevant exception is thrown for AAC, AVC, HEVC, and MPEG4
         * codecs that require CSD in MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4.
         * TODO(b/156767190): Need to evaluate what all codecs need CSD and also what all formats
         * can contain these codecs, and add test cases accordingly.
         * TODO(b/156767190): Add similar tests in the native side/NDK as well.
         * TODO(b/156767190): Make a separate class, like TestNoCSDMux, instead of being part of
         * TestSimpleMux?
         */
        @Test
        public void testNoCSDMux() throws IOException {
            Assume.assumeTrue(doesCodecRequireCSD(mMime));
            MuxerTestHelper mediaInfo = new MuxerTestHelper(mInpPath, true);
            for (int format = MUXER_OUTPUT_FIRST; format <= MUXER_OUTPUT_LAST; format++) {
                // TODO(b/156767190)
                if(format != MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) continue;
                MediaMuxer muxer = new MediaMuxer(mOutPath, format);
                Exception expected = null;
                String msg = String.format("testNoCSDMux: inp: %s, mime %s, fmt: %s", mSrcFile,
                                            mMime, formatStringPair.get(format));
                try {
                    mediaInfo.muxMedia(muxer);
                } catch (IllegalStateException e) {
                    expected = e;
                } catch (Exception e) {
                    fail(msg + ", unexpected exception:" + e.getMessage());
                } finally {
                    assertNotNull(msg, expected);
                    muxer.release();
                }
            }
        }

        @Test
        public void testSimpleMuxNative() {
            Assume.assumeTrue("TODO(b/146421018)",
                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_OPUS));
            Assume.assumeTrue("TODO(b/146923287)",
                    !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
            assertTrue(nativeTestSimpleMux(mInpPath, mOutPath, mMime, selector));
        }
    }
}
