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