// 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/MediaHostRenderer.h" #include #include #include #include #include #define MEDIA_H264_DEBUG 0 #if MEDIA_H264_DEBUG #define H264_DPRINT(fmt, ...) \ fprintf(stderr, "media-host-renderer: %s:%d " fmt "\n", __func__, \ __LINE__, ##__VA_ARGS__); #else #define H264_DPRINT(fmt, ...) #endif namespace android { namespace emulation { using TextureFrame = MediaTexturePool::TextureFrame; MediaHostRenderer::MediaHostRenderer() { mVirtioGpuOps = android_getVirtioGpuOps(); if (mVirtioGpuOps == nullptr) { H264_DPRINT("Error, cannot get mVirtioGpuOps"); } } MediaHostRenderer::~MediaHostRenderer() { 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; TextureFrame MediaHostRenderer::getTextureFrame(int w, int h) { return mTexturePool.getTextureFrame(w, h); } void MediaHostRenderer::saveDecodedFrameToTexture(TextureFrame frame, void* privData, void* func) { mTexturePool.saveDecodedFrameToTexture(frame, privData, func); } void MediaHostRenderer::cleanUpTextures() { mTexturePool.cleanUpTextures(); } void MediaHostRenderer::renderToHostColorBuffer(int hostColorBufferId, unsigned int outputWidth, unsigned int outputHeight, uint8_t* decodedFrame) { H264_DPRINT("Calling %s at %d buffer id %d", __func__, __LINE__, hostColorBufferId); if (hostColorBufferId < 0) { H264_DPRINT("ERROR: negative buffer id %d", hostColorBufferId); return; } if (mVirtioGpuOps) { mVirtioGpuOps->update_color_buffer(hostColorBufferId, 0, 0, outputWidth, outputHeight, kGL_RGBA, kGlUnsignedByte, decodedFrame); } else { H264_DPRINT("ERROR: there is no virtio Gpu Ops is not setup"); } } void MediaHostRenderer::renderToHostColorBufferWithTextures( int hostColorBufferId, unsigned int outputWidth, unsigned int outputHeight, TextureFrame frame) { H264_DPRINT("Calling %s at %d buffer id %d", __func__, __LINE__, hostColorBufferId); if (hostColorBufferId < 0) { H264_DPRINT("ERROR: negative buffer id %d", hostColorBufferId); // try to recycle valid textures: this could happen mTexturePool.putTextureFrame(frame); return; } if (frame.Ytex <= 0 || frame.UVtex <= 0) { H264_DPRINT("ERROR: invalid tex ids: Ytex %d UVtex %d", (int)frame.Ytex, (int)frame.UVtex); return; } if (mVirtioGpuOps) { uint32_t textures[2] = {frame.Ytex, frame.UVtex}; mVirtioGpuOps->swap_textures_and_update_color_buffer( hostColorBufferId, 0, 0, outputWidth, outputHeight, kGL_RGBA, kGlUnsignedByte, kFRAMEWORK_FORMAT_NV12, textures); if (textures[0] > 0 && textures[1] > 0) { frame.Ytex = textures[0]; frame.UVtex = textures[1]; H264_DPRINT("return textures to pool %d %d", frame.Ytex, frame.UVtex); mTexturePool.putTextureFrame(frame); } } else { H264_DPRINT("ERROR: there is no virtio Gpu Ops is not setup"); } } } // namespace emulation } // namespace android