• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/MediaTexturePool.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-texture-pool: %s:%d myid: %d " fmt "\n", __func__, \
29             __LINE__, m_id, ##__VA_ARGS__);
30 #else
31 #define H264_DPRINT(fmt, ...)
32 #endif
33 
34 namespace android {
35 namespace emulation {
36 
37 static int s_texturePoolId = 0;
MediaTexturePool()38 MediaTexturePool::MediaTexturePool() {
39     mVirtioGpuOps = android_getVirtioGpuOps();
40     if (mVirtioGpuOps == nullptr) {
41         H264_DPRINT("Error, cannot get mVirtioGpuOps");
42     }
43     m_id = s_texturePoolId++;
44     H264_DPRINT("created texturepool");
45 }
46 
~MediaTexturePool()47 MediaTexturePool::~MediaTexturePool() {
48     H264_DPRINT("destroyed texturepool");
49     cleanUpTextures();
50 }
51 
52 const uint32_t kGlUnsignedByte = 0x1401;
53 
54 constexpr uint32_t kGL_RGBA8 = 0x8058;
55 constexpr uint32_t kGL_RGBA = 0x1908;
56 constexpr uint32_t kFRAME_POOL_SIZE = 8;
57 constexpr uint32_t kFRAMEWORK_FORMAT_NV12 = 3;
58 
getTextureFrame(int w,int h)59 MediaTexturePool::TextureFrame MediaTexturePool::getTextureFrame(int w, int h) {
60     H264_DPRINT("calling %s %d for tex of w %d h %d\n", __func__, __LINE__, w,
61                 h);
62     PoolHandle ph = m_WH_to_PoolHandle[TexSizes{w, h}];
63     if (ph == nullptr) {
64         ph = new Pool;
65         m_WH_to_PoolHandle[TexSizes{w, h}] = ph;
66     }
67     if (ph->empty()) {
68         std::vector<uint32_t> textures(2 * kFRAME_POOL_SIZE);
69         mVirtioGpuOps->create_yuv_textures(kFRAMEWORK_FORMAT_NV12,
70                                            kFRAME_POOL_SIZE, w, h,
71                                            textures.data());
72         for (uint32_t i = 0; i < kFRAME_POOL_SIZE; ++i) {
73             TextureFrame frame{textures[2 * i], textures[2 * i + 1]};
74             H264_DPRINT("allocated Y %d UV %d", frame.Ytex, frame.UVtex);
75             m_Frame_to_PoolHandle[TexFrame{frame.Ytex, frame.UVtex}] = ph;
76             ph->push_back(frame);
77         }
78     }
79     TextureFrame frame = ph->front();
80     ph->pop_front();
81     H264_DPRINT("done %s %d ret Y %d UV %d", __func__, __LINE__, frame.Ytex,
82                 frame.UVtex);
83     return frame;
84 }
85 
saveDecodedFrameToTexture(TextureFrame frame,void * privData,void * func)86 void MediaTexturePool::saveDecodedFrameToTexture(TextureFrame frame,
87                                                  void* privData,
88                                                  void* func) {
89     H264_DPRINT("calling %s %d for tex of  %d  %d\n", __func__, __LINE__,
90                 (int)frame.Ytex, (int)frame.UVtex);
91     if (mVirtioGpuOps) {
92         uint32_t textures[2] = {frame.Ytex, frame.UVtex};
93         mVirtioGpuOps->update_yuv_textures(kFRAMEWORK_FORMAT_NV12, textures,
94                                            privData, func);
95     }
96 }
97 
putTextureFrame(TextureFrame frame)98 void MediaTexturePool::putTextureFrame(TextureFrame frame) {
99     H264_DPRINT("try recycle textures %d %d", (int)frame.Ytex,
100                 (int)frame.UVtex);
101     if (frame.Ytex > 0 && frame.UVtex > 0) {
102         TexFrame tframe{frame.Ytex, frame.UVtex};
103         auto iter = m_Frame_to_PoolHandle.find(tframe);
104         if (iter != m_Frame_to_PoolHandle.end()) {
105             PoolHandle phandle = iter->second;
106             H264_DPRINT("recycle registered textures %d %d", (int)frame.Ytex,
107                         (int)frame.UVtex);
108             phandle->push_back(std::move(frame));
109         } else {
110             H264_DPRINT("recycle un-registered textures %d %d", (int)frame.Ytex,
111                         (int)frame.UVtex);
112             deleteTextures(frame);
113         }
114     }
115 }
116 
deleteTextures(TextureFrame frame)117 void MediaTexturePool::deleteTextures(TextureFrame frame) {
118     if (mVirtioGpuOps && frame.Ytex > 0 && frame.UVtex > 0) {
119         std::vector<uint32_t> textures;
120         textures.push_back(frame.Ytex);
121         textures.push_back(frame.UVtex);
122         mVirtioGpuOps->destroy_yuv_textures(kFRAMEWORK_FORMAT_NV12, 1,
123                                             textures.data());
124     }
125 }
126 
cleanUpTextures()127 void MediaTexturePool::cleanUpTextures() {
128     if (m_WH_to_PoolHandle.empty()) {
129         return;
130     }
131     for (auto iter : m_WH_to_PoolHandle) {
132         auto& myFramePool = *(iter.second);
133         std::vector<uint32_t> textures;
134         for (auto& frame : myFramePool) {
135             textures.push_back(frame.Ytex);
136             textures.push_back(frame.UVtex);
137             H264_DPRINT("delete Y %d UV %d", frame.Ytex, frame.UVtex);
138         }
139         mVirtioGpuOps->destroy_yuv_textures(
140                 kFRAMEWORK_FORMAT_NV12, myFramePool.size(), textures.data());
141         myFramePool.clear();
142     }
143 }
144 
145 }  // namespace emulation
146 }  // namespace android
147