Fix FRC distortion issue.
Bug: 18629797
BZ: 230319
Change-Id: I2b6f1b0dac91214473666cd1075ca0018a954429
Signed-off-by: Xigui Wang <[email protected]>
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;
+}