Fix FRC distortion issue.

Bug: 18629797
BZ: 230319

Change-Id: I2b6f1b0dac91214473666cd1075ca0018a954429
Signed-off-by: Xigui Wang <xigui.wang@intel.com>
diff --git a/ISV/base/isv_bufmanager.cpp b/ISV/base/isv_bufmanager.cpp
index 205268b..a00e4fc 100644
--- a/ISV/base/isv_bufmanager.cpp
+++ b/ISV/base/isv_bufmanager.cpp
@@ -28,6 +28,10 @@
 
 using namespace android;
 
+#define GRALLOC_SUB_BUFFER_MAX  3
+#define RANDOM_BUFFER_SIZE      200
+static char random_buf[RANDOM_BUFFER_SIZE];
+
 ISVBuffer::~ISVBuffer() {
     if (mWorker != NULL) {
         ALOGV("%s: mSurface %d", __func__, mSurface);
@@ -62,18 +66,19 @@
         mGrallocHandle = mBuffer;
     }
 
+    int32_t err = 0;
+    if (!mpGralloc) {
+        err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const**)&mpGralloc);
+        if (0 != err)
+            return UNKNOWN_ERROR;
+    }
 #ifdef TARGET_VPP_USE_GEN
-    gralloc_module_t* pGralloc = NULL;
     ufo_buffer_details_t info;
 
     memset(&info, 0, sizeof(ufo_buffer_details_t));
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const**)&pGralloc);
-    if (!pGralloc) err = -1;
-    if (0 == err)
-        err = pGralloc->perform(pGralloc, INTEL_UFO_GRALLOC_MODULE_PERFORM_GET_BO_INFO, mGrallocHandle, &info);
+    err = mpGralloc->perform(mpGralloc, INTEL_UFO_GRALLOC_MODULE_PERFORM_GET_BO_INFO, mGrallocHandle, &info);
 
-    if (0 != err)
-    {
+    if (0 != err) {
         ALOGE("%s: can't get graphic buffer info", __func__);
     }
     mWidth = info.width;
@@ -83,6 +88,7 @@
 #else
     IMG_native_handle_t* grallocHandle = (IMG_native_handle_t*)mGrallocHandle;
     mStride = grallocHandle->iWidth;
+    mSurfaceHeight = grallocHandle->iHeight;
     mColorFormat = (hackFormat != 0) ? hackFormat : grallocHandle->iFormat;
 #endif
     if (mWorker == NULL) {
@@ -100,6 +106,43 @@
     return OK;
 }
 
+status_t ISVBuffer::clearIfNeed()
+{
+#ifndef TARGET_VPP_USE_GEN
+    static bool bRandomBufferInit = false;
+    if (!bRandomBufferInit) {
+        time_t my_time;
+        srand((unsigned)time(&my_time));
+        for (int32_t i = 0; i < RANDOM_BUFFER_SIZE; i++)
+            random_buf[i] = (char)(((double)rand()/(double)RAND_MAX) * 255.0);
+        bRandomBufferInit = true;
+    }
+
+    if ((mFlags & ISV_BUFFER_NEED_CLEAR) && mpGralloc) {
+        int32_t usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+        void *vaddr[GRALLOC_SUB_BUFFER_MAX];
+
+        int32_t err = mpGralloc->lock(mpGralloc, (buffer_handle_t)mGrallocHandle, usage, 0, 0, mStride, mSurfaceHeight, &vaddr[0]);
+
+        if (0 != err) {
+            ALOGE("%s: get graphic buffer ptr failed", __func__);
+            return UNKNOWN_ERROR;
+        }
+
+        int32_t buffer_size = mStride * mSurfaceHeight * 3 / 2;
+        char* ptr = (char*)vaddr[0];
+        for (int32_t i = 0; i < buffer_size/RANDOM_BUFFER_SIZE; i++) {
+            memcpy(ptr, random_buf, sizeof(random_buf));
+            ptr += sizeof(random_buf);
+        }
+        mpGralloc->unlock(mpGralloc, (buffer_handle_t)mGrallocHandle);
+        ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: clear isv buffer %p finished, buffer size %d", __func__, this, buffer_size);
+        mFlags &= ~ISV_BUFFER_NEED_CLEAR;
+    }
+#endif
+    return OK;
+}
+
 status_t ISVBufferManager::setBufferCount(int32_t size)
 {
     Mutex::Autolock autoLock(mBufferLock);
@@ -146,7 +189,9 @@
         }
     }
 
