// Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto.  Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once

#include <carb/Interface.h>
#include <carb/cudainterop/CudaInterop.h>
#include <carb/graphics/Graphics.h>
#include <carb/graphicsmux/GraphicsMux.h>
#include <carb/input/IInput.h>

namespace carb
{
namespace livestream
{
class Context;


enum class AudioSampleFormat: uint32_t
{
    eSFloat, //! floating point in the range [-1 .. 1]
    eUFloat, //! floating point in the range [0 .. 1]
    eSInt16, //! signed 16-bit integer in the range [INT16_MIN .. INT16_MAX]
    eUInt16 //! unsigned 16-bit integer in the range [0 .. UINT16_MAX]
};

/**
 * Describes audio samples buffer
 */
struct AudioSamplesDesc
{
    AudioSampleFormat sampleFormat; //! audio sample format
    uint32_t samplingRate; //! sampling rate (sampling frequency) in Hertz
    uint32_t channelCount; //! total number of channels
    uint32_t channelMask; //! channel presence mask (unmuted channels are marked with non-zero bits)
};

/**
 * Defines the Livestream Vision interface.
 */
struct Vision
{
    CARB_PLUGIN_INTERFACE("carb::livestream::Vision", 0, 4);

    /**
     * Creates Livestream Vision context.
     *
     * @param graphics Pointer to optional graphics interface to use or nullptr.
     * @param graphicsmux Pointer to optional graphics multiplexing API for async CUDA command recording or nullptr.
     * @param device Pointer to optional graphics device instance or nullptr.
     * @return Pointer to Livestream Vision context or nullptr.
     */
    Context*(CARB_ABI* createContext)(carb::graphics::Graphics* graphics,
                                      carb::graphicsmux::GraphicsMux* graphicsMux,
                                      carb::graphics::Device* device);

    /**
     * Destroys Livestream Vision context.
     *
     * @param ctx Pointer to the Livestream Vision context.
     */
    void(CARB_ABI* destroyContext)(Context* ctx);

    /**
     * Binds input interfaces to a Livestream Vision context.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param keyboard Pointer to the keyboard input interface.
     * @param mouse Pointer to the mouse input interface.
     * @param gamepad Pointer to the gamepad input interface.
     */
    void(CARB_ABI* bindInput)(Context* ctx,
                              carb::input::Keyboard* keyboard,
                              carb::input::Mouse* mouse,
                              carb::input::Gamepad* gamepad);

    /**
     * Pump the cached livestream input events into carb::input.
     * This function must be called from main thread.
     *
     * @param ctx Pointer to the Livestream Vision context.
     */
    void(CARB_ABI* updateInput)(Context* ctx);

    /**
     * Starts Livestream Vision server.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @return true if server started successfully.
     */
    bool(CARB_ABI* startServer)(Context* ctx);

    /**
     * Stops Livestream Vision server.
     *
     * @param ctx Pointer to the Livestream Vision context.
     */
    void(CARB_ABI* stopServer)(Context* ctx);

    /**
     * Get remote client width and height.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param extent Pointer to an extent destination.
     * @return true if extent is filled with valid data.
     */
    bool(CARB_ABI* getRemoteClientExtent)(Context* ctx, carb::Uint2* extent);

    /**
     * Records a command to send a frame from a CUDA buffer memory.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param commandList Pointer to the command list to use.
     * @param cudaMemory Unified pointer to the CUDA buffer memory.
     * @param pitch The frame row pitch in bytes.
     * @param width The frame width in pixels.
     * @param height The frame height in rows.
     */
    void(CARB_ABI* cmdSendCudaMemoryFrame)(Context* ctx,
                                           carb::graphicsmux::CommandList* commandList,
                                           void* cudaMemory,
                                           uint32_t pitch,
                                           uint32_t width,
                                           uint32_t height);

    /**
     * Enqueue a frame from a CUDA buffer memory.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param cudaMemory Unified pointer to the CUDA buffer memory.
     * @param pitch The frame row pitch in bytes.
     * @param width The frame width in pixels.
     * @param height The frame height in rows.
     */
    void(CARB_ABI* sendCudaMemoryFrame)(Context* ctx, void* cudaMemory, uint32_t pitch, uint32_t width, uint32_t height);

    /**
     * Enqueue a frame from a CUDA buffer external memory.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param cudaExternalMemory Pointer to the CUDA buffer external memory.
     * @param pitch The frame row pitch in bytes.
     * @param width The frame width in pixels
     * @param height The frame height in rows
     */
    void(CARB_ABI* sendCudaExternalMemoryFrame)(Context* ctx,
                                                carb::cudainterop::ExternalMemory* cudaExternalMemory,
                                                uint32_t pitch,
                                                uint32_t width,
                                                uint32_t height);

    /**
     * Enqueue a frame from a shared texture.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param textureHandle Pointer to the shared texture handle description.
     * @param texture Pointer to the texture object.
     */
    void(CARB_ABI* sendSharedTextureFrame)(Context* ctx,
                                           carb::graphics::SharedResourceHandle* textureHandle,
                                           carb::graphics::Texture* texture);

    /**
     * Enqueue an audio samples.
     *
     * @param ctx Pointer to the Livestream Vision context.
     * @param buf Pointer to the auduo samples buffer.
     * @param size Audio samples buffer size in bytes.
     * @param time Audio samples starting time in milleseconds.
     * @param desc Audio samples description.
     */
    void(CARB_ABI* sendAudioSamples)(Context* ctx, const void* buf, size_t size, uint32_t time, const AudioSamplesDesc& desc);
};
} // namespace livestream
} // namespace carb
