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
34using namespace android;
35
36#define GRALLOC_SUB_BUFFER_MAX  3
37#define RANDOM_BUFFER_SIZE      200
38static char random_buf[RANDOM_BUFFER_SIZE];
39
40ISVBuffer::~ISVBuffer() {
41    if (mWorker != NULL) {
42        ALOGV("%s: mSurface %d", __func__, mSurface);
43        mWorker->freeSurface(&mSurface);
44    }
45}
46
47status_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
122status_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
167status_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
181status_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
199status_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
225status_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
256ISVBuffer* 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
267status_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