-    ISVBuffer* isvBuffer = new ISVBuffer(mWorker, handle, mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC);
+    ISVBuffer* isvBuffer = new ISVBuffer(mWorker, handle,
+                                         mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC,
+                                         mNeedClearBuffers ? ISVBuffer::ISV_BUFFER_NEED_CLEAR : 0);
 
     ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: add handle 0x%08x, and then mBuffers.size() %d", __func__,
             handle, mBuffers.size());
@@ -173,7 +218,8 @@
             (unsigned long)nativeBuffer->handle, (unsigned long)nativeBuffer->handle,
             nativeBuffer->width, nativeBuffer->height,
             nativeBuffer->stride, nativeBuffer->format,
-            mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC);
+            mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC,
+            mNeedClearBuffers ? ISVBuffer::ISV_BUFFER_NEED_CLEAR : 0);
 
     ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: add handle 0x%08x, and then mBuffers.size() %d", __func__,
             nativeBuffer->handle, mBuffers.size());
@@ -192,3 +238,19 @@
     return NULL;
 }
 
+status_t ISVBufferManager::setBuffersFlag(uint32_t flag)
+{
+    Mutex::Autolock autoLock(mBufferLock);
+
+    if (flag & ISVBuffer::ISV_BUFFER_NEED_CLEAR) {
+        if (mBuffers.size() == 0)
+            mNeedClearBuffers = true;
+        else {
+            for (uint32_t i = 0; i < mBuffers.size(); i++) {
+                ISVBuffer* isvBuffer = mBuffers.itemAt(i);
+                isvBuffer->setFlag(ISVBuffer::ISV_BUFFER_NEED_CLEAR);
+            }
+        }
+    }
+    return OK;
+}
diff --git a/ISV/base/isv_processor.cpp b/ISV/base/isv_processor.cpp
index ff0df7f..990c15a 100644
--- a/ISV/base/isv_processor.cpp
+++ b/ISV/base/isv_processor.cpp
@@ -172,6 +172,7 @@
     OMX_BUFFERHEADERTYPE *outputBuffer;
     OMX_BUFFERHEADERTYPE *inputBuffer;
     OMX_ERRORTYPE err;
+    bool cropChanged = false;
 
     if (mInputBuffers.empty()) {
         ALOGE("%s: input buffer queue is empty. no buffer need to be sync", __func__);
@@ -186,6 +187,20 @@
     {
         Mutex::Autolock autoLock(mInputLock);
         inputBuffer = mInputBuffers.itemAt(0);
+        unsigned long inputHandle = reinterpret_cast<unsigned long>(inputBuffer->pBuffer);
+        ISVBuffer* inputBuf = mBufferManager->mapBuffer(inputHandle);
+        uint32_t flags = inputBuf->getFlags();
+
+        if (flags & ISVBuffer::ISV_BUFFER_CROP_CHANGED) {
+            err = mpOwner->reportOutputCrop();
+            if (err != OMX_ErrorNone) {
+                ALOGE("%s: failed to reportOutputCrop", __func__);
+                return UNKNOWN_ERROR;
+            }
+            cropChanged = true;
+            inputBuf->unsetFlag(ISVBuffer::ISV_BUFFER_CROP_CHANGED);
+        }
+
         err = mpOwner->releaseBuffer(kPortIndexInput, inputBuffer, false);
         if (err != OMX_ErrorNone) {
             ALOGE("%s: failed to fillInputBuffer", __func__);
@@ -218,7 +233,9 @@
             }
 
             //return filled buffers for rendering
-            err = mpOwner->releaseBuffer(kPortIndexOutput, outputBuffer, false);
+            //skip rendering for crop change
+            err = mpOwner->releaseBuffer(kPortIndexOutput, outputBuffer, cropChanged);
+
             if (err != OMX_ErrorNone) {
                 ALOGE("%s: failed to releaseOutputBuffer", __func__);
                 return UNKNOWN_ERROR;
diff --git a/ISV/include/isv_bufmanager.h b/ISV/include/isv_bufmanager.h
index cc50909..18c3209 100644
--- a/ISV/include/isv_bufmanager.h
+++ b/ISV/include/isv_bufmanager.h
@@ -23,6 +23,9 @@
 #include <utils/Errors.h>
 #include <utils/Vector.h>
 #include "isv_worker.h"
+#ifndef TARGET_VPP_USE_GEN
+#include "hal_public.h"
+#endif
 
 using namespace android;
 
@@ -37,6 +40,11 @@
         ISV_BUFFER_GRALLOC,
         ISV_BUFFER_METADATA,
     } ISV_BUFFERTYPE;
+
+    typedef enum {
+        ISV_BUFFER_NEED_CLEAR       = 0x00000001,
+        ISV_BUFFER_CROP_CHANGED     = 0x00000002,
+    } ISV_BUFFERFLAG;
 private:
     //FIX ME: copy from ufo gralloc.h
     typedef struct _ufo_buffer_details_t
@@ -66,29 +74,36 @@
             unsigned long buffer, unsigned long grallocHandle,
             uint32_t width, uint32_t height,
             uint32_t stride, uint32_t colorFormat,
-            ISV_BUFFERTYPE type)
+            ISV_BUFFERTYPE type, uint32_t flag)
         :mWorker(worker),
         mBuffer(buffer),
         mGrallocHandle(grallocHandle),
         mWidth(width),
         mHeight(height),
