// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// #define LOG_NDEBUG 0
#define LOG_TAG "C2VDAAdaptorProxy"

#include <C2ArcVideoAcceleratorFactory.h>
#include <C2VDAAdaptorProxy.h>

#include <arc/MojoProcessSupport.h>
#include <arc/MojoThread.h>
#include <base/bind.h>
#include <base/files/scoped_file.h>
#include <mojo/public/cpp/platform/platform_handle.h>
#include <mojo/public/cpp/system/platform_handle.h>

#include <binder/IServiceManager.h>
#include <utils/Log.h>

namespace mojo {
template <>
struct TypeConverter<::arc::VideoFramePlane, android::VideoFramePlane> {
    static ::arc::VideoFramePlane Convert(const android::VideoFramePlane& plane) {
        return ::arc::VideoFramePlane{static_cast<int32_t>(plane.mOffset),
                                      static_cast<int32_t>(plane.mStride)};
    }
};
}  // namespace mojo

namespace android {
namespace arc {
C2VDAAdaptorProxy::C2VDAAdaptorProxy()
      : C2VDAAdaptorProxy(::arc::MojoProcessSupport::getLeakyInstance()) {}

C2VDAAdaptorProxy::C2VDAAdaptorProxy(::arc::MojoProcessSupport* mojoProcessSupport)
      : mClient(nullptr),
        mMojoTaskRunner(mojoProcessSupport->mojo_thread().getTaskRunner()),
        mBinding(this),
        mRelay(new ::arc::CancellationRelay()) {}

C2VDAAdaptorProxy::~C2VDAAdaptorProxy() {}

void C2VDAAdaptorProxy::onConnectionError(const std::string& pipeName) {
    ALOGE("onConnectionError (%s)", pipeName.c_str());
    mRelay->cancel();
    NotifyError(::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
}

bool C2VDAAdaptorProxy::establishChannel() {
    ALOGV("establishChannel");
    auto future = ::arc::Future<bool>::make_shared(mRelay);
    mMojoTaskRunner->PostTask(FROM_HERE,
                              ::base::Bind(&C2VDAAdaptorProxy::establishChannelOnMojoThread,
                                         ::base::Unretained(this), future));
    return future->wait() && future->get();
}

void C2VDAAdaptorProxy::establishChannelOnMojoThread(std::shared_ptr<::arc::Future<bool>> future) {
    auto& factory = ::android::GetC2ArcVideoAcceleratorFactory();

    if (!factory.createVideoDecodeAccelerator(mojo::MakeRequest(&mVDAPtr))) {
        future->set(false);
        return;
    }
    mVDAPtr.set_connection_error_handler(::base::Bind(&C2VDAAdaptorProxy::onConnectionError,
                                                    ::base::Unretained(this),
                                                    std::string("mVDAPtr (vda pipe)")));
    mVDAPtr.QueryVersion(::base::Bind(&C2VDAAdaptorProxy::onVersionReady, ::base::Unretained(this),
                                    std::move(future)));
}

void C2VDAAdaptorProxy::onVersionReady(std::shared_ptr<::arc::Future<bool>> future, uint32_t version) {
    ALOGI("VideoDecodeAccelerator ready (version=%d)", version);

    future->set(true);
}

void C2VDAAdaptorProxy::ProvidePictureBuffers(::arc::mojom::PictureBufferFormatPtr format) {
    ALOGV("ProvidePictureBuffers");
    mClient->providePictureBuffers(
            format->min_num_buffers,
            media::Size(format->coded_size.width(), format->coded_size.height()));
}
void C2VDAAdaptorProxy::PictureReady(::arc::mojom::PicturePtr picture) {
    ALOGV("PictureReady");
    const auto& rect = picture->crop_rect;
    mClient->pictureReady(picture->picture_buffer_id, picture->bitstream_id,
                          media::Rect(rect.x(), rect.y(), rect.right(), rect.bottom()));
}

static VideoDecodeAcceleratorAdaptor::Result convertErrorCode(
        ::arc::mojom::VideoDecodeAccelerator::Result error) {
    switch (error) {
    case ::arc::mojom::VideoDecodeAccelerator::Result::ILLEGAL_STATE:
        return VideoDecodeAcceleratorAdaptor::ILLEGAL_STATE;
    case ::arc::mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT:
        return VideoDecodeAcceleratorAdaptor::INVALID_ARGUMENT;
    case ::arc::mojom::VideoDecodeAccelerator::Result::UNREADABLE_INPUT:
        return VideoDecodeAcceleratorAdaptor::UNREADABLE_INPUT;
    case ::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE:
        return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
    case ::arc::mojom::VideoDecodeAccelerator::Result::INSUFFICIENT_RESOURCES:
        return VideoDecodeAcceleratorAdaptor::INSUFFICIENT_RESOURCES;

    default:
        ALOGE("Unknown error code: %d", static_cast<int>(error));
        return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
    }
}

void C2VDAAdaptorProxy::NotifyError(::arc::mojom::VideoDecodeAccelerator::Result error) {
    ALOGE("NotifyError %d", static_cast<int>(error));
    mClient->notifyError(convertErrorCode(error));
}

void C2VDAAdaptorProxy::NotifyEndOfBitstreamBuffer(int32_t bitstream_id) {
    ALOGV("NotifyEndOfBitstreamBuffer");
    mClient->notifyEndOfBitstreamBuffer(bitstream_id);
}

void C2VDAAdaptorProxy::NotifyResetDone(::arc::mojom::VideoDecodeAccelerator::Result result) {
    ALOGV("NotifyResetDone");
    // Always notify reset done to component even if result is not success. On shutdown, MediaCodec
    // will wait on shutdown complete notification despite any error. If no notification, it will be
    // hanging until timeout and force release.
    if (result != ::arc::mojom::VideoDecodeAccelerator::Result::SUCCESS) {
        ALOGE("Reset is done incorrectly.");
        NotifyError(result);
    }
    mClient->notifyResetDone();
}

void C2VDAAdaptorProxy::NotifyFlushDone(::arc::mojom::VideoDecodeAccelerator::Result result) {
    ALOGV("NotifyFlushDone");
    if (result == ::arc::mojom::VideoDecodeAccelerator::Result::CANCELLED) {
        // Flush is cancelled by a succeeding Reset(). A client expects this behavior.
        ALOGE("Flush is canceled.");
        return;
    }
    if (result != ::arc::mojom::VideoDecodeAccelerator::Result::SUCCESS) {
        ALOGE("Flush is done incorrectly.");
        NotifyError(result);
        return;
    }
    mClient->notifyFlushDone();
}

//static
media::VideoDecodeAccelerator::SupportedProfiles C2VDAAdaptorProxy::GetSupportedProfiles(
        InputCodec inputCodec) {
    media::VideoDecodeAccelerator::SupportedProfiles profiles(1);
    profiles[0].min_resolution = media::Size(16, 16);
    profiles[0].max_resolution = media::Size(4096, 4096);
    switch (inputCodec) {
    case InputCodec::H264:
        profiles[0].profile = media::H264PROFILE_MAIN;
        break;
    case InputCodec::VP8:
        profiles[0].profile = media::VP8PROFILE_ANY;
        break;
    case InputCodec::VP9:
        profiles[0].profile = media::VP9PROFILE_PROFILE0;
        break;
    default:
        ALOGE("Unknown input codec: %d", inputCodec);
        return {};
    }
    return profiles;
}

VideoDecodeAcceleratorAdaptor::Result C2VDAAdaptorProxy::initialize(
        media::VideoCodecProfile profile, bool secureMode,
        VideoDecodeAcceleratorAdaptor::Client* client) {
    ALOGV("initialize(profile=%d, secureMode=%d)", static_cast<int>(profile),
          static_cast<int>(secureMode));
    DCHECK(client);
    DCHECK(!mClient);
    mClient = client;

    if (!establishChannel()) {
        ALOGE("establishChannel failed");
        return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
    }

    auto future = ::arc::Future<::arc::mojom::VideoDecodeAccelerator::Result>::make_shared(mRelay);
    mMojoTaskRunner->PostTask(FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::initializeOnMojoThread,
                                                    ::base::Unretained(this), profile, secureMode,
                                                    ::arc::FutureCallback(future)));

    if (!future->wait()) {
        ALOGE("Connection lost");
        return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
    }
    return static_cast<VideoDecodeAcceleratorAdaptor::Result>(future->get());
}

void C2VDAAdaptorProxy::initializeOnMojoThread(
        const media::VideoCodecProfile profile, const bool secureMode,
        const ::arc::mojom::VideoDecodeAccelerator::InitializeCallback& cb) {
    // base::Unretained is safe because we own |mBinding|.
    mojo::InterfacePtr<::arc::mojom::VideoDecodeClient> client;
    mBinding.Bind(mojo::MakeRequest(&client));
    mBinding.set_connection_error_handler(::base::Bind(&C2VDAAdaptorProxy::onConnectionError,
                                                     ::base::Unretained(this),
                                                     std::string("mBinding (client pipe)")));

    ::arc::mojom::VideoDecodeAcceleratorConfigPtr arcConfig =
            ::arc::mojom::VideoDecodeAcceleratorConfig::New();
    arcConfig->secure_mode = secureMode;
    arcConfig->profile = static_cast<::arc::mojom::VideoCodecProfile>(profile);
    mVDAPtr->Initialize(std::move(arcConfig), std::move(client), cb);
}

void C2VDAAdaptorProxy::decode(int32_t bitstreamId, int handleFd, off_t offset, uint32_t size) {
    ALOGV("decode");
    mMojoTaskRunner->PostTask(
            FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::decodeOnMojoThread, ::base::Unretained(this),
                                  bitstreamId, handleFd, offset, size));
}

void C2VDAAdaptorProxy::decodeOnMojoThread(int32_t bitstreamId, int handleFd, off_t offset,
                                           uint32_t size) {
    mojo::ScopedHandle wrappedHandle =
            mojo::WrapPlatformHandle(mojo::PlatformHandle(::base::ScopedFD(handleFd)));
    if (!wrappedHandle.is_valid()) {
        ALOGE("failed to wrap handle");
        NotifyError(::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
        return;
    }
    auto bufferPtr = ::arc::mojom::BitstreamBuffer::New();
    bufferPtr->bitstream_id = bitstreamId;
    bufferPtr->handle_fd = std::move(wrappedHandle);
    bufferPtr->offset = offset;
    bufferPtr->bytes_used = size;
    mVDAPtr->Decode(std::move(bufferPtr));
}

void C2VDAAdaptorProxy::assignPictureBuffers(uint32_t numOutputBuffers) {
    ALOGV("assignPictureBuffers: %d", numOutputBuffers);
    mMojoTaskRunner->PostTask(FROM_HERE,
                              ::base::Bind(&C2VDAAdaptorProxy::assignPictureBuffersOnMojoThread,
                                         ::base::Unretained(this), numOutputBuffers));
}

void C2VDAAdaptorProxy::assignPictureBuffersOnMojoThread(uint32_t numOutputBuffers) {
    mVDAPtr->AssignPictureBuffers(numOutputBuffers);
}

void C2VDAAdaptorProxy::importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
                                               int handleFd,
                                               const std::vector<VideoFramePlane>& planes) {
    ALOGV("importBufferForPicture");
    mMojoTaskRunner->PostTask(
            FROM_HERE,
            ::base::Bind(&C2VDAAdaptorProxy::importBufferForPictureOnMojoThread,
                       ::base::Unretained(this), pictureBufferId, format, handleFd, planes));
}

void C2VDAAdaptorProxy::importBufferForPictureOnMojoThread(
        int32_t pictureBufferId, HalPixelFormat format, int handleFd,
        const std::vector<VideoFramePlane>& planes) {
    mojo::ScopedHandle wrappedHandle =
            mojo::WrapPlatformHandle(mojo::PlatformHandle(::base::ScopedFD(handleFd)));
    if (!wrappedHandle.is_valid()) {
        ALOGE("failed to wrap handle");
        NotifyError(::arc::mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
        return;
    }

    mVDAPtr->ImportBufferForPicture(pictureBufferId,
                                    static_cast<::arc::mojom::HalPixelFormat>(format),
                                    std::move(wrappedHandle),
                                    mojo::ConvertTo<std::vector<::arc::VideoFramePlane>>(planes));
}

void C2VDAAdaptorProxy::reusePictureBuffer(int32_t pictureBufferId) {
    ALOGV("reusePictureBuffer: %d", pictureBufferId);
    mMojoTaskRunner->PostTask(FROM_HERE,
                              ::base::Bind(&C2VDAAdaptorProxy::reusePictureBufferOnMojoThread,
                                         ::base::Unretained(this), pictureBufferId));
}

void C2VDAAdaptorProxy::reusePictureBufferOnMojoThread(int32_t pictureBufferId) {
    mVDAPtr->ReusePictureBuffer(pictureBufferId);
}

void C2VDAAdaptorProxy::flush() {
    ALOGV("flush");
    mMojoTaskRunner->PostTask(
            FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::flushOnMojoThread, ::base::Unretained(this)));
}

void C2VDAAdaptorProxy::flushOnMojoThread() {
    mVDAPtr->Flush(::base::Bind(&C2VDAAdaptorProxy::NotifyFlushDone, ::base::Unretained(this)));
}

void C2VDAAdaptorProxy::reset() {
    ALOGV("reset");
    mMojoTaskRunner->PostTask(
            FROM_HERE, ::base::Bind(&C2VDAAdaptorProxy::resetOnMojoThread, ::base::Unretained(this)));
}

void C2VDAAdaptorProxy::resetOnMojoThread() {
    mVDAPtr->Reset(::base::Bind(&C2VDAAdaptorProxy::NotifyResetDone, ::base::Unretained(this)));
}

void C2VDAAdaptorProxy::destroy() {
    ALOGV("destroy");
    ::arc::Future<void> future;
    ::arc::PostTaskAndSetFutureWithResult(
            mMojoTaskRunner.get(), FROM_HERE,
            ::base::Bind(&C2VDAAdaptorProxy::closeChannelOnMojoThread, ::base::Unretained(this)),
            &future);
    future.get();
}

void C2VDAAdaptorProxy::closeChannelOnMojoThread() {
    if (mBinding.is_bound()) mBinding.Close();
    mVDAPtr.reset();
}

}  // namespace arc
}  // namespace android
