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 <OMX_Component.h>
21#include "isv_omxcomponent.h"
22#include <media/hardware/HardwareAPI.h>
23#include "isv_profile.h"
24#include <OMX_IndexExt.h>
25#include <hal_public.h>
26
27#include "OMX_adaptor.h"
28
29//#define LOG_NDEBUG 0
30#undef LOG_TAG
31#define LOG_TAG "isv-omxil"
32
33#define OUTPUT_STARTUP_DEC_BUF_NUM (38)
34#define FLUSH_WIDTH  352
35#define FLUSH_HEIGHT 288
36
37using namespace android;
38
39/**********************************************************************************
40 * component methods & helpers
41 */
42#define GET_ISVOMX_COMPONENT(hComponent)                                    \
43    ISVComponent *pComp = static_cast<ISVComponent*>                        \
44        ((static_cast<OMX_COMPONENTTYPE*>(hComponent))->pComponentPrivate); \
45    if (!pComp)                                                             \
46        return OMX_ErrorBadParameter;
47
48Vector<ISVComponent*> ISVComponent::g_isv_components;
49
50extern MRM_OMX_Adaptor* g_mrm_omx_adaptor;
51
52#ifndef TARGET_VPP_USE_GEN
53//global, static
54sp<ISVProcessor> ISVComponent::mProcThread = NULL;
55#endif
56
57//global, static
58pthread_mutex_t ISVComponent::ProcThreadInstanceLock = PTHREAD_MUTEX_INITIALIZER;
59
60ISVComponent::ISVComponent(
61        OMX_PTR pAppData)
62    :   mComponent(NULL),
63        mpCallBacks(NULL),
64        mCore(NULL),
65        mpISVCallBacks(NULL),
66        mISVBufferManager(NULL),
67        mThreadRunning(false),
68        mProcThreadObserver(NULL),
69        mNumISVBuffers(MIN_ISV_BUFFER_NUM),
70        mNumDecoderBuffers(0),
71        mNumDecoderBuffersBak(0),
72        mOutputDecoderBufferNum(0),
73        mWidth(0),
74        mHeight(0),
75        mUseAndroidNativeBufferIndex(0),
76        mStoreMetaDataInBuffersIndex(0),
77        mHackFormat(0),
78        mUseAndroidNativeBuffer(false),
79        mUseAndroidNativeBuffer2(false),
80        mVPPEnabled(false),
81        mVPPFlushing(false),
82        mOutputCropChanged(false),
83        mInitialized(false),
84#ifdef TARGET_VPP_USE_GEN
85        mProcThread(NULL),
86#endif
87        mOwnProcessor(false)
88{
89    memset(&mBaseComponent, 0, sizeof(OMX_COMPONENTTYPE));
90    /* handle initialization */
91    SetTypeHeader(&mBaseComponent, sizeof(mBaseComponent));
92    mBaseComponent.pApplicationPrivate = pAppData;
93    mBaseComponent.pComponentPrivate = static_cast<OMX_PTR>(this);
94
95    /* connect handle's functions */
96    mBaseComponent.GetComponentVersion = NULL;
97    mBaseComponent.SendCommand = SendCommand;
98    mBaseComponent.GetParameter = GetParameter;
99    mBaseComponent.SetParameter = SetParameter;
100    mBaseComponent.GetConfig = GetConfig;
101    mBaseComponent.SetConfig = SetConfig;
102    mBaseComponent.GetExtensionIndex = GetExtensionIndex;
103    mBaseComponent.GetState = GetState;
104    mBaseComponent.ComponentTunnelRequest = NULL;
105    mBaseComponent.UseBuffer = UseBuffer;
106    mBaseComponent.AllocateBuffer = AllocateBuffer;
107    mBaseComponent.FreeBuffer = FreeBuffer;
108    mBaseComponent.EmptyThisBuffer = EmptyThisBuffer;
109    mBaseComponent.FillThisBuffer = FillThisBuffer;
110    mBaseComponent.SetCallbacks = SetCallbacks;
111    mBaseComponent.ComponentDeInit = NULL;
112    mBaseComponent.UseEGLImage = NULL;
113    mBaseComponent.ComponentRoleEnum = ComponentRoleEnum;
114    g_isv_components.push_back(static_cast<ISVComponent*>(this));
115
116    mVPPOn = ISVProfile::isFRCOn() || ISVProfile::isVPPOn();
117    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPPOn %d", __func__, mVPPOn);
118
119    if (mISVBufferManager == NULL) {
120        mISVBufferManager = new ISVBufferManager();
121    }
122
123}
124
125ISVComponent::~ISVComponent()
126{
127    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
128    if (mpISVCallBacks) {
129        free(mpISVCallBacks);
130        mpISVCallBacks = NULL;
131    }
132
133    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
134        if (g_isv_components.itemAt(i) == static_cast<ISVComponent*>(this)) {
135            g_isv_components.removeAt(i);
136        }
137    }
138
139    memset(&mBaseComponent, 0, sizeof(OMX_COMPONENTTYPE));
140    deinit();
141    mVPPOn = false;
142    mISVBufferManager = NULL;
143}
144
145status_t ISVComponent::init(int32_t width, int32_t height)
146{
147    if (mInitialized)
148        return STATUS_OK;
149
150    bool frcOn = false;
151    if (mProcThreadObserver == NULL)
152        mProcThreadObserver = new ISVProcThreadObserver(&mBaseComponent, mComponent, mpCallBacks, mISVBufferManager);
153
154    pthread_mutex_lock(&ProcThreadInstanceLock);
155    if (mProcThread == NULL) {
156        mProcThread = new ISVProcessor(false, mISVBufferManager, mProcThreadObserver, width, height);
157        mOwnProcessor = true;
158        mProcThread->start();
159    }
160#ifndef TARGET_VPP_USE_GEN
161    else {
162        mVPPEnabled = false;
163        mOwnProcessor = false;
164        ALOGI("%s: failed to alloc isv processor", __func__);
165        pthread_mutex_unlock(&ProcThreadInstanceLock);
166        return STATUS_ERROR;
167    }
168#endif
169    pthread_mutex_unlock(&ProcThreadInstanceLock);
170
171    mInitialized = true;
172    return STATUS_OK;
173}
174
175void ISVComponent::deinit()
176{
177    pthread_mutex_lock(&ProcThreadInstanceLock);
178    if (mOwnProcessor) {
179        if (mProcThread != NULL) {
180            mProcThread->stop();
181            mProcThread = NULL;
182            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: delete ISV processor ", __func__);
183        }
184    }
185    pthread_mutex_unlock(&ProcThreadInstanceLock);
186
187    mProcThreadObserver = NULL;
188
189    mInitialized = false;
190}
191
192OMX_CALLBACKTYPE* ISVComponent::getCallBacks(OMX_CALLBACKTYPE* pCallBacks)
193{
194    //reset component callback functions
195    mpCallBacks = pCallBacks;
196    if (mpISVCallBacks) {
197        free(mpISVCallBacks);
198        mpISVCallBacks = NULL;
199    }
200
201    mpISVCallBacks = (OMX_CALLBACKTYPE *)calloc(1, sizeof(OMX_CALLBACKTYPE));
202    if (!mpISVCallBacks) {
203        ALOGE("%s: failed to alloc isv callbacks", __func__);
204        return NULL;
205    }
206    mpISVCallBacks->EventHandler = EventHandler;
207    mpISVCallBacks->EmptyBufferDone = pCallBacks->EmptyBufferDone;
208    mpISVCallBacks->FillBufferDone = FillBufferDone;
209    return mpISVCallBacks;
210}
211
212OMX_ERRORTYPE ISVComponent::SendCommand(
213    OMX_IN  OMX_HANDLETYPE hComponent,
214    OMX_IN  OMX_COMMANDTYPE Cmd,
215    OMX_IN  OMX_U32 nParam1,
216    OMX_IN  OMX_PTR pCmdData)
217{
218    GET_ISVOMX_COMPONENT(hComponent);
219
220    return pComp->ISV_SendCommand(Cmd, nParam1, pCmdData);
221}
222
223OMX_ERRORTYPE ISVComponent::ISV_SendCommand(
224    OMX_IN  OMX_COMMANDTYPE Cmd,
225    OMX_IN  OMX_U32 nParam1,
226    OMX_IN  OMX_PTR pCmdData)
227{
228    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: Cmd index 0x%08x, nParam1 %d", __func__, Cmd, nParam1);
229
230    if (mVPPEnabled && mVPPOn) {
231        if ((Cmd == OMX_CommandFlush && (nParam1 == kPortIndexOutput || nParam1 == OMX_ALL))
232                || (Cmd == OMX_CommandStateSet && nParam1 == OMX_StateIdle)
233                || (Cmd == OMX_CommandPortDisable && nParam1 == 1)) {
234            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: receive flush command, notify vpp thread to flush(Seek begin)", __func__);
235            mVPPFlushing = true;
236            mProcThread->notifyFlush();
237        }
238    }
239
240    return OMX_SendCommand(mComponent, Cmd, nParam1, pCmdData);
241}
242
243OMX_ERRORTYPE ISVComponent::GetParameter(
244    OMX_IN  OMX_HANDLETYPE hComponent,
245    OMX_IN  OMX_INDEXTYPE nParamIndex,
246    OMX_INOUT OMX_PTR pComponentParameterStructure)
247{
248    GET_ISVOMX_COMPONENT(hComponent);
249
250    return pComp->ISV_GetParameter(nParamIndex, pComponentParameterStructure);
251}
252
253OMX_ERRORTYPE ISVComponent::ISV_GetParameter(
254    OMX_IN  OMX_INDEXTYPE nParamIndex,
255    OMX_INOUT OMX_PTR pComponentParameterStructure)
256{
257    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nParamIndex);
258
259    OMX_ERRORTYPE err = OMX_GetParameter(mComponent, nParamIndex, pComponentParameterStructure);
260
261    if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) {
262        OMX_PARAM_PORTDEFINITIONTYPE *def =
263            static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure);
264
265        if (nParamIndex == OMX_IndexParamPortDefinition
266                && def->nPortIndex == kPortIndexOutput) {
267            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: orignal bufferCountActual %d, bufferCountMin %d",  __func__, def->nBufferCountActual, def->nBufferCountMin);
268#ifndef TARGET_VPP_USE_GEN
269            //FIXME: THIS IS A HACK!! Request NV12 buffer for YV12 format
270            //because VSP only support NV12 output
271            OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
272            if ((video_def->eColorFormat == VA_FOURCC_YV12) ||
273                (video_def->eColorFormat == HAL_PIXEL_FORMAT_INTEL_YV12)) {
274                //FIXME workaround Disable ISV for YV12 input
275                mVPPEnabled = false;
276                ALOGI("%s: Disable ISV for YV12 input. mVPPEnabled %d", __func__, mVPPEnabled);
277            } else {
278                //FIXME workaround avc low resolution playback
279                def->nBufferCountActual += mNumISVBuffers + 9;
280                def->nBufferCountMin += mNumISVBuffers + 9;
281            }
282#endif
283        }
284    }
285
286    return err;
287}
288
289OMX_ERRORTYPE ISVComponent::SetParameter(
290    OMX_IN  OMX_HANDLETYPE hComponent,
291    OMX_IN  OMX_INDEXTYPE nIndex,
292    OMX_IN  OMX_PTR pComponentParameterStructure)
293{
294    GET_ISVOMX_COMPONENT(hComponent);
295
296    return pComp->ISV_SetParameter(nIndex, pComponentParameterStructure);
297}
298
299OMX_ERRORTYPE ISVComponent::ISV_SetParameter(
300    OMX_IN  OMX_INDEXTYPE nIndex,
301    OMX_IN  OMX_PTR pComponentParameterStructure)
302{
303    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
304
305    if (nIndex == static_cast<OMX_INDEXTYPE>(OMX_IndexExtSetISVMode)) {
306        ISV_MODE* def = static_cast<ISV_MODE*>(pComponentParameterStructure);
307
308        if (*def == ISV_AUTO) {
309            mVPPEnabled = true;
310            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPPEnabled -->true", __func__);
311#ifndef TARGET_VPP_USE_GEN
312            if (mVPPOn) {
313                uint32_t number = MIN_INPUT_NUM + MIN_OUTPUT_NUM;
314                OMX_INDEXTYPE index;
315                status_t error =
316                    OMX_GetExtensionIndex(
317                            mComponent,
318                            (OMX_STRING)"OMX.Intel.index.vppBufferNum",
319                            &index);
320                if (error == OK) {
321                    error = OMX_SetParameter(mComponent, index, (OMX_PTR)&number);
322                } else {
323                    // ingore this error
324                    ALOGW("Get vpp number index failed");
325                }
326            }
327#endif
328        } else if (*def == ISV_DISABLE)
329            mVPPEnabled = false;
330        return OMX_ErrorNone;
331    }
332
333    // before setting param to real omx component, firstly set to media resource manager
334    OMX_ERRORTYPE err = g_mrm_omx_adaptor->MRM_OMX_SetParameter(mComponent,
335                                                                nIndex,
336                                                                pComponentParameterStructure);
337    if (err == OMX_ErrorInsufficientResources) {
338        return OMX_ErrorInsufficientResources;
339    }
340
341    err = OMX_SetParameter(mComponent, nIndex, pComponentParameterStructure);
342    if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) {
343        if (nIndex == OMX_IndexParamPortDefinition) {
344            OMX_PARAM_PORTDEFINITIONTYPE *def =
345                static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure);
346
347            if (def->nPortIndex == kPortIndexOutput) {
348                //set the buffer count we should fill to decoder before feed buffer to VPP
349                mNumDecoderBuffersBak = mNumDecoderBuffers = def->nBufferCountActual - MIN_OUTPUT_NUM - UNDEQUEUED_NUM;
350                mOutputDecoderBufferNum = 0;
351                OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
352
353                //FIXME: init itself here
354                if (mWidth != video_def->nFrameWidth
355                        || mHeight != video_def->nFrameHeight) {
356                    deinit();
357                    if (STATUS_OK == init(video_def->nFrameWidth, video_def->nFrameHeight)) {
358                        mWidth = video_def->nFrameWidth;
359                        mHeight = video_def->nFrameHeight;
360                    }
361                }
362                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: def->nBufferCountActual %d, mNumDecoderBuffersBak %d", __func__,
363                        def->nBufferCountActual, mNumDecoderBuffersBak);
364                if (mISVBufferManager != NULL && OK != mISVBufferManager->setBufferCount(def->nBufferCountActual)) {
365                    ALOGE("%s: failed to set ISV buffer count, set VPPEnabled -->false", __func__);
366                    mVPPEnabled = false;
367                }
368                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: video frame width %d, height %d",  __func__,
369                        video_def->nFrameWidth, video_def->nFrameHeight);
370            }
371
372            if (def->nPortIndex == kPortIndexInput) {
373                OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
374
375                if (mProcThread != NULL)
376                    mProcThread->configFRC(video_def->xFramerate);
377            }
378        }
379
380        if (mUseAndroidNativeBuffer
381                && nIndex == static_cast<OMX_INDEXTYPE>(mUseAndroidNativeBufferIndex)) {
382            UseAndroidNativeBufferParams *def =
383                static_cast<UseAndroidNativeBufferParams*>(pComponentParameterStructure);
384
385            if (mISVBufferManager != NULL && OK != mISVBufferManager->useBuffer(def->nativeBuffer)) {
386                    ALOGE("%s: failed to register graphic buffers to ISV, set mVPPEnabled -->false", __func__);
387                    mVPPEnabled = false;
388            }
389        }
390
391        if (nIndex == static_cast<OMX_INDEXTYPE>(mStoreMetaDataInBuffersIndex)) {
392            StoreMetaDataInBuffersParams *params = static_cast<StoreMetaDataInBuffersParams*>(pComponentParameterStructure);
393            if (params->nPortIndex == kPortIndexOutput) {
394                if (mISVBufferManager != NULL) {
395                    bool bMetaDataMode = params->bStoreMetaData == OMX_TRUE;
396                    mISVBufferManager->setMetaDataMode(bMetaDataMode);
397                } else {
398                    ALOGE("%s: falied to set Meta Data Mode ", __func__);
399                }
400            }
401            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: receive ISVStoreMetaDataInBuffers mISVWorkMode %d", __func__, (params->bStoreMetaData == OMX_TRUE));
402        }
403    }
404    return err;
405}
406
407OMX_ERRORTYPE ISVComponent::GetConfig(
408    OMX_IN  OMX_HANDLETYPE hComponent,
409    OMX_IN  OMX_INDEXTYPE nIndex,
410    OMX_INOUT OMX_PTR pComponentConfigStructure)
411{
412    GET_ISVOMX_COMPONENT(hComponent);
413
414    return pComp->ISV_GetConfig(nIndex, pComponentConfigStructure);
415}
416
417OMX_ERRORTYPE ISVComponent::ISV_GetConfig(
418    OMX_IN  OMX_INDEXTYPE nIndex,
419    OMX_INOUT OMX_PTR pComponentConfigStructure)
420{
421    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
422
423    OMX_ERRORTYPE err = OMX_GetConfig(mComponent, nIndex, pComponentConfigStructure);
424    if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) {
425        if (nIndex == OMX_IndexConfigCommonOutputCrop) {
426            OMX_CONFIG_RECTTYPE *rect = static_cast<OMX_CONFIG_RECTTYPE*>(pComponentConfigStructure);
427            if (rect->nPortIndex == kPortIndexOutput &&
428                    rect->nWidth < mWidth &&
429                    rect->nHeight < mHeight) {
430                mISVBufferManager->setBuffersFlag(ISVBuffer::ISV_BUFFER_NEED_CLEAR);
431                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mark all buffers need clear", __func__);
432            }
433        }
434    }
435    return err;
436}
437
438OMX_ERRORTYPE ISVComponent::SetConfig(
439    OMX_IN  OMX_HANDLETYPE hComponent,
440    OMX_IN  OMX_INDEXTYPE nIndex,
441    OMX_IN  OMX_PTR pComponentConfigStructure)
442{
443    GET_ISVOMX_COMPONENT(hComponent);
444
445    return pComp->ISV_SetConfig(nIndex, pComponentConfigStructure);
446}
447
448OMX_ERRORTYPE ISVComponent::ISV_SetConfig(
449    OMX_IN  OMX_INDEXTYPE nIndex,
450    OMX_IN  OMX_PTR pComponentConfigStructure)
451{
452    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
453
454    if (nIndex == static_cast<OMX_INDEXTYPE>(OMX_IndexConfigAutoFramerateConversion)) {
455        OMX_CONFIG_BOOLEANTYPE *config = static_cast<OMX_CONFIG_BOOLEANTYPE*>(pComponentConfigStructure);
456        if (config->bEnabled) {
457            mVPPEnabled = true;
458            ALOGI("%s: mVPPEnabled=true", __func__);
459        } else {
460            mVPPEnabled = false;
461            ALOGI("%s: mVPPEnabled=false", __func__);
462        }
463        return OMX_ErrorNone;
464    }
465
466    return OMX_SetConfig(mComponent, nIndex, pComponentConfigStructure);
467}
468
469OMX_ERRORTYPE ISVComponent::GetExtensionIndex(
470    OMX_IN  OMX_HANDLETYPE hComponent,
471    OMX_IN  OMX_STRING cParameterName,
472    OMX_OUT OMX_INDEXTYPE* pIndexType)
473{
474    GET_ISVOMX_COMPONENT(hComponent);
475
476    return pComp->ISV_GetExtensionIndex(cParameterName, pIndexType);
477}
478
479OMX_ERRORTYPE ISVComponent::ISV_GetExtensionIndex(
480    OMX_IN  OMX_STRING cParameterName,
481    OMX_OUT OMX_INDEXTYPE* pIndexType)
482{
483    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: cParameterName %s", __func__, cParameterName);
484    if(!strncmp(cParameterName, "OMX.intel.index.SetISVMode", strlen(cParameterName))) {
485        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtSetISVMode);
486        return OMX_ErrorNone;
487    }
488
489    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mComponent, cParameterName, pIndexType);
490
491    if(err == OMX_ErrorNone &&
492            !strncmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer2", strlen(cParameterName)))
493        mUseAndroidNativeBuffer2 = true;
494
495    if(err == OMX_ErrorNone &&
496            !strncmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer", strlen(cParameterName))) {
497        mUseAndroidNativeBuffer = true;
498        mUseAndroidNativeBufferIndex = static_cast<uint32_t>(*pIndexType);
499    }
500
501    if(err == OMX_ErrorNone &&
502            !strncmp(cParameterName, "OMX.google.android.index.storeMetaDataInBuffers", strlen(cParameterName))) {
503        mStoreMetaDataInBuffersIndex = static_cast<uint32_t>(*pIndexType);
504        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: storeMetaDataInBuffersIndex 0x%08x return %d", __func__, mStoreMetaDataInBuffersIndex, err);
505    }
506    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: cParameterName %s, nIndex 0x%08x", __func__,
507            cParameterName, *pIndexType);
508    return err;
509}
510
511OMX_ERRORTYPE ISVComponent::GetState(
512    OMX_IN  OMX_HANDLETYPE hComponent,
513    OMX_OUT OMX_STATETYPE* pState)
514{
515    GET_ISVOMX_COMPONENT(hComponent);
516
517    return pComp->ISV_GetState(pState);
518}
519
520OMX_ERRORTYPE ISVComponent::ISV_GetState(
521    OMX_OUT OMX_STATETYPE* pState)
522{
523    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
524
525    return OMX_GetState(mComponent, pState);
526}
527
528OMX_ERRORTYPE ISVComponent::UseBuffer(
529    OMX_IN OMX_HANDLETYPE hComponent,
530    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
531    OMX_IN OMX_U32 nPortIndex,
532    OMX_IN OMX_PTR pAppPrivate,
533    OMX_IN OMX_U32 nSizeBytes,
534    OMX_IN OMX_U8 *pBuffer)
535{
536    GET_ISVOMX_COMPONENT(hComponent);
537
538    return pComp->ISV_UseBuffer(ppBufferHdr, nPortIndex,
539                                 pAppPrivate, nSizeBytes, pBuffer);
540}
541
542OMX_ERRORTYPE ISVComponent::ISV_UseBuffer(
543    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
544    OMX_IN OMX_U32 nPortIndex,
545    OMX_IN OMX_PTR pAppPrivate,
546    OMX_IN OMX_U32 nSizeBytes,
547    OMX_IN OMX_U8 *pBuffer)
548{
549    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
550
551    OMX_ERRORTYPE err = OMX_UseBuffer(mComponent, ppBufferHdr, nPortIndex,
552            pAppPrivate, nSizeBytes, pBuffer);
553#ifndef USE_IVP
554    if(err == OMX_ErrorNone
555            && mVPPEnabled
556            && mVPPOn
557            && nPortIndex == kPortIndexOutput
558            /*&& mUseAndroidNativeBuffer2*/) {
559        if (mISVBufferManager != NULL) {
560            if (OK != mISVBufferManager->useBuffer(reinterpret_cast<unsigned long>(pBuffer))) {
561                ALOGE("%s: failed to register graphic buffers to ISV, set mVPPEnabled -->false", __func__);
562                mVPPEnabled = false;
563            } else
564                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPP useBuffer success. buffer handle %p", __func__, pBuffer);
565        }
566    }
567#endif
568    return err;
569}
570
571OMX_ERRORTYPE ISVComponent::AllocateBuffer(
572    OMX_IN OMX_HANDLETYPE hComponent,
573    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
574    OMX_IN OMX_U32 nPortIndex,
575    OMX_IN OMX_PTR pAppPrivate,
576    OMX_IN OMX_U32 nSizeBytes)
577{
578    GET_ISVOMX_COMPONENT(hComponent);
579
580    return pComp->ISV_AllocateBuffer(ppBuffer, nPortIndex,
581                                      pAppPrivate, nSizeBytes);
582}
583
584OMX_ERRORTYPE ISVComponent::ISV_AllocateBuffer(
585    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
586    OMX_IN OMX_U32 nPortIndex,
587    OMX_IN OMX_PTR pAppPrivate,
588    OMX_IN OMX_U32 nSizeBytes)
589{
590    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
591
592    return OMX_AllocateBuffer(mComponent, ppBuffer, nPortIndex,
593                                      pAppPrivate, nSizeBytes);
594}
595
596OMX_ERRORTYPE ISVComponent::FreeBuffer(
597    OMX_IN  OMX_HANDLETYPE hComponent,
598    OMX_IN  OMX_U32 nPortIndex,
599    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
600{
601    GET_ISVOMX_COMPONENT(hComponent);
602
603    return pComp->ISV_FreeBuffer(nPortIndex, pBuffer);
604}
605
606OMX_ERRORTYPE ISVComponent::ISV_FreeBuffer(
607    OMX_IN  OMX_U32 nPortIndex,
608    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
609{
610    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer);
611
612    if(mVPPEnabled && mVPPOn
613            && nPortIndex == kPortIndexOutput) {
614        if (mISVBufferManager != NULL && OK != mISVBufferManager->freeBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer)))
615            ALOGW("%s: pBuffer %p has not been registered into ISV", __func__, pBuffer);
616    }
617    return OMX_FreeBuffer(mComponent, nPortIndex, pBuffer);
618}
619
620OMX_ERRORTYPE ISVComponent::EmptyThisBuffer(
621    OMX_IN  OMX_HANDLETYPE hComponent,
622    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
623{
624    GET_ISVOMX_COMPONENT(hComponent);
625
626    return pComp->ISV_EmptyThisBuffer(pBuffer);
627}
628
629OMX_ERRORTYPE ISVComponent::ISV_EmptyThisBuffer(
630    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
631{
632    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer);
633
634    return OMX_EmptyThisBuffer(mComponent, pBuffer);
635}
636
637OMX_ERRORTYPE ISVComponent::FillThisBuffer(
638    OMX_IN  OMX_HANDLETYPE hComponent,
639    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
640{
641    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry.", __func__);
642    GET_ISVOMX_COMPONENT(hComponent);
643
644    return pComp->ISV_FillThisBuffer(pBuffer);
645}
646
647OMX_ERRORTYPE ISVComponent::ISV_FillThisBuffer(
648    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
649{
650    if(!mVPPEnabled || !mVPPOn)
651        return OMX_FillThisBuffer(mComponent, pBuffer);
652
653    ISVBuffer* isvBuffer = NULL;
654
655    if (mISVBufferManager != NULL) {
656        isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
657        if (isvBuffer == NULL) {
658            ALOGE("%s: failed to map ISVBuffer, set mVPPEnabled -->false", __func__);
659            mVPPEnabled = false;
660            return OMX_FillThisBuffer(mComponent, pBuffer);
661        }
662
663        if (OK != isvBuffer->initBufferInfo(mHackFormat)) {
664            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: isvBuffer %p failed to initBufferInfo", __func__, isvBuffer);
665            mVPPEnabled = false;
666            return OMX_FillThisBuffer(mComponent, pBuffer);
667        }
668    }
669
670    if (mNumDecoderBuffers > 0) {
671        Mutex::Autolock autoLock(mDecoderBufLock);
672        mNumDecoderBuffers--;
673        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: fill pBuffer %p to the decoder, decoder still need extra %d buffers", __func__,
674                pBuffer, mNumDecoderBuffers);
675
676        if (isvBuffer != NULL)
677            isvBuffer->clearIfNeed();
678
679        return OMX_FillThisBuffer(mComponent, pBuffer);
680    }
681    mProcThread->addOutput(pBuffer);
682
683    return OMX_ErrorNone;
684}
685
686OMX_ERRORTYPE ISVComponent::FillBufferDone(
687        OMX_OUT OMX_HANDLETYPE hComponent,
688        OMX_OUT OMX_PTR pAppData,
689        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
690{
691    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry. ISV component num %d, component handle %p on index 0", __func__,
692            g_isv_components.size(),
693            g_isv_components.itemAt(0));
694    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
695        if (static_cast<OMX_HANDLETYPE>(g_isv_components.itemAt(i)->mComponent) == hComponent)
696            return g_isv_components.itemAt(i)->ISV_FillBufferDone(hComponent, pAppData, pBuffer);
697    }
698    return OMX_ErrorUndefined;
699}
700
701OMX_ERRORTYPE ISVComponent::ISV_FillBufferDone(
702        OMX_OUT OMX_HANDLETYPE __maybe_unused hComponent,
703        OMX_OUT OMX_PTR pAppData,
704        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
705{
706    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: %p <== buffer_handle_t %p. mVPPEnabled %d, mVPPOn %d", __func__,
707            pBuffer, pBuffer->pBuffer, mVPPEnabled, mVPPOn);
708    if (!mpCallBacks) {
709        ALOGE("%s: no call back functions were registered.", __func__);
710        return OMX_ErrorUndefined;
711    }
712
713    if(!mVPPEnabled || !mVPPOn || mVPPFlushing || pBuffer->nFilledLen == 0) {
714        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBufferDone pBuffer %p, timeStamp %.2f ms", __func__, pBuffer, pBuffer->nTimeStamp/1E3);
715        return mpCallBacks->FillBufferDone(&mBaseComponent, pAppData, pBuffer);
716    }
717
718    if (mOutputCropChanged && mISVBufferManager != NULL) {
719        ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
720        if (isvBuffer != NULL)
721            isvBuffer->setFlag(ISVBuffer::ISV_BUFFER_CROP_CHANGED);
722        mOutputCropChanged = false;
723    }
724
725    if ((mWidth > FLUSH_WIDTH) && (mHeight > FLUSH_HEIGHT) &&
726        (pBuffer->nFilledLen != 0) && (mOutputDecoderBufferNum < OUTPUT_STARTUP_DEC_BUF_NUM)) {
727        Mutex::Autolock autoLock(mDecoderBufLock);
728        // take one buffer from decoder loop here. Fill one buffer to the loop by mNumDecoderBuffers++
729        mNumDecoderBuffers++;
730        mOutputDecoderBufferNum++;
731        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: return %d decoder output Buffer, mNumDecoderBuffers get %d input buffer",
732                __func__, mOutputDecoderBufferNum, mNumDecoderBuffers);
733        return mpCallBacks->FillBufferDone(&mBaseComponent, pAppData, pBuffer);
734    }
735
736    mProcThread->addInput(pBuffer);
737
738    return OMX_ErrorNone;
739}
740
741OMX_ERRORTYPE ISVComponent::EventHandler(
742        OMX_IN OMX_HANDLETYPE hComponent,
743        OMX_IN OMX_PTR pAppData,
744        OMX_IN OMX_EVENTTYPE eEvent,
745        OMX_IN OMX_U32 nData1,
746        OMX_IN OMX_U32 nData2,
747        OMX_IN OMX_PTR pEventData)
748{
749    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry. ISV component num %d, component handle %p on index 0", __func__,
750            g_isv_components.size(),
751            g_isv_components.itemAt(0));
752    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
753        if (static_cast<OMX_HANDLETYPE>(g_isv_components.itemAt(i)->mComponent) == hComponent)
754            return g_isv_components.itemAt(i)->ISV_EventHandler(hComponent, pAppData, eEvent, nData1, nData2, pEventData);
755    }
756    return OMX_ErrorUndefined;
757}
758
759OMX_ERRORTYPE ISVComponent::ISV_EventHandler(
760        OMX_IN OMX_HANDLETYPE __maybe_unused hComponent,
761        OMX_IN OMX_PTR pAppData,
762        OMX_IN OMX_EVENTTYPE eEvent,
763        OMX_IN OMX_U32 nData1,
764        OMX_IN OMX_U32 nData2,
765        OMX_IN OMX_PTR pEventData)
766{
767    if (!mpCallBacks) {
768        ALOGE("%s: no call back functions were registered.", __func__);
769        return OMX_ErrorUndefined;
770    }
771
772    if(!mVPPEnabled || !mVPPOn)
773        return mpCallBacks->EventHandler(&mBaseComponent, pAppData, eEvent, nData1, nData2, pEventData);
774
775    switch (eEvent) {
776        case OMX_EventCmdComplete:
777        {
778            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: OMX_EventCmdComplete Cmd type 0x%08x, data2 %d", __func__,
779                    nData1, nData2);
780            if (((OMX_COMMANDTYPE)nData1 == OMX_CommandFlush && (nData2 == kPortIndexOutput || nData2 == OMX_ALL))
781                || ((OMX_COMMANDTYPE)nData1 == OMX_CommandStateSet && nData2 == OMX_StateIdle)
782                || ((OMX_COMMANDTYPE)nData1 == OMX_CommandPortDisable && nData2 == 1)) {
783                mProcThread->waitFlushFinished();
784                mVPPFlushing = false;
785                mNumDecoderBuffers = mNumDecoderBuffersBak;
786                mOutputDecoderBufferNum = 0;
787            }
788            break;
789        }
790
791        case OMX_EventError:
792        {
793            //do we need do anything here?
794            ALOGE("%s: ERROR(0x%08x, %d)", __func__, nData1, nData2);
795            //mProcThread->flush();
796            break;
797        }
798
799        case OMX_EventPortSettingsChanged:
800        {
801            if (nData1 == kPortIndexOutput && nData2 == OMX_IndexConfigCommonOutputCrop) {
802                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: output crop changed", __func__);
803                mOutputCropChanged = true;
804                return OMX_ErrorNone;
805            } else if (nData1 == kPortIndexOutput && nData2 == OMX_IndexParamPortDefinition) {
806                ALOGI("%s: output format changed. ISV flush buffers", __func__);
807                mProcThread->notifyFlush();
808            }
809            break;
810        }
811
812        default:
813        {
814            ALOGD_IF(
815                ISV_COMPONENT_DEBUG, "%s: EVENT(%d, %" PRId32 ", %" PRId32 ")",
816                __func__, eEvent, nData1, nData2);
817            break;
818        }
819    }
820    return mpCallBacks->EventHandler(&mBaseComponent, pAppData, eEvent, nData1, nData2, pEventData);
821}
822
823OMX_ERRORTYPE ISVComponent::SetCallbacks(
824    OMX_IN  OMX_HANDLETYPE hComponent,
825    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
826    OMX_IN  OMX_PTR pAppData)
827{
828    GET_ISVOMX_COMPONENT(hComponent);
829
830    return pComp->ISV_SetCallbacks(pCallbacks, pAppData);
831}
832
833OMX_ERRORTYPE ISVComponent::ISV_SetCallbacks(
834    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
835    OMX_IN  OMX_PTR pAppData)
836{
837    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
838
839    if (mVPPEnabled && mVPPOn) {
840        if (mpISVCallBacks == NULL) {
841            mpISVCallBacks = (OMX_CALLBACKTYPE *)calloc(1, sizeof(OMX_CALLBACKTYPE));
842            if (!mpISVCallBacks) {
843                ALOGE("%s: failed to alloc isv callbacks", __func__);
844                return OMX_ErrorUndefined;
845            }
846        }
847        mpISVCallBacks->EventHandler = EventHandler;
848        mpISVCallBacks->EmptyBufferDone = pCallbacks->EmptyBufferDone;
849        mpISVCallBacks->FillBufferDone = FillBufferDone;
850        mpCallBacks = pCallbacks;
851        return mComponent->SetCallbacks(mComponent, mpISVCallBacks, pAppData);
852    }
853    return mComponent->SetCallbacks(mComponent, pCallbacks, pAppData);
854}
855
856OMX_ERRORTYPE ISVComponent::ComponentRoleEnum(
857    OMX_IN OMX_HANDLETYPE hComponent,
858    OMX_OUT OMX_U8 *cRole,
859    OMX_IN OMX_U32 nIndex)
860{
861    GET_ISVOMX_COMPONENT(hComponent);
862
863    return pComp->ISV_ComponentRoleEnum(cRole, nIndex);
864}
865
866OMX_ERRORTYPE ISVComponent::ISV_ComponentRoleEnum(
867    OMX_OUT OMX_U8 *cRole,
868    OMX_IN OMX_U32 nIndex)
869{
870    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
871
872    return mComponent->ComponentRoleEnum(mComponent, cRole, nIndex);
873}
874
875
876void ISVComponent::SetTypeHeader(OMX_PTR type, OMX_U32 size)
877{
878    OMX_U32 *nsize;
879    OMX_VERSIONTYPE *nversion;
880
881    if (!type)
882        return;
883
884    nsize = (OMX_U32 *)type;
885    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
886
887    *nsize = size;
888    nversion->nVersion = OMX_SPEC_VERSION;
889}
890
891
892ISVProcThreadObserver::ISVProcThreadObserver(
893        OMX_COMPONENTTYPE *pBaseComponent,
894        OMX_COMPONENTTYPE *pComponent,
895        OMX_CALLBACKTYPE *pCallBacks,
896        sp<ISVBufferManager> bufferManager)
897    :   mBaseComponent(pBaseComponent),
898        mComponent(pComponent),
899        mpCallBacks(pCallBacks),
900        mISVBufferManager(bufferManager)
901{
902    ALOGV("VPPProcThreadObserver!");
903}
904
905ISVProcThreadObserver::~ISVProcThreadObserver()
906{
907    ALOGV("~VPPProcThreadObserver!");
908    mBaseComponent = NULL;
909    mComponent = NULL;
910    mpCallBacks = NULL;
911}
912
913OMX_ERRORTYPE ISVProcThreadObserver::releaseBuffer(PORT_INDEX index, OMX_BUFFERHEADERTYPE* pBuffer, bool bFLush)
914{
915    if (!mBaseComponent || !mComponent || !mpCallBacks)
916        return OMX_ErrorUndefined;
917
918    OMX_ERRORTYPE err = OMX_ErrorNone;
919    if (bFLush) {
920        if(index == kPortIndexOutput) {
921            pBuffer->nFilledLen = 0;
922            pBuffer->nOffset = 0;
923            pBuffer->nTimeStamp = 0;
924            pBuffer->nFlags = 0;
925        }
926        err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
927        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: flush pBuffer %p", __func__, pBuffer);
928        return err;
929    }
930
931    if (index == kPortIndexInput) {
932        pBuffer->nFilledLen = 0;
933        pBuffer->nOffset = 0;
934        pBuffer->nFlags = 0;
935        pBuffer->nTimeStamp = 0;
936
937        if (mISVBufferManager != NULL) {
938            ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
939            if (isvBuffer != NULL)
940                isvBuffer->clearIfNeed();
941        }
942
943        err = OMX_FillThisBuffer(mComponent, pBuffer);
944        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBuffer pBuffer %p", __func__, pBuffer);
945    } else {
946        err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
947        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBufferDone pBuffer %p, timeStamp %.2f ms", __func__, pBuffer, pBuffer->nTimeStamp/1E3);
948    }
949
950    return err;
951}
952
953OMX_ERRORTYPE ISVProcThreadObserver::reportOutputCrop()
954{
955    if (!mBaseComponent || !mComponent || !mpCallBacks)
956        return OMX_ErrorUndefined;
957
958    OMX_ERRORTYPE err = OMX_ErrorNone;
959    err = mpCallBacks->EventHandler(&mBaseComponent, mBaseComponent->pApplicationPrivate,
960                                    OMX_EventPortSettingsChanged,
961                                    kPortIndexOutput, OMX_IndexConfigCommonOutputCrop, NULL);
962    return err;
963}
964