+        mSurfaceHeight(0),
         mStride(stride),
         mColorFormat(colorFormat),
         mType(type),
-        mSurface(-1) {}
+        mSurface(-1),
+        mFlags(flag),
+        mpGralloc(NULL) {}
 
     ISVBuffer(sp<ISVWorker> worker,
             unsigned long buffer,
-            ISV_BUFFERTYPE type)
+            ISV_BUFFERTYPE type,
+            uint32_t flag)
         :mWorker(worker),
         mBuffer(buffer),
         mGrallocHandle(0),
         mWidth(0),
         mHeight(0),
+        mSurfaceHeight(0),
         mStride(0),
         mColorFormat(0),
         mType(type),
-        mSurface(-1) {}
+        mSurface(-1),
+        mFlags(flag),
+        mpGralloc(NULL) {}
 
     ~ISVBuffer();
 
@@ -100,17 +115,26 @@
     int32_t getSurface() { return mSurface; }
     // get buffer handle
     unsigned long getHandle() { return mBuffer; }
+    // set/clear/get flag
+    uint32_t getFlags() { return mFlags; }
+    void setFlag(uint32_t flag) { mFlags |= flag; return; }
+    void unsetFlag(uint32_t flag) { mFlags &= ~flag; return; }
+    status_t clearIfNeed();
 
 private:
+
     sp<ISVWorker> mWorker;
     unsigned long mBuffer;
     unsigned long mGrallocHandle;
     uint32_t mWidth;
     uint32_t mHeight;
+    uint32_t mSurfaceHeight;
     uint32_t mStride;
     uint32_t mColorFormat;
     ISV_BUFFERTYPE mType;
     int32_t mSurface;
+    uint32_t mFlags;
+    gralloc_module_t* mpGralloc;
 };
 
 class ISVBufferManager: public RefBase
@@ -118,7 +142,8 @@
 public:
     ISVBufferManager()
         :mWorker(NULL),
-        mMetaDataMode(false) {}
+        mMetaDataMode(false),
+        mNeedClearBuffers(false) {}
 
     ~ISVBufferManager() {}
     // set mBuffers size
@@ -134,6 +159,8 @@
     // set isv worker
     void setWorker(sp<ISVWorker> worker) { mWorker = worker; }
     void setMetaDataMode(bool metaDataMode) { mMetaDataMode = metaDataMode; }
+    // set buffer flag.
+    status_t setBuffersFlag(uint32_t flag);
 private:
     typedef enum {
         GRALLOC_BUFFER_MODE = 0,
@@ -145,6 +172,7 @@
     // VPP buffer queue
     Vector<ISVBuffer*> mBuffers;
     Mutex mBufferLock; // to protect access to mBuffers
+    bool mNeedClearBuffers;
 };
 
 
