Merge tag android-5.1.0_r1 into AOSP_5.1_MERGE

Change-Id: Iad354104e40ec797045e8bc250815c33e24bcdb7
diff --git a/ISV/Android.mk b/ISV/Android.mk
new file mode 100644
index 0000000..12965a9
--- /dev/null
+++ b/ISV/Android.mk
@@ -0,0 +1,49 @@
+ifeq ($(TARGET_HAS_ISV),true)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    omx/isv_omxcore.cpp \
+    omx/isv_omxcomponent.cpp \
+    base/isv_bufmanager.cpp \
+    base/isv_processor.cpp \
+    base/isv_worker.cpp \
+    profile/isv_profile.cpp
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libisv_omx_core
+LOCAL_32_BIT_ONLY := true
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+    libcutils \
+    libdl \
+    libhardware \
+    libexpat \
+    libva \
+    libva-android
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/include \
+    $(call include-path-for, frameworks-openmax) \
+    $(TARGET_OUT_HEADERS)/libmedia_utils_vpp \
+    $(TARGET_OUT_HEADERS)/display \
+    $(TARGET_OUT_HEADERS)/khronos/openmax \
+    $(TARGET_OUT_HEADERS)/libva \
+    $(TARGET_OUT_HEADERS)/pvr/hal \
+    $(call include-path-for, frameworks-native)/media/openmax
+
+ifeq ($(USE_MEDIASDK),true)
+    LOCAL_CFLAGS += -DUSE_MEDIASDK
+endif
+
+ifeq ($(TARGET_VPP_USE_GEN),true)
+    LOCAL_CFLAGS += -DTARGET_VPP_USE_GEN
+endif
+
+LOCAL_CFLAGS += -Werror
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/ISV/base/isv_bufmanager.cpp b/ISV/base/isv_bufmanager.cpp
new file mode 100644
index 0000000..a00e4fc
--- /dev/null
+++ b/ISV/base/isv_bufmanager.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <media/hardware/HardwareAPI.h>
+#include <system/graphics.h>
+#include "isv_bufmanager.h"
+#ifndef TARGET_VPP_USE_GEN
+#include "hal_public.h"
+#endif
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "isv-omxil"
+
+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);
+        mWorker->freeSurface(&mSurface);
+    }
+}
+
+status_t ISVBuffer::initBufferInfo(uint32_t hackFormat)
+{
+    if (mType == ISV_BUFFER_METADATA) {
+        VideoDecoderOutputMetaData *metaData =
+            reinterpret_cast<VideoDecoderOutputMetaData*>(mBuffer);
+
+        if (metaData->eType != kMetadataBufferTypeGrallocSource) {
+            ALOGE("%s: unsupported meta data format eType = %d", __func__, metaData->eType);
+            return UNKNOWN_ERROR;
+        }
+
+        if (mGrallocHandle != 0) {
+            if ((unsigned long)metaData->pHandle != mGrallocHandle) {
+                if (STATUS_OK != mWorker->freeSurface(&mSurface)) {
+                    ALOGE("%s: free surface %d failed.", __func__, mSurface);
+                    return UNKNOWN_ERROR;
+                }
+            } else
+                return OK;
+        }
+        mGrallocHandle = (unsigned long)metaData->pHandle;
+    } else {
+        if (mSurface != -1)
+            return OK;
+        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
+    ufo_buffer_details_t info;
+
+    memset(&info, 0, sizeof(ufo_buffer_details_t));
+    err = mpGralloc->perform(mpGralloc, INTEL_UFO_GRALLOC_MODULE_PERFORM_GET_BO_INFO, mGrallocHandle, &info);
+
+    if (0 != err) {
+        ALOGE("%s: can't get graphic buffer info", __func__);
+    }
+    mWidth = info.width;
+    mHeight = info.height;
+    mStride = info.pitch;
+    mColorFormat = info.format;
+#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) {
+        ALOGE("%s: mWorker == NULL!!", __func__);
+        return UNKNOWN_ERROR;
+    }
+
+    if (STATUS_OK != mWorker->allocSurface(&mWidth, &mHeight, mStride, mColorFormat, mGrallocHandle, &mSurface)) {
+        ALOGE("%s: alloc surface failed, mGrallocHandle %p", __func__, mGrallocHandle);
+        return UNKNOWN_ERROR;
+    }
+
+    ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: mWidth %d, mHeight %d, mStride %d, mColorFormat %d, mGrallocHandle %p, mSurface %d",
+            __func__, mWidth, mHeight, mStride, mColorFormat, mGrallocHandle, mSurface);
+    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);
+#if 0
+    if (!mBuffers.isEmpty()) {
+        ALOGE("%s: the buffer queue should be empty before we set its size", __func__);
+        return STATUS_ERROR;
+    }
+#endif
+    mBuffers.setCapacity(size);
+
+    return OK;
+}
+
+status_t ISVBufferManager::freeBuffer(unsigned long handle)
+{
+    Mutex::Autolock autoLock(mBufferLock);
+    for (uint32_t i = 0; i < mBuffers.size(); i++) {
+        ISVBuffer* isvBuffer = mBuffers.itemAt(i);
+        if (isvBuffer->getHandle() == handle) {
+            delete isvBuffer;
+            mBuffers.removeAt(i);
+            ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: remove handle 0x%08x, and then mBuffers.size() %d", __func__,
+                    handle, mBuffers.size());
+            return OK;
+        }
+    }
+
+    ALOGW("%s: can't find buffer %u", __func__, handle);
+    return UNKNOWN_ERROR;
+}
+
+status_t ISVBufferManager::useBuffer(unsigned long handle)
+{
+    Mutex::Autolock autoLock(mBufferLock);
+    if (handle == 0 || mBuffers.size() >= mBuffers.capacity())
+        return BAD_VALUE;
+
+    for (uint32_t i = 0; i < mBuffers.size(); i++) {
+        ISVBuffer* isvBuffer = mBuffers.itemAt(i);
+        if (isvBuffer->getHandle() == handle) {
+            ALOGE("%s: this buffer 0x%08x has already been registered", __func__, handle);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    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());
+    mBuffers.push_back(isvBuffer);
+    return OK;
+
+}
+
+status_t ISVBufferManager::useBuffer(const sp<ANativeWindowBuffer> nativeBuffer)
+{
+    Mutex::Autolock autoLock(mBufferLock);
+    if (nativeBuffer == NULL || mBuffers.size() >= mBuffers.capacity())
+        return BAD_VALUE;
+
+    for (uint32_t i = 0; i < mBuffers.size(); i++) {
+        ISVBuffer* isvBuffer = mBuffers.itemAt(i);
+        if (isvBuffer->getHandle() == (unsigned long)nativeBuffer->handle) {
+            ALOGE("%s: this buffer 0x%08x has already been registered", __func__, nativeBuffer->handle);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    ISVBuffer* isvBuffer = new ISVBuffer(mWorker,
+            (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,
+            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());
+    mBuffers.push_back(isvBuffer);
+    return OK;
+}
+
+ISVBuffer* ISVBufferManager::mapBuffer(unsigned long handle)
+{
+    Mutex::Autolock autoLock(mBufferLock);
+    for (uint32_t i = 0; i < mBuffers.size(); i++) {
+        ISVBuffer* isvBuffer = mBuffers.itemAt(i);
+        if (isvBuffer->getHandle() == handle)
+            return isvBuffer;
+    }
+    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
new file mode 100644
index 0000000..990c15a
--- /dev/null
+++ b/ISV/base/isv_processor.cpp
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <math.h>
+#include <utils/Errors.h>
+#include "isv_processor.h"
+#include "isv_profile.h"
+#include "isv_omxcomponent.h"
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "isv-omxil"
+
+using namespace android;
+
+#define MAX_RETRY_NUM   10
+
+ISVProcessor::ISVProcessor(bool canCallJava,
+        sp<ISVBufferManager> bufferManager,
+        sp<ISVProcessorObserver> owner,
+        uint32_t width, uint32_t height)
+    :Thread(canCallJava),
+    mpOwner(owner),
+    mThreadId(NULL),
+    mThreadRunning(false),
+    mISVWorker(NULL),
+    mBufferManager(bufferManager),
+    mOutputProcIdx(0),
+    mInputProcIdx(0),
+    mNumTaskInProcesing(0),
+    mNumRetry(0),
+    mError(false),
+    mbFlush(false),
+    mbBypass(false),
+    mFlagEnd(false),
+    mFilters(0)
+{
+    //FIXME: for 1920 x 1088, we also consider it as 1080p
+    mISVProfile = new ISVProfile(width, (height == 1088) ? 1080 : height);
+
+    // get platform ISV cap first
+    mFilters = mISVProfile->getFilterStatus();
+
+    // turn off filters if dynamic vpp/frc setting is off
+    if (!ISVProfile::isVPPOn())
+        mFilters &= FilterFrameRateConversion;
+
+    if (!ISVProfile::isFRCOn())
+        mFilters &= ~FilterFrameRateConversion;
+
+    //FIXME: move this into profile.
+    if (width > 2048)
+        mFilters &= ~FilterSharpening;
+
+    memset(&mFilterParam, 0, sizeof(mFilterParam));
+    //FIXME: we don't support scaling yet, so set src region equal to dst region
+    mFilterParam.srcWidth = mFilterParam.dstWidth = width;
+    mFilterParam.srcHeight = mFilterParam.dstHeight = height;
+    mOutputBuffers.clear();
+    mInputBuffers.clear();
+    mTimeWindow.clear();
+}
+
+ISVProcessor::~ISVProcessor() {
+    ALOGV("ISVProcessor is deleted");
+    flush();
+    mOutputBuffers.clear();
+    mInputBuffers.clear();
+
+    mISVProfile = NULL;
+    mFilters = 0;
+    memset(&mFilterParam, 0, sizeof(mFilterParam));
+}
+
+status_t ISVProcessor::readyToRun()
+{
+    mThreadId = androidGetThreadId();
+    //do init ops here
+    return Thread::readyToRun();
+}
+
+void ISVProcessor::start()
+{
+    ALOGD_IF(ISV_THREAD_DEBUG, "ISVProcessor::start");
+
+    if (mISVWorker == NULL) {
+        mISVWorker = new ISVWorker();
+        if (STATUS_OK != mISVWorker->init(mFilterParam.srcWidth, mFilterParam.srcHeight))
+            ALOGE("%s: mISVWorker init failed", __func__);
+    }
+
+    mBufferManager->setWorker(mISVWorker);
+
+    this->run("ISVProcessor", ANDROID_PRIORITY_NORMAL);
+    mThreadRunning = true;
+    return;
+}
+
+void ISVProcessor::stop()
+{
+    ALOGD_IF(ISV_THREAD_DEBUG, "ISVProcessor::stop");
+
+    if(mThreadRunning) {
+        this->requestExit();
+        {
+            Mutex::Autolock autoLock(mLock);
+            mRunCond.signal();
+        }
+        this->requestExitAndWait();
+        mThreadRunning = false;
+    }
+
+    if (STATUS_OK != mISVWorker->deinit())
+        ALOGE("%s: mISVWorker deinit failed", __func__);
+
+    mISVWorker = NULL;
+    return;
+}
+
+bool ISVProcessor::getBufForFirmwareOutput(Vector<ISVBuffer*> *fillBufList,uint32_t *fillBufNum){
+    uint32_t i = 0;
+    // output buffer number for filling
+    *fillBufNum = 0;
+    uint32_t needFillNum = 0;
+    OMX_BUFFERHEADERTYPE *outputBuffer;
+
+    //output data available
+    needFillNum = mISVWorker->getFillBufCount();
+    if (mOutputProcIdx < needFillNum ||
+            mInputProcIdx < 1) {
+        ALOGE("%s: no enough input or output buffer which need to be sync", __func__);
+        return false;
+    }
+
+    if ((needFillNum == 0) || (needFillNum > 4))
+       return false;
+
+    Mutex::Autolock autoLock(mOutputLock);
+    for (i = 0; i < needFillNum; i++) {
+        //fetch the render buffer from the top of output buffer queue
+        outputBuffer = mOutputBuffers.itemAt(i);
+        if (!outputBuffer) {
+            ALOGE("%s: failed to fetch output buffer for sync.", __func__);
+            return false;
+        }
+        unsigned long fillHandle = reinterpret_cast<unsigned long>(outputBuffer->pBuffer);
+        ISVBuffer* fillBuf = mBufferManager->mapBuffer(fillHandle);
+        fillBufList->push_back(fillBuf);
+    }
+
+    *fillBufNum  = i;
+    return true;
+}
+
+
+status_t ISVProcessor::updateFirmwareOutputBufStatus(uint32_t fillBufNum) {
+    int64_t timeUs;
+    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__);
+        return UNKNOWN_ERROR;
+    }
+
+    if (mOutputBuffers.size() < fillBufNum) {
+        ALOGE("%s: no enough output buffer which need to be sync", __func__);
+        return UNKNOWN_ERROR;
+    }
+    // remove one buffer from intput buffer queue
+    {
+        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__);
+            return UNKNOWN_ERROR;
+        }
+
+        mInputBuffers.removeAt(0);
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: fetch buffer %u from input buffer queue for fill to decoder, and then queue size is %d", __func__,
+                inputBuffer, mInputBuffers.size());
+        mInputProcIdx--;
+    }
+
+    //set the time stamp for interpreted frames
+    {
+        Mutex::Autolock autoLock(mOutputLock);
+        timeUs = mOutputBuffers[0]->nTimeStamp;
+
+        for(uint32_t i = 0; i < fillBufNum; i++) {
+            outputBuffer = mOutputBuffers.itemAt(i);
+            if (fillBufNum > 1) {
+                if (mFilterParam.frameRate == 24) {
+                    if (fillBufNum == 2) {
+                        outputBuffer->nTimeStamp = timeUs + 1000000ll * (i + 1) / 60 - 1000000ll * 1 / 24;
+                    } else if (fillBufNum == 3) {
+                        outputBuffer->nTimeStamp = timeUs + 1000000ll * (i + 3) / 60 - 1000000ll * 2 / 24;
+                    }
+                }
+                else
+                    outputBuffer->nTimeStamp = timeUs - 1000000ll * (fillBufNum - i - 1) / (mFilterParam.frameRate * 2);
+            }
+
+            //return filled buffers for rendering
+            //skip rendering for crop change
+            err = mpOwner->releaseBuffer(kPortIndexOutput, outputBuffer, cropChanged);
+
+            if (err != OMX_ErrorNone) {
+                ALOGE("%s: failed to releaseOutputBuffer", __func__);
+                return UNKNOWN_ERROR;
+            }
+
+            ALOGD_IF(ISV_THREAD_DEBUG, "%s: fetch buffer %u(timestamp %.2f ms) from output buffer queue for render, and then queue size is %d", __func__,
+                    outputBuffer, outputBuffer->nTimeStamp/1E3, mOutputBuffers.size());
+        }
+        // remove filled buffers from output buffer queue
+        mOutputBuffers.removeItemsAt(0, fillBufNum);
+        mOutputProcIdx -= fillBufNum;
+    }
+    return OK;
+}
+
+
+bool ISVProcessor::getBufForFirmwareInput(Vector<ISVBuffer*> *procBufList,
+                                   ISVBuffer **inputBuf,
+                                   uint32_t *procBufNum)
+{
+    OMX_BUFFERHEADERTYPE *outputBuffer;
+    OMX_BUFFERHEADERTYPE *inputBuffer;
+
+    if (mbFlush) {
+        *inputBuf = NULL;
+        *procBufNum = 0;
+        return true;
+    }
+
+    int32_t procBufCount = mISVWorker->getProcBufCount();
+    if ((procBufCount == 0) || (procBufCount > 4)) {
+       return false;
+    }
+
+    //fetch a input buffer for processing
+    {
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mInputLock", __func__);
+        Mutex::Autolock autoLock(mInputLock);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mInputLock", __func__);
+        inputBuffer = mInputBuffers.itemAt(mInputProcIdx);
+        if (!inputBuffer) {
+            ALOGE("%s: failed to get input buffer for processing.", __func__);
+            return false;
+        }
+        unsigned long inputHandle = reinterpret_cast<unsigned long>(inputBuffer->pBuffer);
+        *inputBuf = mBufferManager->mapBuffer(inputHandle);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mInputLock", __func__);
+    }
+
+    //fetch output buffers for processing
+    {
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mOutputLock", __func__);
+        Mutex::Autolock autoLock(mOutputLock);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mOutputLock", __func__);
+        for (int32_t i = 0; i < procBufCount; i++) {
+            outputBuffer = mOutputBuffers.itemAt(mOutputProcIdx + i);
+            if (!outputBuffer) {
+                ALOGE("%s: failed to get output buffer for processing.", __func__);
+                return false;
+            }
+            unsigned long outputHandle = reinterpret_cast<unsigned long>(outputBuffer->pBuffer);
+            procBufList->push_back(mBufferManager->mapBuffer(outputHandle));
+        }
+        *procBufNum = procBufCount;
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mOutputLock", __func__);
+    }
+
+    return true;
+}
+
+
+status_t ISVProcessor::updateFirmwareInputBufStatus(uint32_t procBufNum)
+{
+    OMX_BUFFERHEADERTYPE *outputBuffer;
+    OMX_BUFFERHEADERTYPE *inputBuffer;
+
+    inputBuffer = mInputBuffers.itemAt(mInputProcIdx);
+    mInputProcIdx++;
+
+    Mutex::Autolock autoLock(mOutputLock);
+    for(uint32_t i = 0; i < procBufNum; i++) {
+        outputBuffer = mOutputBuffers.editItemAt(mOutputProcIdx + i);
+        // set output buffer timestamp as the same as input
+        outputBuffer->nTimeStamp = inputBuffer->nTimeStamp;
+        outputBuffer->nFilledLen = inputBuffer->nFilledLen;
+        outputBuffer->nOffset = inputBuffer->nOffset;
+        outputBuffer->nFlags = inputBuffer->nFlags;
+        //outputBuffer->nTickCount = inputBuffer->nTickCount;
+        //outputBuffer->pMarkData = intputBuffer->pMarkData;
+    }
+    mOutputProcIdx += procBufNum;
+    return OK;
+}
+
+
+bool ISVProcessor::isReadytoRun()
+{
+    ALOGD_IF(ISV_THREAD_DEBUG, "%s: mISVWorker->getProcBufCount() return %d", __func__,
+            mISVWorker->getProcBufCount());
+    if (mInputProcIdx < mInputBuffers.size() 
+            && (mOutputBuffers.size() - mOutputProcIdx) >= mISVWorker->getProcBufCount())
+       return true;
+    else
+       return false;
+}
+
+
+bool ISVProcessor::threadLoop() {
+    uint32_t procBufNum = 0, fillBufNum = 0;
+    ISVBuffer* inputBuf;
+    Vector<ISVBuffer*> procBufList;
+    Vector<ISVBuffer*> fillBufList;
+    uint32_t flags = 0;
+    bool bGetBufSuccess = true;
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (!isReadytoRun() && !mbFlush) {
+        mRunCond.wait(mLock);
+    }
+
+    if (isReadytoRun() || mbFlush) {
+        procBufList.clear();
+        bool bGetInBuf = getBufForFirmwareInput(&procBufList, &inputBuf, &procBufNum);
+        if (bGetInBuf) {
+            if (!mbFlush)
+                flags = mInputBuffers[mInputProcIdx]->nFlags;
+            status_t ret = mISVWorker->process(inputBuf, procBufList, procBufNum, mbFlush, flags);
+            if (ret == STATUS_OK) {
+                // for seek and EOS
+                if (mbFlush) {
+                    mISVWorker->reset();
+                    flush();
+
+                    mNumTaskInProcesing = 0;
+                    mInputProcIdx = 0;
+                    mOutputProcIdx = 0;
+
+                    mbFlush = false;
+
+                    Mutex::Autolock endLock(mEndLock);
+                    mEndCond.signal();
+                    return true;
+                }
+                mNumTaskInProcesing++;
+                updateFirmwareInputBufStatus(procBufNum);
+            } else {
+                mbBypass = true;
+                flush();
+                ALOGE("VSP process error %d .... ISV changes to bypass mode", __LINE__);
+            }
+        }
+    }
+
+    ALOGV("mNumTaskInProcesing %d", mNumTaskInProcesing);
+    while ((mNumTaskInProcesing > 0) && mNumTaskInProcesing >= mISVWorker->mNumForwardReferences && bGetBufSuccess ) {
+        fillBufList.clear();
+        bGetBufSuccess = getBufForFirmwareOutput(&fillBufList, &fillBufNum);
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: bGetOutput %d, buf num %d", __func__,
+                bGetBufSuccess, fillBufNum);
+        if (bGetBufSuccess) {
+            status_t ret = mISVWorker->fill(fillBufList, fillBufNum);
+            if (ret == STATUS_OK) {
+                mNumTaskInProcesing--;
+                ALOGV("mNumTaskInProcesing: %d ...", mNumTaskInProcesing);
+                updateFirmwareOutputBufStatus(fillBufNum);
+            } else {
+                mError = true;
+                ALOGE("ISV read firmware data error! Thread EXIT...");
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+bool ISVProcessor::isCurrentThread() const {
+    return mThreadId == androidGetThreadId();
+}
+
+inline bool ISVProcessor::isFrameRateValid(uint32_t fps)
+{
+    return (fps == 15 || fps == 24 || fps == 25 || fps == 30 || fps == 50 || fps == 60) ? true : false;
+}
+
+status_t ISVProcessor::configFRC(uint32_t fps)
+{
+    if (isFrameRateValid(fps)) {
+        if (fps == 50 || fps == 60) {
+            ALOGD_IF(ISV_THREAD_DEBUG, "%s: %d fps don't need do FRC, so disable FRC", __func__, fps);
+            mFilters &= ~FilterFrameRateConversion;
+            mFilterParam.frcRate = FRC_RATE_1X;
+        } else {
+            mFilterParam.frameRate = fps;
+            mFilterParam.frcRate = mISVProfile->getFRCRate(mFilterParam.frameRate);
+            ALOGD_IF(ISV_THREAD_DEBUG, "%s: fps is set to %d, frc rate is %d", __func__,
+                    mFilterParam.frameRate, mFilterParam.frcRate);
+        }
+        return OK;
+    }
+
+    return UNKNOWN_ERROR;
+}
+
+status_t ISVProcessor::calculateFps(int64_t timeStamp, uint32_t* fps)
+{
+    int32_t i = 0;
+    *fps = 0;
+
+    mTimeWindow.push_back(timeStamp);
+    if (mTimeWindow.size() > WINDOW_SIZE) {
+        mTimeWindow.removeAt(0);
+    }
+    else if (mTimeWindow.size() < WINDOW_SIZE)
+        return NOT_ENOUGH_DATA;
+
+    int64_t delta = mTimeWindow[WINDOW_SIZE-1] - mTimeWindow[0];
+    if (delta == 0)
+        return NOT_ENOUGH_DATA;
+
+    *fps = ceil(1.0 / delta * 1E6 * (WINDOW_SIZE-1));
+    return OK;
+}
+
+status_t ISVProcessor::configFilters(OMX_BUFFERHEADERTYPE* buffer)
+{
+    if ((mFilters & FilterFrameRateConversion) != 0) {
+        if (!isFrameRateValid(mFilterParam.frameRate)) {
+            if (mNumRetry++ < MAX_RETRY_NUM) {
+                uint32_t fps = 0;
+                if (OK != calculateFps(buffer->nTimeStamp, &fps))
+                    return NOT_ENOUGH_DATA;
+
+                if (OK != configFRC(fps))
+                    return NOT_ENOUGH_DATA;
+            } else {
+                ALOGD_IF(ISV_THREAD_DEBUG, "%s: exceed max retry to get a valid frame rate(%d), disable FRC", __func__,
+                        mFilterParam.frameRate);
+                mFilters &= ~FilterFrameRateConversion;
+                mFilterParam.frcRate = FRC_RATE_1X;
+            }
+        }
+    }
+
+    if ((buffer->nFlags & OMX_BUFFERFLAG_TFF) != 0 ||
+            (buffer->nFlags & OMX_BUFFERFLAG_BFF) != 0)
+        mFilters |= FilterDeinterlacing;
+    else
+        mFilters &= ~FilterDeinterlacing;
+
+    if (mFilters == 0) {
+        ALOGI("%s: no filter need to be config, bypass ISV", __func__);
+        return UNKNOWN_ERROR;
+    }
+
+    //config filters to mISVWorker
+    return (mISVWorker->configFilters(mFilters, &mFilterParam) == STATUS_OK) ? OK : UNKNOWN_ERROR;
+}
+
+void ISVProcessor::addInput(OMX_BUFFERHEADERTYPE* input)
+{
+    if (mbFlush) {
+        mpOwner->releaseBuffer(kPortIndexInput, input, true);
+        return;
+    }
+
+    if (mbBypass) {
+        // return this buffer to framework
+        mpOwner->releaseBuffer(kPortIndexOutput, input, false);
+        return;
+    }
+
+    if (input->nFlags & OMX_BUFFERFLAG_EOS) {
+        mpOwner->releaseBuffer(kPortIndexInput, input, true);
+        notifyFlush();
+        return;
+    }
+
+    status_t ret = configFilters(input);
+    if (ret == NOT_ENOUGH_DATA) {
+        // release this buffer if frc is not ready.
+        mpOwner->releaseBuffer(kPortIndexInput, input, false);
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: frc rate is not ready, release this buffer %u, fps %d", __func__,
+                input, mFilterParam.frameRate);
+        return;
+    } else if (ret == UNKNOWN_ERROR) {
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: configFilters failed, bypass ISV", __func__);
+        mbBypass = true;
+        mpOwner->releaseBuffer(kPortIndexOutput, input, false);
+        return;
+    }
+
+    {
+        //put the decoded buffer into fill buffer queue
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mInputLock", __func__);
+        Mutex::Autolock autoLock(mInputLock);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mInputLock", __func__);
+
+        mInputBuffers.push_back(input);
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: hold pBuffer %u in input buffer queue. Intput queue size is %d, mInputProIdx %d.\
+                Output queue size is %d, mOutputProcIdx %d", __func__,
+                input, mInputBuffers.size(), mInputProcIdx,
+                mOutputBuffers.size(), mOutputProcIdx);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mInputLock", __func__);
+    }
+
+    {
+        Mutex::Autolock autoLock(mLock);
+        mRunCond.signal();
+    }
+    return;
+}
+
+void ISVProcessor::addOutput(OMX_BUFFERHEADERTYPE* output)
+{
+    if (mbFlush) {
+        mpOwner->releaseBuffer(kPortIndexOutput, output, true);
+        return;
+    }
+
+    if (mbBypass || mOutputBuffers.size() >= MIN_OUTPUT_NUM) {
+        // return this buffer to decoder
+        mpOwner->releaseBuffer(kPortIndexInput, output, false);
+        return;
+    }
+
+    {
+        //push the buffer into the output queue if it is not full
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mOutputLock", __func__);
+        Mutex::Autolock autoLock(mOutputLock);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mOutputLock", __func__);
+
+        mOutputBuffers.push_back(output);
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: hold pBuffer %u in output buffer queue. Input queue size is %d, mInputProIdx %d.\
+                Output queue size is %d, mOutputProcIdx %d", __func__,
+                output, mInputBuffers.size(), mInputProcIdx,
+                mOutputBuffers.size(), mOutputProcIdx);
+        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mOutputLock", __func__);
+    }
+
+    {
+        Mutex::Autolock autoLock(mLock);
+        mRunCond.signal();
+    }
+    return;
+}
+
+void ISVProcessor::notifyFlush()
+{
+    if (mInputBuffers.empty() && mOutputBuffers.empty()) {
+        ALOGD_IF(ISV_THREAD_DEBUG, "%s: input and ouput buffer queue is empty, nothing need to do", __func__);
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    mbFlush = true;
+    mRunCond.signal();
+    ALOGD_IF(ISV_THREAD_DEBUG, "wake up proc thread");
+    return;
+}
+
+void ISVProcessor::waitFlushFinished()
+{
+    Mutex::Autolock endLock(mEndLock);
+    ALOGD_IF(ISV_THREAD_DEBUG, "waiting mEnd lock(seek finish) ");
+    while(mbFlush) {
+        mEndCond.wait(mEndLock);
+    }
+    return;
+}
+
+void ISVProcessor::flush()
+{
+    OMX_BUFFERHEADERTYPE* pBuffer = NULL;
+    {
+        Mutex::Autolock autoLock(mInputLock);
+        while (!mInputBuffers.empty()) {
+            pBuffer = mInputBuffers.itemAt(0);
+            mpOwner->releaseBuffer(kPortIndexInput, pBuffer, true);
+            ALOGD_IF(ISV_THREAD_DEBUG, "%s: Flush the pBuffer %u in input buffer queue.", __func__, pBuffer);
+            mInputBuffers.removeAt(0);
+        }
+    }
+    {
+        Mutex::Autolock autoLock(mOutputLock);
+        while (!mOutputBuffers.empty()) {
+            pBuffer = mOutputBuffers.itemAt(0);
+            mpOwner->releaseBuffer(kPortIndexOutput, pBuffer, true);
+            ALOGD_IF(ISV_THREAD_DEBUG, "%s: Flush the pBuffer %u in output buffer queue.", __func__, pBuffer);
+            mOutputBuffers.removeAt(0);
+        }
+    }
+    //flush finished.
+    return;
+}
diff --git a/ISV/base/isv_worker.cpp b/ISV/base/isv_worker.cpp
new file mode 100644
index 0000000..3f699a5
--- /dev/null
+++ b/ISV/base/isv_worker.cpp
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <cutils/properties.h>
+#include <system/graphics.h>
+#include "isv_worker.h"
+#ifndef TARGET_VPP_USE_GEN
+#include <hal_public.h>
+#else
+#include <ufo/graphics.h>
+#endif
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "isv-omxil"
+
+#define CHECK_VASTATUS(str) \
+    do { \
+        if (vaStatus != VA_STATUS_SUCCESS) { \
+                ALOGE("%s failed\n", str); \
+                return STATUS_ERROR;}   \
+        }while(0);
+
+enum STRENGTH {
+    STRENGTH_LOW = 0,
+    STRENGTH_MEDIUM,
+    STRENGTH_HIGH
+};
+
+#define DENOISE_DEBLOCK_STRENGTH STRENGTH_MEDIUM
+#define COLOR_STRENGTH STRENGTH_MEDIUM
+#ifdef TARGET_VPP_USE_GEN
+#define COLOR_NUM 4
+#else
+#define COLOR_NUM 2
+#endif
+
+#define MAX_FRC_OUTPUT 4 /*for frcx4*/
+
+using namespace android;
+
+ISVWorker::ISVWorker()
+    :mNumForwardReferences(0),
+    mVAContext(VA_INVALID_ID),
+    mWidth(0), mHeight(0),
+    mDisplay(NULL), mVADisplay(NULL),
+    mVAConfig(VA_INVALID_ID),
+    mForwardReferences(NULL),
+    mPrevInput(0), mPrevOutput(0),
+    mNumFilterBuffers(0),
+    mFilterFrc(VA_INVALID_ID), mFilters(0),
+    mInputIndex(0), mOutputIndex(0),
+    mOutputCount(0) {
+    memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
+    memset(&mFilterParam, 0, sizeof(mFilterParam));
+}
+
+bool ISVWorker::isSupport() const {
+    bool support = false;
+
+    int num_entrypoints = vaMaxNumEntrypoints(mVADisplay);
+    VAEntrypoint * entrypoints = (VAEntrypoint *)malloc(num_entrypoints * sizeof(VAEntrypoint));
+    if (entrypoints == NULL) {
+        ALOGE("failed to malloc entrypoints array\n");
+        return false;
+    }
+
+    // check if it contains VPP entry point VAEntrypointVideoProc
+    VAStatus vaStatus = vaQueryConfigEntrypoints(mVADisplay, VAProfileNone, entrypoints, &num_entrypoints);
+    if (vaStatus != VA_STATUS_SUCCESS) {
+        ALOGE("vaQueryConfigEntrypoints failed");
+        return false;
+    }
+    for (int i = 0; !support && i < num_entrypoints; i++) {
+        support = entrypoints[i] == VAEntrypointVideoProc;
+    }
+    free(entrypoints);
+    entrypoints = NULL;
+
+    return support;
+}
+
+uint32_t ISVWorker::getProcBufCount() {
+    return getOutputBufCount(mInputIndex);
+}
+
+uint32_t ISVWorker::getFillBufCount() {
+        return getOutputBufCount(mOutputIndex);
+}
+
+uint32_t ISVWorker::getOutputBufCount(uint32_t index) {
+    uint32_t bufCount = 1;
+    if (((mFilters & FilterFrameRateConversion) != 0)
+            && index > 0)
+            bufCount = mFilterParam.frcRate - (((mFilterParam.frcRate == FRC_RATE_2_5X) ? (index & 1): 0));
+    return bufCount;
+}
+
+
+status_t ISVWorker::init(uint32_t width, uint32_t height) {
+    ALOGV("init");
+
+    if (mDisplay != NULL) {
+        ALOGE("VA is particially started");
+        return STATUS_ERROR;
+    }
+    mDisplay = new Display;
+    *mDisplay = ANDROID_DISPLAY_HANDLE;
+
+    mVADisplay = vaGetDisplay(mDisplay);
+    if (mVADisplay == NULL) {
+        ALOGE("vaGetDisplay failed");
+        return STATUS_ERROR;
+    }
+
+    int majorVersion, minorVersion;
+    VAStatus vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
+    CHECK_VASTATUS("vaInitialize");
+
+    // Check if VPP entry point is supported
+    if (!isSupport()) {
+        ALOGE("VPP is not supported on current platform");
+        return STATUS_NOT_SUPPORT;
+    }
+
+    // Find out the format for the target
+    VAConfigAttrib attrib;
+    attrib.type = VAConfigAttribRTFormat;
+    vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileNone, VAEntrypointVideoProc, &attrib, 1);
+    CHECK_VASTATUS("vaGetConfigAttributes");
+
+    if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
+        ALOGE("attribute is %x vs wanted %x", attrib.value, VA_RT_FORMAT_YUV420);
+        return STATUS_NOT_SUPPORT;
+    }
+
+    ALOGV("ready to create config");
+    // Create the configuration
+    vaStatus = vaCreateConfig(mVADisplay, VAProfileNone, VAEntrypointVideoProc, &attrib, 1, &mVAConfig);
+    CHECK_VASTATUS("vaCreateConfig");
+
+
+    // Create Context
+    ALOGV("ready to create context");
+    mWidth = width;
+    mHeight = height;
+    vaStatus = vaCreateContext(mVADisplay, mVAConfig, mWidth, mHeight, 0, NULL, 0, &mVAContext);
+    CHECK_VASTATUS("vaCreateContext");
+
+    ALOGV("VA has been successfully started");
+    return STATUS_OK;
+}
+
+status_t ISVWorker::deinit() {
+    {
+        Mutex::Autolock autoLock(mPipelineBufferLock);
+        while (!mPipelineBuffers.isEmpty()) {
+            VABufferID pipelineBuffer = mPipelineBuffers.itemAt(0);
+            if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineBuffer))
+                ALOGW("%s: failed to destroy va buffer id %d", __func__, pipelineBuffer);
+            mPipelineBuffers.removeAt(0);
+        }
+    }
+
+    if (mNumFilterBuffers != 0) {
+        for (uint32_t i = 0; i < mNumFilterBuffers; i++) {
+            if(VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, mFilterBuffers[i]))
+                ALOGW("%s: failed to destroy va buffer id %d", __func__, mFilterBuffers[i]);
+        }
+        mNumFilterBuffers = 0;
+        memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
+        mFilterFrc = VA_INVALID_ID;
+    }
+
+    if (mForwardReferences != NULL) {
+        free(mForwardReferences);
+        mForwardReferences = NULL;
+        mNumForwardReferences = 0;
+    }
+
+    if (mVAContext != VA_INVALID_ID) {
+         vaDestroyContext(mVADisplay, mVAContext);
+         mVAContext = VA_INVALID_ID;
+    }
+
+    if (mVAConfig != VA_INVALID_ID) {
+        vaDestroyConfig(mVADisplay, mVAConfig);
+        mVAConfig = VA_INVALID_ID;
+    }
+
+    if (mVADisplay) {
+        vaTerminate(mVADisplay);
+        mVADisplay = NULL;
+    }
+
+    if (mDisplay) {
+        delete mDisplay;
+        mDisplay = NULL;
+    }
+
+    return STATUS_OK;
+}
+
+status_t ISVWorker::allocSurface(uint32_t* width, uint32_t* height,
+        uint32_t stride, uint32_t format, unsigned long handle, int32_t* surfaceId)
+{
+    if (mWidth == 0 || mHeight == 0) {
+        ALOGE("%s: isv worker has not been initialized.", __func__);
+        return STATUS_ERROR;
+    }
+
+#ifndef TARGET_VPP_USE_GEN
+    *width = mWidth;
+    *height = mHeight;
+#endif
+    // Create VASurfaces
+    VASurfaceAttrib attribs[3];
+    VASurfaceAttribExternalBuffers vaExtBuf;
+
+    memset(&vaExtBuf, 0, sizeof(VASurfaceAttribExternalBuffers));
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YV12:
+            vaExtBuf.pixel_format = VA_FOURCC_YV12;
+            vaExtBuf.num_planes = 3;
+            vaExtBuf.pitches[0] = stride;
+            vaExtBuf.pitches[1] = stride / 2;
+            vaExtBuf.pitches[2] = stride / 2;
+            vaExtBuf.pitches[3] = 0;
+            vaExtBuf.offsets[0] = 0;
+            vaExtBuf.offsets[1] = stride * *height;
+            vaExtBuf.offsets[2] = vaExtBuf.offsets[1] + (stride / 2) * (*height / 2);
+            vaExtBuf.offsets[3] = 0;
+            break;
+#ifdef TARGET_VPP_USE_GEN
+        case HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL:
+        case HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL:
+        //it will be removed in future, it indicate the same format with HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL
+        case HAL_PIXEL_FORMAT_YUV420PackedSemiPlanar_Tiled_INTEL:
+#else
+        case HAL_PIXEL_FORMAT_NV12_VED:
+        case HAL_PIXEL_FORMAT_NV12_VEDT:
+#endif
+            vaExtBuf.pixel_format = VA_FOURCC_NV12;
+            vaExtBuf.num_planes = 2;
+            vaExtBuf.pitches[0] = stride;
+            vaExtBuf.pitches[1] = stride;
+            vaExtBuf.pitches[2] = 0;
+            vaExtBuf.pitches[3] = 0;
+            vaExtBuf.offsets[0] = 0;
+            vaExtBuf.offsets[1] = stride * *height;
+            vaExtBuf.offsets[2] = 0;
+            vaExtBuf.offsets[3] = 0;
+            break;
+        default:
+            ALOGE("%s: can't support this format 0x%08x", __func__, format);
+            return STATUS_ERROR;
+    }
+    vaExtBuf.width = *width;
+    vaExtBuf.height = *height;
+    vaExtBuf.data_size = stride * *height * 1.5;
+    vaExtBuf.num_buffers = 1;
+#ifndef TARGET_VPP_USE_GEN
+    if (format == HAL_PIXEL_FORMAT_NV12_VEDT) {
+        ALOGV("set TILING flag");
+        vaExtBuf.flags |= VA_SURFACE_EXTBUF_DESC_ENABLE_TILING;
+    }
+#endif
+    vaExtBuf.flags |= VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
+    vaExtBuf.buffers = (long unsigned int*)&handle;
+
+    attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
+    attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attribs[0].value.type = VAGenericValueTypeInteger;
+    attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
+
+    attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
+    attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attribs[1].value.type = VAGenericValueTypePointer;
+    attribs[1].value.value.p = &vaExtBuf;
+
+    attribs[2].type = (VASurfaceAttribType)VASurfaceAttribUsageHint;
+    attribs[2].flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attribs[2].value.type = VAGenericValueTypeInteger;
+    attribs[2].value.value.i = VA_SURFACE_ATTRIB_USAGE_HINT_VPP_READ;
+
+    ALOGV("%s: Ext buffer: width %d, height %d, data_size %d, pitch %d", __func__,
+            vaExtBuf.width, vaExtBuf.height, vaExtBuf.data_size, vaExtBuf.pitches[0]);
+    VAStatus vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420, vaExtBuf.width,
+                                 vaExtBuf.height, (VASurfaceID*)surfaceId, 1, attribs, 3);
+    CHECK_VASTATUS("vaCreateSurfaces");
+
+    return (vaStatus == VA_STATUS_SUCCESS) ? STATUS_OK : STATUS_ERROR;
+}
+
+status_t ISVWorker::freeSurface(int32_t* surfaceId)
+{
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    vaDestroySurfaces(mVADisplay, (VASurfaceID*)surfaceId, 1);
+    CHECK_VASTATUS("vaDestroySurfaces");
+
+    return (vaStatus == VA_STATUS_SUCCESS) ? STATUS_OK : STATUS_ERROR;
+}
+
+status_t ISVWorker::configFilters(uint32_t filters,
+                                  const FilterParam* filterParam)
+{
+    status_t ret = STATUS_OK;
+
+    if (!filterParam) {
+        ALOGE("%s: invalid filterParam", __func__);
+        return STATUS_ERROR;
+    }
+
+    if (filters != 0) {
+        mFilterParam.srcWidth = filterParam->srcWidth;
+        mFilterParam.srcHeight = filterParam->srcHeight;
+        mFilterParam.dstWidth = filterParam->dstWidth;
+        mFilterParam.dstHeight = filterParam->dstHeight;
+        mFilterParam.frameRate = filterParam->frameRate;
+        mFilterParam.frcRate = filterParam->frcRate;
+    }
+
+    if (mFilters != filters) {
+        mFilters = filters;
+        ALOGI("%s: mFilters 0x%x, fps %d, frc rate %d", __func__, mFilters, mFilterParam.frameRate, mFilterParam.frcRate);
+        ret = setupFilters();
+    }
+
+    return ret;
+}
+
+bool ISVWorker::isFpsSupport(int32_t fps, int32_t *fpsSet, int32_t fpsSetCnt) {
+    bool ret = false;
+    for (int32_t i = 0; i < fpsSetCnt; i++) {
+        if (fps == fpsSet[i]) {
+            ret = true;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+status_t ISVWorker::setupFilters() {
+    ALOGV("setupFilters");
+    VAProcFilterParameterBuffer deblock, denoise, sharpen, stde;
+    VAProcFilterParameterBufferDeinterlacing deint;
+    VAProcFilterParameterBufferColorBalance color[COLOR_NUM];
+    VAProcFilterParameterBufferFrameRateConversion frc;
+    VABufferID deblockId, denoiseId, deintId, sharpenId, colorId, frcId, stdeId;
+    uint32_t numCaps;
+    VAProcFilterCap deblockCaps, denoiseCaps, sharpenCaps, frcCaps, stdeCaps;
+    VAProcFilterCapDeinterlacing deinterlacingCaps[VAProcDeinterlacingCount];
+    VAProcFilterCapColorBalance colorCaps[COLOR_NUM];
+    VAStatus vaStatus;
+    uint32_t numSupportedFilters = VAProcFilterCount;
+    VAProcFilterType supportedFilters[VAProcFilterCount];
+
+    if (mNumFilterBuffers != 0) {
+        for (uint32_t i = 0; i < mNumFilterBuffers; i++) {
+            if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, mFilterBuffers[i]))
+                ALOGW("%s: failed to destroy va buffer %d", __func__, mFilterBuffers[i]);
+                //return STATUS_ERROR;
+        }
+        memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
+        mFilterFrc = VA_INVALID_ID;
+        mNumFilterBuffers = 0;
+    }
+
+    // query supported filters
+    vaStatus = vaQueryVideoProcFilters(mVADisplay, mVAContext, supportedFilters, &numSupportedFilters);
+    CHECK_VASTATUS("vaQueryVideoProcFilters");
+
+    // create filter buffer for each filter
+    for (uint32_t i = 0; i < numSupportedFilters; i++) {
+        switch (supportedFilters[i]) {
+            case VAProcFilterDeblocking:
+                if ((mFilters & FilterDeblocking) != 0) {
+                    // check filter caps
+                    numCaps = 1;
+                    vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
+                            VAProcFilterDeblocking,
+                            &deblockCaps,
+                            &numCaps);
+                    CHECK_VASTATUS("vaQueryVideoProcFilterCaps for deblocking");
+                    // create parameter buffer
+                    deblock.type = VAProcFilterDeblocking;
+                    deblock.value = deblockCaps.range.min_value + DENOISE_DEBLOCK_STRENGTH * deblockCaps.range.step;
+                    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                        VAProcFilterParameterBufferType, sizeof(deblock), 1,
+                        &deblock, &deblockId);
+                    CHECK_VASTATUS("vaCreateBuffer for deblocking");
+                    mFilterBuffers[mNumFilterBuffers] = deblockId;
+                    mNumFilterBuffers++;
+                }
+                break;
+            case VAProcFilterNoiseReduction:
+                if((mFilters & FilterNoiseReduction) != 0) {
+                    // check filter caps
+                    numCaps = 1;
+                    vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
+                            VAProcFilterNoiseReduction,
+                            &denoiseCaps,
+                            &numCaps);
+                    CHECK_VASTATUS("vaQueryVideoProcFilterCaps for denoising");
+                    // create parameter buffer
+                    denoise.type = VAProcFilterNoiseReduction;
+#ifdef TARGET_VPP_USE_GEN
+                    char propValueString[PROPERTY_VALUE_MAX];
+
+                    // placeholder for vpg driver: can't support denoise factor auto adjust, so leave config to user.
+                    property_get("vpp.filter.denoise.factor", propValueString, "64.0");
+                    denoise.value = atof(propValueString);
+                    denoise.value = (denoise.value < 0.0f) ? 0.0f : denoise.value;
+                    denoise.value = (denoise.value > 64.0f) ? 64.0f : denoise.value;
+#else
+                    denoise.value = denoiseCaps.range.min_value + DENOISE_DEBLOCK_STRENGTH * denoiseCaps.range.step;
+#endif
+                    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                        VAProcFilterParameterBufferType, sizeof(denoise), 1,
+                        &denoise, &denoiseId);
+                    CHECK_VASTATUS("vaCreateBuffer for denoising");
+                    mFilterBuffers[mNumFilterBuffers] = denoiseId;
+                    mNumFilterBuffers++;
+                }
+                break;
+            case VAProcFilterDeinterlacing:
+                if ((mFilters & FilterDeinterlacing) != 0) {
+                    numCaps = VAProcDeinterlacingCount;
+                    vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
+                            VAProcFilterDeinterlacing,
+                            &deinterlacingCaps[0],
+                            &numCaps);
+                    CHECK_VASTATUS("vaQueryVideoProcFilterCaps for deinterlacing");
+                    for (uint32_t i = 0; i < numCaps; i++)
+                    {
+                        VAProcFilterCapDeinterlacing * const cap = &deinterlacingCaps[i];
+                        if (cap->type != VAProcDeinterlacingBob) // desired Deinterlacing Type
+                            continue;
+
+                        deint.type = VAProcFilterDeinterlacing;
+                        deint.algorithm = VAProcDeinterlacingBob;
+                        vaStatus = vaCreateBuffer(mVADisplay,
+                                mVAContext,
+                                VAProcFilterParameterBufferType,
+                                sizeof(deint), 1,
+                                &deint, &deintId);
+                        CHECK_VASTATUS("vaCreateBuffer for deinterlacing");
+                        mFilterBuffers[mNumFilterBuffers] = deintId;
+                        mNumFilterBuffers++;
+                    }
+                }
+                break;
+            case VAProcFilterSharpening:
+                if((mFilters & FilterSharpening) != 0) {
+                    // check filter caps
+                    numCaps = 1;
+                    vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
+                            VAProcFilterSharpening,
+                            &sharpenCaps,
+                            &numCaps);
+                    CHECK_VASTATUS("vaQueryVideoProcFilterCaps for sharpening");
+                    // create parameter buffer
+                    sharpen.type = VAProcFilterSharpening;
+#ifdef TARGET_VPP_USE_GEN
+                    char propValueString[PROPERTY_VALUE_MAX];
+
+                    // placeholder for vpg driver: can't support sharpness factor auto adjust, so leave config to user.
+                    property_get("vpp.filter.sharpen.factor", propValueString, "8.0");
+                    sharpen.value = atof(propValueString);
+                    sharpen.value = (sharpen.value < 0.0f) ? 0.0f : sharpen.value;
+                    sharpen.value = (sharpen.value > 64.0f) ? 64.0f : sharpen.value;
+#else
+                    sharpen.value = sharpenCaps.range.default_value;
+#endif
+                    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                        VAProcFilterParameterBufferType, sizeof(sharpen), 1,
+                        &sharpen, &sharpenId);
+                    CHECK_VASTATUS("vaCreateBuffer for sharpening");
+                    mFilterBuffers[mNumFilterBuffers] = sharpenId;
+                    mNumFilterBuffers++;
+                }
+                break;
+            case VAProcFilterColorBalance:
+                if((mFilters & FilterColorBalance) != 0) {
+                    uint32_t featureCount = 0;
+                    // check filter caps
+                    // FIXME: it's not used at all!
+                    numCaps = COLOR_NUM;
+                    vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
+                            VAProcFilterColorBalance,
+                            colorCaps,
+                            &numCaps);
+                    CHECK_VASTATUS("vaQueryVideoProcFilterCaps for color balance");
+                    // create parameter buffer
+                    for (uint32_t i = 0; i < numCaps; i++) {
+                        if (colorCaps[i].type == VAProcColorBalanceAutoSaturation) {
+                            color[i].type = VAProcFilterColorBalance;
+                            color[i].attrib = VAProcColorBalanceAutoSaturation;
+                            color[i].value = colorCaps[i].range.min_value + COLOR_STRENGTH * colorCaps[i].range.step;
+                            featureCount++;
+                        }
+                        else if (colorCaps[i].type == VAProcColorBalanceAutoBrightness) {
+                            color[i].type = VAProcFilterColorBalance;
+                            color[i].attrib = VAProcColorBalanceAutoBrightness;
+                            color[i].value = colorCaps[i].range.min_value + COLOR_STRENGTH * colorCaps[i].range.step;
+                            featureCount++;
+                        }
+                    }
+#ifdef TARGET_VPP_USE_GEN
+                    //TODO: VPG need to support check input value by colorCaps.
+                    enum {kHue = 0, kSaturation, kBrightness, kContrast};
+                    char propValueString[PROPERTY_VALUE_MAX];
+                    color[kHue].type = VAProcFilterColorBalance;
+                    color[kHue].attrib = VAProcColorBalanceHue;
+
+                    // placeholder for vpg driver: can't support auto color balance, so leave config to user.
+                    property_get("vpp.filter.procamp.hue", propValueString, "179.0");
+                    color[kHue].value = atof(propValueString);
+                    color[kHue].value = (color[kHue].value < -180.0f) ? -180.0f : color[kHue].value;
+                    color[kHue].value = (color[kHue].value > 180.0f) ? 180.0f : color[kHue].value;
+                    featureCount++;
+
+                    color[kSaturation].type   = VAProcFilterColorBalance;
+                    color[kSaturation].attrib = VAProcColorBalanceSaturation;
+                    property_get("vpp.filter.procamp.saturation", propValueString, "1.0");
+                    color[kSaturation].value = atof(propValueString);
+                    color[kSaturation].value = (color[kSaturation].value < 0.0f) ? 0.0f : color[kSaturation].value;
+                    color[kSaturation].value = (color[kSaturation].value > 10.0f) ? 10.0f : color[kSaturation].value;
+                    featureCount++;
+
+                    color[kBrightness].type   = VAProcFilterColorBalance;
+                    color[kBrightness].attrib = VAProcColorBalanceBrightness;
+                    property_get("vpp.filter.procamp.brightness", propValueString, "0.0");
+                    color[kBrightness].value = atof(propValueString);
+                    color[kBrightness].value = (color[kBrightness].value < -100.0f) ? -100.0f : color[kBrightness].value;
+                    color[kBrightness].value = (color[kBrightness].value > 100.0f) ? 100.0f : color[kBrightness].value;
+                    featureCount++;
+
+                    color[kContrast].type   = VAProcFilterColorBalance;
+                    color[kContrast].attrib = VAProcColorBalanceContrast;
+                    property_get("vpp.filter.procamp.contrast", propValueString, "1.0");
+                    color[kContrast].value = atof(propValueString);
+                    color[kContrast].value = (color[kContrast].value < 0.0f) ? 0.0f : color[kContrast].value;
+                    color[kContrast].value = (color[kContrast].value > 10.0f) ? 10.0f : color[kContrast].value;
+                    featureCount++;
+#endif
+                    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                        VAProcFilterParameterBufferType, sizeof(*color), featureCount,
+                        color, &colorId);
+                    CHECK_VASTATUS("vaCreateBuffer for color balance");
+                    mFilterBuffers[mNumFilterBuffers] = colorId;
+                    mNumFilterBuffers++;
+                }
+                break;
+            case VAProcFilterFrameRateConversion:
+                if((mFilters & FilterFrameRateConversion) != 0) {
+                    frc.type = VAProcFilterFrameRateConversion;
+                    frc.input_fps = mFilterParam.frameRate;
+                    switch (mFilterParam.frcRate){
+                        case FRC_RATE_1X:
+                            frc.output_fps = frc.input_fps;
+                            break;
+                        case FRC_RATE_2X:
+                            frc.output_fps = frc.input_fps * 2;
+                            break;
+                        case FRC_RATE_2_5X:
+                            frc.output_fps = frc.input_fps * 5/2;
+                            break;
+                        case FRC_RATE_4X:
+                            frc.output_fps = frc.input_fps * 4;
+                            break;
+                    }
+                    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                        VAProcFilterParameterBufferType, sizeof(frc), 1,
+                        &frc, &frcId);
+                    CHECK_VASTATUS("vaCreateBuffer for frc");
+                    mFilterBuffers[mNumFilterBuffers] = frcId;
+                    mNumFilterBuffers++;
+                    mFilterFrc = frcId;
+                }
+                break;
+            case VAProcFilterSkinToneEnhancement:
+                if((mFilters & FilterSkinToneEnhancement) != 0) {
+                    // check filter caps
+                    numCaps = 1;
+                    vaStatus = vaQueryVideoProcFilterCaps(mVADisplay, mVAContext,
+                            VAProcFilterSkinToneEnhancement,
+                            &stdeCaps,
+                            &numCaps);
+                    CHECK_VASTATUS("vaQueryVideoProcFilterCaps for skintone");
+                    // create parameter buffer
+                    stde.type = VAProcFilterSkinToneEnhancement;
+#ifdef TARGET_VPP_USE_GEN
+                    char propValueString[PROPERTY_VALUE_MAX];
+
+                    // placeholder for vpg driver: can't support skintone factor auto adjust, so leave config to user.
+                    property_get("vpp.filter.skintone.factor", propValueString, "8.0");
+                    stde.value = atof(propValueString);
+                    stde.value = (stde.value < 0.0f) ? 0.0f : stde.value;
+                    stde.value = (stde.value > 8.0f) ? 8.0f : stde.value;
+#else
+                    stde.value = stdeCaps.range.default_value;
+#endif
+                    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                        VAProcFilterParameterBufferType, sizeof(stde), 1,
+                        &stde, &stdeId);
+                    CHECK_VASTATUS("vaCreateBuffer for skintone");
+                    mFilterBuffers[mNumFilterBuffers] = stdeId;
+                    mNumFilterBuffers++;
+                }
+                break;
+            default:
+                ALOGW("%s: Not supported filter 0x%08x", __func__, supportedFilters[i]);
+                break;
+        }
+    }
+
+    return setupPipelineCaps();
+}
+
+status_t ISVWorker::setupPipelineCaps() {
+    ALOGV("setupPipelineCaps");
+    //TODO color standards
+    VAProcPipelineCaps pipelineCaps;
+    VAStatus vaStatus;
+    pipelineCaps.input_color_standards = in_color_standards;
+    pipelineCaps.num_input_color_standards = VAProcColorStandardCount;
+    pipelineCaps.output_color_standards = out_color_standards;
+    pipelineCaps.num_output_color_standards = VAProcColorStandardCount;
+
+    vaStatus = vaQueryVideoProcPipelineCaps(mVADisplay, mVAContext,
+        mFilterBuffers, mNumFilterBuffers,
+        &pipelineCaps);
+    CHECK_VASTATUS("vaQueryVideoProcPipelineCaps");
+
+    if (mForwardReferences != NULL) {
+        free(mForwardReferences);
+        mForwardReferences = NULL;
+        mNumForwardReferences = 0;
+    }
+
+    mNumForwardReferences = pipelineCaps.num_forward_references;
+    if (mNumForwardReferences > 0) {
+        mForwardReferences = (VASurfaceID*)malloc(mNumForwardReferences * sizeof(VASurfaceID));
+        if (mForwardReferences == NULL)
+            return STATUS_ALLOCATION_ERROR;
+        memset(mForwardReferences, 0, mNumForwardReferences * sizeof(VASurfaceID));
+    }
+    return STATUS_OK;
+}
+
+status_t ISVWorker::process(ISVBuffer* inputBuffer, Vector<ISVBuffer*> outputBuffer,
+                             uint32_t outputCount, bool isEOS, uint32_t flags) {
+    ALOGV("process: outputCount=%d, mInputIndex=%d", outputCount, mInputIndex);
+    VASurfaceID input;
+    VASurfaceID output[MAX_FRC_OUTPUT];
+    VABufferID pipelineId;
+    VAProcPipelineParameterBuffer *pipeline;
+    VAProcFilterParameterBufferFrameRateConversion *frc;
+    VAStatus vaStatus = STATUS_OK;
+    uint32_t i = 0;
+
+    if (isEOS) {
+        if (mInputIndex == 0) {
+            ALOGV("%s: don't need to flush VSP", __func__);
+            return STATUS_OK;
+        }
+        input = VA_INVALID_SURFACE;
+        outputCount = 1;
+        output[0] = mPrevOutput;
+    } else {
+        if (!inputBuffer || outputBuffer.size() != outputCount) {
+            ALOGE("%s: invalid input/output buffer", __func__);
+            return STATUS_ERROR;
+        }
+
+        if (outputCount < 1 || outputCount > 4) {
+            ALOGE("%s: invalid outputCount", __func__);
+            return STATUS_ERROR;
+        }
+
+        input = inputBuffer->getSurface();
+        for (i = 0; i < outputCount; i++) {
+            output[i] = outputBuffer[i]->getSurface();
+            if (output[i] == VA_INVALID_SURFACE) {
+                ALOGE("invalid output buffer");
+                return STATUS_ERROR;
+            }
+        }
+    }
+
+    // reference frames setting
+    if (mNumForwardReferences > 0) {
+        /* add previous frame into reference array*/
+        for (i = 1; i < mNumForwardReferences; i++) {
+            mForwardReferences[i - 1] = mForwardReferences[i];
+        }
+
+        //make last reference to input
+        mForwardReferences[mNumForwardReferences - 1] = mPrevInput;
+    }
+
+    mPrevInput = input;
+
+    // create pipeline parameter buffer
+    vaStatus = vaCreateBuffer(mVADisplay,
+            mVAContext,
+            VAProcPipelineParameterBufferType,
+            sizeof(VAProcPipelineParameterBuffer),
+            1,
+            NULL,
+            &pipelineId);
+    CHECK_VASTATUS("vaCreateBuffer for VAProcPipelineParameterBufferType");
+
+    ALOGV("before vaBeginPicture");
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, output[0]);
+    CHECK_VASTATUS("vaBeginPicture");
+
+    // map pipeline paramter buffer
+    vaStatus = vaMapBuffer(mVADisplay, pipelineId, (void**)&pipeline);
+    CHECK_VASTATUS("vaMapBuffer for pipeline parameter buffer");
+
+    // frc pamameter setting
+    if ((mFilters & FilterFrameRateConversion) != 0) {
+        vaStatus = vaMapBuffer(mVADisplay, mFilterFrc, (void **)&frc);
+        CHECK_VASTATUS("vaMapBuffer for frc parameter buffer");
+        if (isEOS)
+            frc->num_output_frames = 0;
+        else
+            frc->num_output_frames = outputCount - 1;
+        frc->output_frames = output + 1;
+    }
+
+    // pipeline parameter setting
+    VARectangle dst_region;
+    dst_region.x = 0;
+    dst_region.y = 0;
+    dst_region.width = mFilterParam.dstWidth;
+    dst_region.height = mFilterParam.dstHeight;
+
+    VARectangle src_region;
+    src_region.x = 0;
+    src_region.y = 0;
+    src_region.width = mFilterParam.srcWidth;
+    src_region.height = mFilterParam.srcHeight;
+
+    if (isEOS) {
+        pipeline->surface = 0;
+        pipeline->pipeline_flags = VA_PIPELINE_FLAG_END;
+    }
+    else {
+        pipeline->surface = input;
+        pipeline->pipeline_flags = 0;
+    }
+#ifdef TARGET_VPP_USE_GEN
+    pipeline->surface_region = &src_region;
+    pipeline->output_region = &dst_region;
+    pipeline->surface_color_standard = VAProcColorStandardBT601;
+    pipeline->output_color_standard = VAProcColorStandardBT601;
+#else
+    pipeline->surface_region = NULL;
+    pipeline->output_region = NULL;//&output_region;
+    pipeline->surface_color_standard = VAProcColorStandardNone;
+    pipeline->output_color_standard = VAProcColorStandardNone;
+    /* real rotate state will be decided in psb video */
+    pipeline->rotation_state = 0;
+#endif
+    /* FIXME: set more meaningful background color */
+    pipeline->output_background_color = 0;
+    pipeline->filters = mFilterBuffers;
+    pipeline->num_filters = mNumFilterBuffers;
+    pipeline->forward_references = mForwardReferences;
+    pipeline->num_forward_references = mNumForwardReferences;
+    pipeline->backward_references = NULL;
+    pipeline->num_backward_references = 0;
+
+    //currently, we only transfer TOP field to frame, no frame rate change.
+    if (flags & (OMX_BUFFERFLAG_TFF | OMX_BUFFERFLAG_BFF)) {
+        pipeline->filter_flags = VA_TOP_FIELD;
+    } else {
+        pipeline->filter_flags = VA_FRAME_PICTURE;
+    }
+
+    if ((mFilters & FilterFrameRateConversion) != 0) {
+        vaStatus = vaUnmapBuffer(mVADisplay, mFilterFrc);
+        CHECK_VASTATUS("vaUnmapBuffer for frc parameter buffer");
+    }
+
+    vaStatus = vaUnmapBuffer(mVADisplay, pipelineId);
+    CHECK_VASTATUS("vaUnmapBuffer for pipeline parameter buffer");
+
+    ALOGV("before vaRenderPicture");
+    // Send parameter to driver
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &pipelineId, 1);
+    CHECK_VASTATUS("vaRenderPicture");
+
+    ALOGV("before vaEndPicture");
+    vaStatus = vaEndPicture(mVADisplay, mVAContext);
+    CHECK_VASTATUS("vaEndPicture");
+    
+    if (isEOS) {
+        vaStatus = vaSyncSurface(mVADisplay, mPrevOutput);
+        CHECK_VASTATUS("vaSyncSurface");
+        if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineId)) {
+            ALOGE("%s: failed to destroy va buffer %d", __func__, pipelineId);
+            return STATUS_ERROR;
+        }
+        return STATUS_OK;
+    }
+
+    mPrevOutput = output[0];
+    mInputIndex++;
+
+    Mutex::Autolock autoLock(mPipelineBufferLock);
+    mPipelineBuffers.push_back(pipelineId);
+
+    ALOGV("process, exit");
+    return STATUS_OK;
+}
+
+status_t ISVWorker::fill(Vector<ISVBuffer*> outputBuffer, uint32_t outputCount) {
+    ALOGV("fill, outputCount=%d, mOutputIndex=%d",outputCount, mOutputIndex);
+    // get output surface
+    VASurfaceID output[MAX_FRC_OUTPUT];
+    VAStatus vaStatus;
+    VASurfaceStatus surStatus;
+
+    if (outputCount < 1)
+        return STATUS_ERROR;
+    // map GraphicBuffer to VASurface
+    for (uint32_t i = 0; i < outputCount; i++) {
+
+        output[i] = outputBuffer[i]->getSurface();
+        if (output[i] == VA_INVALID_SURFACE) {
+            ALOGE("invalid output buffer");
+            return STATUS_ERROR;
+        }
+        //FIXME: only enable sync mode
+#if 0
+        vaStatus = vaQuerySurfaceStatus(mVADisplay, output[i],&surStatus);
+        CHECK_VASTATUS("vaQuerySurfaceStatus");
+        if (surStatus == VASurfaceRendering) {
+            ALOGV("Rendering %d", i);
+            /* The behavior of driver is: all output of one process task are return in one interruption.
+               The whole outputs of one FRC task are all ready or none of them is ready.
+               If the behavior changed, it hurts the performance.
+            */
+            if (0 != i) {
+                ALOGW("*****Driver behavior changed. The performance is hurt.");
+                ALOGW("Please check driver behavior: all output of one task return in one interruption.");
+            }
+            vaStatus = STATUS_DATA_RENDERING;
+            break;
+        }
+
+        if ((surStatus != VASurfaceRendering) && (surStatus != VASurfaceReady)) {
+            ALOGE("surface statu Error %d", surStatus);
+            vaStatus = STATUS_ERROR;
+        }
+#endif
+        vaStatus = vaSyncSurface(mVADisplay, output[i]);
+        CHECK_VASTATUS("vaSyncSurface");
+        vaStatus = STATUS_OK;
+        mOutputCount++;
+        //dumpYUVFrameData(output[i]);
+    }
+
+    {
+        Mutex::Autolock autoLock(mPipelineBufferLock);
+        if (vaStatus == STATUS_OK) {
+            VABufferID pipelineBuffer = mPipelineBuffers.itemAt(0);
+            if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineBuffer)) {
+                ALOGE("%s: failed to destroy va buffer %d", __func__, pipelineBuffer);
+                return STATUS_ERROR;
+            }
+            mPipelineBuffers.removeAt(0);
+            mOutputIndex++;
+        }
+    }
+
+    ALOGV("fill, exit");
+    return vaStatus;
+}
+
+// Debug only
+#define FRAME_OUTPUT_FILE_NV12 "/storage/sdcard0/vpp_output.nv12"
+status_t ISVWorker::dumpYUVFrameData(VASurfaceID surfaceID) {
+    status_t ret;
+    if (surfaceID == VA_INVALID_SURFACE)
+        return STATUS_ERROR;
+
+    VAStatus vaStatus;
+    VAImage image;
+    unsigned char *data_ptr;
+
+    vaStatus = vaDeriveImage(mVADisplay,
+            surfaceID,
+            &image);
+    CHECK_VASTATUS("vaDeriveImage");
+
+    vaStatus = vaMapBuffer(mVADisplay, image.buf, (void **)&data_ptr);
+    CHECK_VASTATUS("vaMapBuffer");
+
+    ret = writeNV12(mFilterParam.srcWidth, mFilterParam.srcHeight, data_ptr, image.pitches[0], image.pitches[1]);
+    if (ret != STATUS_OK) {
+        ALOGV("writeNV12 error");
+        return STATUS_ERROR;
+    }
+
+    vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
+    CHECK_VASTATUS("vaUnMapBuffer");
+
+    vaStatus = vaDestroyImage(mVADisplay,image.image_id);
+    CHECK_VASTATUS("vaDestroyImage");
+
+    return STATUS_OK;
+}
+
+status_t ISVWorker::reset() {
+    status_t ret;
+    ALOGV("reset");
+    if (mOutputCount > 0) {
+        ALOGI("======mVPPInputCount=%d, mVPPRenderCount=%d======",
+                mInputIndex, mOutputCount);
+    }
+    mInputIndex = 0;
+    mOutputIndex = 0;
+    mOutputCount = 0;
+
+    {
+        Mutex::Autolock autoLock(mPipelineBufferLock);
+        while (!mPipelineBuffers.isEmpty()) {
+            VABufferID pipelineBuffer = mPipelineBuffers.itemAt(0);
+            if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, pipelineBuffer)) {
+                ALOGE("%s: failed to destroy va buffer %d", __func__, pipelineBuffer);
+                return STATUS_ERROR;
+            }
+            mPipelineBuffers.removeAt(0);
+        }
+    }
+
+    if (mNumFilterBuffers != 0) {
+        for (uint32_t i = 0; i < mNumFilterBuffers; i++) {
+            if (VA_STATUS_SUCCESS != vaDestroyBuffer(mVADisplay, mFilterBuffers[i]))
+                ALOGW("%s: failed to destroy va buffer %d", __func__, mFilterBuffers[i]);
+                //return STATUS_ERROR;
+        }
+        mNumFilterBuffers = 0;
+        memset(&mFilterBuffers, VA_INVALID_ID, VAProcFilterCount * sizeof(VABufferID));
+        mFilterFrc = VA_INVALID_ID;
+    }
+
+    // we need to clear the cache for reference surfaces
+    if (mForwardReferences != NULL) {
+        free(mForwardReferences);
+        mForwardReferences = NULL;
+        mNumForwardReferences = 0;
+    }
+
+    if (mVAContext != VA_INVALID_ID) {
+         vaDestroyContext(mVADisplay, mVAContext);
+         mVAContext = VA_INVALID_ID;
+    }
+    VAStatus vaStatus = vaCreateContext(mVADisplay, mVAConfig, mWidth, mHeight, 0, NULL, 0, &mVAContext);
+    CHECK_VASTATUS("vaCreateContext");
+
+    return setupFilters();
+}
+
+uint32_t ISVWorker::getVppOutputFps() {
+    uint32_t outputFps;
+    //mFilterParam.frcRate is 1 if FRC is disabled or input FPS is not changed by VPP.
+    if (FRC_RATE_2_5X == mFilterParam.frcRate) {
+        outputFps = mFilterParam.frameRate * 5 / 2;
+    } else {
+        outputFps = mFilterParam.frameRate * mFilterParam.frcRate;
+    }
+
+    ALOGV("vpp is on in settings %d %d %d", outputFps,  mFilterParam.frameRate, mFilterParam.frcRate);
+    return outputFps;
+}
+
+
+status_t ISVWorker::writeNV12(int width, int height, unsigned char *out_buf, int y_pitch, int uv_pitch) {
+    size_t result;
+    int frame_size;
+    unsigned char *y_start, *uv_start;
+    int h;
+
+    FILE *ofile = fopen(FRAME_OUTPUT_FILE_NV12, "ab");
+    if(ofile == NULL) {
+        ALOGE("Open %s failed!", FRAME_OUTPUT_FILE_NV12);
+        return STATUS_ERROR;
+    }
+
+    if (out_buf == NULL)
+    {
+        fclose(ofile);
+        return STATUS_ERROR;
+    }
+    if ((width % 2) || (height % 2))
+    {
+        fclose(ofile);
+        return STATUS_ERROR;
+    }
+    // Set frame size
+    frame_size = height * width * 3/2;
+
+    /* write y */
+    y_start = out_buf;
+    for (h = 0; h < height; ++h) {
+        result = fwrite(y_start, sizeof(unsigned char), width, ofile);
+        y_start += y_pitch;
+    }
+
+    /* write uv */
+    uv_start = out_buf + uv_pitch * height;
+    for (h = 0; h < height / 2; ++h) {
+        result = fwrite(uv_start, sizeof(unsigned char), width, ofile);
+        uv_start += uv_pitch;
+    }
+    // Close file
+    fclose(ofile);
+    return STATUS_OK;
+}
+
diff --git a/ISV/include/isv_bufmanager.h b/ISV/include/isv_bufmanager.h
new file mode 100644
index 0000000..18c3209
--- /dev/null
+++ b/ISV/include/isv_bufmanager.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __ISV_BUFMANAGER_H
+#define __ISV_BUFMANAGER_H
+
+#include <utils/RefBase.h>
+#include <utils/Mutex.h>
+#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;
+
+#define ISV_BUFFER_MANAGER_DEBUG 0
+
+class ISVWorker;
+
+class ISVBuffer
+{
+public:
+    typedef enum {
+        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
+    {
+        int width;       // \see alloc_device_t::alloc
+        int height;      // \see alloc_device_t::alloc
+        int format;      // \see alloc_device_t::alloc
+        int usage;       // \see alloc_device_t::alloc
+        int name;        // flink
+        uint32_t fb;     // framebuffer id
+        int drmformat;   // drm format
+        int pitch;       // buffer pitch (in bytes)
+        int size;        // buffer size (in bytes)
+        int allocWidth;  // allocated buffer width in pixels.
+        int allocHeight; // allocated buffer height in lines.
+        int allocOffsetX;// horizontal pixel offset to content origin within allocated buffer.
+        int allocOffsetY;// vertical line offset to content origin within allocated buffer.
+    } ufo_buffer_details_t;
+
+    enum
+    {
+        INTEL_UFO_GRALLOC_MODULE_PERFORM_GET_BO_INFO = 6 // (buffer_handle_t, buffer_info_t*)
+    };
+
+public:
+    ISVBuffer(sp<ISVWorker> worker,
+            unsigned long buffer, unsigned long grallocHandle,
+            uint32_t width, uint32_t height,
+            uint32_t stride, uint32_t colorFormat,
+            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),
+        mFlags(flag),
+        mpGralloc(NULL) {}
+
+    ISVBuffer(sp<ISVWorker> worker,
+            unsigned long buffer,
+            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),
+        mFlags(flag),
+        mpGralloc(NULL) {}
+
+    ~ISVBuffer();
+
+    // init buffer info
+    // FIXME: hackFormat is for VP9, should be removed in future
+    status_t initBufferInfo(uint32_t hackFormat);
+
+    // get va surface
+    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
+{
+public:
+    ISVBufferManager()
+        :mWorker(NULL),
+        mMetaDataMode(false),
+        mNeedClearBuffers(false) {}
+
+    ~ISVBufferManager() {}
+    // set mBuffers size
+    status_t setBufferCount(int32_t size);
+
+    // register/unregister ISVBuffers to mBuffers
+    status_t useBuffer(const sp<ANativeWindowBuffer> nativeBuffer);
+    status_t useBuffer(unsigned long handle);
+    status_t freeBuffer(unsigned long handle);
+
+    // Map to ISVBuffer
+    ISVBuffer* mapBuffer(unsigned long handle);
+    // 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,
+        META_DATA_MODE = 1,
+    } ISV_WORK_MODE;
+
+    sp<ISVWorker> mWorker;
+    bool mMetaDataMode;
+    // VPP buffer queue
+    Vector<ISVBuffer*> mBuffers;
+    Mutex mBufferLock; // to protect access to mBuffers
+    bool mNeedClearBuffers;
+};
+
+
+#endif //#define __ISV_BUFMANAGER_H
diff --git a/ISV/include/isv_omxcomponent.h b/ISV/include/isv_omxcomponent.h
new file mode 100644
index 0000000..5acea30
--- /dev/null
+++ b/ISV/include/isv_omxcomponent.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef ISV_OMXCOMPONENT_H_
+
+#define ISV_OMXCOMPONENT_H_
+
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+#include "isv_omxcore.h"
+#include "isv_processor.h"
+#include "isv_profile.h"
+#include "isv_worker.h"
+#include "isv_bufmanager.h"
+
+#define ISV_COMPONENT_DEBUG 0
+
+#ifdef TARGET_VPP_USE_GEN
+#define MIN_INPUT_NUM           (3)
+#define MIN_OUTPUT_NUM          (3)
+#else
+#define MIN_INPUT_NUM           (4)    // forward reference frame number is 3 for merrifield/moorefield
+#define MIN_OUTPUT_NUM          (10)   // 2.5FRC need hold 2 + 3 + 2 + 3= 10 buffers, without FRC we set to 6
+#endif
+#define MIN_ISV_BUFFER_NUM      ((MIN_OUTPUT_NUM) + (MIN_INPUT_NUM))
+#define UNDEQUEUED_NUM          (4)   // display system hold 4 buffers
+
+using namespace android;
+class ISVComponent;
+
+class ISVProcThreadObserver: public ISVProcessorObserver
+{
+public:
+    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
+{
+public:
+    /*
+     * construct & destruct
+     */
+    ISVComponent(OMX_PTR);
+    ~ISVComponent();
+
+    // replace component callbacks
+    OMX_CALLBACKTYPE *getCallBacks(OMX_CALLBACKTYPE*);
+    // pass down the real component&core
+    void setComponent(OMX_COMPONENTTYPE *pComp, ISVOMXCore *pCore){mComponent = pComp; mCore = pCore;return;}
+    // free the real component
+    OMX_ERRORTYPE freeComponent(){return (*(mCore->mFreeHandle))(static_cast<OMX_HANDLETYPE>(mComponent));}
+    // return ISV component handle
+    OMX_COMPONENTTYPE *getBaseComponent(){return &mBaseComponent;}
+
+    static Vector<ISVComponent*> g_isv_components;
+private:
+    /*
+     * component methods & helpers
+     */
+
+    static OMX_ERRORTYPE SendCommand(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_COMMANDTYPE Cmd,
+        OMX_IN  OMX_U32 nParam1,
+        OMX_IN  OMX_PTR pCmdData);
+    OMX_ERRORTYPE ISV_SendCommand(
+        OMX_IN  OMX_COMMANDTYPE Cmd,
+        OMX_IN  OMX_U32 nParam1,
+        OMX_IN  OMX_PTR pCmdData);
+
+    static OMX_ERRORTYPE GetParameter(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_INDEXTYPE nParamIndex,
+        OMX_INOUT OMX_PTR pComponentParameterStructure);
+    OMX_ERRORTYPE ISV_GetParameter(
+        OMX_IN  OMX_INDEXTYPE nParamIndex,
+        OMX_INOUT OMX_PTR pComponentParameterStructure);
+
+    static OMX_ERRORTYPE SetParameter(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_INDEXTYPE nIndex,
+        OMX_IN  OMX_PTR pComponentParameterStructure);
+    OMX_ERRORTYPE ISV_SetParameter(
+        OMX_IN  OMX_INDEXTYPE nIndex,
+        OMX_IN  OMX_PTR pComponentParameterStructure);
+
+    static OMX_ERRORTYPE GetConfig(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_INDEXTYPE nIndex,
+        OMX_INOUT OMX_PTR pComponentConfigStructure);
+    OMX_ERRORTYPE ISV_GetConfig(
+        OMX_IN  OMX_INDEXTYPE nIndex,
+        OMX_INOUT OMX_PTR pComponentConfigStructure);
+
+    static OMX_ERRORTYPE SetConfig(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_INDEXTYPE nIndex,
+        OMX_IN  OMX_PTR pComponentConfigStructure);
+    OMX_ERRORTYPE ISV_SetConfig(
+        OMX_IN  OMX_INDEXTYPE nIndex,
+        OMX_IN  OMX_PTR pComponentConfigStructure);
+
+    static OMX_ERRORTYPE GetExtensionIndex(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_STRING cParameterName,
+        OMX_OUT OMX_INDEXTYPE* pIndexType);
+    OMX_ERRORTYPE ISV_GetExtensionIndex(
+        OMX_IN  OMX_STRING cParameterName,
+        OMX_OUT OMX_INDEXTYPE* pIndexType);
+
+    static OMX_ERRORTYPE GetState(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_OUT OMX_STATETYPE* pState);
+    OMX_ERRORTYPE ISV_GetState(
+        OMX_OUT OMX_STATETYPE* pState);
+
+    static OMX_ERRORTYPE UseBuffer(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+        OMX_IN OMX_U32 nPortIndex,
+        OMX_IN OMX_PTR pAppPrivate,
+        OMX_IN OMX_U32 nSizeBytes,
+        OMX_IN OMX_U8* pBuffer);
+    OMX_ERRORTYPE ISV_UseBuffer(
+        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
+        OMX_IN OMX_U32 nPortIndex,
+        OMX_IN OMX_PTR pAppPrivate,
+        OMX_IN OMX_U32 nSizeBytes,
+        OMX_IN OMX_U8* pBuffer);
+
+    static OMX_ERRORTYPE AllocateBuffer(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
+        OMX_IN OMX_U32 nPortIndex,
+        OMX_IN OMX_PTR pAppPrivate,
+        OMX_IN OMX_U32 nSizeBytes);
+    OMX_ERRORTYPE ISV_AllocateBuffer(
+        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
+        OMX_IN OMX_U32 nPortIndex,
+        OMX_IN OMX_PTR pAppPrivate,
+        OMX_IN OMX_U32 nSizeBytes);
+
+    static OMX_ERRORTYPE FreeBuffer(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_U32 nPortIndex,
+        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
+    OMX_ERRORTYPE ISV_FreeBuffer(
+        OMX_IN  OMX_U32 nPortIndex,
+        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
+
+    static OMX_ERRORTYPE EmptyThisBuffer(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
+    OMX_ERRORTYPE ISV_EmptyThisBuffer(
+        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
+
+    static OMX_ERRORTYPE FillThisBuffer(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
+    OMX_ERRORTYPE ISV_FillThisBuffer(
+        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
+
+    static OMX_ERRORTYPE SetCallbacks(
+        OMX_IN  OMX_HANDLETYPE hComponent,
+        OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
+        OMX_IN  OMX_PTR pAppData);
+    OMX_ERRORTYPE ISV_SetCallbacks(
+        OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
+        OMX_IN  OMX_PTR pAppData);
+
+    static OMX_ERRORTYPE ComponentRoleEnum(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_OUT OMX_U8 *cRole,
+        OMX_IN OMX_U32 nIndex);
+    OMX_ERRORTYPE ISV_ComponentRoleEnum(
+        OMX_OUT OMX_U8 *cRole,
+        OMX_IN OMX_U32 nIndex);
+
+    static OMX_ERRORTYPE FillBufferDone(
+        OMX_OUT OMX_HANDLETYPE hComponent,
+        OMX_OUT OMX_PTR pAppData,
+        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+    OMX_ERRORTYPE ISV_FillBufferDone(
+        OMX_OUT OMX_HANDLETYPE hComponent,
+        OMX_OUT OMX_PTR pAppData,
+        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer);
+
+    static OMX_ERRORTYPE EventHandler(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_EVENTTYPE eEvent,
+            OMX_IN OMX_U32 nData1,
+            OMX_IN OMX_U32 nData2,
+            OMX_IN OMX_PTR pEventData);
+    OMX_ERRORTYPE ISV_EventHandler(
+            OMX_IN OMX_HANDLETYPE hComponent,
+            OMX_IN OMX_PTR pAppData,
+            OMX_IN OMX_EVENTTYPE eEvent,
+            OMX_IN OMX_U32 nData1,
+            OMX_IN OMX_U32 nData2,
+            OMX_IN OMX_PTR pEventData);
+    /* end of component methods & helpers */
+
+    void SetTypeHeader(OMX_PTR type, OMX_U32 size);
+
+    // init & deinit functions
+    status_t init(int32_t width, int32_t height);
+    void deinit();
+
+    const static OMX_U8 OMX_SPEC_VERSION_MAJOR = 1;
+    const static OMX_U8 OMX_SPEC_VERSION_MINOR = 0;
+    const static OMX_U8 OMX_SPEC_VERSION_REVISION = 0;
+    const static OMX_U8 OMX_SPEC_VERSION_STEP = 0;
+
+    const static OMX_U32 OMX_SPEC_VERSION = 0
+        | (OMX_SPEC_VERSION_MAJOR << 0)
+        | (OMX_SPEC_VERSION_MINOR << 8)
+        | (OMX_SPEC_VERSION_REVISION << 16)
+        | (OMX_SPEC_VERSION_STEP << 24);
+
+    typedef enum OMX_ISVINDEXEXTTYPE {
+        OMX_IndexISVStartUsed = OMX_IndexVendorStartUnused + 0x0000F000,
+        OMX_IndexExtSetISVMode,                  /**< reference: OMX_U32 */
+    } OMX_ISVINDEXEXTTYPE;
+
+    typedef enum {
+        ISV_DISABLE = 0,
+        ISV_AUTO,
+    } ISV_MODE;
+
+private:
+    OMX_COMPONENTTYPE mBaseComponent;  //returned by GetComponetHandle()
+    OMX_COMPONENTTYPE *mComponent;      // passed from the real OMX core
+    OMX_CALLBACKTYPE *mpCallBacks;
+    ISVOMXCore *mCore;                  // owend by mComponent
+    OMX_CALLBACKTYPE *mpISVCallBacks;
+
+    // buffer manager
+    sp<ISVBufferManager> mISVBufferManager;
+
+    bool mThreadRunning;
+
+    // vpp thread observer
+    sp<ISVProcThreadObserver> mProcThreadObserver;
+
+    // vpp input buffer count + output buffer count
+    int32_t mNumISVBuffers;
+    int32_t mNumDecoderBuffers;
+    int32_t mNumDecoderBuffersBak;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mUseAndroidNativeBufferIndex;
+    uint32_t mStoreMetaDataInBuffersIndex;
+    uint32_t mHackFormat;
+
+    bool mUseAndroidNativeBuffer;
+    bool mUseAndroidNativeBuffer2;
+
+    bool mVPPEnabled;
+    bool mVPPOn;
+    bool mVPPFlushing;
+    bool mOutputCropChanged;
+    bool mInitialized;
+#ifdef TARGET_VPP_USE_GEN
+    // vpp thread
+    sp<ISVProcessor> mProcThread;
+#else
+    static sp<ISVProcessor> mProcThread;
+#endif
+    // protect create mProcThread instance
+    bool mOwnProcessor;
+    static pthread_mutex_t ProcThreadInstanceLock;
+};
+
+#endif  // #define ISV_OMXCOMPONENT_H_
diff --git a/ISV/include/isv_omxcore.h b/ISV/include/isv_omxcore.h
new file mode 100644
index 0000000..01d3cea
--- /dev/null
+++ b/ISV/include/isv_omxcore.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifndef ISV_OMXCORE_H_
+
+#define ISV_OMXCORE_H_
+
+#define ISV_CORE_DEBUG 0
+
+struct ISVOMXCore {
+    typedef OMX_ERRORTYPE (*InitFunc)();
+    typedef OMX_ERRORTYPE (*DeinitFunc)();
+    typedef OMX_ERRORTYPE (*ComponentNameEnumFunc)(
+            OMX_STRING, OMX_U32, OMX_U32);
+
+    typedef OMX_ERRORTYPE (*GetHandleFunc)(
+            OMX_HANDLETYPE *, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE *);
+
+    typedef OMX_ERRORTYPE (*FreeHandleFunc)(OMX_HANDLETYPE);
+
+    typedef OMX_ERRORTYPE (*GetRolesOfComponentFunc)(
+            OMX_STRING, OMX_U32 *, OMX_U8 **);
+
+    void *mLibHandle;
+
+    InitFunc mInit;
+    DeinitFunc mDeinit;
+    ComponentNameEnumFunc mComponentNameEnum;
+    GetHandleFunc mGetHandle;
+    FreeHandleFunc mFreeHandle;
+    GetRolesOfComponentFunc mGetRolesOfComponentHandle;
+
+    OMX_U32 mNumComponents;
+};
+
+#endif  //ISV_OMXCORE_H_
diff --git a/ISV/include/isv_processor.h b/ISV/include/isv_processor.h
new file mode 100644
index 0000000..c50fb65
--- /dev/null
+++ b/ISV/include/isv_processor.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __ISV_PROCESSOR_H
+#define __ISV_PROCESSOR_H
+
+#include <media/stagefright/MetaData.h>
+#include "isv_worker.h"
+
+#include <utils/Mutex.h>
+#include <utils/threads.h>
+#include <utils/Errors.h>
+#include "isv_bufmanager.h"
+#define ISV_COMPONENT_LOCK_DEBUG 0
+#define ISV_THREAD_DEBUG 0
+
+using namespace android;
+
+typedef enum {
+    kPortIndexInput  = 0,
+    kPortIndexOutput = 1
+}PORT_INDEX;
+
+class ISVBufferManager;
+class ISVProcessorObserver: public RefBase
+{
+public:
+    virtual OMX_ERRORTYPE releaseBuffer(PORT_INDEX index, OMX_BUFFERHEADERTYPE* pBuffer, bool bFlush) = 0;
+    virtual OMX_ERRORTYPE reportOutputCrop() = 0;
+};
+
+class ISVProcessor : public Thread
+{
+public:
+    ISVProcessor(bool canCallJava, sp<ISVBufferManager> bufferManager, sp<ISVProcessorObserver> observer, uint32_t width, uint32_t height);
+    virtual ~ISVProcessor();
+
+    virtual status_t readyToRun();
+
+    // Derived class must implement threadLoop(). The thread starts its life
+    // here. There are two ways of using the Thread object:
+                                                // 1) loop: if threadLoop() returns true, it will be called again if
+                                                //          requestExit() wasn't called.
+                                                // 2) once: if threadLoop() returns false, the thread will exit upon return.
+    virtual bool threadLoop();
+    bool isCurrentThread() const;
+
+    void start();
+    void stop();
+    bool isReadytoRun();
+
+    //configure FRC factor
+    status_t configFRC(uint32_t fps);
+    //add output buffer into mOutputBuffers
+    void addOutput(OMX_BUFFERHEADERTYPE* output);
+    //add intput buffer into mInputBuffers
+    void addInput(OMX_BUFFERHEADERTYPE* input);
+    //notify flush and wait flush finish
+    void notifyFlush();
+    void waitFlushFinished();
+
+private:
+    bool getBufForFirmwareOutput(Vector<ISVBuffer*> *fillBufList,
+            uint32_t *fillBufNum);
+    status_t updateFirmwareOutputBufStatus(uint32_t fillBufNum);
+    bool getBufForFirmwareInput(Vector<ISVBuffer*> *procBufList,
+            ISVBuffer **inputBuf,
+            uint32_t *procBufNum );
+    status_t updateFirmwareInputBufStatus(uint32_t procBufNum);
+    //flush input&ouput buffer queue
+    void flush();
+    //return whether this fps is valid
+    inline bool isFrameRateValid(uint32_t fps);
+    //auto calculate fps if the framework doesn't set the correct fps
+    status_t calculateFps(int64_t timeStamp, uint32_t* fps);
+    //config vpp filters
+    status_t configFilters(OMX_BUFFERHEADERTYPE* buffer);
+
+private:
+    sp<ISVProcessorObserver> mpOwner;
+    android_thread_id_t mThreadId;
+    bool mThreadRunning;
+
+    sp<ISVWorker> mISVWorker;
+    sp<ISVProfile> mISVProfile;
+    // buffer manager
+    sp<ISVBufferManager> mBufferManager;
+
+    Vector<OMX_BUFFERHEADERTYPE*> mOutputBuffers;
+    Mutex mOutputLock; // to protect access to mOutputBuffers
+    uint32_t mOutputProcIdx;
+
+    Vector<OMX_BUFFERHEADERTYPE*> mInputBuffers;
+    Mutex mInputLock; // to protect access to mFillBuffers
+    uint32_t mInputProcIdx;
+
+    const static uint32_t WINDOW_SIZE = 4;  // must >= 2
+    Vector<int64_t>mTimeWindow;
+    // conditon for thread running
+    Mutex mLock;
+    Condition mRunCond;
+
+    // condition for seek finish
+    Mutex mEndLock;
+    Condition mEndCond;
+
+    uint32_t mNumTaskInProcesing;
+    uint32_t mNumRetry;
+    bool mError;
+    bool mbFlush;
+    bool mbBypass;
+    bool mFlagEnd;
+    bool mFrcOn;
+
+    // ISV filter configuration
+    uint32_t mFilters;
+    FilterParam mFilterParam;
+};
+
+#endif /* __ISV_THREAD_H*/
diff --git a/ISV/include/isv_profile.h b/ISV/include/isv_profile.h
new file mode 100644
index 0000000..d9a04fd
--- /dev/null
+++ b/ISV/include/isv_profile.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __ISV_PROFILE_H
+#define __ISV_PROFILE_H
+
+#define MAX_BUF_SIZE (4 * 1024)
+#define MAX_TAB_SIZE (10)
+#define MAX_STRING_LEN (50)
+
+#include <utils/RefBase.h>
+using namespace android;
+
+typedef enum _FRC_RATE {
+    FRC_RATE_1X = 1,
+    FRC_RATE_2X,
+    FRC_RATE_2_5X,
+    FRC_RATE_4X
+} FRC_RATE;
+
+typedef enum {
+    VPP_COMMON_ON   = 1,        // VPP is on
+    VPP_FRC_ON      = 1 << 1,   // FRC is on
+} VPP_SETTING_STATUS;
+
+typedef struct _ISVParameter {
+    char name[MAX_STRING_LEN];
+    float value;
+} ISVParameter;
+
+typedef struct _ISVConfig {
+    bool enabled;
+    uint32_t minResolution;
+    uint32_t maxResolution;
+    //bool isOn;
+    ISVParameter paraTables[MAX_TAB_SIZE];
+    uint32_t paraSize;
+} ISVConfig;
+
+typedef struct _ISVFRCRate {
+    uint32_t input_fps;
+    FRC_RATE rate;
+} ISVFRCRate;
+
+//FIXME: need align to ProcFilterType
+typedef enum _FilterType {
+    FilterNone                          = 0x00000001,
+    FilterNoiseReduction                = 0x00000002,
+    FilterDeinterlacing                 = 0x00000004,
+    FilterSharpening                    = 0x00000008,
+    FilterColorBalance                  = 0x00000010,
+    FilterDeblocking                    = 0x00000020,
+    FilterFrameRateConversion           = 0x00000040,
+    FilterSkinToneEnhancement           = 0x00000080,
+    FilterTotalColorCorrection          = 0x00000100,
+    FilterNonLinearAnamorphicScaling    = 0x00000200,
+    FilterImageStabilization            = 0x00000400,
+} FilterType;
+
+class ISVProfile : public RefBase
+{
+public:
+    ISVProfile(const uint32_t width, const uint32_t height);
+    ~ISVProfile();
+
+    /* get the global ISV setting status */
+    FRC_RATE getFRCRate(uint32_t inputFps);
+
+    /* get filter config data
+     * the filters' status are saved in uint32_t
+     */
+    uint32_t getFilterStatus();
+
+    /* the global setting for VPP */
+    static bool isVPPOn();
+
+    /* the global setting for FRC */
+    static bool isFRCOn();
+
+private:
+    /* Read the global setting for ISV */
+    static int32_t getGlobalStatus();
+
+    /* Get the config data from XML file */
+    void getDataFromXmlFile(void);
+
+    /* Update the filter status */
+    void updateFilterStatus();
+
+    /* handle the XML file */
+    static void startElement(void *userData, const char *name, const char **atts);
+    static void endElement(void *userData, const char *name);
+    int getFilterID(const char * name);
+    uint32_t getResolution(const char * name);
+    void getConfigData(const char *name, const char **atts);
+    void handleFilterParameter(const char *name, const char **atts);
+    void handleCommonParameter(const char *name, const char **atts);
+
+    /* dump the config data */
+    void dumpConfigData();
+
+    typedef enum _ProcFilterType {
+        ProcFilterNone = 0,
+        ProcFilterNoiseReduction,
+        ProcFilterDeinterlacing,
+        ProcFilterSharpening,
+        ProcFilterColorBalance,
+        ProcFilterDeblocking,
+        ProcFilterFrameRateConversion,
+        ProcFilterSkinToneEnhancement,
+        ProcFilterTotalColorCorrection,
+        ProcFilterNonLinearAnamorphicScaling,
+        ProcFilterImageStabilization,
+        ProcFilterCount
+    } ProcFilterType;
+
+private:
+    uint32_t mWidth;
+    uint32_t mHeight;
+
+    /* The default value of VPP/FRC.
+     * They will be read from config xml file.
+     */
+    int32_t mDefaultVPPStatus;
+    int32_t mDefaultFRCStatus;
+
+    /* the filters' status according to resolution
+     * bit 0  used for ProcFilterNone
+     * bit 1  used for ProcFilterNoiseReduction
+     * ...
+     * bit 10 used for ProcFilterImageStabilization
+     */
+    uint32_t mStatus;
+
+    ISVConfig mConfigs[ProcFilterCount];
+    uint32_t mCurrentFilter; //used by parasing xml file
+    ISVFRCRate mFrcRates[MAX_TAB_SIZE];
+    uint32_t mCurrentFrcTab;
+
+    static const int mBufSize = MAX_BUF_SIZE;
+};
+
+#endif /* __ISV_PROFILE_H */
diff --git a/ISV/include/isv_worker.h b/ISV/include/isv_worker.h
new file mode 100644
index 0000000..2efee2a
--- /dev/null
+++ b/ISV/include/isv_worker.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __ISVWorker_H_
+#define __ISVWorker_H_
+
+#include <va/va.h>
+#include <va/va_vpp.h>
+#include <va/va_android.h>
+#include <OMX_Component.h>
+#include <utils/RefBase.h>
+#include "isv_profile.h"
+#include "isv_bufmanager.h"
+
+#define ANDROID_DISPLAY_HANDLE 0x18C34078
+#define Display unsigned int
+
+//FIXME: copy from OMX_Core.h
+
+/* interlaced frame flag: This flag is set to indicate the buffer contains a
+ * top and bottom field and display ordering is top field first.
+ * @ingroup buf
+ */
+#define OMX_BUFFERFLAG_TFF 0x00010000
+
+/* interlaced frame flag: This flag is set to indicate the buffer contains a 
+ * top and bottom field and display ordering is bottom field first.
+ * @ingroup buf
+ */
+#define OMX_BUFFERFLAG_BFF 0x00020000
+
+using namespace android;
+
+typedef enum
+{
+    STATUS_OK = 0,
+    STATUS_NOT_SUPPORT,
+    STATUS_ALLOCATION_ERROR,
+    STATUS_ERROR,
+    STATUS_DATA_RENDERING
+} vpp_status;
+
+typedef enum
+{
+    DEINTERLACE_BOB = 0,                   // BOB DI
+    DEINTERLACE_ADI = 1,                   // ADI
+} deinterlace_t;
+
+//Avaiable filter types
+typedef enum
+{
+    FILTER_HQ   = 0,                      // high-quality filter (AVS scaling)
+    FILTER_FAST = 1,                      // fast filter (bilinear scaling)
+} filter_t;
+
+typedef struct {
+    uint32_t srcWidth;
+    uint32_t srcHeight;
+    uint32_t dstWidth;
+    uint32_t dstHeight;
+    uint32_t denoiseLevel;
+    uint32_t sharpnessLevel;
+    uint32_t colorBalanceLevel;
+    deinterlace_t deinterlaceType;
+    filter_t scalarType;
+    uint32_t frameRate;
+    uint32_t hasEncoder;
+    FRC_RATE frcRate;
+} FilterParam;
+
+class ISVBuffer;
+
+class ISVWorker : public RefBase
+{
+
+    public:
+        // config filters on or off based on video info
+        status_t configFilters(uint32_t filters, const FilterParam* filterParam);
+
+        // Initialize: setupVA()->setupFilters()->setupPipelineCaps()
+        status_t init(uint32_t width, uint32_t height);
+        status_t deinit();
+
+        // Get output buffer number needed for processing
+        uint32_t getProcBufCount();
+
+        // Get output buffer number needed for filling
+        uint32_t getFillBufCount();
+
+        // Send input and output buffers to VSP to begin processing
+        status_t process(ISVBuffer* input, Vector<ISVBuffer*> output, uint32_t outputCount, bool isEOS, uint32_t flags);
+
+        // Fill output buffers given, it's a blocking call
+        status_t fill(Vector<ISVBuffer*> output, uint32_t outputCount);
+
+        // reset index
+        status_t reset();
+
+        // set video display mode
+        void setDisplayMode(int32_t mode);
+
+        // get video display mode
+        int32_t getDisplayMode();
+
+        // check HDMI connection status
+        bool isHdmiConnected();
+
+        uint32_t getVppOutputFps();
+
+        // alloc/free VA surface
+        status_t allocSurface(uint32_t* width, uint32_t* height,
+                uint32_t stride, uint32_t format, unsigned long handle, int32_t* surfaceId);
+        status_t freeSurface(int32_t* surfaceId);
+
+        ISVWorker();
+        ~ISVWorker() {}
+
+    private:
+        // Check if VPP is supported
+        bool isSupport() const;
+
+        // Get output buffer number needed for processing
+        uint32_t getOutputBufCount(uint32_t index);
+
+        // Check filter caps and create filter buffers
+        status_t setupFilters();
+
+        // Setup pipeline caps
+        status_t setupPipelineCaps();
+
+        //check if the input fps is suportted in array fpsSet.
+        bool isFpsSupport(int32_t fps, int32_t *fpsSet, int32_t fpsSetCnt);
+
+        // Debug only
+        // Dump YUV frame
+        status_t dumpYUVFrameData(VASurfaceID surfaceID);
+        status_t writeNV12(int width, int height, unsigned char *out_buf, int y_pitch, int uv_pitch);
+
+        ISVWorker(const ISVWorker &);
+        ISVWorker &operator=(const ISVWorker &);
+
+    public:
+        uint32_t mNumForwardReferences;
+
+    private:
+        // VA common variables
+        VAContextID mVAContext;
+        uint32_t mWidth;
+        uint32_t mHeight;
+        Display * mDisplay;
+        VADisplay mVADisplay;
+        VAConfigID mVAConfig;
+
+        // Forward References Surfaces
+        Vector<VABufferID> mPipelineBuffers;
+        Mutex mPipelineBufferLock; // to protect access to mPipelineBuffers
+        VASurfaceID *mForwardReferences;
+        VASurfaceID mPrevInput;
+        VASurfaceID mPrevOutput;
+
+        // VPP Filters Buffers
+        uint32_t mNumFilterBuffers;
+        VABufferID mFilterBuffers[VAProcFilterCount];
+
+        // VPP filter configuration
+        VABufferID mFilterFrc;
+
+        // VPP filter configuration
+        uint32_t mFilters;
+        FilterParam mFilterParam;
+
+        // status
+        uint32_t mInputIndex;
+        uint32_t mOutputIndex;
+        uint32_t mOutputCount;
+
+        // FIXME: not very sure how to check color standard
+        VAProcColorStandardType in_color_standards[VAProcColorStandardCount];
+        VAProcColorStandardType out_color_standards[VAProcColorStandardCount];
+};
+
+#endif //__ISVWorker_H_
diff --git a/ISV/omx/isv_omxcomponent.cpp b/ISV/omx/isv_omxcomponent.cpp
new file mode 100644
index 0000000..94d6f6d
--- /dev/null
+++ b/ISV/omx/isv_omxcomponent.cpp
@@ -0,0 +1,920 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include <OMX_Component.h>
+#include "isv_omxcomponent.h"
+#include <media/hardware/HardwareAPI.h>
+#include "isv_profile.h"
+#include <OMX_IndexExt.h>
+#include <hal_public.h>
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "isv-omxil"
+
+using namespace android;
+
+/**********************************************************************************
+ * component methods & helpers
+ */
+#define GET_ISVOMX_COMPONENT(hComponent)                                    \
+    ISVComponent *pComp = static_cast<ISVComponent*>                        \
+        ((static_cast<OMX_COMPONENTTYPE*>(hComponent))->pComponentPrivate); \
+    if (!pComp)                                                             \
+        return OMX_ErrorBadParameter;
+
+Vector<ISVComponent*> ISVComponent::g_isv_components;
+
+#ifndef TARGET_VPP_USE_GEN
+//global, static
+sp<ISVProcessor> ISVComponent::mProcThread = NULL;
+#endif
+
+//global, static
+pthread_mutex_t ISVComponent::ProcThreadInstanceLock = PTHREAD_MUTEX_INITIALIZER;
+
+ISVComponent::ISVComponent(
+        OMX_PTR pAppData)
+    :   mComponent(NULL),
+        mpCallBacks(NULL),
+        mCore(NULL),
+        mpISVCallBacks(NULL),
+        mISVBufferManager(NULL),
+        mThreadRunning(false),
+        mProcThreadObserver(NULL),
+        mNumISVBuffers(MIN_ISV_BUFFER_NUM),
+        mNumDecoderBuffers(0),
+        mNumDecoderBuffersBak(0),
+        mWidth(0),
+        mHeight(0),
+        mUseAndroidNativeBufferIndex(0),
+        mStoreMetaDataInBuffersIndex(0),
+        mHackFormat(0),
+        mUseAndroidNativeBuffer(false),
+        mUseAndroidNativeBuffer2(false),
+        mVPPEnabled(false),
+        mVPPFlushing(false),
+        mOutputCropChanged(false),
+        mInitialized(false),
+#ifdef TARGET_VPP_USE_GEN
+        mProcThread(NULL),
+#endif
+        mOwnProcessor(false)
+{
+    memset(&mBaseComponent, 0, sizeof(OMX_COMPONENTTYPE));
+    /* handle initialization */
+    SetTypeHeader(&mBaseComponent, sizeof(mBaseComponent));
+    mBaseComponent.pApplicationPrivate = pAppData;
+    mBaseComponent.pComponentPrivate = static_cast<OMX_PTR>(this);
+
+    /* connect handle's functions */
+    mBaseComponent.GetComponentVersion = NULL;
+    mBaseComponent.SendCommand = SendCommand;
+    mBaseComponent.GetParameter = GetParameter;
+    mBaseComponent.SetParameter = SetParameter;
+    mBaseComponent.GetConfig = GetConfig;
+    mBaseComponent.SetConfig = SetConfig;
+    mBaseComponent.GetExtensionIndex = GetExtensionIndex;
+    mBaseComponent.GetState = GetState;
+    mBaseComponent.ComponentTunnelRequest = NULL;
+    mBaseComponent.UseBuffer = UseBuffer;
+    mBaseComponent.AllocateBuffer = AllocateBuffer;
+    mBaseComponent.FreeBuffer = FreeBuffer;
+    mBaseComponent.EmptyThisBuffer = EmptyThisBuffer;
+    mBaseComponent.FillThisBuffer = FillThisBuffer;
+    mBaseComponent.SetCallbacks = SetCallbacks;
+    mBaseComponent.ComponentDeInit = NULL;
+    mBaseComponent.UseEGLImage = NULL;
+    mBaseComponent.ComponentRoleEnum = ComponentRoleEnum;
+    g_isv_components.push_back(static_cast<ISVComponent*>(this));
+
+    mVPPOn = ISVProfile::isFRCOn() || ISVProfile::isVPPOn();
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPPOn %d", __func__, mVPPOn);
+
+    if (mISVBufferManager == NULL) {
+        mISVBufferManager = new ISVBufferManager();
+    }
+
+}
+
+ISVComponent::~ISVComponent()
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
+    if (mpISVCallBacks) {
+        free(mpISVCallBacks);
+        mpISVCallBacks = NULL;
+    }
+
+    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
+        if (g_isv_components.itemAt(i) == static_cast<ISVComponent*>(this)) {
+            g_isv_components.removeAt(i);
+        }
+    }
+
+    memset(&mBaseComponent, 0, sizeof(OMX_COMPONENTTYPE));
+    deinit();
+    mVPPOn = false;
+    mISVBufferManager = NULL;
+}
+
+status_t ISVComponent::init(int32_t width, int32_t height)
+{
+    if (mInitialized)
+        return STATUS_OK;
+
+    bool frcOn = false;
+    if (mProcThreadObserver == NULL)
+        mProcThreadObserver = new ISVProcThreadObserver(&mBaseComponent, mComponent, mpCallBacks, mISVBufferManager);
+
+    pthread_mutex_lock(&ProcThreadInstanceLock);
+    if (mProcThread == NULL) {
+        mProcThread = new ISVProcessor(false, mISVBufferManager, mProcThreadObserver, width, height);
+        mOwnProcessor = true;
+        mProcThread->start();
+    }
+#ifndef TARGET_VPP_USE_GEN
+    else {
+        mVPPEnabled = false;
+        mOwnProcessor = false;
+        ALOGI("%s: failed to alloc isv processor", __func__);
+        pthread_mutex_unlock(&ProcThreadInstanceLock);
+        return STATUS_ERROR;
+    }
+#endif
+    pthread_mutex_unlock(&ProcThreadInstanceLock);
+
+    mInitialized = true;
+    return STATUS_OK;
+}
+
+void ISVComponent::deinit()
+{
+    pthread_mutex_lock(&ProcThreadInstanceLock);
+    if (mOwnProcessor) {
+        if (mProcThread != NULL) {
+            mProcThread->stop();
+            mProcThread = NULL;
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: delete ISV processor ", __func__);
+        }
+    }
+    pthread_mutex_unlock(&ProcThreadInstanceLock);
+
+    mProcThreadObserver = NULL;
+
+    mInitialized = false;
+}
+
+OMX_CALLBACKTYPE* ISVComponent::getCallBacks(OMX_CALLBACKTYPE* pCallBacks)
+{
+    //reset component callback functions
+    mpCallBacks = pCallBacks;
+    if (mpISVCallBacks) {
+        free(mpISVCallBacks);
+        mpISVCallBacks = NULL;
+    }
+
+    mpISVCallBacks = (OMX_CALLBACKTYPE *)calloc(1, sizeof(OMX_CALLBACKTYPE));
+    if (!mpISVCallBacks) {
+        ALOGE("%s: failed to alloc isv callbacks", __func__);
+        return NULL;
+    }
+    mpISVCallBacks->EventHandler = EventHandler;
+    mpISVCallBacks->EmptyBufferDone = pCallBacks->EmptyBufferDone;
+    mpISVCallBacks->FillBufferDone = FillBufferDone;
+    return mpISVCallBacks;
+}
+
+OMX_ERRORTYPE ISVComponent::SendCommand(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_COMMANDTYPE Cmd,
+    OMX_IN  OMX_U32 nParam1,
+    OMX_IN  OMX_PTR pCmdData)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_SendCommand(Cmd, nParam1, pCmdData);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_SendCommand(
+    OMX_IN  OMX_COMMANDTYPE Cmd,
+    OMX_IN  OMX_U32 nParam1,
+    OMX_IN  OMX_PTR pCmdData)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: Cmd index 0x%08x, nParam1 %d", __func__, Cmd, nParam1);
+
+    if (mVPPEnabled && mVPPOn) {
+        if ((Cmd == OMX_CommandFlush && (nParam1 == kPortIndexOutput || nParam1 == OMX_ALL))
+                || (Cmd == OMX_CommandStateSet && nParam1 == OMX_StateIdle)
+                || (Cmd == OMX_CommandPortDisable && nParam1 == 1)) {
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: receive flush command, notify vpp thread to flush(Seek begin)", __func__);
+            mVPPFlushing = true;
+            mProcThread->notifyFlush();
+        }
+    }
+
+    return OMX_SendCommand(mComponent, Cmd, nParam1, pCmdData);
+}
+
+OMX_ERRORTYPE ISVComponent::GetParameter(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_INDEXTYPE nParamIndex,
+    OMX_INOUT OMX_PTR pComponentParameterStructure)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_GetParameter(nParamIndex, pComponentParameterStructure);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_GetParameter(
+    OMX_IN  OMX_INDEXTYPE nParamIndex,
+    OMX_INOUT OMX_PTR pComponentParameterStructure)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nParamIndex);
+
+    OMX_ERRORTYPE err = OMX_GetParameter(mComponent, nParamIndex, pComponentParameterStructure);
+
+    if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) {
+        OMX_PARAM_PORTDEFINITIONTYPE *def =
+            static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure);
+
+        if (nParamIndex == OMX_IndexParamPortDefinition
+                && def->nPortIndex == kPortIndexOutput) {
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: orignal bufferCountActual %d, bufferCountMin %d",  __func__, def->nBufferCountActual, def->nBufferCountMin);
+#ifndef TARGET_VPP_USE_GEN
+            //FIXME: THIS IS A HACK!! Request NV12 buffer for YV12 format
+            //because VSP only support NV12 output
+            OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
+            if (video_def->eColorFormat == VA_FOURCC_YV12) {
+                //FIXME workaround Disable ISV for YV12 input
+                mVPPEnabled = false;
+                ALOGI("%s: Disable ISV for YV12 input. mVPPEnabled %d", __func__, mVPPEnabled);
+            } else {
+                //FIXME workaround avc low resolution playback
+                def->nBufferCountActual += mNumISVBuffers + 9;
+                def->nBufferCountMin += mNumISVBuffers + 9;
+            }
+#endif
+        }
+    }
+
+    return err;
+}
+
+OMX_ERRORTYPE ISVComponent::SetParameter(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_INDEXTYPE nIndex,
+    OMX_IN  OMX_PTR pComponentParameterStructure)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+ 
+    return pComp->ISV_SetParameter(nIndex, pComponentParameterStructure);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_SetParameter(
+    OMX_IN  OMX_INDEXTYPE nIndex,
+    OMX_IN  OMX_PTR pComponentParameterStructure)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
+
+    if (nIndex == static_cast<OMX_INDEXTYPE>(OMX_IndexExtSetISVMode)) {
+        ISV_MODE* def = static_cast<ISV_MODE*>(pComponentParameterStructure);
+
+        if (*def == ISV_AUTO) {
+            mVPPEnabled = true;
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPPEnabled -->true", __func__);
+#ifndef TARGET_VPP_USE_GEN
+            if (mVPPOn) {
+                uint32_t number = MIN_INPUT_NUM + MIN_OUTPUT_NUM;
+                OMX_INDEXTYPE index;
+                status_t error =
+                    OMX_GetExtensionIndex(
+                            mComponent,
+                            (OMX_STRING)"OMX.Intel.index.vppBufferNum",
+                            &index);
+                if (error == OK) {
+                    error = OMX_SetParameter(mComponent, index, (OMX_PTR)&number);
+                } else {
+                    // ingore this error
+                    ALOGW("Get vpp number index failed");
+                }
+            }
+#endif
+        } else if (*def == ISV_DISABLE)
+            mVPPEnabled = false;
+        return OMX_ErrorNone;
+    }
+
+    OMX_ERRORTYPE err = OMX_SetParameter(mComponent, nIndex, pComponentParameterStructure);
+    if (err == OMX_ErrorNone && mVPPEnabled && mVPPOn) {
+        if (nIndex == OMX_IndexParamPortDefinition) {
+            OMX_PARAM_PORTDEFINITIONTYPE *def =
+                static_cast<OMX_PARAM_PORTDEFINITIONTYPE*>(pComponentParameterStructure);
+
+            if (def->nPortIndex == kPortIndexOutput) {
+                //set the buffer count we should fill to decoder before feed buffer to VPP
+                mNumDecoderBuffersBak = mNumDecoderBuffers = def->nBufferCountActual - MIN_OUTPUT_NUM - UNDEQUEUED_NUM;
+                OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
+
+                //FIXME: init itself here
+                if (mWidth != video_def->nFrameWidth
+                        || mHeight != video_def->nFrameHeight) {
+                    deinit();
+                    if (STATUS_OK == init(video_def->nFrameWidth, video_def->nFrameHeight)) {
+                        mWidth = video_def->nFrameWidth;
+                        mHeight = video_def->nFrameHeight;
+                    }
+                }
+                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: def->nBufferCountActual %d, mNumDecoderBuffersBak %d", __func__,
+                        def->nBufferCountActual, mNumDecoderBuffersBak);
+                if (mISVBufferManager != NULL && OK != mISVBufferManager->setBufferCount(def->nBufferCountActual)) {
+                    ALOGE("%s: failed to set ISV buffer count, set VPPEnabled -->false", __func__);
+                    mVPPEnabled = false;
+                }
+                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: video frame width %d, height %d",  __func__, 
+                        video_def->nFrameWidth, video_def->nFrameHeight);
+            }
+
+            if (def->nPortIndex == kPortIndexInput) {
+                OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def->format.video;
+
+                if (mProcThread != NULL)
+                    mProcThread->configFRC(video_def->xFramerate);
+            }
+        }
+
+        if (mUseAndroidNativeBuffer
+                && nIndex == static_cast<OMX_INDEXTYPE>(mUseAndroidNativeBufferIndex)) {
+            UseAndroidNativeBufferParams *def =
+                static_cast<UseAndroidNativeBufferParams*>(pComponentParameterStructure);
+
+            if (mISVBufferManager != NULL && OK != mISVBufferManager->useBuffer(def->nativeBuffer)) {
+                    ALOGE("%s: failed to register graphic buffers to ISV, set mVPPEnabled -->false", __func__);
+                    mVPPEnabled = false;
+            }
+        }
+
+        if (nIndex == static_cast<OMX_INDEXTYPE>(mStoreMetaDataInBuffersIndex)) {
+            StoreMetaDataInBuffersParams *params = static_cast<StoreMetaDataInBuffersParams*>(pComponentParameterStructure);
+            if (params->nPortIndex == kPortIndexOutput) {
+                if (mISVBufferManager != NULL) {
+                    bool bMetaDataMode = params->bStoreMetaData == OMX_TRUE;
+                    mISVBufferManager->setMetaDataMode(bMetaDataMode);
+                } else {
+                    ALOGE("%s: falied to set Meta Data Mode ", __func__);
+                }
+            }
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: receive ISVStoreMetaDataInBuffers mISVWorkMode %d", __func__, (params->bStoreMetaData == OMX_TRUE));
+        }
+    }
+    return err;
+}
+
+OMX_ERRORTYPE ISVComponent::GetConfig(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_INDEXTYPE nIndex,
+    OMX_INOUT OMX_PTR pComponentConfigStructure)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_GetConfig(nIndex, pComponentConfigStructure);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_GetConfig(
+    OMX_IN  OMX_INDEXTYPE nIndex,
+    OMX_INOUT OMX_PTR pComponentConfigStructure)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
+
+    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(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_INDEXTYPE nIndex,
+    OMX_IN  OMX_PTR pComponentConfigStructure)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_SetConfig(nIndex, pComponentConfigStructure);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_SetConfig(
+    OMX_IN  OMX_INDEXTYPE nIndex,
+    OMX_IN  OMX_PTR pComponentConfigStructure)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: nIndex 0x%08x", __func__, nIndex);
+
+    if (nIndex == static_cast<OMX_INDEXTYPE>(OMX_IndexConfigAutoFramerateConversion)) {
+        OMX_CONFIG_BOOLEANTYPE *config = static_cast<OMX_CONFIG_BOOLEANTYPE*>(pComponentConfigStructure);
+        if (config->bEnabled) {
+            mVPPEnabled = true;
+            ALOGI("%s: mVPPEnabled=true", __func__);
+        } else {
+            mVPPEnabled = false;
+            ALOGI("%s: mVPPEnabled=false", __func__);
+        }
+        return OMX_ErrorNone;
+    }
+
+    return OMX_SetConfig(mComponent, nIndex, pComponentConfigStructure);
+}
+
+OMX_ERRORTYPE ISVComponent::GetExtensionIndex(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_STRING cParameterName,
+    OMX_OUT OMX_INDEXTYPE* pIndexType)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_GetExtensionIndex(cParameterName, pIndexType);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_GetExtensionIndex(
+    OMX_IN  OMX_STRING cParameterName,
+    OMX_OUT OMX_INDEXTYPE* pIndexType)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: cParameterName %s", __func__, cParameterName);
+    if(!strncmp(cParameterName, "OMX.intel.index.SetISVMode", strlen(cParameterName))) {
+        *pIndexType = static_cast<OMX_INDEXTYPE>(OMX_IndexExtSetISVMode);
+        return OMX_ErrorNone;
+    }
+
+    OMX_ERRORTYPE err = OMX_GetExtensionIndex(mComponent, cParameterName, pIndexType);
+
+    if(err == OMX_ErrorNone &&
+            !strncmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer2", strlen(cParameterName)))
+        mUseAndroidNativeBuffer2 = true;
+
+    if(err == OMX_ErrorNone &&
+            !strncmp(cParameterName, "OMX.google.android.index.useAndroidNativeBuffer", strlen(cParameterName))) {
+        mUseAndroidNativeBuffer = true;
+        mUseAndroidNativeBufferIndex = static_cast<uint32_t>(*pIndexType);
+    }
+
+    if(err == OMX_ErrorNone &&
+            !strncmp(cParameterName, "OMX.google.android.index.storeMetaDataInBuffers", strlen(cParameterName))) {
+        mStoreMetaDataInBuffersIndex = static_cast<uint32_t>(*pIndexType);
+        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: storeMetaDataInBuffersIndex 0x%08x return %d", __func__, mStoreMetaDataInBuffersIndex, err);
+    }
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: cParameterName %s, nIndex 0x%08x", __func__,
+            cParameterName, *pIndexType);
+    return err;
+}
+
+OMX_ERRORTYPE ISVComponent::GetState(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_OUT OMX_STATETYPE* pState)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_GetState(pState);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_GetState(
+    OMX_OUT OMX_STATETYPE* pState)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
+
+    return OMX_GetState(mComponent, pState);
+}
+
+OMX_ERRORTYPE ISVComponent::UseBuffer(
+    OMX_IN OMX_HANDLETYPE hComponent,
+    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
+    OMX_IN OMX_U32 nPortIndex,
+    OMX_IN OMX_PTR pAppPrivate,
+    OMX_IN OMX_U32 nSizeBytes,
+    OMX_IN OMX_U8 *pBuffer)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_UseBuffer(ppBufferHdr, nPortIndex,
+                                 pAppPrivate, nSizeBytes, pBuffer);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_UseBuffer(
+    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr,
+    OMX_IN OMX_U32 nPortIndex,
+    OMX_IN OMX_PTR pAppPrivate,
+    OMX_IN OMX_U32 nSizeBytes,
+    OMX_IN OMX_U8 *pBuffer)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
+
+    OMX_ERRORTYPE err = OMX_UseBuffer(mComponent, ppBufferHdr, nPortIndex,
+            pAppPrivate, nSizeBytes, pBuffer);
+#ifndef USE_IVP
+    if(err == OMX_ErrorNone
+            && mVPPEnabled
+            && mVPPOn
+            && nPortIndex == kPortIndexOutput
+            /*&& mUseAndroidNativeBuffer2*/) {
+        if (mISVBufferManager != NULL) {
+            if (OK != mISVBufferManager->useBuffer(reinterpret_cast<unsigned long>(pBuffer))) {
+                ALOGE("%s: failed to register graphic buffers to ISV, set mVPPEnabled -->false", __func__);
+                mVPPEnabled = false;
+            } else
+                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: mVPP useBuffer success. buffer handle %p", __func__, pBuffer);
+        }
+    }
+#endif
+    return err;
+}
+
+OMX_ERRORTYPE ISVComponent::AllocateBuffer(
+    OMX_IN OMX_HANDLETYPE hComponent,
+    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
+    OMX_IN OMX_U32 nPortIndex,
+    OMX_IN OMX_PTR pAppPrivate,
+    OMX_IN OMX_U32 nSizeBytes)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_AllocateBuffer(ppBuffer, nPortIndex,
+                                      pAppPrivate, nSizeBytes);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_AllocateBuffer(
+    OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer,
+    OMX_IN OMX_U32 nPortIndex,
+    OMX_IN OMX_PTR pAppPrivate,
+    OMX_IN OMX_U32 nSizeBytes)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
+
+    return OMX_AllocateBuffer(mComponent, ppBuffer, nPortIndex,
+                                      pAppPrivate, nSizeBytes);
+}
+
+OMX_ERRORTYPE ISVComponent::FreeBuffer(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_U32 nPortIndex,
+    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_FreeBuffer(nPortIndex, pBuffer);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_FreeBuffer(
+    OMX_IN  OMX_U32 nPortIndex,
+    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer);
+
+    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 OMX_FreeBuffer(mComponent, nPortIndex, pBuffer);
+}
+
+OMX_ERRORTYPE ISVComponent::EmptyThisBuffer(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_EmptyThisBuffer(pBuffer);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_EmptyThisBuffer(
+    OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: pBuffer %p", __func__, pBuffer);
+
+    return OMX_EmptyThisBuffer(mComponent, pBuffer);
+}
+
+OMX_ERRORTYPE ISVComponent::FillThisBuffer(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry.", __func__);
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_FillThisBuffer(pBuffer);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_FillThisBuffer(
+    OMX_IN  OMX_BUFFERHEADERTYPE *pBuffer)
+{
+    if(!mVPPEnabled || !mVPPOn)
+        return OMX_FillThisBuffer(mComponent, pBuffer);
+
+    ISVBuffer* isvBuffer = NULL;
+
+    if (mISVBufferManager != NULL) {
+        isvBuffer = mISVBufferManager->mapBuffer(reinterpret_cast<unsigned long>(pBuffer->pBuffer));
+        if (isvBuffer == NULL) {
+            ALOGE("%s: failed to map ISVBuffer, set mVPPEnabled -->false", __func__);
+            mVPPEnabled = false;
+            return OMX_FillThisBuffer(mComponent, pBuffer);
+        }
+
+        if (OK != isvBuffer->initBufferInfo(mHackFormat)) {
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: isvBuffer %p failed to initBufferInfo", __func__, isvBuffer);
+            mVPPEnabled = false;
+            return OMX_FillThisBuffer(mComponent, pBuffer);
+        }
+    }
+
+    if (mNumDecoderBuffers > 0) {
+        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);
+
+    return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE ISVComponent::FillBufferDone(
+        OMX_OUT OMX_HANDLETYPE hComponent,
+        OMX_OUT OMX_PTR pAppData,
+        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry. ISV component num %d, component handle %p on index 0", __func__,
+            g_isv_components.size(),
+            g_isv_components.itemAt(0));
+    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
+        if (static_cast<OMX_HANDLETYPE>(g_isv_components.itemAt(i)->mComponent) == hComponent)
+            return g_isv_components.itemAt(i)->ISV_FillBufferDone(hComponent, pAppData, pBuffer);
+    }
+    return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_FillBufferDone(
+        OMX_OUT OMX_HANDLETYPE __maybe_unused hComponent,
+        OMX_OUT OMX_PTR pAppData,
+        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: %p <== buffer_handle_t %p. mVPPEnabled %d, mVPPOn %d", __func__,
+            pBuffer, pBuffer->pBuffer, mVPPEnabled, mVPPOn);
+    if (!mpCallBacks) {
+        ALOGE("%s: no call back functions were registered.", __func__);
+        return OMX_ErrorUndefined;
+    }
+
+    if(!mVPPEnabled || !mVPPOn || mVPPFlushing || pBuffer->nFilledLen == 0) {
+        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: FillBufferDone pBuffer %p, timeStamp %.2f ms", __func__, pBuffer, pBuffer->nTimeStamp/1E3);
+        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;
+}
+
+OMX_ERRORTYPE ISVComponent::EventHandler(
+        OMX_IN OMX_HANDLETYPE hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_EVENTTYPE eEvent,
+        OMX_IN OMX_U32 nData1,
+        OMX_IN OMX_U32 nData2,
+        OMX_IN OMX_PTR pEventData)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: API entry. ISV component num %d, component handle %p on index 0", __func__,
+            g_isv_components.size(),
+            g_isv_components.itemAt(0));
+    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
+        if (static_cast<OMX_HANDLETYPE>(g_isv_components.itemAt(i)->mComponent) == hComponent)
+            return g_isv_components.itemAt(i)->ISV_EventHandler(hComponent, pAppData, eEvent, nData1, nData2, pEventData);
+    }
+    return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_EventHandler(
+        OMX_IN OMX_HANDLETYPE __maybe_unused hComponent,
+        OMX_IN OMX_PTR pAppData,
+        OMX_IN OMX_EVENTTYPE eEvent,
+        OMX_IN OMX_U32 nData1,
+        OMX_IN OMX_U32 nData2,
+        OMX_IN OMX_PTR pEventData)
+{
+    if (!mpCallBacks) {
+        ALOGE("%s: no call back functions were registered.", __func__);
+        return OMX_ErrorUndefined;
+    }
+
+    if(!mVPPEnabled || !mVPPOn)
+        return mpCallBacks->EventHandler(&mBaseComponent, pAppData, eEvent, nData1, nData2, pEventData);
+
+    switch (eEvent) {
+        case OMX_EventCmdComplete:
+        {
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: OMX_EventCmdComplete Cmd type 0x%08x, data2 %d", __func__,
+                    nData1, nData2);
+            if (((OMX_COMMANDTYPE)nData1 == OMX_CommandFlush && (nData2 == kPortIndexOutput || nData2 == OMX_ALL))
+                || ((OMX_COMMANDTYPE)nData1 == OMX_CommandStateSet && nData2 == OMX_StateIdle)
+                || ((OMX_COMMANDTYPE)nData1 == OMX_CommandPortDisable && nData2 == 1)) {
+                mProcThread->waitFlushFinished();
+                mVPPFlushing = false;
+                mNumDecoderBuffers = mNumDecoderBuffersBak;
+            }
+            break;
+        }
+
+        case OMX_EventError:
+        {
+            //do we need do anything here?
+            ALOGE("%s: ERROR(0x%08x, %d)", __func__, nData1, nData2);
+            //mProcThread->flush();
+            break;
+        }
+
+        case OMX_EventPortSettingsChanged:
+        {
+            if (nData1 == kPortIndexOutput && nData2 == OMX_IndexConfigCommonOutputCrop) {
+                ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: output crop changed", __func__);
+                mOutputCropChanged = true;
+                return OMX_ErrorNone;
+            }
+            break;
+        }
+
+        default:
+        {
+            ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: EVENT(%d, %ld, %ld)", __func__, eEvent, nData1, nData2);
+            break;
+        }
+    }
+    return mpCallBacks->EventHandler(&mBaseComponent, pAppData, eEvent, nData1, nData2, pEventData);
+}
+
+OMX_ERRORTYPE ISVComponent::SetCallbacks(
+    OMX_IN  OMX_HANDLETYPE hComponent,
+    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
+    OMX_IN  OMX_PTR pAppData)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_SetCallbacks(pCallbacks, pAppData);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_SetCallbacks(
+    OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
+    OMX_IN  OMX_PTR pAppData)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
+
+    if (mVPPEnabled && mVPPOn) {
+        if (mpISVCallBacks == NULL) {
+            mpISVCallBacks = (OMX_CALLBACKTYPE *)calloc(1, sizeof(OMX_CALLBACKTYPE));
+            if (!mpISVCallBacks) {
+                ALOGE("%s: failed to alloc isv callbacks", __func__);
+                return OMX_ErrorUndefined;
+            }
+        }
+        mpISVCallBacks->EventHandler = EventHandler;
+        mpISVCallBacks->EmptyBufferDone = pCallbacks->EmptyBufferDone;
+        mpISVCallBacks->FillBufferDone = FillBufferDone;
+        mpCallBacks = pCallbacks;
+        return mComponent->SetCallbacks(mComponent, mpISVCallBacks, pAppData);
+    }
+    return mComponent->SetCallbacks(mComponent, pCallbacks, pAppData);
+}
+
+OMX_ERRORTYPE ISVComponent::ComponentRoleEnum(
+    OMX_IN OMX_HANDLETYPE hComponent,
+    OMX_OUT OMX_U8 *cRole,
+    OMX_IN OMX_U32 nIndex)
+{
+    GET_ISVOMX_COMPONENT(hComponent);
+
+    return pComp->ISV_ComponentRoleEnum(cRole, nIndex);
+}
+
+OMX_ERRORTYPE ISVComponent::ISV_ComponentRoleEnum(
+    OMX_OUT OMX_U8 *cRole,
+    OMX_IN OMX_U32 nIndex)
+{
+    ALOGD_IF(ISV_COMPONENT_DEBUG, "%s", __func__);
+
+    return mComponent->ComponentRoleEnum(mComponent, cRole, nIndex);
+}
+
+
+void ISVComponent::SetTypeHeader(OMX_PTR type, OMX_U32 size)
+{
+    OMX_U32 *nsize;
+    OMX_VERSIONTYPE *nversion;
+
+    if (!type)
+        return;
+
+    nsize = (OMX_U32 *)type;
+    nversion = (OMX_VERSIONTYPE *)((OMX_U8 *)type + sizeof(OMX_U32));
+
+    *nsize = size;
+    nversion->nVersion = OMX_SPEC_VERSION;
+}
+
+
+ISVProcThreadObserver::ISVProcThreadObserver(
+        OMX_COMPONENTTYPE *pBaseComponent,
+        OMX_COMPONENTTYPE *pComponent,
+        OMX_CALLBACKTYPE *pCallBacks,
+        sp<ISVBufferManager> bufferManager)
+    :   mBaseComponent(pBaseComponent),
+        mComponent(pComponent),
+        mpCallBacks(pCallBacks),
+        mISVBufferManager(bufferManager)
+{
+    ALOGV("VPPProcThreadObserver!");
+}
+
+ISVProcThreadObserver::~ISVProcThreadObserver()
+{
+    ALOGV("~VPPProcThreadObserver!");
+    mBaseComponent = NULL;
+    mComponent = NULL;
+    mpCallBacks = NULL;
+}
+
+OMX_ERRORTYPE ISVProcThreadObserver::releaseBuffer(PORT_INDEX index, OMX_BUFFERHEADERTYPE* pBuffer, bool bFLush)
+{
+    if (!mBaseComponent || !mComponent || !mpCallBacks)
+        return OMX_ErrorUndefined;
+
+    OMX_ERRORTYPE err = OMX_ErrorNone;
+    if (bFLush) {
+        pBuffer->nFilledLen = 0;
+        pBuffer->nOffset = 0;
+        err = mpCallBacks->FillBufferDone(&mBaseComponent, mBaseComponent->pApplicationPrivate, pBuffer);
+        ALOGD_IF(ISV_COMPONENT_DEBUG, "%s: flush pBuffer %p", __func__, pBuffer);
+        return err;
+    }
+
+    if (index == kPortIndexInput) {
+        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);
+        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;
+}
diff --git a/ISV/omx/isv_omxcore.cpp b/ISV/omx/isv_omxcore.cpp
new file mode 100644
index 0000000..5f6933b
--- /dev/null
+++ b/ISV/omx/isv_omxcore.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <OMX_Core.h>
+#include <OMX_Component.h>
+#include <dlfcn.h>
+
+#include "isv_omxcore.h"
+#include "isv_omxcomponent.h"
+#include "isv_profile.h"
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "isv-omxil"
+
+#define WRS_CORE_NAME "libwrs_omxil_core_pvwrapped.so"
+#define CORE_NUMBER 1
+#ifdef USE_MEDIASDK
+#define MSDK_CORE_NAME "libmfx_omx_core.so"
+#undef CORE_NUMBER
+#define CORE_NUMBER 2
+#endif
+
+
+using namespace android;
+
+static unsigned int g_initialized = 0;
+static unsigned int g_nr_instances = 0;
+static unsigned int g_nr_comp = 0;
+
+static pthread_mutex_t g_module_lock = PTHREAD_MUTEX_INITIALIZER;
+static ISVOMXCore g_cores[CORE_NUMBER];
+static Vector<ISVComponent*> g_isv_components;
+
+/**********************************************************************************
+ * core entry
+ */
+
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void)
+{
+    int ret;
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
+
+    pthread_mutex_lock(&g_module_lock);
+    if (!g_initialized) {
+        for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
+
+            void* libHandle = NULL;
+            if (i == 0)
+                libHandle = dlopen(WRS_CORE_NAME, RTLD_LAZY);
+#ifdef USE_MEDIASDK
+            else
+                libHandle = dlopen(MSDK_CORE_NAME, RTLD_LAZY);
+#endif
+            if (libHandle != NULL) {
+                g_cores[i].mLibHandle = libHandle;
+                g_cores[i].mInit = (ISVOMXCore::InitFunc)dlsym(libHandle, "OMX_Init");
+                g_cores[i].mDeinit = (ISVOMXCore::DeinitFunc)dlsym(libHandle, "OMX_Deinit");
+
+                g_cores[i].mComponentNameEnum =
+                    (ISVOMXCore::ComponentNameEnumFunc)dlsym(libHandle, "OMX_ComponentNameEnum");
+
+                g_cores[i].mGetHandle = (ISVOMXCore::GetHandleFunc)dlsym(libHandle, "OMX_GetHandle");
+                g_cores[i].mFreeHandle = (ISVOMXCore::FreeHandleFunc)dlsym(libHandle, "OMX_FreeHandle");
+
+                g_cores[i].mGetRolesOfComponentHandle =
+                    (ISVOMXCore::GetRolesOfComponentFunc)dlsym(
+                            libHandle, "OMX_GetRolesOfComponent");
+                if (g_cores[i].mInit != NULL) {
+                    (*(g_cores[i].mInit))();
+                }
+                if (g_cores[i].mComponentNameEnum != NULL) {
+                    // calculating number of components registered inside given OMX core
+                    char tmpComponentName[OMX_MAX_STRINGNAME_SIZE] = { 0 };
+                    OMX_U32 tmpIndex = 0;
+                    while (OMX_ErrorNone == ((*(g_cores[i].mComponentNameEnum))(tmpComponentName, OMX_MAX_STRINGNAME_SIZE, tmpIndex))) {
+                        tmpIndex++;
+                        ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: declares component %s", tmpComponentName);
+                    }
+                    g_cores[i].mNumComponents = tmpIndex;
+                    g_nr_comp += g_cores[i].mNumComponents;
+                    ALOGD_IF(ISV_CORE_DEBUG, "OMX IL core: contains %ld components", g_cores[i].mNumComponents);
+                }
+            } else {
+                pthread_mutex_unlock(&g_module_lock);
+                ALOGW("OMX IL core not found");
+            }
+        }
+        g_initialized = 1;
+    }
+    pthread_mutex_unlock(&g_module_lock);
+
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
+    return OMX_ErrorNone;
+}
+
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void)
+{
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
+    OMX_ERRORTYPE ret = OMX_ErrorNone;
+
+    ALOGV("%s: enter", __func__);
+    if (g_initialized == 0)
+        return OMX_ErrorNone;
+
+    pthread_mutex_lock(&g_module_lock);
+    for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
+        if (g_cores[i].mDeinit != NULL) {
+            (*(g_cores[i].mDeinit))();
+        }
+    }
+    pthread_mutex_unlock(&g_module_lock);
+
+    g_initialized = 0;
+
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: exit %d", __func__, ret);
+    return ret;
+}
+
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
+    OMX_OUT OMX_STRING cComponentName,
+    OMX_IN OMX_U32 nNameLength,
+    OMX_IN OMX_U32 nIndex)
+{
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
+    pthread_mutex_lock(&g_module_lock);
+    OMX_U32 relativeIndex = nIndex;
+    if (nIndex >= g_nr_comp) {
+        pthread_mutex_unlock(&g_module_lock);
+        ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
+        return OMX_ErrorNoMore;
+    }
+
+    for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
+        if (g_cores[i].mLibHandle == NULL) {
+           continue;
+        }
+        if (relativeIndex < g_cores[i].mNumComponents) {
+            pthread_mutex_unlock(&g_module_lock);
+            ALOGD_IF(ISV_CORE_DEBUG, "%s: found %luth component %s", __func__, nIndex, cComponentName);
+            return ((*(g_cores[i].mComponentNameEnum))(cComponentName, nNameLength, relativeIndex));
+        } else relativeIndex -= g_cores[i].mNumComponents;
+    }
+    pthread_mutex_unlock(&g_module_lock);
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: exit error!!!", __func__);
+    return OMX_ErrorUndefined;
+}
+
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
+    OMX_OUT OMX_HANDLETYPE* pHandle,
+    OMX_IN OMX_STRING cComponentName,
+    OMX_IN OMX_PTR pAppData,
+    OMX_IN OMX_CALLBACKTYPE *pCallBacks)
+{
+    struct list *entry;
+    OMX_ERRORTYPE ret;
+    OMX_HANDLETYPE tempHandle;
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to get %s", __func__, cComponentName);
+    pthread_mutex_lock(&g_module_lock);
+
+    // create a isv component instant
+    ISVComponent *pISVComponent = new ISVComponent(pAppData);
+    if (!pISVComponent) {
+        ALOGE("%s: failed to alloc isv omx component", __func__);
+        pthread_mutex_unlock(&g_module_lock);
+        return OMX_ErrorInsufficientResources;
+    }
+
+    OMX_CALLBACKTYPE *pISVCallBacks = pISVComponent->getCallBacks(pCallBacks);
+    if (!pISVCallBacks) {
+        ALOGE("%s: failed to get isv callback functions", __func__);
+        pthread_mutex_unlock(&g_module_lock);
+        return OMX_ErrorInsufficientResources;
+    }
+
+    /* find the real component*/
+    for (OMX_U32 i = 0; i < CORE_NUMBER; i++) {
+        if (g_cores[i].mLibHandle == NULL) {
+            continue;
+        }
+
+        OMX_ERRORTYPE omx_res = (*(g_cores[i].mGetHandle))(
+                &tempHandle,
+                const_cast<char *>(cComponentName),
+                pAppData, pISVCallBacks);
+        if(omx_res == OMX_ErrorNone) {
+            pISVComponent->setComponent(static_cast<OMX_COMPONENTTYPE*>(tempHandle), &g_cores[i]);
+            g_isv_components.push_back(pISVComponent);
+            *pHandle = pISVComponent->getBaseComponent();
+
+            ALOGD_IF(ISV_CORE_DEBUG, "%s: found component %s, pHandle %p", __func__, cComponentName, *pHandle);
+            pthread_mutex_unlock(&g_module_lock);
+            return OMX_ErrorNone;
+        }
+    }
+    pthread_mutex_unlock(&g_module_lock);
+
+    delete pISVComponent;
+    pISVComponent = NULL;
+    ALOGD_IF(ISV_CORE_DEBUG, "%s(): exit failure, %s not found", __func__, cComponentName);
+    return OMX_ErrorInvalidComponent;
+}
+
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
+    OMX_IN OMX_HANDLETYPE hComponent)
+{
+    OMX_ERRORTYPE ret;
+
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter, try to free component hanle %p", __func__, hComponent);
+    pthread_mutex_lock(&g_module_lock);
+
+    for (OMX_U32 i = 0; i < g_isv_components.size(); i++) {
+        ISVComponent *pComp = g_isv_components.itemAt(i);
+        if (static_cast<OMX_HANDLETYPE>(pComp->getBaseComponent()) == hComponent) {
+            OMX_ERRORTYPE omx_res = pComp->freeComponent();
+            if (omx_res != OMX_ErrorNone) {
+                ALOGE("%s: free OMX handle %p failed", __func__, hComponent);
+                pthread_mutex_unlock(&g_module_lock);
+                return omx_res;
+            }
+            delete pComp;
+            g_isv_components.removeAt(i);
+            ALOGD_IF(ISV_CORE_DEBUG, "%s: free component %p success", __func__, hComponent);
+            pthread_mutex_unlock(&g_module_lock);
+            return OMX_ErrorNone;
+        }
+    }
+    pthread_mutex_unlock(&g_module_lock);
+    ALOGE("%s(): exit failure, component %p not found", __func__, hComponent);
+    return OMX_ErrorInvalidComponent;
+}
+
+OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
+    OMX_IN OMX_HANDLETYPE __maybe_unused hOutput,
+    OMX_IN OMX_U32 __maybe_unused nPortOutput,
+    OMX_IN OMX_HANDLETYPE __maybe_unused hInput,
+    OMX_IN OMX_U32 __maybe_unused nPortInput)
+{
+    return OMX_ErrorNotImplemented;
+}
+
+OMX_API OMX_ERRORTYPE   OMX_GetContentPipe(
+    OMX_OUT OMX_HANDLETYPE __maybe_unused *hPipe,
+    OMX_IN OMX_STRING __maybe_unused szURI)
+{
+    return OMX_ErrorNotImplemented;
+}
+
+OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
+    OMX_IN OMX_STRING __maybe_unused role,
+    OMX_INOUT OMX_U32 __maybe_unused *pNumComps,
+    OMX_INOUT OMX_U8  __maybe_unused **compNames)
+{
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
+    return OMX_ErrorNotImplemented;
+}
+
+OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
+    OMX_IN OMX_STRING compName,
+    OMX_INOUT OMX_U32 *pNumRoles,
+    OMX_OUT OMX_U8 **roles)
+{
+    ALOGD_IF(ISV_CORE_DEBUG, "%s: enter", __func__);
+    pthread_mutex_lock(&g_module_lock);
+    for (OMX_U32 j = 0; j < CORE_NUMBER; j++) {
+        if (g_cores[j].mLibHandle == NULL) {
+           continue;
+        }
+
+        OMX_U32 numRoles;
+        OMX_ERRORTYPE err = (*(g_cores[j].mGetRolesOfComponentHandle))(
+                const_cast<OMX_STRING>(compName), &numRoles, NULL);
+
+        if (err != OMX_ErrorNone) {
+            continue;
+        }
+
+        if (numRoles > 0) {
+            OMX_U8 **array = new OMX_U8 *[numRoles];
+            for (OMX_U32 i = 0; i < numRoles; ++i) {
+                array[i] = new OMX_U8[OMX_MAX_STRINGNAME_SIZE];
+            }
+
+            OMX_U32 numRoles2 = numRoles;
+            err = (*(g_cores[j].mGetRolesOfComponentHandle))(
+                    const_cast<OMX_STRING>(compName), &numRoles2, array);
+
+            *pNumRoles = numRoles;
+            for (OMX_U32 i = 0; i < numRoles; i++) {
+                if (i < numRoles-1)
+                    roles[i+1] = roles[i] + OMX_MAX_STRINGNAME_SIZE;
+
+                strncpy((OMX_STRING)&roles[i][0],
+                        (const OMX_STRING)&array[i][0], OMX_MAX_STRINGNAME_SIZE);
+                delete[] array[i];
+                array[i] = NULL;
+            }
+
+            delete[] array;
+            array = NULL;
+        }
+
+        pthread_mutex_unlock(&g_module_lock);
+        ALOGD_IF(ISV_CORE_DEBUG, "%s: exit done", __func__);
+        return OMX_ErrorNone;
+    }
+    pthread_mutex_unlock(&g_module_lock);
+
+    ALOGE("%s: invalid component", __func__);
+    return OMX_ErrorInvalidComponent;
+}
+
diff --git a/ISV/profile/isv_profile.cpp b/ISV/profile/isv_profile.cpp
new file mode 100644
index 0000000..86fdd02
--- /dev/null
+++ b/ISV/profile/isv_profile.cpp
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2014 Intel Corporation.  All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <libexpat/expat.h>
+#include <string.h>
+#include <stdio.h>
+#include <utils/Log.h>
+#include "isv_profile.h"
+
+#undef LOG_TAG
+#define LOG_TAG "ISVProfile"
+
+#define QCIF_AREA (176 * 144)
+
+#define DEFAULT_XML_FILE "/etc/video_isv_profile.xml"
+
+using namespace android;
+static const char StatusOn[][5] = {"1frc", "1vpp"};
+
+ISVProfile::ISVProfile(const uint32_t width, const uint32_t height)
+{
+    int i;
+
+    mWidth = width;
+    mHeight = height;
+
+    mCurrentFilter = 0;
+    mCurrentFrcTab = 0;
+    mDefaultVPPStatus = 0;
+    mDefaultFRCStatus = 0;
+
+    mStatus = 0;
+
+    memset(mConfigs, 0, sizeof(ISVConfig) * ProcFilterCount);
+
+    for (i = 0; i < MAX_TAB_SIZE; i++) {
+        mFrcRates[i].input_fps = 0;
+        mFrcRates[i].rate = FRC_RATE_1X;
+    }
+
+    /* get the vpp global setting */
+    //getGlobalStatus();
+
+    /* load the config data from XML file */
+    getDataFromXmlFile();
+
+    /* update the filter status according to the configs */
+    updateFilterStatus();
+
+    /* dump data for debug */
+    dumpConfigData();
+}
+
+ISVProfile::~ISVProfile()
+{
+}
+
+FRC_RATE ISVProfile::getFRCRate(uint32_t inputFps)
+{
+    FRC_RATE rate = FRC_RATE_1X;
+    int i;
+
+    for (i = 0; i < MAX_TAB_SIZE; i++) {
+        if (mFrcRates[i].input_fps == inputFps) {
+            rate = mFrcRates[i].rate;
+            break;
+        }
+    }
+    return rate;
+}
+
+uint32_t ISVProfile::getFilterStatus()
+{
+    return mStatus;
+}
+
+bool ISVProfile::isVPPOn()
+{
+    int32_t status = getGlobalStatus();
+    return (status != -1) ? (((status & VPP_COMMON_ON) != 0) ? true : false) : false;
+}
+
+bool ISVProfile::isFRCOn()
+{
+    int32_t status = getGlobalStatus();
+    return (status != -1) ? (((status & VPP_FRC_ON) != 0) ? true : false) : false;
+}
+
+void ISVProfile::updateFilterStatus() {
+    int i;
+    uint32_t area = mWidth * mHeight;
+
+    for (i = 1; i < ProcFilterCount; i++) {
+        /* check config */
+        if (mConfigs[i].enabled == false)
+            continue;
+
+        if (area > mConfigs[i].minResolution && area <= mConfigs[i].maxResolution)
+            mStatus |= 1 << i;
+        /* we should cover QCIF */
+        else if (area == mConfigs[i].minResolution && area == QCIF_AREA)
+            mStatus |= 1 << i;
+    }
+}
+
+int ISVProfile::getFilterID(const char * name)
+{
+    int index = 0;
+
+    if (strcmp(name, "ProcFilterNoiseReduction") == 0)
+        index = ProcFilterNoiseReduction;
+    else if (strcmp(name, "ProcFilterDeinterlacing") == 0)
+        index = ProcFilterDeinterlacing;
+    else if (strcmp(name, "ProcFilterSharpening") == 0)
+        index = ProcFilterSharpening;
+    else if (strcmp(name, "ProcFilterColorBalance") == 0)
+        index = ProcFilterColorBalance;
+    else if (strcmp(name, "ProcFilterDeblocking") == 0)
+        index = ProcFilterDeblocking;
+    else if (strcmp(name, "ProcFilterFrameRateConversion") == 0)
+        index = ProcFilterFrameRateConversion;
+    else if (strcmp(name, "ProcFilterSkinToneEnhancement") == 0)
+        index = ProcFilterSkinToneEnhancement;
+    else if (strcmp(name, "ProcFilterTotalColorCorrection") == 0)
+        index = ProcFilterTotalColorCorrection;
+    else if (strcmp(name, "ProcFilterNonLinearAnamorphicScaling") == 0)
+        index = ProcFilterNonLinearAnamorphicScaling;
+    else if (strcmp(name, "ProcFilterImageStabilization") == 0)
+        index = ProcFilterImageStabilization;
+    else
+        index = 0;
+
+    mCurrentFilter = index;
+
+    return index;
+}
+
+uint32_t ISVProfile::getResolution(const char * name)
+{
+    uint32_t width = 0, height = 0;
+    char *p = NULL, *str = NULL;
+    int32_t lenth = strlen(name);
+
+    str = (char*)malloc(lenth+1);
+    if (NULL == str) {
+        ALOGE("%s: failed to malloc buffer", __func__);
+        return 0;
+    }
+    strncpy(str, name, lenth);
+    str[lenth] = '\0';
+
+    p = strtok(str, "x");
+    if (p)
+        width = atoi(p);
+    p = strtok(NULL, "x");
+    if (p)
+        height = atoi(p);
+
+    if (str) {
+        free(str);
+        str = NULL;
+    }
+    return width * height;
+}
+
+void ISVProfile::getConfigData(const char *name, const char **atts)
+{
+    int attIndex = 0;
+
+    if (strcmp(name, "VideoPostProcessSettings") == 0) {
+        return;
+    } else if (strcmp(name, "Filter") == 0) {
+        if (strcmp(atts[attIndex], "name") == 0) {
+            if (getFilterID(atts[attIndex + 1]) == 0) {
+                ALOGE("Couldn't parase the filter %s\n", atts[attIndex+1]);
+            }
+        } else {
+            ALOGE("couldn't handle \"%s\" element for Filter\n", name);
+        }
+    } else if (strcmp(name, "enabled") == 0) {
+        if (mCurrentFilter) {
+            if (!strcmp(atts[attIndex], "value") && !strcmp(atts[attIndex + 1], "true"))
+                mConfigs[mCurrentFilter].enabled = true;
+        } else {
+            ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name);
+        }
+    } else if (strcmp(name, "minResolution") == 0) {
+        if (mCurrentFilter && !strcmp(atts[attIndex], "value")) {
+            if (!strcmp(atts[attIndex + 1], "0"))
+                mConfigs[mCurrentFilter].minResolution = 0;
+            else if (!strcmp(atts[attIndex + 1], "FFFFFFFF"))
+                mConfigs[mCurrentFilter].minResolution = 0xFFFFFFFF;
+            else
+                mConfigs[mCurrentFilter].minResolution = getResolution(atts[attIndex + 1]);
+        } else {
+            ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name);
+        }
+    } else if (strcmp(name, "maxResolution") == 0) {
+        if (mCurrentFilter && !strcmp(atts[attIndex], "value")) {
+            if (!strcmp(atts[attIndex + 1], "0"))
+                mConfigs[mCurrentFilter].maxResolution = 0;
+            else if (!strcmp(atts[attIndex + 1], "FFFFFFFF"))
+                mConfigs[mCurrentFilter].maxResolution = 0xFFFFFFFF;
+            else
+                mConfigs[mCurrentFilter].maxResolution = getResolution(atts[attIndex + 1]);
+        } else {
+            ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name);
+        }
+    } else if (strcmp(name, "FRCRate") == 0) {
+        if (mCurrentFilter == ProcFilterFrameRateConversion) {
+            if (!strcmp(atts[attIndex], "input") && !strcmp(atts[attIndex + 2], "rate")) {
+                mFrcRates[mCurrentFrcTab].input_fps = atoi(atts[attIndex + 1]);
+                if (!strcmp(atts[attIndex + 3], "2"))
+                    mFrcRates[mCurrentFrcTab].rate = FRC_RATE_2X;
+                else if (!strcmp(atts[attIndex + 3], "2.5"))
+                    mFrcRates[mCurrentFrcTab].rate = FRC_RATE_2_5X;
+                else if (!strcmp(atts[attIndex + 3], "4"))
+                    mFrcRates[mCurrentFrcTab].rate = FRC_RATE_4X;
+                else
+                     mFrcRates[mCurrentFrcTab].rate = FRC_RATE_1X;
+
+                /* update the pointer */
+                if (mCurrentFrcTab < MAX_TAB_SIZE)
+                    mCurrentFrcTab++;
+            }
+        } else {
+            ALOGE("\"FRCRate\" element is only for ProcFilterFrameRateConversion\n");
+        }
+    } else if (strcmp(name, "parameter") == 0) {
+        /* <parameter /> */
+        handleFilterParameter(name, atts);
+    } else if (strcmp(name, "Parameter") == 0) {
+        /* <Parameter /> */
+        handleCommonParameter(name, atts);
+    } else
+        ALOGE("Couldn't handle this element %s!\n", name);
+}
+
+void ISVProfile::handleFilterParameter(const char *name, const char **atts)
+{
+    int attIndex = 0;
+
+    if (!mCurrentFilter) {
+        ALOGE("\"%s\" must be in Filter element\n");
+        return;
+    }
+
+    if (strcmp(atts[attIndex], "name") || strcmp(atts[attIndex + 2], "value")) {
+        ALOGE("\"%s\" or \"%s\" couldn't match the %s format\n", atts[attIndex], atts[attIndex + 2], name);
+        return;
+    }
+
+}
+
+void ISVProfile::handleCommonParameter(const char *name, const char **atts)
+{
+    int attIndex = 0;
+
+    if (strcmp(atts[attIndex], "name") || strcmp(atts[attIndex + 2], "value")) {
+        ALOGE("\"%s\" or \"%s\" couldn't match the %s format\n", atts[attIndex], atts[attIndex + 2], name);
+        return;
+    }
+
+    /* The default status of VPP */
+    if (strcmp(atts[attIndex + 1], "DefaultVPPStatus") == 0)
+        mDefaultVPPStatus = atoi(atts[attIndex + 3]);
+    /* The default status of FRC */
+    else if (strcmp(atts[attIndex + 1], "DefaultFRCStatus") == 0)
+        mDefaultFRCStatus = atoi(atts[attIndex + 3]);
+}
+
+void ISVProfile::startElement(void *userData, const char *name, const char **atts)
+{
+    ISVProfile *profile = (ISVProfile *)userData;
+
+    profile->getConfigData(name, atts);
+}
+
+void ISVProfile::endElement(void *userData, const char *name)
+{
+    ISVProfile *profile = (ISVProfile *)userData;
+
+    if (!strcmp(name, "Filter"))
+        profile->mCurrentFilter = 0;
+}
+
+void ISVProfile::getDataFromXmlFile()
+{
+    int done;
+    void *pBuf = NULL;
+    FILE *fp = NULL;
+
+    fp = ::fopen(DEFAULT_XML_FILE, "r");
+    if (NULL == fp) {
+        ALOGE("@%s, line:%d, couldn't open profile %s", __func__, __LINE__, DEFAULT_XML_FILE);
+        return;
+    }
+
+    XML_Parser parser = ::XML_ParserCreate(NULL);
+    if (NULL == parser) {
+        ALOGE("@%s, line:%d, parser is NULL", __func__, __LINE__);
+        goto exit;
+    }
+    ::XML_SetUserData(parser, this);
+    ::XML_SetElementHandler(parser, startElement, endElement);
+
+    pBuf = malloc(mBufSize);
+    if (NULL == pBuf) {
+        ALOGE("@%s, line:%d, failed to malloc buffer", __func__, __LINE__);
+        goto exit;
+    }
+
+    do {
+        int len = (int)::fread(pBuf, 1, mBufSize, fp);
+        if (!len) {
+            if (ferror(fp)) {
+                clearerr(fp);
+                goto exit;
+            }
+        }
+        done = len < mBufSize;
+        if (XML_Parse(parser, (const char *)pBuf, len, done) == XML_STATUS_ERROR) {
+            ALOGE("@%s, line:%d, XML_Parse error", __func__, __LINE__);
+            goto exit;
+        }
+    } while (!done);
+
+exit:
+    if (parser)
+        ::XML_ParserFree(parser);
+    if (pBuf)
+        free(pBuf);
+    if (fp)
+    ::fclose(fp);
+}
+
+int32_t ISVProfile::getGlobalStatus()
+{
+    char path[80];
+    int userId = 0;
+    int32_t status = 0;
+    FILE *setting_handle, *config_handle;
+
+    snprintf(path, 80, "/data/user/%d/com.intel.vpp/shared_prefs/vpp_settings.xml", userId);
+    ALOGV("%s: %s",__func__, path);
+    setting_handle = fopen(path, "r");
+    if(setting_handle == NULL) {
+        ALOGE("%s: failed to open file %s\n", __func__, path);
+
+        /* Read the Filter config file to get default value */
+        config_handle = fopen(DEFAULT_XML_FILE, "r");
+        if (config_handle == NULL) {
+            ALOGE("%s: failed to open file %s\n", __func__, DEFAULT_XML_FILE);
+            return -1;
+        }
+
+        char xml_buf[MAX_BUF_SIZE + 1] = {0};
+        memset(xml_buf, 0, MAX_BUF_SIZE);
+        if (fread(xml_buf, 1, MAX_BUF_SIZE, config_handle) <= 0) {
+            ALOGE("%s: failed to read config xml file!\n", __func__);
+            fclose(config_handle);
+            return -1;
+        }
+        xml_buf[MAX_BUF_SIZE] = '\0';
+
+        if (strstr(xml_buf, "name=\"DefaultVPPStatus\" value=\"1\"") != NULL)
+            status |= VPP_COMMON_ON;
+        if (strstr(xml_buf, "name=\"DefaultFRCStatus\" value=\"1\"") != NULL)
+            status |= VPP_FRC_ON;
+
+        ALOGV("%s: using the default status: VPP=%d, FRC=%d\n", __func__,
+            ((status & VPP_COMMON_ON) == 0) ? 0 : 1,
+            ((status & VPP_FRC_ON) == 0) ? 0: 1);
+
+        fclose(config_handle);
+        return status;
+    }
+
+    const int MAXLEN = 1024;
+    char buf[MAXLEN] = {0};
+    memset(buf, 0 ,MAXLEN);
+    if(fread(buf, 1, MAXLEN, setting_handle) <= 0) {
+        ALOGE("%s: failed to read vpp config file %d", __func__, userId);
+        fclose(setting_handle);
+        return -1;
+    }
+    buf[MAXLEN - 1] = '\0';
+
+    if(strstr(buf, StatusOn[0]) != NULL)
+        status |= VPP_FRC_ON;
+
+    if(strstr(buf, StatusOn[1]) != NULL)
+        status |= VPP_COMMON_ON;
+
+    fclose(setting_handle);
+    return status;
+}
+
+void ISVProfile::dumpConfigData()
+{
+    uint32_t i, j;
+    char filterNames[][50] = {
+        "ProcFilterNone",
+        "ProcFilterNoiseReduction",
+        "ProcFilterDeinterlacing",
+        "ProcFilterSharpening",
+        "ProcFilterColorBalance",
+        "ProcFilterDeblocking",
+        "ProcFilterFrameRateConversion",
+        "ProcFilterSkinToneEnhancement",
+        "ProcFilterTotalColorCorrection",
+        "ProcFilterNonLinearAnamorphicScaling",
+        "ProcFilterImageStabilization"
+    };
+    char rateNames[][20] = {
+        "FRC_RATE_0X",
+        "FRC_RATE_1X",
+        "FRC_RATE_2X",
+        "FRC_RATE_2_5X",
+        "FRC_RATE_4X",
+    };
+
+    ALOGV("========== VPP filter configs:==========\n");
+    for (i = 1; i < ProcFilterCount; i++) {
+        ALOGV("name=%s, enabled=%s, minResolution=%d, maxResolution=%d, isOn=%s\n",
+            filterNames[i],
+            (mConfigs[i].enabled == true) ? "true" : "false",
+            mConfigs[i].minResolution,
+            mConfigs[i].maxResolution,
+            ((mStatus & (1 << i)) == 0) ? "false" : "true");
+        if (mConfigs[i].paraSize) {
+            ALOGV("\t\t parameters: ");
+            for(j = 0; j < mConfigs[i].paraSize; j++)
+                ALOGE("%s=%f,", mConfigs[i].paraTables[j].name, mConfigs[i].paraTables[j].value);
+            ALOGV("\n");
+        }
+    }
+
+    ALOGV("========== FRC rate configs:===========\n");
+    for (i = 0; i < MAX_TAB_SIZE; i++) {
+        if (mFrcRates[i].input_fps == 0)
+            break;
+        ALOGV("input_fps=%d, rate=%s\n", mFrcRates[i].input_fps, rateNames[mFrcRates[i].rate]);
+    }
+
+    ALOGI("========== common parameter configs:===========\n");
+    ALOGI("mDefaultVPPStatus=%d\n", mDefaultVPPStatus);
+    ALOGI("mDefaultFRCStatus=%d\n", mDefaultFRCStatus);
+
+}
diff --git a/ituxd/jni/thermalJNI.cpp b/ituxd/jni/thermalJNI.cpp
index 4c92775..8a64906 100644
--- a/ituxd/jni/thermalJNI.cpp
+++ b/ituxd/jni/thermalJNI.cpp
@@ -248,9 +248,35 @@
     }
 }
 
