1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "host-common/MediaHostRenderer.h"
16 
17 #include <cstdint>
18 #include <string>
19 #include <vector>
20 
21 #include <stdio.h>
22 #include <string.h>
23 
24 #define MEDIA_H264_DEBUG 0
25 
26 #if MEDIA_H264_DEBUG
27 #define H264_DPRINT(fmt, ...)                                         \
28     fprintf(stderr, "media-host-renderer: %s:%d " fmt "\n", __func__, \
29             __LINE__, ##__VA_ARGS__);
30 #else
31 #define H264_DPRINT(fmt, ...)
32 #endif
33 
34 namespace android {
35 namespace emulation {
36 
37 using TextureFrame = MediaTexturePool::TextureFrame;
38 
MediaHostRenderer()39 MediaHostRenderer::MediaHostRenderer() {
40     mVirtioGpuOps = android_getVirtioGpuOps();
41     if (mVirtioGpuOps == nullptr) {
42         H264_DPRINT("Error, cannot get mVirtioGpuOps");
43     }
44 }
45 
~MediaHostRenderer()46 MediaHostRenderer::~MediaHostRenderer() {
47     cleanUpTextures();
48 }
49 
50 const uint32_t kGlUnsignedByte = 0x1401;
51 
52 constexpr uint32_t kGL_RGBA8 = 0x8058;
53 constexpr uint32_t kGL_RGBA = 0x1908;
54 constexpr uint32_t kFRAME_POOL_SIZE = 8;
55 constexpr uint32_t kFRAMEWORK_FORMAT_NV12 = 3;
56 
getTextureFrame(int w,int h)57 TextureFrame MediaHostRenderer::getTextureFrame(int w, int h) {
58     return mTexturePool.getTextureFrame(w, h);
59 }
60 
saveDecodedFrameToTexture(TextureFrame frame,void * privData,void * func)61 void MediaHostRenderer::saveDecodedFrameToTexture(TextureFrame frame,
62                                                   void* privData,
63                                                   void* func) {
64     mTexturePool.saveDecodedFrameToTexture(frame, privData, func);
65 }
66 
cleanUpTextures()67 void MediaHostRenderer::cleanUpTextures() {
68     mTexturePool.cleanUpTextures();
69 }
70 
renderToHostColorBuffer(int hostColorBufferId,unsigned int outputWidth,unsigned int outputHeight,uint8_t * decodedFrame)71 void MediaHostRenderer::renderToHostColorBuffer(int hostColorBufferId,
72                                                 unsigned int outputWidth,
73                                                 unsigned int outputHeight,
74                                                 uint8_t* decodedFrame) {
75     H264_DPRINT("Calling %s at %d buffer id %d", __func__, __LINE__,
76                 hostColorBufferId);
77     if (hostColorBufferId < 0) {
78         H264_DPRINT("ERROR: negative buffer id %d", hostColorBufferId);
79         return;
80     }
81     if (mVirtioGpuOps) {
82         mVirtioGpuOps->update_color_buffer(hostColorBufferId, 0, 0, outputWidth,
83                                            outputHeight, kGL_RGBA,
84                                            kGlUnsignedByte, decodedFrame);
85     } else {
86         H264_DPRINT("ERROR: there is no virtio Gpu Ops is not setup");
87     }
88 }
89 
renderToHostColorBufferWithTextures(int hostColorBufferId,unsigned int outputWidth,unsigned int outputHeight,TextureFrame frame)90 void MediaHostRenderer::renderToHostColorBufferWithTextures(
91         int hostColorBufferId,
92         unsigned int outputWidth,
93         unsigned int outputHeight,
94         TextureFrame frame) {
95     H264_DPRINT("Calling %s at %d buffer id %d", __func__, __LINE__,
96                 hostColorBufferId);
97     if (hostColorBufferId < 0) {
98         H264_DPRINT("ERROR: negative buffer id %d", hostColorBufferId);
99         // try to recycle valid textures: this could happen
100         mTexturePool.putTextureFrame(frame);
101         return;
102     }
103     if (frame.Ytex <= 0 || frame.UVtex <= 0) {
104         H264_DPRINT("ERROR: invalid tex ids: Ytex %d UVtex %d", (int)frame.Ytex,
105                     (int)frame.UVtex);
106         return;
107     }
108     if (mVirtioGpuOps) {
109         uint32_t textures[2] = {frame.Ytex, frame.UVtex};
110         mVirtioGpuOps->swap_textures_and_update_color_buffer(
111                 hostColorBufferId, 0, 0, outputWidth, outputHeight, kGL_RGBA,
112                 kGlUnsignedByte, kFRAMEWORK_FORMAT_NV12, textures);
113         if (textures[0] > 0 && textures[1] > 0) {
114             frame.Ytex = textures[0];
115             frame.UVtex = textures[1];
116             H264_DPRINT("return textures to pool %d %d", frame.Ytex,
117                         frame.UVtex);
118             mTexturePool.putTextureFrame(frame);
119         }
120     } else {
121         H264_DPRINT("ERROR: there is no virtio Gpu Ops is not setup");
122     }
123 }
124 
125 }  // namespace emulation
126 }  // namespace android
127