diff --git a/ISV/include/isv_omxcomponent.h b/ISV/include/isv_omxcomponent.h
index e8f0c05..5acea30 100644
--- a/ISV/include/isv_omxcomponent.h
+++ b/ISV/include/isv_omxcomponent.h
@@ -47,14 +47,16 @@
 class ISVProcThreadObserver: public ISVProcessorObserver
 {
 public:
-    ISVProcThreadObserver(OMX_COMPONENTTYPE *pBaseComponent, OMX_COMPONENTTYPE *pComponent, OMX_CALLBACKTYPE *pCallBacks);
+    ISVProcThreadObserver(OMX_COMPONENTTYPE *pBaseComponent, OMX_COMPONENTTYPE *pComponent, OMX_CALLBACKTYPE *pCallBacks, sp<ISVBufferManager> bufferManager);
     ~ISVProcThreadObserver();
 
     virtual OMX_ERRORTYPE releaseBuffer(PORT_INDEX index, OMX_BUFFERHEADERTYPE* pBuffer, bool flush);
+    virtual OMX_ERRORTYPE reportOutputCrop();
 private:
     OMX_COMPONENTTYPE *mBaseComponent;
     OMX_COMPONENTTYPE *mComponent;
     OMX_CALLBACKTYPE *mpCallBacks;
+    sp<ISVBufferManager> mISVBufferManager;
 };
 
 class ISVComponent //: public RefBase
@@ -282,6 +284,7 @@
     bool mVPPEnabled;
     bool mVPPOn;
     bool mVPPFlushing;
+    bool mOutputCropChanged;
     bool mInitialized;
 #ifdef TARGET_VPP_USE_GEN
     // vpp thread
diff --git a/ISV/include/isv_processor.h b/ISV/include/isv_processor.h
index 9ea4e4c..c50fb65 100644
--- a/ISV/include/isv_processor.h
+++ b/ISV/include/isv_processor.h
@@ -40,6 +40,7 @@
 {
 public:
     virtual OMX_ERRORTYPE releaseBuffer(PORT_INDEX index, OMX_BUFFERHEADERTYPE* pBuffer, bool bFlush) = 0;
+    virtual OMX_ERRORTYPE reportOutputCrop() = 0;
 };
 
 class ISVProcessor : public Thread
diff --git a/ISV/omx/isv_omxcomponent.cpp b/ISV/omx/isv_omxcomponent.cpp
index b6cdbdb..94d6f6d 100644
--- a/ISV/omx/isv_omxcomponent.cpp
+++ b/ISV/omx/isv_omxcomponent.cpp
@@ -69,6 +69,7 @@
         mUseAndroidNativeBuffer2(false),
         mVPPEnabled(false),
         mVPPFlushing(false),
+        mOutputCropChanged(false),
         mInitialized(false),
 #ifdef TARGET_VPP_USE_GEN
         mProcThread(NULL),
@@ -138,7 +139,7 @@
 
     bool frcOn = false;
     if (mProcThreadObserver == NULL)
-        mProcThreadObserver = new ISVProcThreadObserver(&mBaseComponent, mComponent, mpCallBacks);
+        mProcThreadObserver = new ISVProcThreadObserver(&mBaseComponent, mComponent, mpCallBacks, mISVBufferManager);
 
     pthread_mutex_lock(&ProcThreadInstanceLock);
     if (mProcThread == NULL) {
@@ -399,7 +400,19 @@
 {
     ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
 
-    return OMX_GetConfig(mComponent, nIndex, pComponentConfigStructure);
+    OMX_ERRORTYPE err = OMX_GetConfig(mComponent, nIndex, pComponentConfigStructure);
+    if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) {
+        if (nIndex == OMX_IndexConfigCommonOutputCrop) {
+            OMX_CONFIG_RECTTYPE *rect = static_cast<OMX_CONFIG_RECTTYPE*>(pComponentConfigStructure);
+            if (rect->nPortIndex == kPortIndexOutput &&
+                    rect->nWidth < mWidth &&
+                    rect->nHeight < mHeight) {
+                mISVBufferManager->setBuffersFlag(ISVBuffer::ISV_BUFFER_NEED_CLEAR);
+                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mark all buffers need clear", __func__);
+            }
+        }
+    }
+    return err;
 }
 
 OMX_ERRORTYPE ISVComponent::SetConfig(
@@ -576,15 +589,12 @@
 {
     ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer);
 
-    OMX_ERRORTYPE err = OMX_FreeBuffer(mComponent, nPortIndex, pBuffer);
-    if(err == OMX_ErrorNone
-            && mVPPEnabled
-            && mVPPOn
+    if(mVPPEnabled && mVPPOn
             && nPortIndex == kPortIndexOutput) {
         if (mISVBufferManager != NULL && OK != mISVBufferManager->freeBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer)))
             ALOGW("%s: pBuffer %p has not been registered into ISV", __func__, pBuffer);
     }
