/*
 * Copyright (C) 2022 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.videocodec.cts;

import static android.media.MediaFormat.PICTURE_TYPE_I;
import static android.media.MediaFormat.PICTURE_TYPE_UNKNOWN;

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

import android.media.Image;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.mediav2.common.cts.BitStreamUtils;
import android.mediav2.common.cts.DecodeStreamToYuv;
import android.mediav2.common.cts.EncoderConfigParams;
import android.mediav2.common.cts.EncoderTestBase;
import android.mediav2.common.cts.RawResource;
import android.util.Log;

import androidx.annotation.NonNull;

import com.android.compatibility.common.util.Preconditions;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;

/**
 * Wrapper class for handling and testing video encoder components.
 */
public class VideoEncoderValidationTestBase extends EncoderTestBase {
    private static final String LOG_TAG = VideoEncoderValidationTestBase.class.getSimpleName();
    private static final String MEDIA_DIR = WorkDir.getMediaDirString();

    static final boolean ENABLE_LOGS = false;

    protected final CompressedResource mCRes;

    final TreeMap<Long, Integer> mPtsPicTypeMap = new TreeMap<>();

    RandomAccessFile mFileInp;
    long mFileReadOffset;
    long mFileLength;

    public static class CompressedResource {
        final String mMediaType;
        final String mResFile;

        CompressedResource(String mediaType, String resFile) {
            mMediaType = mediaType;
            mResFile = resFile;
        }

        @NonNull
        @Override
        public String toString() {
            return "CompressedResource{" + "res file ='" + mResFile + '\'' + '}';
        }

        public String uniqueLabel() {
            return mMediaType + mResFile;
        }
    }

    protected static final CompressedResource BIRTHDAY_FULLHD_LANDSCAPE =
            new CompressedResource(MediaFormat.MIMETYPE_VIDEO_AVC, MEDIA_DIR
                    + "AVICON-MOBILE-BirthdayHalfway-SI17-CRUW03-L-420-8bit-SDR-1080p-30fps.mp4");
    protected static final CompressedResource SELFIEGROUP_FULLHD_PORTRAIT =
            new CompressedResource(MediaFormat.MIMETYPE_VIDEO_AVC, MEDIA_DIR
                    + "AVICON-MOBILE-SelfieGroupGarden-SF15-CF01-P-420-8bit-SDR-1080p-30fps.mp4");

    static void decodeStreamsToYuv(ArrayList<CompressedResource> resources,
            HashMap<String, RawResource> streamYuvMap) {
        decodeStreamsToYuv(resources, streamYuvMap, Integer.MAX_VALUE);
    }

    static void decodeStreamsToYuv(ArrayList<CompressedResource> resources,
            HashMap<String, RawResource> streamYuvMap, int frameLimit) {
        for (CompressedResource res : resources) {
            if (!(streamYuvMap.containsKey(res.uniqueLabel()))) {
                try {
                    DecodeStreamToYuv yuv =
                            new DecodeStreamToYuv(res.mMediaType, res.mResFile, frameLimit);
                    streamYuvMap.put(res.uniqueLabel(), yuv.getDecodedYuv());
                } catch (Exception e) {
                    streamYuvMap.put(res.uniqueLabel(), null);
                }
            }
        }
    }

    VideoEncoderValidationTestBase(String encoder, String mediaType,
            EncoderConfigParams encCfgParams, CompressedResource res, String allTestParams) {
        super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
        mCRes = res;
    }

    protected void setUpSource(String inpPath) throws IOException {
        Preconditions.assertTestFileExists(inpPath);
        mFileInp = new RandomAccessFile(inpPath, "r");
        mInputData = null;
        mFileReadOffset = 0L;
        mFileLength = mFileInp.length();
    }

    protected void enqueueInput(int bufferIndex) {
        int frmSize = 3 * mActiveRawRes.mBytesPerSample * mActiveRawRes.mWidth
                * mActiveRawRes.mHeight / 2;
        if (mInputData == null || mInputData.length != frmSize) {
            mInputData = new byte[frmSize];
        }
        int bytesRead = 0;
        try {
            bytesRead = mFileInp.read(mInputData);
            if (mIsLoopBack && mInputCount < mLoopBackFrameLimit && bytesRead == -1) {
                mFileInp.seek(0);
                bytesRead = mFileInp.read(mInputData);
            }
        } catch (IOException e) {
            fail("encountered exception during file read." + e + "\n" + mTestConfig + mTestEnv);
        }
        if (bytesRead != -1 && bytesRead != frmSize) {
            fail("received partial frame to encode \n" + mTestConfig + mTestEnv);
        }
        if (bytesRead == -1) {
            assertEquals("mFileReadOffset, mFileLength and EOS state are not in sync \n"
                    + mTestConfig + mTestEnv, mFileReadOffset, mFileLength);
            enqueueEOS(bufferIndex);
        } else {
            int size = mActiveRawRes.mBytesPerSample * mActiveEncCfg.mWidth
                    * mActiveEncCfg.mHeight * 3 / 2;
            int flags = 0;
            long pts = mInputOffsetPts + mInputCount * 1000000L / mActiveEncCfg.mFrameRate;

            Image img = mCodec.getInputImage(bufferIndex);
            assertNotNull("CPU-read via ImageReader API is not available \n" + mTestConfig
                    + mTestEnv, img);
            fillImage(img);
            if (mSignalEOSWithLastFrame) {
                if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
                        (mFileReadOffset + frmSize >= mFileLength)) {
                    flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
                    mSawInputEOS = true;
                }
            }
            mNumBytesSubmitted += size;
            mFileReadOffset += frmSize;
            mCodec.queueInputBuffer(bufferIndex, 0, size, pts, flags);
            if (ENABLE_LOGS) {
                Log.v(LOG_TAG, "input: id: " + bufferIndex + " size: " + size + " pts: " + pts
                        + " flags: " + flags);
            }
            mOutputBuff.saveInPTS(pts);
            mInputCount++;
        }
    }

    protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
        if (info.size > 0 && ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0)) {
            int picType = PICTURE_TYPE_UNKNOWN;

            if ((info.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) {
                picType = PICTURE_TYPE_I;
            }
            if (picType == PICTURE_TYPE_UNKNOWN) {
                MediaFormat format = mCodec.getOutputFormat(bufferIndex);
                picType = format.getInteger(MediaFormat.KEY_PICTURE_TYPE, PICTURE_TYPE_UNKNOWN);
            }
            if (picType == PICTURE_TYPE_UNKNOWN) {
                ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
                picType = BitStreamUtils.getFrameTypeFromBitStream(mMime, buf, info);
            }
            mPtsPicTypeMap.put(info.presentationTimeUs, picType);
        }
        super.dequeueOutput(bufferIndex, info);
    }
}
