/*
 * Copyright 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.
 */

#include <algorithm>

#include "WOmxNode.h"
#include "WOmxBufferSource.h"
#include "Conversion.h"

namespace android {
namespace hardware {
namespace media {
namespace omx {
namespace V1_0 {
namespace implementation {

using ::android::hardware::Void;

// LWOmxNode
LWOmxNode::LWOmxNode(sp<IOmxNode> const& base) : mBase(base) {
}

status_t LWOmxNode::freeNode() {
    return toStatusT(mBase->freeNode());
}

status_t LWOmxNode::sendCommand(
        OMX_COMMANDTYPE cmd, OMX_S32 param) {
    return toStatusT(mBase->sendCommand(
            toRawCommandType(cmd), param));
}

status_t LWOmxNode::getParameter(
        OMX_INDEXTYPE index, void *params, size_t size) {
    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->getParameter(
            toRawIndexType(index),
            tParams,
            [&fnStatus, params, size](
                    Status status, hidl_vec<uint8_t> const& outParams) {
                fnStatus = toStatusT(status);
                std::copy(
                        outParams.data(),
                        outParams.data() + outParams.size(),
                        static_cast<uint8_t*>(params));
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::setParameter(
        OMX_INDEXTYPE index, const void *params, size_t size) {
    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
    return toStatusT(mBase->setParameter(
            toRawIndexType(index), tParams));
}

status_t LWOmxNode::getConfig(
        OMX_INDEXTYPE index, void *params, size_t size) {
    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->getConfig(
            toRawIndexType(index),
            tParams,
            [&fnStatus, params, size](
                    Status status, hidl_vec<uint8_t> const& outParams) {
                fnStatus = toStatusT(status);
                std::copy(
                        outParams.data(),
                        outParams.data() + size,
                        static_cast<uint8_t*>(params));
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::setConfig(
        OMX_INDEXTYPE index, const void *params, size_t size) {
    hidl_vec<uint8_t> tParams = inHidlBytes(params, size);
    return toStatusT(mBase->setConfig(toRawIndexType(index), tParams));
}

status_t LWOmxNode::setPortMode(
        OMX_U32 port_index, IOMX::PortMode mode) {
    return toStatusT(mBase->setPortMode(port_index, toHardwarePortMode(mode)));
}

status_t LWOmxNode::prepareForAdaptivePlayback(
        OMX_U32 portIndex, OMX_BOOL enable,
        OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
    return toStatusT(mBase->prepareForAdaptivePlayback(
            portIndex, toRawBool(enable), maxFrameWidth, maxFrameHeight));
}

status_t LWOmxNode::configureVideoTunnelMode(
        OMX_U32 portIndex, OMX_BOOL tunneled,
        OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->configureVideoTunnelMode(
            portIndex,
            toRawBool(tunneled),
            audioHwSync,
            [&fnStatus, sidebandHandle](
                    Status status, hidl_handle const& outSidebandHandle) {
                fnStatus = toStatusT(status);
                *sidebandHandle = outSidebandHandle == nullptr ?
                        nullptr : native_handle_clone(outSidebandHandle);
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::getGraphicBufferUsage(
        OMX_U32 portIndex, OMX_U32* usage) {
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->getGraphicBufferUsage(
            portIndex,
            [&fnStatus, usage](
                    Status status, uint32_t outUsage) {
                fnStatus = toStatusT(status);
                *usage = outUsage;
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::setInputSurface(
        const sp<IOMXBufferSource> &bufferSource) {
    return toStatusT(mBase->setInputSurface(
            new TWOmxBufferSource(bufferSource)));
}

status_t LWOmxNode::allocateSecureBuffer(
        OMX_U32 portIndex, size_t size, buffer_id *buffer,
        void **buffer_data, sp<NativeHandle> *native_handle) {
    *buffer_data = nullptr;
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->allocateSecureBuffer(
            portIndex,
            static_cast<uint64_t>(size),
            [&fnStatus, buffer, buffer_data, native_handle](
                    Status status,
                    uint32_t outBuffer,
                    hidl_handle const& outNativeHandle) {
                fnStatus = toStatusT(status);
                *buffer = outBuffer;
                *native_handle = NativeHandle::create(
                        native_handle_clone(outNativeHandle), true);
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::useBuffer(
        OMX_U32 portIndex, const OMXBuffer &omxBuffer, buffer_id *buffer) {
    CodecBuffer codecBuffer;
    if (!wrapAs(&codecBuffer, omxBuffer)) {
        return BAD_VALUE;
    }
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->useBuffer(
            portIndex,
            codecBuffer,
            [&fnStatus, buffer](Status status, uint32_t outBuffer) {
                fnStatus = toStatusT(status);
                *buffer = outBuffer;
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::freeBuffer(
        OMX_U32 portIndex, buffer_id buffer) {
    return toStatusT(mBase->freeBuffer(portIndex, buffer));
}

status_t LWOmxNode::fillBuffer(
        buffer_id buffer, const OMXBuffer &omxBuffer, int fenceFd) {
    CodecBuffer codecBuffer;
    if (!wrapAs(&codecBuffer, omxBuffer)) {
        return BAD_VALUE;
    }
    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
    if (!fenceNh) {
        return NO_MEMORY;
    }
    status_t status = toStatusT(mBase->fillBuffer(
            buffer, codecBuffer, fenceNh));
    native_handle_close(fenceNh);
    native_handle_delete(fenceNh);
    return status;
}

status_t LWOmxNode::emptyBuffer(
        buffer_id buffer, const OMXBuffer &omxBuffer,
        OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    CodecBuffer codecBuffer;
    if (!wrapAs(&codecBuffer, omxBuffer)) {
        return BAD_VALUE;
    }
    native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd);
    if (!fenceNh) {
        return NO_MEMORY;
    }
    status_t status = toStatusT(mBase->emptyBuffer(
            buffer,
            codecBuffer,
            flags,
            toRawTicks(timestamp),
            fenceNh));
    native_handle_close(fenceNh);
    native_handle_delete(fenceNh);
    return status;
}
status_t LWOmxNode::getExtensionIndex(
        const char *parameter_name,
        OMX_INDEXTYPE *index) {
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->getExtensionIndex(
            hidl_string(parameter_name),
            [&fnStatus, index](Status status, uint32_t outIndex) {
                fnStatus = toStatusT(status);
                *index = toEnumIndexType(outIndex);
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

status_t LWOmxNode::dispatchMessage(const omx_message &lMsg) {
    Message tMsg;
    native_handle_t* nh;
    if (!wrapAs(&tMsg, &nh, lMsg)) {
        return NO_MEMORY;
    }
    status_t status = toStatusT(mBase->dispatchMessage(tMsg));
    native_handle_close(nh);
    native_handle_delete(nh);
    return status;
}

// TWOmxNode
TWOmxNode::TWOmxNode(sp<IOMXNode> const& base) : mBase(base) {
}

Return<Status> TWOmxNode::freeNode() {
    return toStatus(mBase->freeNode());
}

Return<Status> TWOmxNode::sendCommand(uint32_t cmd, int32_t param) {
    return toStatus(mBase->sendCommand(toEnumCommandType(cmd), param));
}

Return<void> TWOmxNode::getParameter(
        uint32_t index, hidl_vec<uint8_t> const& inParams,
        getParameter_cb _hidl_cb) {
    hidl_vec<uint8_t> params(inParams);
    Status status = toStatus(mBase->getParameter(
            toEnumIndexType(index),
            static_cast<void*>(params.data()),
            params.size()));
    _hidl_cb(status, params);
    return Void();
}

Return<Status> TWOmxNode::setParameter(
        uint32_t index, hidl_vec<uint8_t> const& inParams) {
    hidl_vec<uint8_t> params(inParams);
    return toStatus(mBase->setParameter(
            toEnumIndexType(index),
            static_cast<void const*>(params.data()),
            params.size()));
}

Return<void> TWOmxNode::getConfig(
        uint32_t index, const hidl_vec<uint8_t>& inConfig,
        getConfig_cb _hidl_cb) {
    hidl_vec<uint8_t> config(inConfig);
    Status status = toStatus(mBase->getConfig(
            toEnumIndexType(index),
            static_cast<void*>(config.data()),
            config.size()));
    _hidl_cb(status, config);
    return Void();
}

Return<Status> TWOmxNode::setConfig(
        uint32_t index, const hidl_vec<uint8_t>& inConfig) {
    hidl_vec<uint8_t> config(inConfig);
    return toStatus(mBase->setConfig(
            toEnumIndexType(index),
            static_cast<void const*>(config.data()),
            config.size()));
}

Return<Status> TWOmxNode::setPortMode(uint32_t portIndex, PortMode mode) {
    return toStatus(mBase->setPortMode(portIndex, toIOMXPortMode(mode)));
}

Return<Status> TWOmxNode::prepareForAdaptivePlayback(
        uint32_t portIndex, bool enable,
        uint32_t maxFrameWidth, uint32_t maxFrameHeight) {
    return toStatus(mBase->prepareForAdaptivePlayback(
            portIndex,
            toEnumBool(enable),
            maxFrameWidth,
            maxFrameHeight));
}

Return<void> TWOmxNode::configureVideoTunnelMode(
        uint32_t portIndex, bool tunneled, uint32_t audioHwSync,
        configureVideoTunnelMode_cb _hidl_cb) {
    native_handle_t* sidebandHandle = nullptr;
    Status status = toStatus(mBase->configureVideoTunnelMode(
            portIndex,
            toEnumBool(tunneled),
            audioHwSync,
            &sidebandHandle));
    _hidl_cb(status, hidl_handle(sidebandHandle));
    return Void();
}

Return<void> TWOmxNode::getGraphicBufferUsage(
        uint32_t portIndex, getGraphicBufferUsage_cb _hidl_cb) {
    OMX_U32 usage;
    Status status = toStatus(mBase->getGraphicBufferUsage(
            portIndex, &usage));
    _hidl_cb(status, usage);
    return Void();
}

Return<Status> TWOmxNode::setInputSurface(
        const sp<IOmxBufferSource>& bufferSource) {
    return toStatus(mBase->setInputSurface(new LWOmxBufferSource(
            bufferSource)));
}

Return<void> TWOmxNode::allocateSecureBuffer(
        uint32_t portIndex, uint64_t size,
        allocateSecureBuffer_cb _hidl_cb) {
    IOMX::buffer_id buffer;
    void* bufferData;
    sp<NativeHandle> nativeHandle;
    Status status = toStatus(mBase->allocateSecureBuffer(
            portIndex,
            static_cast<size_t>(size),
            &buffer,
            &bufferData,
            &nativeHandle));
    _hidl_cb(status, buffer, nativeHandle == nullptr ?
            nullptr : nativeHandle->handle());
    return Void();
}

Return<void> TWOmxNode::useBuffer(
        uint32_t portIndex, const CodecBuffer& codecBuffer,
        useBuffer_cb _hidl_cb) {
    IOMX::buffer_id buffer;
    OMXBuffer omxBuffer;
    if (!convertTo(&omxBuffer, codecBuffer)) {
        _hidl_cb(Status::BAD_VALUE, 0);
        return Void();
    }
    Status status = toStatus(mBase->useBuffer(
            portIndex, omxBuffer, &buffer));
    _hidl_cb(status, buffer);
    return Void();
}

Return<Status> TWOmxNode::freeBuffer(uint32_t portIndex, uint32_t buffer) {
    return toStatus(mBase->freeBuffer(portIndex, buffer));
}

Return<Status> TWOmxNode::fillBuffer(
        uint32_t buffer, const CodecBuffer& codecBuffer,
        const hidl_handle& fence) {
    OMXBuffer omxBuffer;
    if (!convertTo(&omxBuffer, codecBuffer)) {
        return Status::BAD_VALUE;
    }
    return toStatus(mBase->fillBuffer(
            buffer,
            omxBuffer,
            dup(native_handle_read_fd(fence))));
}

Return<Status> TWOmxNode::emptyBuffer(
        uint32_t buffer, const CodecBuffer& codecBuffer, uint32_t flags,
        uint64_t timestampUs, const hidl_handle& fence) {
    OMXBuffer omxBuffer;
    if (!convertTo(&omxBuffer, codecBuffer)) {
        return Status::BAD_VALUE;
    }
    return toStatus(mBase->emptyBuffer(
            buffer,
            omxBuffer,
            flags,
            toOMXTicks(timestampUs),
            dup(native_handle_read_fd(fence))));
}

Return<void> TWOmxNode::getExtensionIndex(
        const hidl_string& parameterName,
        getExtensionIndex_cb _hidl_cb) {
    OMX_INDEXTYPE index;
    Status status = toStatus(mBase->getExtensionIndex(
            parameterName.c_str(), &index));
    _hidl_cb(status, toRawIndexType(index));
    return Void();
}

Return<Status> TWOmxNode::dispatchMessage(const Message& tMsg) {
    omx_message lMsg;
    if (!convertTo(&lMsg, tMsg)) {
        return Status::BAD_VALUE;
    }
    return toStatus(mBase->dispatchMessage(lMsg));
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace omx
}  // namespace media
}  // namespace hardware
}  // namespace android