-    return err;
+    return OMX_FreeBuffer(mComponent, nPortIndex, pBuffer);
 }
 
 OMX_ERRORTYPE ISVComponent::EmptyThisBuffer(
@@ -620,8 +630,10 @@
     if(!mVPPEnabled || !mVPPOn)
         return OMX_FillThisBuffer(mComponent, pBuffer);
 
+    ISVBuffer* isvBuffer = NULL;
+
     if (mISVBufferManager != NULL) {
-        ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
+        isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
         if (isvBuffer == NULL) {
             ALOGE("%s: failed to map ISVBuffer, set mVPPEnabled -->false", __func__);
             mVPPEnabled = false;
@@ -639,6 +651,10 @@
         mNumDecoderBuffers--;
         ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: fill pBuffer %p to the decoder, decoder still need extra %d buffers", __func__,
                 pBuffer, mNumDecoderBuffers);
+
+        if (isvBuffer != NULL)
+            isvBuffer->clearIfNeed();
+
         return OMX_FillThisBuffer(mComponent, pBuffer);
     }
     mProcThread->addOutput(pBuffer);
@@ -678,6 +694,13 @@
         return mpCallBacks->FillBufferDone(&mBaseComponent, pAppData, pBuffer);
     }
 
+    if (mOutputCropChanged && mISVBufferManager != NULL) {
+        ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
+        if (isvBuffer != NULL)
+            isvBuffer->setFlag(ISVBuffer::ISV_BUFFER_CROP_CHANGED);
+        mOutputCropChanged = false;
+    }
+
     mProcThread->addInput(pBuffer);
 
     return OMX_ErrorNone;
@@ -742,8 +765,11 @@
 
         case OMX_EventPortSettingsChanged:
         {
-            //FIXME: do we need clear ISV buffer queues for this situation?
-            //mProcThread->notifyFlush();
+            if (nData1 == kPortIndexOutput && nData2 == OMX_IndexConfigCommonOutputCrop) {
+                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: output crop changed", __func__);
+                mOutputCropChanged = true;
+                return OMX_ErrorNone;
+            }
             break;
         }
 
@@ -828,10 +854,12 @@
 ISVProcThreadObserver::ISVProcThreadObserver(
         OMX_COMPONENTTYPE *pBaseComponent,
         OMX_COMPONENTTYPE *pComponent,
-        OMX_CALLBACKTYPE *pCallBacks)
+        OMX_CALLBACKTYPE *pCallBacks,
+        sp<ISVBufferManager> bufferManager)
     :   mBaseComponent(pBaseComponent),
         mComponent(pComponent),
-        mpCallBacks(pCallBacks)
+        mpCallBacks(pCallBacks),
+        mISVBufferManager(bufferManager)
 {
     ALOGV("VPPProcThreadObserver!");
 }
@@ -853,7 +881,7 @@
     if (bFLush) {
         pBuffer->nFilledLen = 0;
         pBuffer->nOffset = 0;
-        OMX_ERRORTYPE err = mpCallBacks->FillBufferDone(mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
+        err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
         ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: flush pBuffer %p", __func__, pBuffer);
         return err;
     }
@@ -862,13 +890,31 @@
         pBuffer->nFilledLen = 0;
         pBuffer->nOffset = 0;
         pBuffer->nFlags = 0;
+
+        if (mISVBufferManager != NULL) {
+            ISVBuffer* isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
+            if (isvBuffer != NULL)
+                isvBuffer->clearIfNeed();
+        }
+
         err = OMX_FillThisBuffer(mComponent, pBuffer);
         ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBuffer pBuffer %p", __func__, pBuffer);
     } else {
-        err = mpCallBacks->FillBufferDone(mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
+        err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
         ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBufferDone pBuffer %p, timeStamp %.2f ms", __func__, pBuffer, pBuffer->nTimeStamp/1E3);
     }
 
     return err;
 }
 
+OMX_ERRORTYPE ISVProcThreadObserver::reportOutputCrop()
+{
+    if (!mBaseComponent || !mComponent || !mpCallBacks)
+        return OMX_ErrorUndefined;
+
+    OMX_ERRORTYPE err = OMX_ErrorNone;
+    err = mpCallBacks->EventHandler(&mBaseComponent, mBaseComponent->pApplicationPrivate,
+                                    OMX_EventPortSettingsChanged,
+                                    kPortIndexOutput, OMX_IndexConfigCommonOutputCrop, NULL);
+    return err;
+}