+static jint readSysfsTemp(JNIEnv* env, jobject obj, jstring jPath)
+{
+    const char *path = NULL;
+    const int SIZE = 64;
+    char buf[SIZE];
+    // Convention: To allow returning of normal negative temperatures
+    // (say -10C), let us return errno as a negative offset from
+    // absolute zero millidegree C.
+    const int ABS_ZERO = -273000;
+    int ret;
+
+    path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
+    if (!path) {
+        jniThrowNullPointerException(env, "path");
+        return (ABS_ZERO - ENOENT);
+    }
+
+    ret = readFromFile(path, buf, SIZE, true);
+    env->ReleaseStringUTFChars(jPath, path);
+    if (ret > 0) {
+        return atoi(buf);
+    }
+    return (ret + ABS_ZERO);
+}
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
         {"native_readSysfs", "(Ljava/lang/String;)Ljava/lang/String;", (void*)readSysfs},
+        {"native_readSysfsTemp", "(Ljava/lang/String;)I", (void*)readSysfsTemp},
         {"native_writeSysfs", "(Ljava/lang/String;I)I", (void*)writeSysfs},
         {"native_getThermalZoneIndex", "(Ljava/lang/String;)I", (void*)getThermalZoneIndex},
         {"native_getThermalZoneIndexContains", "(Ljava/lang/String;)I",
diff --git a/ituxd/src/com/intel/thermal/RawThermalZone.java b/ituxd/src/com/intel/thermal/RawThermalZone.java
index 4baba9a..9953a02 100644
--- a/ituxd/src/com/intel/thermal/RawThermalZone.java
+++ b/ituxd/src/com/intel/thermal/RawThermalZone.java
@@ -75,9 +75,10 @@
             }
         } else {
             //zone temp is max of all sensor temp
-            for (ThermalSensor ts : getThermalSensorList()) {
-                if (ts != null && ts.getSensorActiveStatus()) {
-                    curTemp = ts.getCurrTemp();
+            for (int i = 0; i < mThermalSensors.size(); i++) {
+                if (mThermalSensors.get(i) != null &&
+                        mThermalSensors.get(i).getSensorActiveStatus()) {
+                    curTemp = mThermalSensors.get(i).getCurrTemp();
                     if (curTemp > maxCurTemp) {
                         maxCurTemp = curTemp;
                     }
diff --git a/ituxd/src/com/intel/thermal/ThermalManager.java b/ituxd/src/com/intel/thermal/ThermalManager.java
index b68bd3d..e9e5597 100644
--- a/ituxd/src/com/intel/thermal/ThermalManager.java
+++ b/ituxd/src/com/intel/thermal/ThermalManager.java
@@ -207,6 +207,9 @@
 
     public static final int INVALID_TEMP = 0xDEADBEEF;
 
+    /* Absolute zero in millidegree C */
+    public static final int ABS_ZERO = -273000;
+
     /* base sysfs path for sensors */
     public static final String sSysfsSensorBasePath = "/sys/class/thermal/thermal_zone";
 
diff --git a/ituxd/src/com/intel/thermal/ThermalSensor.java b/ituxd/src/com/intel/thermal/ThermalSensor.java
index 78c7739..eb6d75f 100644
--- a/ituxd/src/com/intel/thermal/ThermalSensor.java
+++ b/ituxd/src/com/intel/thermal/ThermalSensor.java
@@ -219,14 +219,11 @@
      * Method that actually does a Sysfs read.
      */
     public int readSensorTemp() {
-        int val = ThermalManager.INVALID_TEMP;
-        try {
-            String tempStr = ThermalUtils.readSysfs(mInputTempPath);
-            if (tempStr != null) {
-                val = Integer.parseInt(tempStr.trim());
-            }
-        } catch (NumberFormatException e) {
-            Log.i(TAG, "NumberFormatException in readSensorTemp():" + mInputTempPath);
+        int val = ThermalUtils.readSysfsTemp(mInputTempPath);
+        if (val <= ThermalManager.ABS_ZERO) {
+            // Error will be returned as negative offset from absolute zero in milli degree C
+            Log.e(TAG, "readSensorTemp failed with error:" + (val - ThermalManager.ABS_ZERO));
+            val = ThermalManager.INVALID_TEMP;
         }
         return val;
     }
diff --git a/ituxd/src/com/intel/thermal/ThermalUtils.java b/ituxd/src/com/intel/thermal/ThermalUtils.java
index 7126f9b..0094e5b 100644
--- a/ituxd/src/com/intel/thermal/ThermalUtils.java
+++ b/ituxd/src/com/intel/thermal/ThermalUtils.java
@@ -37,6 +37,7 @@
 
     /* Native methods to access Sysfs Interfaces */
     private native static String native_readSysfs(String path);
+    private native static int native_readSysfsTemp(String path);
     private native static int native_writeSysfs(String path, int val);
     private native static int native_getThermalZoneIndex(String name);
     private native static int native_getThermalZoneIndexContains(String name);
@@ -54,6 +55,15 @@
         }
     }
 
+    public static int readSysfsTemp(String path) {
+        try {
+            return native_readSysfsTemp(path);
+        } catch (UnsatisfiedLinkError e) {
+            Log.i(TAG, "caught UnsatisfiedLinkError in readSysfsTemp");
+            return INVALID_TEMP;
+        }
+    }
+
     public static int writeSysfs(String path, int val) {
         try {
             return native_writeSysfs(path, val);
@@ -143,22 +153,11 @@
     }
 
     public static void getTjMax() {
-        String temp_tjmax;
-
-        temp_tjmax = readSysfs(ThermalManager.TJMAX_PATH);
-        if (temp_tjmax != null) {
-            try {
-                ThermalManager.sTjMaxTemp = Integer.parseInt(temp_tjmax);
-                Log.i(TAG, "TjMax temp = " + ThermalManager.sTjMaxTemp);
-            } catch (NumberFormatException e) {
-                ThermalManager.sTjMaxTemp = ThermalManager.sDefaultTjMax;
-                Log.i(TAG, "TjMax value invalid, Default TjMax value =" +
-                        ThermalManager.sTjMaxTemp);
-            }
-        } else {
-            ThermalManager.sTjMaxTemp = ThermalManager.sDefaultTjMax;
+        ThermalManager.sTjMaxTemp = readSysfsTemp(ThermalManager.TJMAX_PATH);
+        if (ThermalManager.sTjMaxTemp <= ThermalManager.ABS_ZERO) {
             Log.i(TAG, "TjMax temp read failed, Default TjMax value =" +
                     ThermalManager.sTjMaxTemp);
+            ThermalManager.sTjMaxTemp = ThermalManager.sDefaultTjMax;
         }
     }
 
diff --git a/ituxd/src/com/intel/thermal/ThermalZone.java b/ituxd/src/com/intel/thermal/ThermalZone.java
index a3af5af..9844f9e 100644
--- a/ituxd/src/com/intel/thermal/ThermalZone.java
+++ b/ituxd/src/com/intel/thermal/ThermalZone.java
@@ -481,9 +481,9 @@
      * zone operates in polling mode.
      */
     public boolean isZoneStateChanged() {
-        for (ThermalSensor ts : mThermalSensors) {
-            if (ts.getSensorActiveStatus()) {
-                ts.updateSensorTemp();
+        for (int i = 0; i < mThermalSensors.size(); i++) {
+            if (mThermalSensors.get(i).getSensorActiveStatus()) {
+                mThermalSensors.get(i).updateSensorTemp();
             }
         }
         return updateZoneParams();
diff --git a/ituxd/src/com/intel/thermal/VirtualThermalZone.java b/ituxd/src/com/intel/thermal/VirtualThermalZone.java
index 1f4fd4d..52364ca 100644
--- a/ituxd/src/com/intel/thermal/VirtualThermalZone.java
+++ b/ituxd/src/com/intel/thermal/VirtualThermalZone.java
@@ -175,14 +175,15 @@
             // In UEvent mode, the obtained temperature is the zone temperature
             return true;
         } else {
-            for (ThermalSensor ts : getThermalSensorList()) {
-                if (ts != null && ts.getSensorActiveStatus()) {
+            for (int i = 0; i < mThermalSensors.size(); i++) {
+                if (mThermalSensors.get(i) != null
+                        && mThermalSensors.get(i).getSensorActiveStatus()) {
                     if (flag == false) {
                         // one time initialization of zone temp
                         curZoneTemp = 0;
                         flag = true;
                     }
-                    weightedTemp = getWeightedTemp(ts);
+                    weightedTemp = getWeightedTemp(mThermalSensors.get(i));
                     if (weightedTemp != ThermalManager.INVALID_TEMP) {
                         curZoneTemp += weightedTemp;
                     }