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