// Copyright (C) 2020 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 "host-common/MediaTexturePool.h"

#include <cstdint>
#include <string>
#include <vector>

#include <stdio.h>
#include <string.h>

#define MEDIA_H264_DEBUG 0

#if MEDIA_H264_DEBUG
#define H264_DPRINT(fmt, ...)                                                 \
    fprintf(stderr, "media-texture-pool: %s:%d myid: %d " fmt "\n", __func__, \
            __LINE__, m_id, ##__VA_ARGS__);
#else
#define H264_DPRINT(fmt, ...)
#endif

namespace android {
namespace emulation {

static int s_texturePoolId = 0;
MediaTexturePool::MediaTexturePool() {
    mVirtioGpuOps = android_getVirtioGpuOps();
    if (mVirtioGpuOps == nullptr) {
        H264_DPRINT("Error, cannot get mVirtioGpuOps");
    }
    m_id = s_texturePoolId++;
    H264_DPRINT("created texturepool");
}

MediaTexturePool::~MediaTexturePool() {
    H264_DPRINT("destroyed texturepool");
    cleanUpTextures();
}

const uint32_t kGlUnsignedByte = 0x1401;

constexpr uint32_t kGL_RGBA8 = 0x8058;
constexpr uint32_t kGL_RGBA = 0x1908;
constexpr uint32_t kFRAME_POOL_SIZE = 8;
constexpr uint32_t kFRAMEWORK_FORMAT_NV12 = 3;

MediaTexturePool::TextureFrame MediaTexturePool::getTextureFrame(int w, int h) {
    H264_DPRINT("calling %s %d for tex of w %d h %d\n", __func__, __LINE__, w,
                h);
    PoolHandle ph = m_WH_to_PoolHandle[TexSizes{w, h}];
    if (ph == nullptr) {
        ph = new Pool;
        m_WH_to_PoolHandle[TexSizes{w, h}] = ph;
    }
    if (ph->empty()) {
        std::vector<uint32_t> textures(2 * kFRAME_POOL_SIZE);
        mVirtioGpuOps->create_yuv_textures(kFRAMEWORK_FORMAT_NV12,
                                           kFRAME_POOL_SIZE, w, h,
                                           textures.data());
        for (uint32_t i = 0; i < kFRAME_POOL_SIZE; ++i) {
            TextureFrame frame{textures[2 * i], textures[2 * i + 1]};
            H264_DPRINT("allocated Y %d UV %d", frame.Ytex, frame.UVtex);
            m_Frame_to_PoolHandle[TexFrame{frame.Ytex, frame.UVtex}] = ph;
            ph->push_back(frame);
        }
    }
    TextureFrame frame = ph->front();
    ph->pop_front();
    H264_DPRINT("done %s %d ret Y %d UV %d", __func__, __LINE__, frame.Ytex,
                frame.UVtex);
    return frame;
}

void MediaTexturePool::saveDecodedFrameToTexture(TextureFrame frame,
                                                 void* privData,
                                                 void* func) {
    H264_DPRINT("calling %s %d for tex of  %d  %d\n", __func__, __LINE__,
                (int)frame.Ytex, (int)frame.UVtex);
    if (mVirtioGpuOps) {
        uint32_t textures[2] = {frame.Ytex, frame.UVtex};
        mVirtioGpuOps->update_yuv_textures(kFRAMEWORK_FORMAT_NV12, textures,
                                           privData, func);
    }
}

void MediaTexturePool::putTextureFrame(TextureFrame frame) {
    H264_DPRINT("try recycle textures %d %d", (int)frame.Ytex,
                (int)frame.UVtex);
    if (frame.Ytex > 0 && frame.UVtex > 0) {
        TexFrame tframe{frame.Ytex, frame.UVtex};
        auto iter = m_Frame_to_PoolHandle.find(tframe);
        if (iter != m_Frame_to_PoolHandle.end()) {
            PoolHandle phandle = iter->second;
            H264_DPRINT("recycle registered textures %d %d", (int)frame.Ytex,
                        (int)frame.UVtex);
            phandle->push_back(std::move(frame));
        } else {
            H264_DPRINT("recycle un-registered textures %d %d", (int)frame.Ytex,
                        (int)frame.UVtex);
            deleteTextures(frame);
        }
    }
}

void MediaTexturePool::deleteTextures(TextureFrame frame) {
    if (mVirtioGpuOps && frame.Ytex > 0 && frame.UVtex > 0) {
        std::vector<uint32_t> textures;
        textures.push_back(frame.Ytex);
        textures.push_back(frame.UVtex);
        mVirtioGpuOps->destroy_yuv_textures(kFRAMEWORK_FORMAT_NV12, 1,
                                            textures.data());
    }
}

void MediaTexturePool::cleanUpTextures() {
    if (m_WH_to_PoolHandle.empty()) {
        return;
    }
    for (auto iter : m_WH_to_PoolHandle) {
        auto& myFramePool = *(iter.second);
        std::vector<uint32_t> textures;
        for (auto& frame : myFramePool) {
            textures.push_back(frame.Ytex);
            textures.push_back(frame.UVtex);
            H264_DPRINT("delete Y %d UV %d", frame.Ytex, frame.UVtex);
        }
        mVirtioGpuOps->destroy_yuv_textures(
                kFRAMEWORK_FORMAT_NV12, myFramePool.size(), textures.data());
        myFramePool.clear();
    }
}

}  // namespace emulation
}  // namespace android
