/*
 * 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 <media/stagefright/omx/1.0/WOmxNode.h>
#include <media/stagefright/omx/1.0/WOmxBufferSource.h>
#include <media/stagefright/omx/1.0/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](
                    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, native_handle](
                    Status status,
                    uint32_t outBuffer,
                    hidl_handle const& outNativeHandle) {
                fnStatus = toStatusT(status);
                *buffer = outBuffer;
                *native_handle = outNativeHandle.getNativeHandle() == nullptr ?
                        nullptr : 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
