blob: 3b0a7be0207cfa2067ceda3872de8c4fa888b778 [file] [log] [blame]
// 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