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