1 /*
2 * Copyright (C) 2012 Intel Corporation. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <inttypes.h>
19
20 #include <media/hardware/HardwareAPI.h>
21 #include <system/graphics.h>
22 #include <nativebase/nativebase.h>
23
24 #include "isv_bufmanager.h"
25 #ifndef TARGET_VPP_USE_GEN
26 #include "hal_public.h"
27 #include <sync/sync.h>
28 #endif
29
30 //#define LOG_NDEBUG 0
31 #undef LOG_TAG
32 #define LOG_TAG "isv-omxil"
33
34 using namespace android;
35
36 #define GRALLOC_SUB_BUFFER_MAX 3
37 #define RANDOM_BUFFER_SIZE 200
38 static char random_buf[RANDOM_BUFFER_SIZE];
39
~ISVBuffer()40 ISVBuffer::~ISVBuffer() {
41 if (mWorker != NULL) {
42 ALOGV("%s: mSurface %d", __func__, mSurface);
43 mWorker->freeSurface(&mSurface);
44 }
45 }
46
initBufferInfo(uint32_t hackFormat)47 status_t ISVBuffer::initBufferInfo(uint32_t hackFormat)
48 {
49 if (mType == ISV_BUFFER_METADATA) {
50 VideoDecoderOutputMetaData *metaData =
51 reinterpret_cast<VideoDecoderOutputMetaData*>(mBuffer);
52
53 if (metaData->eType != kMetadataBufferTypeGrallocSource) {
54 ALOGE("%s: unsupported meta data format eType = %d", __func__, metaData->eType);
55 return UNKNOWN_ERROR;
56 }
57
58 if (mGrallocHandle != 0) {
59 if ((unsigned long)metaData->pHandle != mGrallocHandle) {
60 if (STATUS_OK != mWorker->freeSurface(&mSurface)) {
61 ALOGE("%s: free surface %d failed.", __func__, mSurface);
62 return UNKNOWN_ERROR;
63 }
64 } else
65 return OK;
66 }
67 mGrallocHandle = (unsigned long)metaData->pHandle;
68 } else {
69 if (mSurface != -1)
70 return OK;
71 mGrallocHandle = mBuffer;
72 }
73
74 int32_t err = 0;
75 #ifdef TARGET_VPP_USE_GEN
76 if (!mpGralloc) {
77 err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const**)&mpGralloc);
78 if (0 != err)
79 return UNKNOWN_ERROR;
80 }
81 ufo_buffer_details_t info;
82
83 memset(&info, 0, sizeof(ufo_buffer_details_t));
84 err = mpGralloc->perform(mpGralloc, INTEL_UFO_GRALLOC_MODULE_PERFORM_GET_BO_INFO, mGrallocHandle, &info);
85
86 if (0 != err) {
87 ALOGE("%s: can't get graphic buffer info", __func__);
88 }
89 mWidth = info.width;
90 mHeight = info.height;
91 mStride = info.pitch;
92 mColorFormat = info.format;
93 #else
94 if (!mpGralloc) {
95 err = gralloc_open_img(&mpGralloc);
96 if (0 != err)
97 return UNKNOWN_ERROR;
98 }
99 IMG_native_handle_t* grallocHandle = (IMG_native_handle_t*)mGrallocHandle;
100 mStride = grallocHandle->aiStride[0];
101 mSurfaceHeight = grallocHandle->iHeight;
102 mColorFormat = (hackFormat != 0) ? hackFormat : grallocHandle->iFormat;
103 #endif
104 if (mWorker == NULL) {
105 ALOGE("%s: mWorker == NULL!!", __func__);
106 return UNKNOWN_ERROR;
107 }
108
109 if (STATUS_OK != mWorker->allocSurface(&mWidth, &mHeight, mStride, mColorFormat, mGrallocHandle, &mSurface)) {
110 ALOGE("%s: alloc surface failed, mGrallocHandle %lu", __func__, mGrallocHandle);
111 return UNKNOWN_ERROR;
112 }
113
114 ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG,
115 "%s: mWidth %d, mHeight %d, mStride %d, mColorFormat %d, "
116 "mGrallocHandle %p, mSurface %d",
117 __func__, mWidth, mHeight, mStride, mColorFormat,
118 reinterpret_cast<void*>(mGrallocHandle), mSurface);
119 return OK;
120 }
121
clearIfNeed()122 status_t ISVBuffer::clearIfNeed()
123 {
124 #ifndef TARGET_VPP_USE_GEN
125 static bool bRandomBufferInit = false;
126 if (!bRandomBufferInit) {
127 time_t my_time;
128 srand((unsigned)time(&my_time));
129 for (int32_t i = 0; i < RANDOM_BUFFER_SIZE; i++)
130 random_buf[i] = (char)(((double)rand()/(double)RAND_MAX) * 255.0);
131 bRandomBufferInit = true;
132 }
133
134 if ((mFlags & ISV_BUFFER_NEED_CLEAR) && mpGralloc) {
135 int32_t usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
136 void *vaddr[GRALLOC_SUB_BUFFER_MAX];
137 const gralloc1_rect_t r = {
138 .width = (int32_t)mStride,
139 .height = (int32_t)mSurfaceHeight
140 };
141 int err, releaseFence = -1;
142
143 err = gralloc_lock_async_img(mpGralloc, (buffer_handle_t)mGrallocHandle, usage, &r, &vaddr[0], -1);
144 if (0 != err) {
145 ALOGE("%s: get graphic buffer ptr failed", __func__);
146 return UNKNOWN_ERROR;
147 }
148
149 int32_t buffer_size = mStride * mSurfaceHeight * 3 / 2;
150 char* ptr = (char*)vaddr[0];
151 for (int32_t i = 0; i < buffer_size/RANDOM_BUFFER_SIZE; i++) {
152 memcpy(ptr, random_buf, sizeof(random_buf));
153 ptr += sizeof(random_buf);
154 }
155 gralloc_unlock_async_img(mpGralloc, (buffer_handle_t)mGrallocHandle, &releaseFence);
156 if (releaseFence >= 0) {
157 sync_wait(releaseFence, -1);
158 close(releaseFence);
159 }
160 ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: clear isv buffer %p finished, buffer size %d", __func__, this, buffer_size);
161 mFlags &= ~ISV_BUFFER_NEED_CLEAR;
162 }
163 #endif
164 return OK;
165 }
166
setBufferCount(int32_t size)167 status_t ISVBufferManager::setBufferCount(int32_t size)
168 {
169 Mutex::Autolock autoLock(mBufferLock);
170 #if 0
171 if (!mBuffers.isEmpty()) {
172 ALOGE("%s: the buffer queue should be empty before we set its size", __func__);
173 return STATUS_ERROR;
174 }
175 #endif
176 mBuffers.setCapacity(size);
177
178 return OK;
179 }
180
freeBuffer(unsigned long handle)181 status_t ISVBufferManager::freeBuffer(unsigned long handle)
182 {
183 Mutex::Autolock autoLock(mBufferLock);
184 for (uint32_t i = 0; i < mBuffers.size(); i++) {
185 ISVBuffer* isvBuffer = mBuffers.itemAt(i);
186 if (isvBuffer->getHandle() == handle) {
187 delete isvBuffer;
188 mBuffers.removeAt(i);
189 ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: remove handle 0x%08lx, and then mBuffers.size() %d", __func__,
190 handle, mBuffers.size());
191 return OK;
192 }
193 }
194
195 ALOGW("%s: can't find buffer %lu", __func__, handle);
196 return UNKNOWN_ERROR;
197 }
198
useBuffer(unsigned long handle)199 status_t ISVBufferManager::useBuffer(unsigned long handle)
200 {
201 Mutex::Autolock autoLock(mBufferLock);
202 if (handle == 0 || mBuffers.size() >= mBuffers.capacity())
203 return BAD_VALUE;
204
205 for (uint32_t i = 0; i < mBuffers.size(); i++) {
206 ISVBuffer* isvBuffer = mBuffers.itemAt(i);
207 if (isvBuffer->getHandle() == handle) {
208 ALOGE("%s: this buffer 0x%08lx has already been registered", __func__, handle);
209 return UNKNOWN_ERROR;
210 }
211 }
212
213 ISVBuffer* isvBuffer = new ISVBuffer(mWorker, handle,
214 mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC,
215 mNeedClearBuffers ? ISVBuffer::ISV_BUFFER_NEED_CLEAR : 0);
216
217 ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG,
218 "%s: add handle 0x%08lx, and then mBuffers.size() %d", __func__,
219 handle, mBuffers.size());
220 mBuffers.push_back(isvBuffer);
221 return OK;
222
223 }
224
useBuffer(const sp<ANativeWindowBuffer> nativeBuffer)225 status_t ISVBufferManager::useBuffer(const sp<ANativeWindowBuffer> nativeBuffer)
226 {
227 Mutex::Autolock autoLock(mBufferLock);
228 if (nativeBuffer == NULL || mBuffers.size() >= mBuffers.capacity())
229 return BAD_VALUE;
230
231 for (uint32_t i = 0; i < mBuffers.size(); i++) {
232 ISVBuffer* isvBuffer = mBuffers.itemAt(i);
233 if (isvBuffer->getHandle() == (unsigned long)nativeBuffer->handle) {
234 ALOGE(
235 "%s: this buffer 0x%08" PRIxPTR " has already been registered",
236 __func__, reinterpret_cast<uintptr_t>(nativeBuffer->handle));
237 return UNKNOWN_ERROR;
238 }
239 }
240
241 ISVBuffer* isvBuffer = new ISVBuffer(mWorker,
242 (unsigned long)nativeBuffer->handle, (unsigned long)nativeBuffer->handle,
243 nativeBuffer->width, nativeBuffer->height,
244 nativeBuffer->stride, nativeBuffer->format,
245 mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC,
246 mNeedClearBuffers ? ISVBuffer::ISV_BUFFER_NEED_CLEAR : 0);
247
248 ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG,
249 "%s: add handle 0x%08" PRIxPTR ", and then mBuffers.size() %d",
250 __func__, reinterpret_cast<uintptr_t>(nativeBuffer->handle),
251 mBuffers.size());
252 mBuffers.push_back(isvBuffer);
253 return OK;
254 }
255
mapBuffer(unsigned long handle)256 ISVBuffer* ISVBufferManager::mapBuffer(unsigned long handle)
257 {
258 Mutex::Autolock autoLock(mBufferLock);
259 for (uint32_t i = 0; i < mBuffers.size(); i++) {
260 ISVBuffer* isvBuffer = mBuffers.itemAt(i);
261 if (isvBuffer->getHandle() == handle)
262 return isvBuffer;
263 }
264 return NULL;
265 }
266
setBuffersFlag(uint32_t flag)267 status_t ISVBufferManager::setBuffersFlag(uint32_t flag)
268 {
269 Mutex::Autolock autoLock(mBufferLock);
270
271 if (flag & ISVBuffer::ISV_BUFFER_NEED_CLEAR) {
272 if (mBuffers.size() == 0)
273 mNeedClearBuffers = true;
274 else {
275 for (uint32_t i = 0; i < mBuffers.size(); i++) {
276 ISVBuffer* isvBuffer = mBuffers.itemAt(i);
277 isvBuffer->setFlag(ISVBuffer::ISV_BUFFER_NEED_CLEAR);
278 }
279 }
280 }
281 return OK;
282 }
283