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

// #define LOG_NDEBUG 0
#define LOG_TAG "SoftVP9Encoder"
#include "SoftVP9Encoder.h"

#include <utils/Log.h>
#include <utils/misc.h>

#include <media/hardware/HardwareAPI.h>
#include <media/hardware/MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>

namespace android {

static const CodecProfileLevel kVp9ProfileLevels[] = {
    { OMX_VIDEO_VP9Profile0, OMX_VIDEO_VP9Level41 },
};

SoftVP9Encoder::SoftVP9Encoder(
        const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
        OMX_COMPONENTTYPE **component)
    : SoftVPXEncoder(
            name, callbacks, appData, component, "video_encoder.vp9",
            OMX_VIDEO_CodingVP9, MEDIA_MIMETYPE_VIDEO_VP9, 4,
            kVp9ProfileLevels, NELEM(kVp9ProfileLevels)),
      mLevel(OMX_VIDEO_VP9Level1),
      mTileColumns(0),
      mFrameParallelDecoding(OMX_FALSE) {
}

void SoftVP9Encoder::setCodecSpecificInterface() {
    mCodecInterface = vpx_codec_vp9_cx();
}

void SoftVP9Encoder::setCodecSpecificConfiguration() {
    mCodecConfiguration->g_profile = 0;
}

vpx_codec_err_t SoftVP9Encoder::setCodecSpecificControls() {
    vpx_codec_err_t codecReturn = vpx_codec_control(
            mCodecContext, VP9E_SET_TILE_COLUMNS, mTileColumns);
    if (codecReturn != VPX_CODEC_OK) {
        ALOGE("Error setting VP9E_SET_TILE_COLUMNS to %d. vpx_codec_control() "
              "returned %d", mTileColumns, codecReturn);
        return codecReturn;
    }
    codecReturn = vpx_codec_control(
            mCodecContext, VP9E_SET_FRAME_PARALLEL_DECODING,
            mFrameParallelDecoding);
    if (codecReturn != VPX_CODEC_OK) {
        ALOGE("Error setting VP9E_SET_FRAME_PARALLEL_DECODING to %d."
              "vpx_codec_control() returned %d", mFrameParallelDecoding,
              codecReturn);
        return codecReturn;
    }
    // For VP9, we always set CPU_USED to 8 (because the realtime default is 0
    // which is too slow).
    codecReturn = vpx_codec_control(mCodecContext, VP8E_SET_CPUUSED, 8);
    if (codecReturn != VPX_CODEC_OK) {
        ALOGE("Error setting VP8E_SET_CPUUSED to 8. vpx_codec_control() "
              "returned %d", codecReturn);
        return codecReturn;
    }
    return codecReturn;
}

OMX_ERRORTYPE SoftVP9Encoder::internalGetParameter(
        OMX_INDEXTYPE index, OMX_PTR param) {
    // can include extension index OMX_INDEXEXTTYPE
    const int32_t indexFull = index;

    switch (indexFull) {
        case OMX_IndexParamVideoVp9:
            return internalGetVp9Params(
                    (OMX_VIDEO_PARAM_VP9TYPE *)param);

        default:
            return SoftVPXEncoder::internalGetParameter(index, param);
    }
}

OMX_ERRORTYPE SoftVP9Encoder::internalSetParameter(
        OMX_INDEXTYPE index, const OMX_PTR param) {
    // can include extension index OMX_INDEXEXTTYPE
    const int32_t indexFull = index;

    switch (indexFull) {
        case OMX_IndexParamVideoVp9:
            return internalSetVp9Params(
                    (const OMX_VIDEO_PARAM_VP9TYPE *)param);

        default:
            return SoftVPXEncoder::internalSetParameter(index, param);
    }
}

OMX_ERRORTYPE SoftVP9Encoder::internalGetVp9Params(
        OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
    if (vp9Params->nPortIndex != kOutputPortIndex) {
        return OMX_ErrorUnsupportedIndex;
    }

    vp9Params->eProfile = OMX_VIDEO_VP9Profile0;
    vp9Params->eLevel = mLevel;
    vp9Params->bErrorResilientMode = mErrorResilience;
    vp9Params->nTileColumns = mTileColumns;
    vp9Params->bEnableFrameParallelDecoding = mFrameParallelDecoding;
    return OMX_ErrorNone;
}

OMX_ERRORTYPE SoftVP9Encoder::internalSetVp9Params(
        const OMX_VIDEO_PARAM_VP9TYPE *vp9Params) {
    if (vp9Params->nPortIndex != kOutputPortIndex) {
        return OMX_ErrorUnsupportedIndex;
    }

    if (vp9Params->eProfile != OMX_VIDEO_VP9Profile0) {
        return OMX_ErrorBadParameter;
    }

    if (vp9Params->eLevel == OMX_VIDEO_VP9Level1 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level11 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level2 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level21 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level3 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level31 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level4 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level41 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level5 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level51 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level52 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level6 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level61 ||
        vp9Params->eLevel == OMX_VIDEO_VP9Level62) {
        mLevel = vp9Params->eLevel;
    } else {
        return OMX_ErrorBadParameter;
    }

    mErrorResilience = vp9Params->bErrorResilientMode;
    mTileColumns = vp9Params->nTileColumns;
    mFrameParallelDecoding = vp9Params->bEnableFrameParallelDecoding;
    return OMX_ErrorNone;
}

}  // namespace android
