Initial libmix commit

Change-Id: I7a0b9afdc83a3274189cef0788c7296a871a3d98
Signed-off-by: Guilhem IMBERTON <guilhem.imberton@intel.com>
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..7c49108
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,6 @@
+AUDIO_PATH := $(call my-dir)
+
+ifeq ($(INTEL_VA),true)
+ include $(AUDIO_PATH)/videodecoder/Android.mk
+ include $(AUDIO_PATH)/videoencoder/Android.mk
+endif
diff --git a/README b/README
new file mode 100644
index 0000000..825359e
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+intel moorestown mix library
diff --git a/videodecoder/Android.mk b/videodecoder/Android.mk
new file mode 100644
index 0000000..885b325
--- /dev/null
+++ b/videodecoder/Android.mk
@@ -0,0 +1,79 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+ifeq ($(TARGET_HAS_VPP),true)
+LOCAL_CFLAGS += -DTARGET_HAS_VPP
+endif
+
+LOCAL_SRC_FILES := \
+    VideoDecoderHost.cpp \
+    VideoDecoderBase.cpp \
+    VideoDecoderWMV.cpp \
+    VideoDecoderMPEG4.cpp \
+    VideoDecoderAVC.cpp \
+    VideoDecoderTrace.cpp
+
+LOCAL_C_INCLUDES := \
+    $(TARGET_OUT_HEADERS)/libva \
+    $(TARGET_OUT_HEADERS)/libmixvbp
+
+ifeq ($(USE_INTEL_SECURE_AVC),true)
+LOCAL_CFLAGS += -DUSE_INTEL_SECURE_AVC
+LOCAL_SRC_FILES += securevideo/$(TARGET_BOARD_PLATFORM)/VideoDecoderAVCSecure.cpp
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/securevideo/$(TARGET_BOARD_PLATFORM)
+LOCAL_CFLAGS += -DUSE_INTEL_SECURE_AVC
+endif
+
+PLATFORM_USE_GEN_HW := \
+    baytrail \
+    cherrytrail
+
+ifneq ($(filter $(TARGET_BOARD_PLATFORM),$(PLATFORM_USE_GEN_HW)),)
+    LOCAL_CFLAGS += -DUSE_AVC_SHORT_FORMAT -DUSE_GEN_HW
+endif
+
+
+PLATFORM_USE_HYBRID_DRIVER := \
+    baytrail
+
+ifneq ($(filter $(TARGET_BOARD_PLATFORM),$(PLATFORM_USE_HYBRID_DRIVER)),)
+    LOCAL_CFLAGS += -DUSE_HYBRID_DRIVER
+endif
+
+PLATFORM_SUPPORT_SLICE_HEADER_PARSER := \
+    merrifield \
+    moorefield
+
+ifneq ($(filter $(TARGET_BOARD_PLATFORM),$(PLATFORM_SUPPORT_SLICE_HEADER_PARSER)),)
+    LOCAL_CFLAGS += -DUSE_SLICE_HEADER_PARSING
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libva \
+    libva-android \
+    libva-tpi \
+    libdl
+
+LOCAL_COPY_HEADERS_TO  := libmix_videodecoder
+
+LOCAL_COPY_HEADERS := \
+    VideoDecoderHost.h \
+    VideoDecoderInterface.h \
+    VideoDecoderDefs.h
+
+ifneq ($(filter $(TARGET_BOARD_PLATFORM),$(PLATFORM_SUPPORT_SLICE_HEADER_PARSER)),)
+    LOCAL_COPY_HEADERS += securevideo/$(TARGET_BOARD_PLATFORM)/VideoFrameInfo.h
+endif
+
+LOCAL_CFLAGS += -Werror
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libva_videodecoder
+
+ifeq ($(USE_HW_VP8),true)
+LOCAL_SRC_FILES += VideoDecoderVP8.cpp
+LOCAL_CFLAGS += -DUSE_HW_VP8
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/videodecoder/VideoDecoderAVC.cpp b/videodecoder/VideoDecoderAVC.cpp
new file mode 100644
index 0000000..8ed91f9
--- /dev/null
+++ b/videodecoder/VideoDecoderAVC.cpp
@@ -0,0 +1,992 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderAVC.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+#include <cutils/properties.h>
+
+// Macros for actual buffer needed calculation
+#define WIDI_CONSUMED   6
+#define HDMI_CONSUMED   2
+#define NW_CONSUMED     2
+#define POC_DEFAULT     0x7FFFFFFF
+
+VideoDecoderAVC::VideoDecoderAVC(const char *mimeType)
+    : VideoDecoderBase(mimeType, VBP_H264),
+      mToggleDPB(0),
+      mErrorConcealment(false){
+
+    invalidateDPB(0);
+    invalidateDPB(1);
+    mLastPictureFlags = VA_PICTURE_H264_INVALID;
+}
+
+VideoDecoderAVC::~VideoDecoderAVC() {
+    stop();
+}
+
+Decode_Status VideoDecoderAVC::start(VideoConfigBuffer *buffer) {
+    Decode_Status status;
+
+    status = VideoDecoderBase::start(buffer);
+    CHECK_STATUS("VideoDecoderBase::start");
+
+    // We don't want base class to manage reference.
+    VideoDecoderBase::ManageReference(false);
+    // output by picture order count
+    VideoDecoderBase::setOutputMethod(OUTPUT_BY_POC);
+
+    mErrorConcealment = buffer->flag & WANT_ERROR_CONCEALMENT;
+    if (buffer->data == NULL || buffer->size == 0) {
+        WTRACE("No config data to start VA.");
+        if ((buffer->flag & HAS_SURFACE_NUMBER) && (buffer->flag & HAS_VA_PROFILE)) {
+            ITRACE("Used client supplied profile and surface to start VA.");
+            return VideoDecoderBase::setupVA(buffer->surfaceNumber, buffer->profile);
+        }
+        return DECODE_SUCCESS;
+    }
+
+    vbp_data_h264 *data = NULL;
+    status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
+    CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+    status = startVA(data);
+    return status;
+}
+
+void VideoDecoderAVC::stop(void) {
+    // drop the last  frame and ignore return value
+    endDecodingFrame(true);
+    VideoDecoderBase::stop();
+    invalidateDPB(0);
+    invalidateDPB(1);
+    mToggleDPB = 0;
+    mErrorConcealment = false;
+    mLastPictureFlags = VA_PICTURE_H264_INVALID;
+}
+
+void VideoDecoderAVC::flush(void) {
+    // drop the frame and ignore return value
+    VideoDecoderBase::flush();
+    invalidateDPB(0);
+    invalidateDPB(1);
+    mToggleDPB = 0;
+    mLastPictureFlags = VA_PICTURE_H264_INVALID;
+}
+
+Decode_Status VideoDecoderAVC::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    vbp_data_h264 *data = NULL;
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+    status =  VideoDecoderBase::parseBuffer(
+            buffer->data,
+            buffer->size,
+            false,
+            (void**)&data);
+    CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+    if (!mVAStarted) {
+         if (data->has_sps && data->has_pps) {
+            status = startVA(data);
+            CHECK_STATUS("startVA");
+        } else {
+            WTRACE("Can't start VA as either SPS or PPS is still not available.");
+            return DECODE_SUCCESS;
+        }
+    }
+
+    VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees);
+
+    status = decodeFrame(buffer, data);
+    if (status == DECODE_MULTIPLE_FRAME) {
+        buffer->ext = &mExtensionBuffer;
+        mExtensionBuffer.extType = PACKED_FRAME_TYPE;
+        mExtensionBuffer.extSize = sizeof(mPackedFrame);
+        mExtensionBuffer.extData = (uint8_t*)&mPackedFrame;
+    }
+    return status;
+}
+
+Decode_Status VideoDecoderAVC::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_h264 *data) {
+    Decode_Status status;
+    if (data->has_sps == 0 || data->has_pps == 0) {
+        return DECODE_NO_CONFIG;
+    }
+
+    mVideoFormatInfo.flags = 0;
+    uint32_t fieldFlags = 0;
+    for (unsigned int i = 0; i < data->num_pictures; i++) {
+        VAPictureH264 &pic = data->pic_data[i].pic_parms->CurrPic;
+        fieldFlags |= pic.flags;
+        // Don't remove the following codes, it can be enabled for debugging DPB.
+#if 0
+        VTRACE("%d: decoding frame %.2f, poc top = %d, poc bottom = %d, flags = %d,  reference = %d",
+                i,
+                buffer->timeStamp/1E6,
+                pic.TopFieldOrderCnt,
+                pic.BottomFieldOrderCnt,
+                pic.flags,
+                (pic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+                (pic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE));
+#endif
+    }
+    int32_t topField = fieldFlags & VA_PICTURE_H264_TOP_FIELD;
+    int32_t botField = fieldFlags & VA_PICTURE_H264_BOTTOM_FIELD;
+    if ((topField == 0 && botField != 0) || (topField != 0 && botField == 0)) {
+        mVideoFormatInfo.flags |= IS_SINGLE_FIELD;
+    }
+
+    if (data->new_sps || data->new_pps) {
+        status = handleNewSequence(data);
+        CHECK_STATUS("handleNewSequence");
+    }
+
+    if (isWiDiStatusChanged()) {
+        mSizeChanged = false;
+        flushSurfaceBuffers();
+        return DECODE_FORMAT_CHANGE;
+    }
+
+    // first pic_data always exists, check if any slice is parsed
+    if (data->pic_data[0].num_slices == 0) {
+        ITRACE("No slice available for decoding.");
+        status = mSizeChanged ? DECODE_FORMAT_CHANGE : DECODE_SUCCESS;
+        mSizeChanged = false;
+        return status;
+    }
+
+    uint64_t lastPTS = mCurrentPTS;
+    mCurrentPTS = buffer->timeStamp;
+    //if (lastPTS != mCurrentPTS) {
+    if (isNewFrame(data, lastPTS == mCurrentPTS)) {
+        if (mLowDelay) {
+            // start decoding a new frame
+            status = beginDecodingFrame(data);
+            if (status != DECODE_SUCCESS) {
+                Decode_Status st = status;
+                // finish decoding the last frame if
+                // encounter error when decode the new frame
+                status = endDecodingFrame(false);
+                CHECK_STATUS("endDecodingFrame");
+                return st;
+            }
+        }
+
+        // finish decoding the last frame
+        status = endDecodingFrame(false);
+        CHECK_STATUS("endDecodingFrame");
+
+        if (!mLowDelay) {
+            // start decoding a new frame
+            status = beginDecodingFrame(data);
+            CHECK_STATUS("beginDecodingFrame");
+        }
+    } else {
+        status = continueDecodingFrame(data);
+        CHECK_STATUS("continueDecodingFrame");
+    }
+
+    // HAS_COMPLETE_FRAME is not reliable as it may indicate end of a field
+#if 0
+    if (buffer->flag & HAS_COMPLETE_FRAME) {
+        // finish decoding current frame
+        status = endDecodingFrame(false);
+        CHECK_STATUS("endDecodingFrame");
+    }
+#endif
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVC::beginDecodingFrame(vbp_data_h264 *data) {
+    Decode_Status status;
+
+    status = acquireSurfaceBuffer();
+    CHECK_STATUS("acquireSurfaceBuffer");
+    VAPictureH264 *picture = &(data->pic_data[0].pic_parms->CurrPic);
+    if ((picture->flags  & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+        (picture->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)) {
+        mAcquiredBuffer->referenceFrame = true;
+    } else {
+        mAcquiredBuffer->referenceFrame = false;
+    }
+    // set asReference in updateDPB
+
+    if (picture->flags & VA_PICTURE_H264_TOP_FIELD) {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD | VA_TOP_FIELD;
+    } else {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
+    }
+
+    // TODO: Set the discontinuity flag
+    mAcquiredBuffer->renderBuffer.flag = 0;
+    mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
+    mAcquiredBuffer->pictureOrder = getPOC(picture);
+
+    if (mSizeChanged) {
+        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
+        mSizeChanged = false;
+    }
+
+    status  = continueDecodingFrame(data);
+    // surface buffer is released if decode fails
+    return status;
+}
+
+
+Decode_Status VideoDecoderAVC::continueDecodingFrame(vbp_data_h264 *data) {
+    Decode_Status status;
+    vbp_picture_data_h264 *picData = data->pic_data;
+
+    // TODO: remove these debugging codes
+    if (mAcquiredBuffer == NULL || mAcquiredBuffer->renderBuffer.surface == VA_INVALID_SURFACE) {
+        ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
+        return DECODE_FAIL;
+    }
+    for (uint32_t picIndex = 0; picIndex < data->num_pictures; picIndex++, picData++) {
+        // sanity check
+        if (picData == NULL || picData->pic_parms == NULL || picData->slc_data == NULL || picData->num_slices == 0) {
+            return DECODE_PARSER_FAIL;
+        }
+
+        if (picIndex > 0 &&
+            (picData->pic_parms->CurrPic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) == 0) {
+            // it is a packed frame buffer
+            vbp_picture_data_h264 *lastPic = &data->pic_data[picIndex - 1];
+            vbp_slice_data_h264 *sliceData = &(lastPic->slc_data[lastPic->num_slices - 1]);
+            mPackedFrame.offSet = sliceData->slice_size + sliceData->slice_offset;
+            mPackedFrame.timestamp = mCurrentPTS; // use the current time stamp for the packed frame
+            ITRACE("slice data offset= %d, size = %d", sliceData->slice_offset, sliceData->slice_size);
+            return DECODE_MULTIPLE_FRAME;
+        }
+
+        for (uint32_t sliceIndex = 0; sliceIndex < picData->num_slices; sliceIndex++) {
+            status = decodeSlice(data, picIndex, sliceIndex);
+            if (status != DECODE_SUCCESS) {
+                endDecodingFrame(true);
+                // TODO: this is new code
+                // remove current frame from DPB as it can't be decoded.
+                removeReferenceFromDPB(picData->pic_parms);
+                return status;
+            }
+        }
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVC::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+    VABufferID bufferIDs[4];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+            // TODO: handle the first slice lost
+        }
+        if (mDecodingFrame) {
+            // interlace content, complete decoding the first field
+            vaStatus = vaEndPicture(mVADisplay, mVAContext);
+            CHECK_VA_STATUS("vaEndPicture");
+
+            // for interlace content, top field may be valid only after the second field is parsed
+            int32_t poc = getPOC(&(picParam->CurrPic));
+            if (poc < mAcquiredBuffer->pictureOrder) {
+                mAcquiredBuffer->pictureOrder = poc;
+            }
+        }
+
+        // Check there is no reference frame loss before decoding a frame
+
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+#ifndef USE_AVC_SHORT_FORMAT
+        //We have to provide a hacked DPB rather than complete DPB for libva as workaround
+        status = updateReferenceFrames(picData);
+        CHECK_STATUS("updateReferenceFrames");
+#endif
+        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+        CHECK_VA_STATUS("vaBeginPicture");
+
+        // start decoding a frame
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+    }
+
+#ifndef USE_AVC_SHORT_FORMAT
+
+    status = setReference(sliceParam);
+    CHECK_STATUS("setReference");
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+#else
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264Base),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+#endif
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceDataBufferType,
+        sliceData->slice_size, //size
+        1,        //num_elements
+        sliceData->buffer_addr + sliceData->slice_offset,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVC::setReference(VASliceParameterBufferH264 *sliceParam) {
+    int32_t numList = 1;
+    // TODO: set numList to 0 if it is I slice
+    if (sliceParam->slice_type == 1 || sliceParam->slice_type == 6) {
+        // B slice
+        numList = 2;
+    }
+
+    int32_t activeMinus1 = sliceParam->num_ref_idx_l0_active_minus1;
+    VAPictureH264 *ref = sliceParam->RefPicList0;
+
+    for (int32_t i = 0; i < numList; i++) {
+        if (activeMinus1 >= REF_LIST_SIZE) {
+            ETRACE("Invalid activeMinus1 (%d)", activeMinus1);
+            return DECODE_PARSER_FAIL;
+        }
+        for (int32_t j = 0; j <= activeMinus1; j++, ref++) {
+            if (!(ref->flags & VA_PICTURE_H264_INVALID)) {
+                ref->picture_id = findSurface(ref);
+                if (ref->picture_id == VA_INVALID_SURFACE) {
+                    // Error DecodeRefMissing is counted once even there're multiple
+                    mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 1;
+                    mAcquiredBuffer->renderBuffer.errBuf.errorArray[0].type = DecodeRefMissing;
+
+                    if (mLastReference) {
+                        WTRACE("Reference frame %d is missing. Use last reference", getPOC(ref));
+                        ref->picture_id = mLastReference->renderBuffer.surface;
+                    } else {
+                        ETRACE("Reference frame %d is missing. Stop decoding.", getPOC(ref));
+                        return DECODE_NO_REFERENCE;
+                    }
+                }
+            }
+        }
+        activeMinus1 = sliceParam->num_ref_idx_l1_active_minus1;
+        ref = sliceParam->RefPicList1;
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVC::updateDPB(VAPictureParameterBufferH264 *picParam) {
+    clearAsReference(mToggleDPB);
+    // pointer to toggled DPB (new)
+    DecodedPictureBuffer *dpb = mDPBs[!mToggleDPB];
+    VAPictureH264 *ref = picParam->ReferenceFrames;
+
+    // update current picture ID
+    picParam->CurrPic.picture_id = mAcquiredBuffer->renderBuffer.surface;
+
+    // build new DPB
+    for (int32_t i = 0; i < MAX_REF_NUMBER; i++, ref++) {
+        if (ref->flags & VA_PICTURE_H264_INVALID) {
+            continue;
+        }
+#ifdef USE_AVC_SHORT_FORMAT
+        ref->picture_id = findSurface(ref);
+#endif
+        dpb->poc = getPOC(ref);
+        // looking for the latest ref frame in the DPB with specified POC, in case frames have same POC
+        dpb->surfaceBuffer = findRefSurfaceBuffer(ref);
+        if (dpb->surfaceBuffer == NULL) {
+            ETRACE("Reference frame %d is missing for current frame %d", dpb->poc, getPOC(&(picParam->CurrPic)));
+            // Error DecodeRefMissing is counted once even there're multiple
+            mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 1;
+            mAcquiredBuffer->renderBuffer.errBuf.errorArray[0].type = DecodeRefMissing;
+            if (dpb->poc == getPOC(&(picParam->CurrPic))) {
+                WTRACE("updateDPB: Using the current picture for missing reference.");
+                dpb->surfaceBuffer = mAcquiredBuffer;
+            } else if (mLastReference) {
+                WTRACE("updateDPB: Use last reference frame %d for missing reference.", mLastReference->pictureOrder);
+                // TODO: this is new code for error resilience
+                dpb->surfaceBuffer = mLastReference;
+            } else {
+                WTRACE("updateDPB: Unable to recover the missing reference frame.");
+                // continue buillding DPB without updating dpb pointer.
+                continue;
+                // continue building DPB as this reference may not be actually used.
+                // especially happen after seeking to a non-IDR I frame.
+                //return DECODE_NO_REFERENCE;
+            }
+        }
+        if (dpb->surfaceBuffer) {
+            // this surface is used as reference
+            dpb->surfaceBuffer->asReferernce = true;
+        }
+        dpb++;
+    }
+
+    // add current frame to DPB if it  is a reference frame
+    if ((picParam->CurrPic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+        (picParam->CurrPic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)) {
+        dpb->poc = getPOC(&(picParam->CurrPic));
+        dpb->surfaceBuffer = mAcquiredBuffer;
+        dpb->surfaceBuffer->asReferernce = true;
+    }
+    // invalidate the current used DPB
+    invalidateDPB(mToggleDPB);
+    mToggleDPB = !mToggleDPB;
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVC::updateReferenceFrames(vbp_picture_data_h264 *picData) {
+    bool found = false;
+    uint32_t flags = 0;
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = NULL;
+    uint8_t activeMinus1 = 0;
+    VAPictureH264 *refList = NULL;
+    VAPictureH264 *dpb = picParam->ReferenceFrames;
+    VAPictureH264 *refFrame = NULL;
+
+    // invalidate DPB in the picture buffer
+    memset(picParam->ReferenceFrames, 0xFF, sizeof(picParam->ReferenceFrames));
+    picParam->num_ref_frames = 0;
+
+    // update DPB  from the reference list in each slice.
+    for (uint32_t slice = 0; slice < picData->num_slices; slice++) {
+        sliceParam = &(picData->slc_data[slice].slc_parms);
+
+        for (int32_t list = 0; list < 2; list++) {
+            refList = (list == 0) ? sliceParam->RefPicList0 :
+                                    sliceParam->RefPicList1;
+            activeMinus1 = (list == 0) ? sliceParam->num_ref_idx_l0_active_minus1 :
+                                         sliceParam->num_ref_idx_l1_active_minus1;
+            if (activeMinus1 >= REF_LIST_SIZE) {
+                return DECODE_PARSER_FAIL;
+            }
+            for (uint8_t item = 0; item < (uint8_t)(activeMinus1 + 1); item++, refList++) {
+                if (refList->flags & VA_PICTURE_H264_INVALID) {
+                    break;
+                }
+                found = false;
+                refFrame = picParam->ReferenceFrames;
+                for (uint8_t frame = 0; frame < picParam->num_ref_frames; frame++, refFrame++) {
+                    if (refFrame->TopFieldOrderCnt == refList->TopFieldOrderCnt) {
+                        ///check for complementary field
+                        flags = refFrame->flags | refList->flags;
+                        //If both TOP and BOTTOM are set, we'll clear those flags
+                        if ((flags & VA_PICTURE_H264_TOP_FIELD) &&
+                            (flags & VA_PICTURE_H264_BOTTOM_FIELD)) {
+                            refFrame->flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+                        }
+                        found = true;  //already in the DPB; will not add this one
+                        break;
+                    }
+                }
+                if (found == false) {
+                    // add a new reference to the DPB
+                    dpb->picture_id = findSurface(refList);
+                    if (dpb->picture_id == VA_INVALID_SURFACE) {
+                        if (mLastReference != NULL) {
+                            dpb->picture_id = mLastReference->renderBuffer.surface;
+                        } else {
+                            ETRACE("Reference frame %d is missing. Stop updating references frames.", getPOC(refList));
+                            return DECODE_NO_REFERENCE;
+                        }
+                    }
+                    dpb->flags = refList->flags;
+                    // if it's bottom field in dpb, there must have top field in DPB,
+                    // so clear the bottom flag, or will confuse VED to address top field
+                    if (dpb->flags & VA_PICTURE_H264_BOTTOM_FIELD)
+                        dpb->flags &= (~VA_PICTURE_H264_BOTTOM_FIELD);
+                    dpb->frame_idx = refList->frame_idx;
+                    dpb->TopFieldOrderCnt = refList->TopFieldOrderCnt;
+                    dpb->BottomFieldOrderCnt = refList->BottomFieldOrderCnt;
+                    dpb++;
+                    picParam->num_ref_frames++;
+                }
+            }
+        }
+    }
+    return DECODE_SUCCESS;
+}
+
+void VideoDecoderAVC::removeReferenceFromDPB(VAPictureParameterBufferH264 *picParam) {
+    // remove the current frame from DPB as it can't be decoded.
+    if ((picParam->CurrPic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+        (picParam->CurrPic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)) {
+        DecodedPictureBuffer *dpb = mDPBs[mToggleDPB];
+        int32_t poc = getPOC(&(picParam->CurrPic));
+        for (int32_t i = 0; i < DPB_SIZE; i++, dpb++) {
+            if (poc == dpb->poc) {
+                dpb->poc = (int32_t)POC_DEFAULT;
+                if (dpb->surfaceBuffer) {
+                    dpb->surfaceBuffer->asReferernce = false;
+                }
+                dpb->surfaceBuffer = NULL;
+                break;
+            }
+        }
+    }
+}
+
+int32_t VideoDecoderAVC::getPOC(VAPictureH264 *pic) {
+    if (pic->flags & VA_PICTURE_H264_BOTTOM_FIELD) {
+        return pic->BottomFieldOrderCnt;
+    }
+    return pic->TopFieldOrderCnt;
+}
+
+VASurfaceID VideoDecoderAVC::findSurface(VAPictureH264 *pic) {
+    VideoSurfaceBuffer *p = findSurfaceBuffer(pic);
+    if (p == NULL) {
+        ETRACE("Could not find surface for poc %d", getPOC(pic));
+        return VA_INVALID_SURFACE;
+    }
+    return p->renderBuffer.surface;
+}
+
+VideoSurfaceBuffer* VideoDecoderAVC::findSurfaceBuffer(VAPictureH264 *pic) {
+    DecodedPictureBuffer *dpb = mDPBs[mToggleDPB];
+    for (int32_t i = 0; i < DPB_SIZE; i++, dpb++) {
+        if (dpb->poc == pic->BottomFieldOrderCnt ||
+            dpb->poc == pic->TopFieldOrderCnt) {
+            // TODO: remove these debugging codes
+            if (dpb->surfaceBuffer == NULL) {
+                ETRACE("Invalid surface buffer in the DPB for poc %d.", getPOC(pic));
+            }
+            return dpb->surfaceBuffer;
+        }
+    }
+    // ETRACE("Unable to find surface for poc %d", getPOC(pic));
+    return NULL;
+}
+
+VideoSurfaceBuffer* VideoDecoderAVC::findRefSurfaceBuffer(VAPictureH264 *pic) {
+    DecodedPictureBuffer *dpb = mDPBs[mToggleDPB];
+    // always looking for the latest one in the DPB, in case ref frames have same POC
+    dpb += (DPB_SIZE - 1);
+    for (int32_t i = DPB_SIZE; i > 0; i--, dpb--) {
+        if (dpb->poc == pic->BottomFieldOrderCnt ||
+            dpb->poc == pic->TopFieldOrderCnt) {
+            // TODO: remove these debugging codes
+            if (dpb->surfaceBuffer == NULL) {
+                ETRACE("Invalid surface buffer in the DPB for poc %d.", getPOC(pic));
+            }
+            return dpb->surfaceBuffer;
+        }
+    }
+    ETRACE("Unable to find surface for poc %d", getPOC(pic));
+    return NULL;
+}
+
+void VideoDecoderAVC::invalidateDPB(int toggle) {
+    DecodedPictureBuffer* p = mDPBs[toggle];
+    for (int i = 0; i < DPB_SIZE; i++) {
+        p->poc = (int32_t) POC_DEFAULT;
+        p->surfaceBuffer = NULL;
+        p++;
+    }
+}
+
+void VideoDecoderAVC::clearAsReference(int toggle) {
+    DecodedPictureBuffer* p = mDPBs[toggle];
+    for (int i = 0; i < DPB_SIZE; i++) {
+        if (p->surfaceBuffer) {
+            p->surfaceBuffer->asReferernce = false;
+        }
+        p++;
+    }
+}
+
+Decode_Status VideoDecoderAVC::startVA(vbp_data_h264 *data) {
+    int32_t DPBSize = getDPBSize(data);
+
+    //Use high profile for all kinds of H.264 profiles (baseline, main and high) except for constrained baseline
+    VAProfile vaProfile = VAProfileH264High;
+
+    // TODO: determine when to use VAProfileH264ConstrainedBaseline, set only if we are told to do so
+    if ((data->codec_data->profile_idc == 66 || data->codec_data->constraint_set0_flag == 1) &&
+        data->codec_data->constraint_set1_flag == 1) {
+        if (mErrorConcealment) {
+            vaProfile = VAProfileH264ConstrainedBaseline;
+        }
+    }
+
+    VideoDecoderBase::setOutputWindowSize(mConfigBuffer.flag & WANT_ADAPTIVE_PLAYBACK ? OUTPUT_WINDOW_SIZE : DPBSize);
+    updateFormatInfo(data);
+
+   // for 1080p, limit the total surface to 19, according the hardware limitation
+   // change the max surface number from 19->10 to workaround memory shortage
+   // remove the workaround
+    if(mVideoFormatInfo.height == 1088 && DPBSize + AVC_EXTRA_SURFACE_NUMBER > 19) {
+        DPBSize = 19 - AVC_EXTRA_SURFACE_NUMBER;
+    }
+
+    if (mConfigBuffer.flag & WANT_ADAPTIVE_PLAYBACK) {
+        // When Adaptive playback is enabled, turn off low delay mode.
+        // Otherwise there may be a 240ms stuttering if the output mode is changed from LowDelay to Delay.
+        enableLowDelayMode(false);
+    } else {
+        // for baseline profile, enable low delay mode automatically
+        enableLowDelayMode(data->codec_data->profile_idc == 66);
+    }
+
+    return VideoDecoderBase::setupVA(DPBSize + AVC_EXTRA_SURFACE_NUMBER, vaProfile);
+}
+
+void VideoDecoderAVC::updateFormatInfo(vbp_data_h264 *data) {
+    // new video size
+    uint32_t width = (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) * 16;
+    uint32_t height = (data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) * 16;
+    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
+        mVideoFormatInfo.width, mVideoFormatInfo.height, width, height);
+
+    if ((mVideoFormatInfo.width != width ||
+        mVideoFormatInfo.height != height) &&
+        width && height) {
+        if (VideoDecoderBase::alignMB(mVideoFormatInfo.width) != width ||
+            VideoDecoderBase::alignMB(mVideoFormatInfo.height) != height) {
+            mSizeChanged = true;
+            ITRACE("Video size is changed.");
+        }
+        mVideoFormatInfo.width = width;
+        mVideoFormatInfo.height = height;
+    }
+
+    // video_range has default value of 0.
+    mVideoFormatInfo.videoRange = data->codec_data->video_full_range_flag;
+
+    switch (data->codec_data->matrix_coefficients) {
+        case 1:
+            mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
+            break;
+
+        // ITU-R Recommendation BT.470-6 System B, G (MP4), same as
+        // SMPTE 170M/BT601
+        case 5:
+        case 6:
+            mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
+            break;
+
+        default:
+            // unknown color matrix, set to 0 so color space flag will not be set.
+            mVideoFormatInfo.colorMatrix = 0;
+            break;
+    }
+    mVideoFormatInfo.aspectX = data->codec_data->sar_width;
+    mVideoFormatInfo.aspectY = data->codec_data->sar_height;
+    mVideoFormatInfo.bitrate = data->codec_data->bit_rate;
+    mVideoFormatInfo.cropLeft = data->codec_data->crop_left;
+    mVideoFormatInfo.cropRight = data->codec_data->crop_right;
+    mVideoFormatInfo.cropTop = data->codec_data->crop_top;
+    mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom;
+
+    ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d",
+        data->codec_data->crop_left,
+        data->codec_data->crop_top,
+        data->codec_data->crop_right,
+        data->codec_data->crop_bottom);
+
+    if (mConfigBuffer.flag & WANT_SURFACE_PROTECTION) {
+        mVideoFormatInfo.actualBufferNeeded = mConfigBuffer.surfaceNumber;
+    } else {
+        // The number of actual buffer needed is
+        // outputQueue + nativewindow_owned + num_ref_frames + widi_need_max + 1(available buffer)
+        // while outputQueue = DPB < 8? DPB :8
+        mVideoFormatInfo.actualBufferNeeded = mOutputWindowSize + NW_CONSUMED /* Owned by native window */
+                                              + data->codec_data->num_ref_frames
+#ifndef USE_GEN_HW
+                                              + HDMI_CONSUMED /* Two extra buffers are needed for native window buffer cycling */
+                                              + (mWiDiOn ? WIDI_CONSUMED : 0) /* WiDi maximum needs */
+#endif
+                                              + 1;
+    }
+
+    ITRACE("actualBufferNeeded =%d", mVideoFormatInfo.actualBufferNeeded);
+
+    mVideoFormatInfo.valid = true;
+
+    setRenderRect();
+}
+
+bool VideoDecoderAVC::isWiDiStatusChanged() {
+#ifndef USE_GEN_HW
+    if (mWiDiOn)
+        return false;
+
+    if (mConfigBuffer.flag & WANT_SURFACE_PROTECTION)
+        return false;
+
+    if (!(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER))
+        return false;
+
+    char prop[PROPERTY_VALUE_MAX];
+    bool widi_on = (property_get("media.widi.enabled", prop, NULL) > 0) &&
+                    (!strcmp(prop, "1") || !strcasecmp(prop, "true"));
+    if (widi_on) {
+        mVideoFormatInfo.actualBufferNeeded += WIDI_CONSUMED;
+        mWiDiOn = true;
+        ITRACE("WiDi is enabled, actual buffer needed is %d", mVideoFormatInfo.actualBufferNeeded);
+        return true;
+    }
+    return false;
+#else
+    return false;
+#endif
+}
+
+Decode_Status VideoDecoderAVC::handleNewSequence(vbp_data_h264 *data) {
+    updateFormatInfo(data);
+    bool needFlush = false;
+    bool rawDataMode = !(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER);
+
+    if (!rawDataMode) {
+        needFlush = (mVideoFormatInfo.width > mVideoFormatInfo.surfaceWidth)
+                || (mVideoFormatInfo.height > mVideoFormatInfo.surfaceHeight)
+                || isWiDiStatusChanged()
+                || (mVideoFormatInfo.actualBufferNeeded > mConfigBuffer.surfaceNumber);
+    }
+
+    if (needFlush || (rawDataMode && mSizeChanged)) {
+        mSizeChanged = false;
+        flushSurfaceBuffers();
+        return DECODE_FORMAT_CHANGE;
+    } else
+        return DECODE_SUCCESS;
+}
+
+bool VideoDecoderAVC::isNewFrame(vbp_data_h264 *data, bool equalPTS) {
+    if (data->num_pictures == 0) {
+        ETRACE("num_pictures == 0");
+        return true;
+    }
+
+    vbp_picture_data_h264* picData = data->pic_data;
+    if (picData->num_slices == 0) {
+        ETRACE("num_slices == 0");
+        return true;
+    }
+
+    bool newFrame = false;
+    uint32_t fieldFlags = VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD;
+
+    if (picData->slc_data[0].slc_parms.first_mb_in_slice != 0) {
+        // not the first slice, assume it is continuation of a partial frame
+        // TODO: check if it is new frame boundary as the first slice may get lost in streaming case.
+        WTRACE("first_mb_in_slice != 0");
+        if (!equalPTS) {
+            // return true if different timestamp, it is a workaround here for a streaming case
+            WTRACE("different PTS, treat it as a new frame");
+            return true;
+        }
+    } else {
+        if ((picData->pic_parms->CurrPic.flags & fieldFlags) == fieldFlags) {
+            ETRACE("Current picture has both odd field and even field.");
+        }
+        // current picture is a field or a frame, and buffer conains the first slice, check if the current picture and
+        // the last picture form an opposite field pair
+        if (((mLastPictureFlags | picData->pic_parms->CurrPic.flags) & fieldFlags) == fieldFlags) {
+            // opposite field
+            newFrame = false;
+            WTRACE("current picture is not at frame boundary.");
+            mLastPictureFlags = 0;
+        } else {
+            newFrame = true;
+            mLastPictureFlags = 0;
+            for (uint32_t i = 0; i < data->num_pictures; i++) {
+                mLastPictureFlags |= data->pic_data[i].pic_parms->CurrPic.flags;
+            }
+            if ((mLastPictureFlags & fieldFlags) == fieldFlags) {
+                // current buffer contains both odd field and even field.
+                mLastPictureFlags = 0;
+            }
+        }
+    }
+    
+    return newFrame;
+}
+
+int32_t VideoDecoderAVC::getDPBSize(vbp_data_h264 *data) {
+    // 1024 * MaxDPB / ( PicWidthInMbs * FrameHeightInMbs * 384 ), 16
+    struct DPBTable {
+        int32_t level;
+        float maxDPB;
+    } dpbTable[] = {
+        {9,  148.5},
+        {10, 148.5},
+        {11, 337.5},
+        {12, 891.0},
+        {13, 891.0},
+        {20, 891.0},
+        {21, 1782.0},
+        {22, 3037.5},
+        {30, 3037.5},
+        {31, 6750.0},
+        {32, 7680.0},
+        {40, 12288.0},
+        {41, 12288.0},
+        {42, 13056.0},
+        {50, 41400.0},
+        {51, 69120.0}
+    };
+
+    int32_t count = sizeof(dpbTable)/sizeof(DPBTable);
+    float maxDPB = 0;
+    for (int32_t i = 0; i < count; i++)
+    {
+        if (dpbTable[i].level == data->codec_data->level_idc) {
+            maxDPB = dpbTable[i].maxDPB;
+            break;
+        }
+    }
+
+    int32_t maxDPBSize = maxDPB * 1024 / (
+        (data->pic_data[0].pic_parms->picture_width_in_mbs_minus1 + 1) *
+        (data->pic_data[0].pic_parms->picture_height_in_mbs_minus1 + 1) *
+        384);
+
+    if (maxDPBSize > 16) {
+        maxDPBSize = 16;
+    } else if (maxDPBSize == 0) {
+        maxDPBSize = 3;
+    }
+    if(maxDPBSize < data->codec_data->num_ref_frames) {
+        maxDPBSize = data->codec_data->num_ref_frames;
+    }
+
+    // add one extra frame for current frame.
+    maxDPBSize += 1;
+    ITRACE("maxDPBSize = %d, num_ref_frame = %d", maxDPBSize, data->codec_data->num_ref_frames);
+    return maxDPBSize;
+}
+
+Decode_Status VideoDecoderAVC::checkHardwareCapability() {
+#ifndef USE_GEN_HW
+    VAStatus vaStatus;
+    VAConfigAttrib cfgAttribs[2];
+    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
+    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
+    vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileH264High,
+            VAEntrypointVLD, cfgAttribs, 2);
+    CHECK_VA_STATUS("vaGetConfigAttributes");
+    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
+        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
+                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
+        return DECODE_DRIVER_FAIL;
+    }
+#endif
+    return DECODE_SUCCESS;
+}
+
+#ifdef USE_AVC_SHORT_FORMAT
+Decode_Status VideoDecoderAVC::getCodecSpecificConfigs(
+    VAProfile profile, VAConfigID *config)
+{
+    VAStatus vaStatus;
+    VAConfigAttrib attrib[2];
+
+    if (config == NULL) {
+        ETRACE("Invalid parameter!");
+        return DECODE_FAIL;
+    }
+
+    attrib[0].type = VAConfigAttribRTFormat;
+    attrib[0].value = VA_RT_FORMAT_YUV420;
+    attrib[1].type = VAConfigAttribDecSliceMode;
+    attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+
+    vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
+
+    if (attrib[1].value & VA_DEC_SLICE_MODE_BASE) {
+        ITRACE("AVC short format used");
+        attrib[1].value = VA_DEC_SLICE_MODE_BASE;
+    } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
+        ITRACE("AVC long format ssed");
+        attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+    } else {
+        ETRACE("Unsupported Decode Slice Mode!");
+        return DECODE_FAIL;
+    }
+
+    vaStatus = vaCreateConfig(
+            mVADisplay,
+            profile,
+            VAEntrypointVLD,
+            &attrib[0],
+            2,
+            config);
+    CHECK_VA_STATUS("vaCreateConfig");
+
+    return DECODE_SUCCESS;
+}
+#endif
diff --git a/videodecoder/VideoDecoderAVC.h b/videodecoder/VideoDecoderAVC.h
new file mode 100755
index 0000000..6129703
--- /dev/null
+++ b/videodecoder/VideoDecoderAVC.h
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_H_
+#define VIDEO_DECODER_AVC_H_
+
+#include "VideoDecoderBase.h"
+
+
+class VideoDecoderAVC : public VideoDecoderBase {
+public:
+    VideoDecoderAVC(const char *mimeType);
+    virtual ~VideoDecoderAVC();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+    virtual void flush(void);
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+protected:
+    virtual Decode_Status decodeFrame(VideoDecodeBuffer *buffer, vbp_data_h264 *data);
+    virtual Decode_Status beginDecodingFrame(vbp_data_h264 *data);
+    virtual Decode_Status continueDecodingFrame(vbp_data_h264 *data);
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+    Decode_Status setReference(VASliceParameterBufferH264 *sliceParam);
+    Decode_Status updateDPB(VAPictureParameterBufferH264 *picParam);
+    Decode_Status updateReferenceFrames(vbp_picture_data_h264 *picData);
+    void removeReferenceFromDPB(VAPictureParameterBufferH264 *picParam);
+    int32_t getPOC(VAPictureH264 *pic); // Picture Order Count
+    inline VASurfaceID findSurface(VAPictureH264 *pic);
+    inline VideoSurfaceBuffer* findSurfaceBuffer(VAPictureH264 *pic);
+    inline VideoSurfaceBuffer* findRefSurfaceBuffer(VAPictureH264 *pic);
+    inline void invalidateDPB(int toggle);
+    inline void clearAsReference(int toggle);
+    Decode_Status startVA(vbp_data_h264 *data);
+    void updateFormatInfo(vbp_data_h264 *data);
+    Decode_Status handleNewSequence(vbp_data_h264 *data);
+    bool isNewFrame(vbp_data_h264 *data, bool equalPTS);
+    int32_t getDPBSize(vbp_data_h264 *data);
+    virtual Decode_Status checkHardwareCapability();
+#ifdef USE_AVC_SHORT_FORMAT
+    virtual Decode_Status getCodecSpecificConfigs(VAProfile profile, VAConfigID*config);
+#endif
+    bool isWiDiStatusChanged();
+
+private:
+    struct DecodedPictureBuffer {
+        VideoSurfaceBuffer *surfaceBuffer;
+        int32_t poc; // Picture Order Count
+    };
+
+    enum {
+        AVC_EXTRA_SURFACE_NUMBER = 11,
+        // maximum DPB (Decoded Picture Buffer) size
+        MAX_REF_NUMBER = 16,
+        DPB_SIZE = 17,         // DPB_SIZE = MAX_REF_NUMBER + 1,
+        REF_LIST_SIZE = 32,
+    };
+
+    // maintain 2 ping-pong decoded picture buffers
+    DecodedPictureBuffer mDPBs[2][DPB_SIZE];
+    uint8_t mToggleDPB; // 0 or 1
+    bool mErrorConcealment;
+    uint32_t mLastPictureFlags;
+    VideoExtensionBuffer mExtensionBuffer;
+    PackedFrameData mPackedFrame;
+};
+
+
+
+#endif /* VIDEO_DECODER_AVC_H_ */
diff --git a/videodecoder/VideoDecoderBase.cpp b/videodecoder/VideoDecoderBase.cpp
new file mode 100644
index 0000000..1065cd4
--- /dev/null
+++ b/videodecoder/VideoDecoderBase.cpp
@@ -0,0 +1,1514 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderBase.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+#include <va/va_android.h>
+#include <va/va_tpi.h>
+#ifdef  __SSE4_1__
+#include "use_util_sse4.h"
+#endif
+
+#define INVALID_PTS ((uint64_t)-1)
+#define MAXIMUM_POC  0x7FFFFFFF
+#define MINIMUM_POC  0x80000000
+#define ANDROID_DISPLAY_HANDLE 0x18C34078
+
+VideoDecoderBase::VideoDecoderBase(const char *mimeType, _vbp_parser_type type)
+    : mInitialized(false),
+      mLowDelay(false),
+      mDisplay(NULL),
+      mVADisplay(NULL),
+      mVAContext(VA_INVALID_ID),
+      mVAConfig(VA_INVALID_ID),
+      mVAStarted(false),
+      mCurrentPTS(INVALID_PTS),
+      mAcquiredBuffer(NULL),
+      mLastReference(NULL),
+      mForwardReference(NULL),
+      mDecodingFrame(false),
+      mSizeChanged(false),
+      mShowFrame(true),
+      mOutputWindowSize(OUTPUT_WINDOW_SIZE),
+      mRotationDegrees(0),
+      mErrReportEnabled(false),
+      mWiDiOn(false),
+      mRawOutput(false),
+      mManageReference(true),
+      mOutputMethod(OUTPUT_BY_PCT),
+      mNumSurfaces(0),
+      mSurfaceBuffers(NULL),
+      mOutputHead(NULL),
+      mOutputTail(NULL),
+      mSurfaces(NULL),
+      mVASurfaceAttrib(NULL),
+      mSurfaceUserPtr(NULL),
+      mSurfaceAcquirePos(0),
+      mNextOutputPOC(MINIMUM_POC),
+      mParserType(type),
+      mParserHandle(NULL),
+      mSignalBufferSize(0) {
+
+    memset(&mVideoFormatInfo, 0, sizeof(VideoFormatInfo));
+    memset(&mConfigBuffer, 0, sizeof(mConfigBuffer));
+    for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
+         mSignalBufferPre[i] = NULL;
+    }
+    pthread_mutex_init(&mLock, NULL);
+    mVideoFormatInfo.mimeType = strdup(mimeType);
+    mUseGEN = false;
+    mLibHandle = NULL;
+    mParserOpen = NULL;
+    mParserClose = NULL;
+    mParserParse = NULL;
+    mParserQuery = NULL;
+    mParserFlush = NULL;
+    mParserUpdate = NULL;
+}
+
+VideoDecoderBase::~VideoDecoderBase() {
+    pthread_mutex_destroy(&mLock);
+    stop();
+    free(mVideoFormatInfo.mimeType);
+}
+
+Decode_Status VideoDecoderBase::start(VideoConfigBuffer *buffer) {
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+
+    if (mParserHandle != NULL) {
+        WTRACE("Decoder has already started.");
+        return DECODE_SUCCESS;
+    }
+    mLibHandle = dlopen("libmixvbp.so", RTLD_NOW);
+    if (mLibHandle == NULL) {
+       return DECODE_NO_PARSER;
+    }
+    mParserOpen = (OpenFunc)dlsym(mLibHandle, "vbp_open");
+    mParserClose = (CloseFunc)dlsym(mLibHandle, "vbp_close");
+    mParserParse = (ParseFunc)dlsym(mLibHandle, "vbp_parse");
+    mParserQuery = (QueryFunc)dlsym(mLibHandle, "vbp_query");
+    mParserFlush = (FlushFunc)dlsym(mLibHandle, "vbp_flush");
+    if (mParserOpen == NULL || mParserClose == NULL || mParserParse == NULL
+        || mParserQuery == NULL || mParserFlush == NULL) {
+        return DECODE_NO_PARSER;
+    }
+#if (defined USE_AVC_SHORT_FORMAT || defined USE_SLICE_HEADER_PARSING)
+    mParserUpdate = (UpdateFunc)dlsym(mLibHandle, "vbp_update");
+    if (mParserUpdate == NULL) {
+        return DECODE_NO_PARSER;
+    }
+#endif
+    if ((int32_t)mParserType != VBP_INVALID) {
+        ITRACE("mParserType = %d", mParserType);
+        if (mParserOpen(mParserType, &mParserHandle) != VBP_OK) {
+            ETRACE("Failed to open VBP parser.");
+            return DECODE_NO_PARSER;
+        }
+    }
+    // keep a copy of configure buffer, meta data only. It can be used to override VA setup parameter.
+    mConfigBuffer = *buffer;
+    mConfigBuffer.data = NULL;
+    mConfigBuffer.size = 0;
+
+    mVideoFormatInfo.width = buffer->width;
+    mVideoFormatInfo.height = buffer->height;
+    if (buffer->flag & USE_NATIVE_GRAPHIC_BUFFER) {
+        mVideoFormatInfo.surfaceWidth = buffer->graphicBufferWidth;
+        mVideoFormatInfo.surfaceHeight = buffer->graphicBufferHeight;
+    }
+    mLowDelay = buffer->flag & WANT_LOW_DELAY;
+    mRawOutput = buffer->flag & WANT_RAW_OUTPUT;
+    if (mRawOutput) {
+        WTRACE("Output is raw data.");
+    }
+
+    return DECODE_SUCCESS;
+}
+
+
+Decode_Status VideoDecoderBase::reset(VideoConfigBuffer *buffer) {
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+
+    // if VA is already started, terminate VA as graphic buffers are reallocated by omxcodec
+    terminateVA();
+
+    // reset the mconfigBuffer to pass it for startVA.
+    mConfigBuffer = *buffer;
+    mConfigBuffer.data = NULL;
+    mConfigBuffer.size = 0;
+
+    mVideoFormatInfo.width = buffer->width;
+    mVideoFormatInfo.height = buffer->height;
+    if (buffer->flag & USE_NATIVE_GRAPHIC_BUFFER) {
+        mVideoFormatInfo.surfaceWidth = buffer->graphicBufferWidth;
+        mVideoFormatInfo.surfaceHeight = buffer->graphicBufferHeight;
+    }
+    mVideoFormatInfo.actualBufferNeeded = mConfigBuffer.surfaceNumber;
+    mLowDelay = buffer->flag & WANT_LOW_DELAY;
+    mRawOutput = buffer->flag & WANT_RAW_OUTPUT;
+    if (mRawOutput) {
+        WTRACE("Output is raw data.");
+    }
+    return DECODE_SUCCESS;
+}
+
+
+
+void VideoDecoderBase::stop(void) {
+    terminateVA();
+
+    mCurrentPTS = INVALID_PTS;
+    mAcquiredBuffer = NULL;
+    mLastReference = NULL;
+    mForwardReference = NULL;
+    mDecodingFrame = false;
+    mSizeChanged = false;
+
+    // private variables
+    mLowDelay = false;
+    mRawOutput = false;
+    mNumSurfaces = 0;
+    mSurfaceAcquirePos = 0;
+    mNextOutputPOC = MINIMUM_POC;
+    mVideoFormatInfo.valid = false;
+    if (mParserHandle){
+        mParserClose(mParserHandle);
+        mParserHandle = NULL;
+    }
+    if (mLibHandle) {
+        dlclose(mLibHandle);
+        mLibHandle = NULL;
+    }
+}
+
+void VideoDecoderBase::flush(void) {
+    if (mVAStarted == false) {
+        // nothing to flush at this stage
+        return;
+    }
+
+    endDecodingFrame(true);
+
+    VideoSurfaceBuffer *p = mOutputHead;
+    // check if there's buffer with DRC flag in the output queue
+    while (p) {
+        if (p->renderBuffer.flag & IS_RESOLUTION_CHANGE) {
+            mSizeChanged = true;
+            break;
+        }
+        p = p->next;
+    }
+    // avoid setting mSurfaceAcquirePos  to 0 as it may cause tearing
+    // (surface is still being rendered)
+    mSurfaceAcquirePos = (mSurfaceAcquirePos  + 1) % mNumSurfaces;
+    mNextOutputPOC = MINIMUM_POC;
+    mCurrentPTS = INVALID_PTS;
+    mAcquiredBuffer = NULL;
+    mLastReference = NULL;
+    mForwardReference = NULL;
+    mOutputHead = NULL;
+    mOutputTail = NULL;
+    mDecodingFrame = false;
+
+    // flush vbp parser
+    if (mParserHandle && (mParserFlush(mParserHandle) != VBP_OK)) {
+        WTRACE("Failed to flush parser. Continue");
+    }
+
+    // initialize surface buffer without resetting mapped/raw data
+    initSurfaceBuffer(false);
+
+}
+
+void VideoDecoderBase::freeSurfaceBuffers(void) {
+    if (mVAStarted == false) {
+        // nothing to free surface buffers at this stage
+        return;
+    }
+
+    pthread_mutex_lock(&mLock);
+
+    endDecodingFrame(true);
+
+    // if VA is already started, terminate VA as graphic buffers are reallocated by omxcodec
+    terminateVA();
+
+    pthread_mutex_unlock(&mLock);
+}
+
+const VideoFormatInfo* VideoDecoderBase::getFormatInfo(void) {
+    return &mVideoFormatInfo;
+}
+
+const VideoRenderBuffer* VideoDecoderBase::getOutput(bool draining, VideoErrorBuffer *outErrBuf) {
+    VAStatus vaStatus;
+    if (mVAStarted == false) {
+        return NULL;
+    }
+    bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+
+    if (draining) {
+        // complete decoding the last frame and ignore return
+        endDecodingFrame(false);
+    }
+
+    if (mOutputHead == NULL) {
+        return NULL;
+    }
+
+    // output by position (the first buffer)
+    VideoSurfaceBuffer *outputByPos = mOutputHead;
+
+    if (mLowDelay) {
+        mOutputHead = mOutputHead->next;
+        if (mOutputHead == NULL) {
+            mOutputTail = NULL;
+        }
+        vaStatus = vaSetTimestampForSurface(mVADisplay, outputByPos->renderBuffer.surface, outputByPos->renderBuffer.timeStamp);
+        if (useGraphicBuffer && !mUseGEN) {
+            vaSyncSurface(mVADisplay, outputByPos->renderBuffer.surface);
+            fillDecodingErrors(&(outputByPos->renderBuffer));
+        }
+        if (draining && mOutputTail == NULL) {
+            outputByPos->renderBuffer.flag |= IS_EOS;
+        }
+        drainDecodingErrors(outErrBuf, &(outputByPos->renderBuffer));
+
+        return &(outputByPos->renderBuffer);
+    }
+
+    // output by presentation time stamp (the smallest pts)
+    VideoSurfaceBuffer *outputByPts = findOutputByPts();
+
+    VideoSurfaceBuffer *output = NULL;
+    if (mOutputMethod == OUTPUT_BY_POC) {
+        output = findOutputByPoc(draining);
+    } else if (mOutputMethod == OUTPUT_BY_PCT) {
+        output = findOutputByPct(draining);
+    } else {
+        ETRACE("Invalid output method.");
+        return NULL;
+    }
+
+    if (output == NULL) {
+        return NULL;
+    }
+
+    if (output != outputByPts) {
+        // swap time stamp
+        uint64_t ts = output->renderBuffer.timeStamp;
+        output->renderBuffer.timeStamp = outputByPts->renderBuffer.timeStamp;
+        outputByPts->renderBuffer.timeStamp = ts;
+    }
+
+    if (output != outputByPos) {
+        // remove this output from middle or end of the list
+        VideoSurfaceBuffer *p = outputByPos;
+        while (p->next != output) {
+            p = p->next;
+        }
+        p->next = output->next;
+        if (mOutputTail == output) {
+            mOutputTail = p;
+        }
+    } else {
+        // remove this output from head of the list
+        mOutputHead = mOutputHead->next;
+        if (mOutputHead == NULL) {
+            mOutputTail = NULL;
+        }
+    }
+    //VTRACE("Output POC %d for display (pts = %.2f)", output->pictureOrder, output->renderBuffer.timeStamp/1E6);
+    vaStatus = vaSetTimestampForSurface(mVADisplay, output->renderBuffer.surface, output->renderBuffer.timeStamp);
+
+    if (useGraphicBuffer && !mUseGEN) {
+        vaSyncSurface(mVADisplay, output->renderBuffer.surface);
+        fillDecodingErrors(&(output->renderBuffer));
+    }
+
+    if (draining && mOutputTail == NULL) {
+        output->renderBuffer.flag |= IS_EOS;
+    }
+
+    drainDecodingErrors(outErrBuf, &(output->renderBuffer));
+
+    return &(output->renderBuffer);
+}
+
+VideoSurfaceBuffer* VideoDecoderBase::findOutputByPts() {
+    // output by presentation time stamp - buffer with the smallest time stamp is output
+    VideoSurfaceBuffer *p = mOutputHead;
+    VideoSurfaceBuffer *outputByPts = NULL;
+    uint64_t pts = INVALID_PTS;
+    do {
+        if ((uint64_t)(p->renderBuffer.timeStamp) <= pts) {
+            // find buffer with the smallest PTS
+            pts = p->renderBuffer.timeStamp;
+            outputByPts = p;
+        }
+        p = p->next;
+    } while (p != NULL);
+
+    return outputByPts;
+}
+
+VideoSurfaceBuffer* VideoDecoderBase::findOutputByPct(bool draining) {
+    // output by picture coding type (PCT)
+    // if there is more than one reference frame, the first reference frame is ouput, otherwise,
+    // output non-reference frame if there is any.
+
+    VideoSurfaceBuffer *p = mOutputHead;
+    VideoSurfaceBuffer *outputByPct = NULL;
+    int32_t reference = 0;
+    do {
+        if (p->referenceFrame) {
+            reference++;
+            if (reference > 1) {
+                // mOutputHead must be a reference frame
+                outputByPct = mOutputHead;
+                break;
+            }
+        } else {
+            // first non-reference frame
+            outputByPct = p;
+            break;
+        }
+        p = p->next;
+    } while (p != NULL);
+
+    if (outputByPct == NULL && draining) {
+        outputByPct = mOutputHead;
+    }
+    return  outputByPct;
+}
+
+#if 0
+VideoSurfaceBuffer* VideoDecoderBase::findOutputByPoc(bool draining) {
+    // output by picture order count (POC)
+    // Output criteria:
+    // if there is IDR frame (POC == 0), all the frames before IDR must be output;
+    // Otherwise, if draining flag is set or list is full, frame with the least POC is output;
+    // Otherwise, NOTHING is output
+
+    int32_t dpbFullness = 0;
+    for (int32_t i = 0; i < mNumSurfaces; i++) {
+        // count num of reference frames
+        if (mSurfaceBuffers[i].asReferernce) {
+            dpbFullness++;
+        }
+    }
+
+    if (mAcquiredBuffer && mAcquiredBuffer->asReferernce) {
+        // frame is being decoded and is not ready for output yet
+        dpbFullness--;
+    }
+
+    VideoSurfaceBuffer *p = mOutputHead;
+    while (p != NULL) {
+        // count dpbFullness with non-reference frame in the output queue
+        if (p->asReferernce == false) {
+            dpbFullness++;
+        }
+        p = p->next;
+    }
+
+Retry:
+    p = mOutputHead;
+    VideoSurfaceBuffer *outputByPoc = NULL;
+    int32_t count = 0;
+    int32_t poc = MAXIMUM_POC;
+
+    do {
+        if (p->pictureOrder == 0) {
+            // output picture with the least POC before IDR
+            if (outputByPoc != NULL) {
+                mNextOutputPOC = outputByPoc->pictureOrder + 1;
+                return outputByPoc;
+            } else {
+                mNextOutputPOC = MINIMUM_POC;
+            }
+        }
+
+        // POC of  the output candidate must not be less than mNextOutputPOC
+        if (p->pictureOrder < mNextOutputPOC) {
+            break;
+        }
+
+        if (p->pictureOrder < poc) {
+            // update the least POC.
+            poc = p->pictureOrder;
+            outputByPoc = p;
+        }
+        count++;
+        p = p->next;
+    } while (p != NULL && count < mOutputWindowSize);
+
+    if (draining == false && dpbFullness < mOutputWindowSize) {
+        // list is not  full and we are not  in draining state
+        // if DPB is already full, one frame must be output
+        return NULL;
+    }
+
+    if (outputByPoc == NULL) {
+        mNextOutputPOC = MINIMUM_POC;
+        goto Retry;
+    }
+
+    // for debugging purpose
+    if (outputByPoc->pictureOrder != 0 && outputByPoc->pictureOrder < mNextOutputPOC) {
+        ETRACE("Output POC is not incremental, expected %d, actual %d", mNextOutputPOC, outputByPoc->pictureOrder);
+        //gaps_in_frame_num_value_allowed_flag is not currently supported
+    }
+
+    mNextOutputPOC = outputByPoc->pictureOrder + 1;
+
+    return outputByPoc;
+}
+#else
+VideoSurfaceBuffer* VideoDecoderBase::findOutputByPoc(bool draining) {
+    VideoSurfaceBuffer *output = NULL;
+    VideoSurfaceBuffer *p = mOutputHead;
+    int32_t count = 0;
+    int32_t poc = MAXIMUM_POC;
+    VideoSurfaceBuffer *outputleastpoc = mOutputHead;
+    do {
+        count++;
+        if (p->pictureOrder == 0) {
+            // any picture before this POC (new IDR) must be output
+            if (output == NULL) {
+                mNextOutputPOC = MINIMUM_POC;
+                // looking for any POC with negative value
+            } else {
+                mNextOutputPOC = output->pictureOrder + 1;
+                break;
+            }
+        }
+        if (p->pictureOrder < poc && p->pictureOrder >= mNextOutputPOC) {
+            // this POC meets ouput criteria.
+            poc = p->pictureOrder;
+            output = p;
+            outputleastpoc = p;
+        }
+        if (poc == mNextOutputPOC || count == mOutputWindowSize) {
+            if (output != NULL) {
+                // this indicates two cases:
+                // 1) the next output POC is found.
+                // 2) output queue is full and there is at least one buffer meeting the output criteria.
+                mNextOutputPOC = output->pictureOrder + 1;
+                break;
+            } else {
+                // this indicates output queue is full and no buffer in the queue meets the output criteria
+                // restart processing as queue is FULL and output criteria is changed. (next output POC is 0)
+                mNextOutputPOC = MINIMUM_POC;
+                count = 0;
+                poc = MAXIMUM_POC;
+                p = mOutputHead;
+                continue;
+            }
+        }
+        if (p->next == NULL) {
+            output = NULL;
+        }
+
+        p = p->next;
+    } while (p != NULL);
+
+    if (draining == true && output == NULL) {
+        output = outputleastpoc;
+    }
+
+    return output;
+}
+#endif
+
+bool VideoDecoderBase::checkBufferAvail(void) {
+    if (!mInitialized) {
+        if ((mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) == 0) {
+            return true;
+        }
+        for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
+            if (mSignalBufferPre[i] != NULL) {
+                return true;
+            }
+        }
+        return false;
+    }
+    // check whether there is buffer available for decoding
+    // TODO: check frame being referenced for frame skipping
+    VideoSurfaceBuffer *buffer = NULL;
+    for (int32_t i = 0; i < mNumSurfaces; i++) {
+        buffer = mSurfaceBuffers + i;
+
+        if (buffer->asReferernce == false &&
+            buffer->renderBuffer.renderDone == true) {
+            querySurfaceRenderStatus(buffer);
+            if (buffer->renderBuffer.driverRenderDone == true)
+                return true;
+        }
+     }
+    return false;
+}
+
+Decode_Status VideoDecoderBase::acquireSurfaceBuffer(void) {
+    if (mVAStarted == false) {
+        return DECODE_FAIL;
+    }
+
+    if (mAcquiredBuffer != NULL) {
+        ETRACE("mAcquiredBuffer is not NULL. Implementation bug.");
+        return DECODE_FAIL;
+    }
+
+    int nextAcquire = mSurfaceAcquirePos;
+    VideoSurfaceBuffer *acquiredBuffer = NULL;
+    bool acquired = false;
+
+    while (acquired == false) {
+        acquiredBuffer = mSurfaceBuffers + nextAcquire;
+
+        querySurfaceRenderStatus(acquiredBuffer);
+
+        if (acquiredBuffer->asReferernce == false && acquiredBuffer->renderBuffer.renderDone == true && acquiredBuffer->renderBuffer.driverRenderDone == true) {
+            // this is potential buffer for acquisition. Check if it is referenced by other surface for frame skipping
+            VideoSurfaceBuffer *temp;
+            acquired = true;
+            for (int i = 0; i < mNumSurfaces; i++) {
+                if (i == nextAcquire) {
+                    continue;
+                }
+                temp = mSurfaceBuffers + i;
+                // use mSurfaces[nextAcquire] instead of acquiredBuffer->renderBuffer.surface as its the actual surface to use.
+                if (temp->renderBuffer.surface == mSurfaces[nextAcquire] &&
+                    temp->renderBuffer.renderDone == false) {
+                    ITRACE("Surface is referenced by other surface buffer.");
+                    acquired = false;
+                    break;
+                }
+            }
+        }
+        if (acquired) {
+            break;
+        }
+        nextAcquire++;
+        if (nextAcquire == mNumSurfaces) {
+            nextAcquire = 0;
+        }
+        if (nextAcquire == mSurfaceAcquirePos) {
+            return DECODE_NO_SURFACE;
+        }
+    }
+
+    if (acquired == false) {
+        return DECODE_NO_SURFACE;
+    }
+
+    mAcquiredBuffer = acquiredBuffer;
+    mSurfaceAcquirePos = nextAcquire;
+
+    // set surface again as surface maybe reset by skipped frame.
+    // skipped frame is a "non-coded frame" and decoder needs to duplicate the previous reference frame as the output.
+    mAcquiredBuffer->renderBuffer.surface = mSurfaces[mSurfaceAcquirePos];
+    if (mSurfaceUserPtr && mAcquiredBuffer->mappedData) {
+        mAcquiredBuffer->mappedData->data = mSurfaceUserPtr[mSurfaceAcquirePos];
+    }
+    mAcquiredBuffer->renderBuffer.timeStamp = INVALID_PTS;
+    mAcquiredBuffer->renderBuffer.display = mVADisplay;
+    mAcquiredBuffer->renderBuffer.flag = 0;
+    mAcquiredBuffer->renderBuffer.renderDone = false;
+    mAcquiredBuffer->asReferernce = false;
+    mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 0;
+    mAcquiredBuffer->renderBuffer.errBuf.timeStamp = INVALID_PTS;
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::outputSurfaceBuffer(void) {
+    Decode_Status status;
+    if (mAcquiredBuffer == NULL) {
+        ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
+        return DECODE_FAIL;
+    }
+
+    if (mRawOutput) {
+        status = getRawDataFromSurface();
+        CHECK_STATUS();
+    }
+
+    // frame is successfly decoded to the current surface,  it is ready for output
+    if (mShowFrame) {
+        mAcquiredBuffer->renderBuffer.renderDone = false;
+    } else {
+        mAcquiredBuffer->renderBuffer.renderDone = true;
+    }
+
+    // decoder must set "asReference and referenceFrame" flags properly
+
+    // update reference frames
+    if (mAcquiredBuffer->referenceFrame) {
+        if (mManageReference) {
+            // managing reference for MPEG4/H.263/WMV.
+            // AVC should manage reference frame in a different way
+            if (mForwardReference != NULL) {
+                // this foward reference is no longer needed
+                mForwardReference->asReferernce = false;
+            }
+            // Forware reference for either P or B frame prediction
+            mForwardReference = mLastReference;
+            mAcquiredBuffer->asReferernce = true;
+        }
+
+        // the last reference frame.
+        mLastReference = mAcquiredBuffer;
+    }
+    // add to the output list
+    if (mShowFrame) {
+        if (mOutputHead == NULL) {
+            mOutputHead = mAcquiredBuffer;
+        } else {
+            mOutputTail->next = mAcquiredBuffer;
+        }
+        mOutputTail = mAcquiredBuffer;
+        mOutputTail->next = NULL;
+    }
+
+    //VTRACE("Pushing POC %d to queue (pts = %.2f)", mAcquiredBuffer->pictureOrder, mAcquiredBuffer->renderBuffer.timeStamp/1E6);
+
+    mAcquiredBuffer = NULL;
+    mSurfaceAcquirePos = (mSurfaceAcquirePos  + 1 ) % mNumSurfaces;
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::releaseSurfaceBuffer(void) {
+    if (mAcquiredBuffer == NULL) {
+        // this is harmless error
+        return DECODE_SUCCESS;
+    }
+
+    // frame is not decoded to the acquired buffer, current surface is invalid, and can't be output.
+    mAcquiredBuffer->asReferernce = false;
+    mAcquiredBuffer->renderBuffer.renderDone = true;
+    mAcquiredBuffer = NULL;
+    return DECODE_SUCCESS;
+}
+
+void VideoDecoderBase::flushSurfaceBuffers(void) {
+    endDecodingFrame(true);
+    VideoSurfaceBuffer *p = NULL;
+    while (mOutputHead) {
+        mOutputHead->renderBuffer.renderDone = true;
+        p = mOutputHead;
+        mOutputHead = mOutputHead->next;
+        p->next = NULL;
+    }
+    mOutputHead = NULL;
+    mOutputTail = NULL;
+}
+
+Decode_Status VideoDecoderBase::endDecodingFrame(bool dropFrame) {
+    Decode_Status status = DECODE_SUCCESS;
+    VAStatus vaStatus;
+
+    if (mDecodingFrame == false) {
+        if (mAcquiredBuffer != NULL) {
+            //ETRACE("mAcquiredBuffer is not NULL. Implementation bug.");
+            releaseSurfaceBuffer();
+            status = DECODE_FAIL;
+        }
+        return status;
+    }
+    // return through exit label to reset mDecodingFrame
+    if (mAcquiredBuffer == NULL) {
+        ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
+        status = DECODE_FAIL;
+        goto exit;
+    }
+
+    vaStatus = vaEndPicture(mVADisplay, mVAContext);
+    if (vaStatus != VA_STATUS_SUCCESS) {
+        releaseSurfaceBuffer();
+        ETRACE("vaEndPicture failed. vaStatus = %d", vaStatus);
+        status = DECODE_DRIVER_FAIL;
+        goto exit;
+    }
+
+    if (dropFrame) {
+        // we are asked to drop this decoded picture
+        VTRACE("Frame dropped in endDecodingFrame");
+        vaStatus = vaSyncSurface(mVADisplay, mAcquiredBuffer->renderBuffer.surface);
+        releaseSurfaceBuffer();
+        goto exit;
+    }
+    status = outputSurfaceBuffer();
+    // fall through
+exit:
+    mDecodingFrame = false;
+    return status;
+}
+
+
+Decode_Status VideoDecoderBase::setupVA(uint32_t numSurface, VAProfile profile, uint32_t numExtraSurface) {
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    Decode_Status status;
+    VAConfigAttrib attrib;
+
+    if (mVAStarted) {
+        return DECODE_SUCCESS;
+    }
+
+    mRotationDegrees = 0;
+    if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER){
+#ifdef TARGET_HAS_VPP
+        if (mVideoFormatInfo.actualBufferNeeded > mConfigBuffer.surfaceNumber - mConfigBuffer.vppBufferNum)
+#else
+        if (mVideoFormatInfo.actualBufferNeeded > mConfigBuffer.surfaceNumber)
+#endif
+            return DECODE_FORMAT_CHANGE;
+
+        numSurface = mConfigBuffer.surfaceNumber;
+        // if format has been changed in USE_NATIVE_GRAPHIC_BUFFER mode,
+        // we can not setupVA here when the graphic buffer resolution is smaller than the resolution decoder really needs
+        if (mSizeChanged) {
+            if (mVideoFormatInfo.surfaceWidth < mVideoFormatInfo.width || mVideoFormatInfo.surfaceHeight < mVideoFormatInfo.height) {
+                mSizeChanged = false;
+                return DECODE_FORMAT_CHANGE;
+            }
+        }
+    }
+
+    // TODO: validate profile
+    if (numSurface == 0) {
+        return DECODE_FAIL;
+    }
+
+    if (mConfigBuffer.flag & HAS_MINIMUM_SURFACE_NUMBER) {
+        if (numSurface < mConfigBuffer.surfaceNumber) {
+            WTRACE("surface to allocated %d is less than minimum number required %d",
+                    numSurface, mConfigBuffer.surfaceNumber);
+            numSurface = mConfigBuffer.surfaceNumber;
+        }
+    }
+
+    if (mVADisplay != NULL) {
+        ETRACE("VA is partially started.");
+        return DECODE_FAIL;
+    }
+
+    // Display is defined as "unsigned int"
+#ifndef USE_HYBRID_DRIVER
+    mDisplay = new Display;
+    *mDisplay = ANDROID_DISPLAY_HANDLE;
+#else
+    if (profile >= VAProfileH264Baseline && profile <= VAProfileVC1Advanced) {
+        ITRACE("Using GEN driver");
+        mDisplay = "libva_driver_name=i965";
+        mUseGEN = true;
+    } else {
+        ITRACE("Using PVR driver");
+        mDisplay = "libva_driver_name=pvr";
+        mUseGEN = false;
+    }
+
+#endif
+    mVADisplay = vaGetDisplay(mDisplay);
+    if (mVADisplay == NULL) {
+        ETRACE("vaGetDisplay failed.");
+        return DECODE_DRIVER_FAIL;
+    }
+
+    int majorVersion, minorVersion;
+    vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
+    CHECK_VA_STATUS("vaInitialize");
+
+    if ((int32_t)profile != VAProfileSoftwareDecoding) {
+
+        status = checkHardwareCapability();
+        CHECK_STATUS("checkHardwareCapability");
+
+#if (defined USE_AVC_SHORT_FORMAT || defined USE_SLICE_HEADER_PARSING)
+        status = getCodecSpecificConfigs(profile, &mVAConfig);
+        CHECK_STATUS("getCodecSpecificAttributes");
+#else
+        //We are requesting RT attributes
+        attrib.type = VAConfigAttribRTFormat;
+        attrib.value = VA_RT_FORMAT_YUV420;
+
+        vaStatus = vaCreateConfig(
+                mVADisplay,
+                profile,
+                VAEntrypointVLD,
+                &attrib,
+                1,
+                &mVAConfig);
+        CHECK_VA_STATUS("vaCreateConfig");
+#endif
+    }
+
+    mNumSurfaces = numSurface;
+    mNumExtraSurfaces = numExtraSurface;
+    mSurfaces = new VASurfaceID [mNumSurfaces + mNumExtraSurfaces];
+    mExtraSurfaces = mSurfaces + mNumSurfaces;
+    if (mSurfaces == NULL) {
+        return DECODE_MEMORY_FAIL;
+    }
+
+    setRenderRect();
+
+    int32_t format = VA_RT_FORMAT_YUV420;
+    if (mConfigBuffer.flag & WANT_SURFACE_PROTECTION) {
+#ifndef USE_AVC_SHORT_FORMAT
+        format |= VA_RT_FORMAT_PROTECTED;
+        WTRACE("Surface is protected.");
+#endif
+    }
+    if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) {
+        VASurfaceAttrib attribs[2];
+        mVASurfaceAttrib = new VASurfaceAttribExternalBuffers;
+        if (mVASurfaceAttrib == NULL) {
+            return DECODE_MEMORY_FAIL;
+        }
+
+        mVASurfaceAttrib->buffers= (unsigned long *)malloc(sizeof(unsigned long)*mNumSurfaces);
+        if (mVASurfaceAttrib->buffers == NULL) {
+            return DECODE_MEMORY_FAIL;
+        }
+        mVASurfaceAttrib->num_buffers = mNumSurfaces;
+        mVASurfaceAttrib->pixel_format = VA_FOURCC_NV12;
+        mVASurfaceAttrib->width = mVideoFormatInfo.surfaceWidth;
+        mVASurfaceAttrib->height = mVideoFormatInfo.surfaceHeight;
+        mVASurfaceAttrib->data_size = mConfigBuffer.graphicBufferStride * mVideoFormatInfo.surfaceHeight * 1.5;
+        mVASurfaceAttrib->num_planes = 2;
+        mVASurfaceAttrib->pitches[0] = mConfigBuffer.graphicBufferStride;
+        mVASurfaceAttrib->pitches[1] = mConfigBuffer.graphicBufferStride;
+        mVASurfaceAttrib->pitches[2] = 0;
+        mVASurfaceAttrib->pitches[3] = 0;
+        mVASurfaceAttrib->offsets[0] = 0;
+        mVASurfaceAttrib->offsets[1] = mConfigBuffer.graphicBufferStride * mVideoFormatInfo.surfaceHeight;
+        mVASurfaceAttrib->offsets[2] = 0;
+        mVASurfaceAttrib->offsets[3] = 0;
+        mVASurfaceAttrib->private_data = (void *)mConfigBuffer.nativeWindow;
+        mVASurfaceAttrib->flags = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
+        if (mConfigBuffer.flag & USE_TILING_MEMORY)
+            mVASurfaceAttrib->flags |= VA_SURFACE_EXTBUF_DESC_ENABLE_TILING;
+
+        for (int i = 0; i < mNumSurfaces; i++) {
+            mVASurfaceAttrib->buffers[i] = (unsigned long)mConfigBuffer.graphicBufferHandler[i];
+        }
+
+        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 = (void *)mVASurfaceAttrib;
+
+        vaStatus = vaCreateSurfaces(
+            mVADisplay,
+            format,
+            mVideoFormatInfo.surfaceWidth,
+            mVideoFormatInfo.surfaceHeight,
+            mSurfaces,
+            mNumSurfaces,
+            attribs,
+            2);
+
+    } else {
+        vaStatus = vaCreateSurfaces(
+            mVADisplay,
+            format,
+            mVideoFormatInfo.width,
+            mVideoFormatInfo.height,
+            mSurfaces,
+            mNumSurfaces,
+            NULL,
+            0);
+        mVideoFormatInfo.surfaceWidth = mVideoFormatInfo.width;
+        mVideoFormatInfo.surfaceHeight = mVideoFormatInfo.height;
+    }
+    CHECK_VA_STATUS("vaCreateSurfaces");
+
+    if (mNumExtraSurfaces != 0) {
+        vaStatus = vaCreateSurfaces(
+            mVADisplay,
+            format,
+            mVideoFormatInfo.surfaceWidth,
+            mVideoFormatInfo.surfaceHeight,
+            mExtraSurfaces,
+            mNumExtraSurfaces,
+            NULL,
+            0);
+        CHECK_VA_STATUS("vaCreateSurfaces");
+    }
+
+    mVideoFormatInfo.surfaceNumber = mNumSurfaces;
+    mVideoFormatInfo.ctxSurfaces = mSurfaces;
+
+    if ((int32_t)profile != VAProfileSoftwareDecoding) {
+        vaStatus = vaCreateContext(
+                mVADisplay,
+                mVAConfig,
+                mVideoFormatInfo.surfaceWidth,
+                mVideoFormatInfo.surfaceHeight,
+                0,
+                mSurfaces,
+                mNumSurfaces + mNumExtraSurfaces,
+                &mVAContext);
+        CHECK_VA_STATUS("vaCreateContext");
+    }
+
+    mSurfaceBuffers = new VideoSurfaceBuffer [mNumSurfaces];
+    if (mSurfaceBuffers == NULL) {
+        return DECODE_MEMORY_FAIL;
+    }
+    initSurfaceBuffer(true);
+
+    if ((int32_t)profile == VAProfileSoftwareDecoding) {
+        // derive user pointer from surface for direct access
+        status = mapSurface();
+        CHECK_STATUS("mapSurface")
+    }
+
+    setRotationDegrees(mConfigBuffer.rotationDegrees);
+
+    mVAStarted = true;
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::terminateVA(void) {
+    mSignalBufferSize = 0;
+    for (int i = 0; i < MAX_GRAPHIC_BUFFER_NUM; i++) {
+         mSignalBufferPre[i] = NULL;
+    }
+
+    if (mVAStarted == false) {
+        // VA hasn't been started yet
+        return DECODE_SUCCESS;
+    }
+
+    if (mSurfaceBuffers) {
+        for (int32_t i = 0; i < mNumSurfaces; i++) {
+            if (mSurfaceBuffers[i].renderBuffer.rawData) {
+                if (mSurfaceBuffers[i].renderBuffer.rawData->data) {
+                    delete [] mSurfaceBuffers[i].renderBuffer.rawData->data;
+                }
+                delete mSurfaceBuffers[i].renderBuffer.rawData;
+            }
+            if (mSurfaceBuffers[i].mappedData) {
+                // don't  delete data pointer as it is mapped from surface
+                delete mSurfaceBuffers[i].mappedData;
+            }
+        }
+        delete [] mSurfaceBuffers;
+        mSurfaceBuffers = NULL;
+    }
+
+    if (mVASurfaceAttrib) {
+        if (mVASurfaceAttrib->buffers) free(mVASurfaceAttrib->buffers);
+        delete mVASurfaceAttrib;
+        mVASurfaceAttrib = NULL;
+    }
+
+
+    if (mSurfaceUserPtr) {
+        delete [] mSurfaceUserPtr;
+        mSurfaceUserPtr = NULL;
+    }
+
+    if (mSurfaces)
+    {
+        vaDestroySurfaces(mVADisplay, mSurfaces, mNumSurfaces + mNumExtraSurfaces);
+        delete [] mSurfaces;
+        mSurfaces = NULL;
+    }
+
+    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) {
+#ifndef USE_HYBRID_DRIVER
+        delete mDisplay;
+#endif
+        mDisplay = NULL;
+    }
+
+    mVAStarted = false;
+    mInitialized = false;
+    mErrReportEnabled = false;
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::parseBuffer(uint8_t *buffer, int32_t size, bool config, void** vbpData) {
+     // DON'T check if mVAStarted == true
+    if (mParserHandle == NULL) {
+        return DECODE_NO_PARSER;
+    }
+
+    uint32_t vbpStatus;
+    if (buffer == NULL || size <= 0) {
+        return DECODE_INVALID_DATA;
+    }
+
+    uint8_t configFlag = config ? 1 : 0;
+    vbpStatus = mParserParse(mParserHandle, buffer, size, configFlag);
+    CHECK_VBP_STATUS("vbp_parse");
+
+    vbpStatus = mParserQuery(mParserHandle, vbpData);
+    CHECK_VBP_STATUS("vbp_query");
+
+    return DECODE_SUCCESS;
+}
+
+
+
+Decode_Status VideoDecoderBase::mapSurface(void) {
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAImage image;
+    uint8_t *userPtr;
+    mSurfaceUserPtr = new uint8_t* [mNumSurfaces];
+    if (mSurfaceUserPtr == NULL) {
+        return DECODE_MEMORY_FAIL;
+    }
+
+    for (int32_t i = 0; i< mNumSurfaces; i++) {
+        vaStatus = vaDeriveImage(mVADisplay, mSurfaces[i], &image);
+        CHECK_VA_STATUS("vaDeriveImage");
+        vaStatus = vaMapBuffer(mVADisplay, image.buf, (void**)&userPtr);
+        CHECK_VA_STATUS("vaMapBuffer");
+        mSurfaceUserPtr[i] = userPtr;
+        mSurfaceBuffers[i].mappedData = new VideoFrameRawData;
+        if (mSurfaceBuffers[i].mappedData == NULL) {
+            return DECODE_MEMORY_FAIL;
+        }
+        mSurfaceBuffers[i].mappedData->own = false; // derived from surface so can't be released
+        mSurfaceBuffers[i].mappedData->data = NULL;  // specified during acquireSurfaceBuffer
+        mSurfaceBuffers[i].mappedData->fourcc = image.format.fourcc;
+        mSurfaceBuffers[i].mappedData->width = mVideoFormatInfo.width;
+        mSurfaceBuffers[i].mappedData->height = mVideoFormatInfo.height;
+        mSurfaceBuffers[i].mappedData->size = image.data_size;
+        for (int pi = 0; pi < 3; pi++) {
+            mSurfaceBuffers[i].mappedData->pitch[pi] = image.pitches[pi];
+            mSurfaceBuffers[i].mappedData->offset[pi] = image.offsets[pi];
+        }
+        // debug information
+        if (image.pitches[0] != image.pitches[1] ||
+            image.width != mVideoFormatInfo.width ||
+            image.height != mVideoFormatInfo.height ||
+            image.offsets[0] != 0) {
+            WTRACE("Unexpected VAImage format, w = %d, h = %d, offset = %d", image.width, image.height, image.offsets[0]);
+        }
+        // TODO: do we need to unmap buffer?
+        //vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
+        //CHECK_VA_STATUS("vaMapBuffer");
+        vaStatus = vaDestroyImage(mVADisplay,image.image_id);
+        CHECK_VA_STATUS("vaDestroyImage");
+
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::getRawDataFromSurface(VideoRenderBuffer *renderBuffer, uint8_t *pRawData, uint32_t *pSize, bool internal) {
+    if (internal) {
+        if (mAcquiredBuffer == NULL) {
+            return DECODE_FAIL;
+        }
+        renderBuffer = &(mAcquiredBuffer->renderBuffer);
+    }
+
+    VAStatus vaStatus;
+    VAImageFormat imageFormat;
+    VAImage vaImage;
+    vaStatus = vaSyncSurface(renderBuffer->display, renderBuffer->surface);
+    CHECK_VA_STATUS("vaSyncSurface");
+
+    vaStatus = vaDeriveImage(renderBuffer->display, renderBuffer->surface, &vaImage);
+    CHECK_VA_STATUS("vaDeriveImage");
+
+    void *pBuf = NULL;
+    vaStatus = vaMapBuffer(renderBuffer->display, vaImage.buf, &pBuf);
+    CHECK_VA_STATUS("vaMapBuffer");
+
+
+    // size in NV12 format
+    uint32_t cropWidth = mVideoFormatInfo.width - (mVideoFormatInfo.cropLeft + mVideoFormatInfo.cropRight);
+    uint32_t cropHeight = mVideoFormatInfo.height - (mVideoFormatInfo.cropBottom + mVideoFormatInfo.cropTop);
+    int32_t size = cropWidth  * cropHeight * 3 / 2;
+
+    if (internal) {
+        VideoFrameRawData *rawData = NULL;
+        if (renderBuffer->rawData == NULL) {
+            rawData = new VideoFrameRawData;
+            if (rawData == NULL) {
+                return DECODE_MEMORY_FAIL;
+            }
+            memset(rawData, 0, sizeof(VideoFrameRawData));
+            renderBuffer->rawData = rawData;
+        } else {
+            rawData = renderBuffer->rawData;
+        }
+
+        if (rawData->data != NULL && rawData->size != size) {
+            delete [] rawData->data;
+            rawData->data = NULL;
+            rawData->size = 0;
+        }
+        if (rawData->data == NULL) {
+            rawData->data = new uint8_t [size];
+            if (rawData->data == NULL) {
+                return DECODE_MEMORY_FAIL;
+            }
+        }
+
+        rawData->own = true; // allocated by this library
+        rawData->width = cropWidth;
+        rawData->height = cropHeight;
+        rawData->pitch[0] = cropWidth;
+        rawData->pitch[1] = cropWidth;
+        rawData->pitch[2] = 0;  // interleaved U/V, two planes
+        rawData->offset[0] = 0;
+        rawData->offset[1] = cropWidth * cropHeight;
+        rawData->offset[2] = cropWidth * cropHeight * 3 / 2;
+        rawData->size = size;
+        rawData->fourcc = 'NV12';
+
+        pRawData = rawData->data;
+    } else {
+        *pSize = size;
+    }
+
+    if (size == (int32_t)vaImage.data_size) {
+#ifdef  __SSE4_1__
+        stream_memcpy(pRawData, pBuf, size);
+#else
+        memcpy(pRawData, pBuf, size);
+#endif
+    } else {
+        // copy Y data
+        uint8_t *src = (uint8_t*)pBuf;
+        uint8_t *dst = pRawData;
+        uint32_t row = 0;
+        for (row = 0; row < cropHeight; row++) {
+#ifdef  __SSE4_1__
+            stream_memcpy(dst, src, cropWidth);
+#else
+            memcpy(dst, src, cropWidth);
+#endif
+            dst += cropWidth;
+            src += vaImage.pitches[0];
+        }
+        // copy interleaved V and  U data
+        src = (uint8_t*)pBuf + vaImage.offsets[1];
+        for (row = 0; row < cropHeight / 2; row++) {
+#ifdef  __SSE4_1__
+            stream_memcpy(dst, src, cropWidth);
+#else
+            memcpy(dst, src, cropWidth);
+#endif
+            dst += cropWidth;
+            src += vaImage.pitches[1];
+        }
+    }
+
+    vaStatus = vaUnmapBuffer(renderBuffer->display, vaImage.buf);
+    CHECK_VA_STATUS("vaUnmapBuffer");
+
+    vaStatus = vaDestroyImage(renderBuffer->display, vaImage.image_id);
+    CHECK_VA_STATUS("vaDestroyImage");
+
+    return DECODE_SUCCESS;
+}
+
+void VideoDecoderBase::initSurfaceBuffer(bool reset) {
+    bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+    if (useGraphicBuffer && reset) {
+        pthread_mutex_lock(&mLock);
+    }
+    for (int32_t i = 0; i < mNumSurfaces; i++) {
+        mSurfaceBuffers[i].renderBuffer.display = mVADisplay;
+        mSurfaceBuffers[i].renderBuffer.surface = VA_INVALID_SURFACE;  // set in acquireSurfaceBuffer
+        mSurfaceBuffers[i].renderBuffer.flag = 0;
+        mSurfaceBuffers[i].renderBuffer.scanFormat = VA_FRAME_PICTURE;
+        mSurfaceBuffers[i].renderBuffer.timeStamp = 0;
+        mSurfaceBuffers[i].referenceFrame = false;
+        mSurfaceBuffers[i].asReferernce= false;
+        mSurfaceBuffers[i].pictureOrder = 0;
+        mSurfaceBuffers[i].next = NULL;
+        if (reset == true) {
+            mSurfaceBuffers[i].renderBuffer.rawData = NULL;
+            mSurfaceBuffers[i].mappedData = NULL;
+        }
+        if (useGraphicBuffer) {
+            if (reset) {
+               mSurfaceBuffers[i].renderBuffer.graphicBufferHandle = mConfigBuffer.graphicBufferHandler[i];
+               mSurfaceBuffers[i].renderBuffer.renderDone = false; //default false
+               for (uint32_t j = 0; j < mSignalBufferSize; j++) {
+                   if(mSignalBufferPre[j] != NULL && mSignalBufferPre[j] == mSurfaceBuffers[i].renderBuffer.graphicBufferHandle) {
+                      mSurfaceBuffers[i].renderBuffer.renderDone = true;
+                      VTRACE("initSurfaceBuffer set renderDone = true index = %d", i);
+                      mSignalBufferPre[j] = NULL;
+                      break;
+                   }
+               }
+            } else {
+               mSurfaceBuffers[i].renderBuffer.renderDone = false;
+            }
+        } else {
+            mSurfaceBuffers[i].renderBuffer.graphicBufferHandle = NULL;
+            mSurfaceBuffers[i].renderBuffer.renderDone = true;
+        }
+        mSurfaceBuffers[i].renderBuffer.graphicBufferIndex = i;
+    }
+
+    if (useGraphicBuffer && reset) {
+        mInitialized = true;
+        mSignalBufferSize = 0;
+        pthread_mutex_unlock(&mLock);
+    }
+}
+
+Decode_Status VideoDecoderBase::signalRenderDone(void * graphichandler) {
+    if (graphichandler == NULL) {
+        return DECODE_SUCCESS;
+    }
+    pthread_mutex_lock(&mLock);
+    int i = 0;
+    if (!mInitialized) {
+        if (mSignalBufferSize >= MAX_GRAPHIC_BUFFER_NUM) {
+            pthread_mutex_unlock(&mLock);
+            return DECODE_INVALID_DATA;
+        }
+        mSignalBufferPre[mSignalBufferSize++] = graphichandler;
+        VTRACE("SignalRenderDoneFlag mInitialized = false graphichandler = %p, mSignalBufferSize = %d", graphichandler, mSignalBufferSize);
+    } else {
+        if (!(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) {
+            pthread_mutex_unlock(&mLock);
+            return DECODE_SUCCESS;
+        }
+        for (i = 0; i < mNumSurfaces; i++) {
+            if (mSurfaceBuffers[i].renderBuffer.graphicBufferHandle == graphichandler) {
+                mSurfaceBuffers[i].renderBuffer.renderDone = true;
+                VTRACE("SignalRenderDoneFlag mInitialized = true index = %d", i);
+               break;
+           }
+        }
+    }
+    pthread_mutex_unlock(&mLock);
+
+    return DECODE_SUCCESS;
+
+}
+
+void VideoDecoderBase::querySurfaceRenderStatus(VideoSurfaceBuffer* surface) {
+    VASurfaceStatus surfStat = VASurfaceReady;
+    VAStatus    vaStat = VA_STATUS_SUCCESS;
+
+    if (!surface) {
+        LOGW("SurfaceBuffer not ready yet");
+        return;
+    }
+    surface->renderBuffer.driverRenderDone = true;
+
+#ifndef USE_GEN_HW
+    if (surface->renderBuffer.surface != VA_INVALID_SURFACE &&
+       (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) {
+
+        vaStat = vaQuerySurfaceStatus(mVADisplay, surface->renderBuffer.surface, &surfStat);
+
+        if ((vaStat == VA_STATUS_SUCCESS) && (surfStat != VASurfaceReady))
+            surface->renderBuffer.driverRenderDone = false;
+
+    }
+#endif
+
+}
+
+// This function should be called before start() to load different type of parsers
+#if (defined USE_AVC_SHORT_FORMAT || defined USE_SLICE_HEADER_PARSING)
+Decode_Status VideoDecoderBase::setParserType(_vbp_parser_type type) {
+    if ((int32_t)type != VBP_INVALID) {
+        ITRACE("Parser Type = %d", (int32_t)type);
+        mParserType = type;
+        return DECODE_SUCCESS;
+    } else {
+        ETRACE("Invalid parser type = %d", (int32_t)type);
+        return DECODE_NO_PARSER;
+    }
+}
+
+Decode_Status VideoDecoderBase::updateBuffer(uint8_t *buffer, int32_t size, void** vbpData) {
+    if (mParserHandle == NULL) {
+        return DECODE_NO_PARSER;
+    }
+
+    uint32_t vbpStatus;
+    if (buffer == NULL || size <= 0) {
+        return DECODE_INVALID_DATA;
+    }
+
+    vbpStatus = mParserUpdate(mParserHandle, buffer, size, vbpData);
+    CHECK_VBP_STATUS("vbp_update");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::queryBuffer(void** vbpData) {
+    if (mParserHandle == NULL) {
+        return DECODE_NO_PARSER;
+    }
+
+    uint32_t vbpStatus;
+    vbpStatus = mParserQuery(mParserHandle, vbpData);
+    CHECK_VBP_STATUS("vbp_query");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderBase::getCodecSpecificConfigs(VAProfile profile, VAConfigID *config) {
+    VAStatus vaStatus;
+    VAConfigAttrib attrib;
+    attrib.type = VAConfigAttribRTFormat;
+    attrib.value = VA_RT_FORMAT_YUV420;
+
+    if (config == NULL) {
+        ETRACE("Invalid parameter!");
+        return DECODE_FAIL;
+    }
+
+    vaStatus = vaCreateConfig(
+            mVADisplay,
+            profile,
+            VAEntrypointVLD,
+            &attrib,
+            1,
+            config);
+
+    CHECK_VA_STATUS("vaCreateConfig");
+
+    return DECODE_SUCCESS;
+}
+#endif
+Decode_Status VideoDecoderBase::checkHardwareCapability() {
+    return DECODE_SUCCESS;
+}
+
+void VideoDecoderBase::drainDecodingErrors(VideoErrorBuffer *outErrBuf, VideoRenderBuffer *currentSurface) {
+    if (mErrReportEnabled && outErrBuf && currentSurface) {
+        memcpy(outErrBuf, &(currentSurface->errBuf), sizeof(VideoErrorBuffer));
+
+        currentSurface->errBuf.errorNumber = 0;
+        currentSurface->errBuf.timeStamp = INVALID_PTS;
+    }
+    if (outErrBuf)
+        VTRACE("%s: error number is %d", __FUNCTION__, outErrBuf->errorNumber);
+}
+
+void VideoDecoderBase::fillDecodingErrors(VideoRenderBuffer *currentSurface) {
+    VAStatus ret;
+
+    if (mErrReportEnabled) {
+        currentSurface->errBuf.timeStamp = currentSurface->timeStamp;
+        // TODO: is 10 a suitable number?
+        VASurfaceDecodeMBErrors *err_drv_output = NULL;
+        ret = vaQuerySurfaceError(mVADisplay, currentSurface->surface, VA_STATUS_ERROR_DECODING_ERROR, (void **)&err_drv_output);
+        if (ret || !err_drv_output) {
+            WTRACE("vaQuerySurfaceError failed.");
+            return;
+        }
+
+        int offset =  0x1 & currentSurface->errBuf.errorNumber;// offset is either 0 or 1
+        for (int i = 0; i < MAX_ERR_NUM - offset; i++) {
+            if (err_drv_output[i].status != -1) {
+                currentSurface->errBuf.errorNumber++;
+                currentSurface->errBuf.errorArray[i + offset].type = DecodeMBError;
+                currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.start_mb = err_drv_output[i].start_mb;
+                currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.end_mb = err_drv_output[i].end_mb;
+                currentSurface->errBuf.errorArray[i + offset].num_mbs = err_drv_output[i].end_mb - err_drv_output[i].start_mb + 1;
+                ITRACE("Error Index[%d]: type = %d, start_mb = %d, end_mb = %d",
+                    currentSurface->errBuf.errorNumber - 1,
+                    currentSurface->errBuf.errorArray[i + offset].type,
+                    currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.start_mb,
+                    currentSurface->errBuf.errorArray[i + offset].error_data.mb_pos.end_mb);
+            } else break;
+        }
+        ITRACE("%s: error number of current surface is %d, timestamp @%llu",
+            __FUNCTION__, currentSurface->errBuf.errorNumber, currentSurface->timeStamp);
+    }
+}
+
+void VideoDecoderBase::setRotationDegrees(int32_t rotationDegrees) {
+    if (mRotationDegrees == rotationDegrees) {
+        return;
+    }
+
+    ITRACE("set new rotation degree: %d", rotationDegrees);
+    VADisplayAttribute rotate;
+    rotate.type = VADisplayAttribRotation;
+    rotate.value = VA_ROTATION_NONE;
+    if (rotationDegrees == 0)
+        rotate.value = VA_ROTATION_NONE;
+    else if (rotationDegrees == 90)
+        rotate.value = VA_ROTATION_90;
+    else if (rotationDegrees == 180)
+        rotate.value = VA_ROTATION_180;
+    else if (rotationDegrees == 270)
+        rotate.value = VA_ROTATION_270;
+
+    VAStatus ret = vaSetDisplayAttributes(mVADisplay, &rotate, 1);
+    if (ret) {
+        ETRACE("Failed to set rotation degree.");
+    }
+    mRotationDegrees = rotationDegrees;
+}
+
+void VideoDecoderBase::setRenderRect() {
+
+    if (!mVADisplay)
+        return;
+
+    VAStatus ret;
+    VARectangle rect;
+    rect.x = mVideoFormatInfo.cropLeft;
+    rect.y = mVideoFormatInfo.cropTop;
+    rect.width = mVideoFormatInfo.width - (mVideoFormatInfo.cropLeft + mVideoFormatInfo.cropRight);
+    rect.height = mVideoFormatInfo.height - (mVideoFormatInfo.cropBottom + mVideoFormatInfo.cropTop);
+
+    VADisplayAttribute render_rect;
+    render_rect.type = VADisplayAttribRenderRect;
+    render_rect.value = (long)&rect;
+
+    ret = vaSetDisplayAttributes(mVADisplay, &render_rect, 1);
+    if (ret) {
+        ETRACE("Failed to set rotation degree.");
+    }
+}
diff --git a/videodecoder/VideoDecoderBase.h b/videodecoder/VideoDecoderBase.h
new file mode 100755
index 0000000..9cf09e8
--- /dev/null
+++ b/videodecoder/VideoDecoderBase.h
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_BASE_H_
+#define VIDEO_DECODER_BASE_H_
+
+#include <va/va.h>
+#include <va/va_tpi.h>
+#include "VideoDecoderDefs.h"
+#include "VideoDecoderInterface.h"
+#include <pthread.h>
+#include <dlfcn.h>
+
+extern "C" {
+#include "vbp_loader.h"
+}
+
+#ifndef Display
+#ifdef USE_GEN_HW
+typedef char Display;
+#else
+typedef unsigned int Display;
+#endif
+#endif
+
+// TODO: check what is the best number. Must be at least 2 to support one backward reference frame.
+// Currently set to 8 to support 7 backward reference frames. This value is used for AVC frame reordering only.
+// e.g:
+// POC: 4P,  8P,  10P,  6B and mNextOutputPOC = 5
+#define OUTPUT_WINDOW_SIZE 8
+
+class VideoDecoderBase : public IVideoDecoder {
+public:
+    VideoDecoderBase(const char *mimeType, _vbp_parser_type type);
+    virtual ~VideoDecoderBase();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual Decode_Status reset(VideoConfigBuffer *buffer) ;
+    virtual void stop(void);
+    //virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+    virtual void flush(void);
+    virtual void freeSurfaceBuffers(void);
+    virtual const VideoRenderBuffer* getOutput(bool draining = false, VideoErrorBuffer *output_buf = NULL);
+    virtual Decode_Status signalRenderDone(void * graphichandler);
+    virtual const VideoFormatInfo* getFormatInfo(void);
+    virtual bool checkBufferAvail();
+    virtual void enableErrorReport(bool enabled = false) {mErrReportEnabled = enabled; };
+
+protected:
+    // each acquireSurfaceBuffer must be followed by a corresponding outputSurfaceBuffer or releaseSurfaceBuffer.
+    // Only one surface buffer can be acquired at any given time
+    virtual Decode_Status acquireSurfaceBuffer(void);
+    // frame is successfully decoded to the acquired surface buffer and surface is ready for output
+    virtual Decode_Status outputSurfaceBuffer(void);
+    // acquired surface  buffer is not used
+    virtual Decode_Status releaseSurfaceBuffer(void);
+    // flush all decoded but not rendered buffers
+    virtual void flushSurfaceBuffers(void);
+    virtual Decode_Status endDecodingFrame(bool dropFrame);
+    virtual VideoSurfaceBuffer* findOutputByPoc(bool draining = false);
+    virtual VideoSurfaceBuffer* findOutputByPct(bool draining = false);
+    virtual VideoSurfaceBuffer* findOutputByPts();
+    virtual Decode_Status setupVA(uint32_t numSurface, VAProfile profile, uint32_t numExtraSurface = 0);
+    virtual Decode_Status terminateVA(void);
+    virtual Decode_Status parseBuffer(uint8_t *buffer, int32_t size, bool config, void** vbpData);
+
+    static inline uint32_t alignMB(uint32_t a) {
+         return ((a + 15) & (~15));
+    }
+
+    virtual Decode_Status getRawDataFromSurface(VideoRenderBuffer *renderBuffer = NULL, uint8_t *pRawData = NULL, uint32_t *pSize = NULL, bool internal = true);
+
+#if (defined USE_AVC_SHORT_FORMAT) || (defined USE_SLICE_HEADER_PARSING)
+    Decode_Status updateBuffer(uint8_t *buffer, int32_t size, void** vbpData);
+    Decode_Status queryBuffer(void **vbpData);
+    Decode_Status setParserType(_vbp_parser_type type);
+    virtual Decode_Status getCodecSpecificConfigs(VAProfile profile, VAConfigID *config);
+#endif
+    virtual Decode_Status checkHardwareCapability();
+private:
+    Decode_Status mapSurface(void);
+    void initSurfaceBuffer(bool reset);
+    void drainDecodingErrors(VideoErrorBuffer *outErrBuf, VideoRenderBuffer *currentSurface);
+    void fillDecodingErrors(VideoRenderBuffer *currentSurface);
+
+    bool mInitialized;
+    pthread_mutex_t mLock;
+
+protected:
+    bool mLowDelay; // when true, decoded frame is immediately output for rendering
+    VideoFormatInfo mVideoFormatInfo;
+    Display *mDisplay;
+    VADisplay mVADisplay;
+    VAContextID mVAContext;
+    VAConfigID mVAConfig;
+    VASurfaceID *mExtraSurfaces; // extra surfaces array
+    int32_t mNumExtraSurfaces;
+    bool mVAStarted;
+    uint64_t mCurrentPTS; // current presentation time stamp (unit is unknown, depend on the framework: GStreamer 100-nanosec, Android: microsecond)
+    // the following three member variables should be set using
+    // acquireSurfaceBuffer/outputSurfaceBuffer/releaseSurfaceBuffer
+    VideoSurfaceBuffer *mAcquiredBuffer;
+    VideoSurfaceBuffer *mLastReference;
+    VideoSurfaceBuffer *mForwardReference;
+    VideoConfigBuffer  mConfigBuffer; // only store configure meta data.
+    bool mDecodingFrame; // indicate whether a frame is being decoded
+    bool mSizeChanged; // indicate whether video size is changed.
+    bool mShowFrame; // indicate whether the decoded frame is for display
+
+    int32_t mOutputWindowSize; // indicate limit of number of outstanding frames for output
+    int32_t mRotationDegrees;
+
+    bool mErrReportEnabled;
+    bool mWiDiOn;
+    typedef uint32_t (*OpenFunc)(uint32_t, void **);
+    typedef uint32_t (*CloseFunc)(void *);
+    typedef uint32_t (*ParseFunc)(void *, uint8_t *, uint32_t, uint8_t);
+    typedef uint32_t (*QueryFunc)(void *, void **);
+    typedef uint32_t (*FlushFunc)(void *);
+    typedef uint32_t (*UpdateFunc)(void *, void *, uint32_t, void **);
+    void *mLibHandle;
+    OpenFunc mParserOpen;
+    CloseFunc mParserClose;
+    ParseFunc mParserParse;
+    QueryFunc mParserQuery;
+    FlushFunc mParserFlush;
+    UpdateFunc mParserUpdate;
+    enum {
+        // TODO: move this to vbp_loader.h
+        VBP_INVALID = 0xFF,
+        // TODO: move this to va.h
+        VAProfileSoftwareDecoding = 0xFF,
+    };
+
+    enum OUTPUT_METHOD {
+        // output by Picture Coding Type (I, P, B)
+         OUTPUT_BY_PCT,
+        // output by Picture Order Count (for AVC only)
+         OUTPUT_BY_POC,
+         //OUTPUT_BY_POS,
+         //OUTPUT_BY_PTS,
+     };
+
+private:
+    bool mRawOutput; // whether to output NV12 raw data
+    bool mManageReference;  // this should stay true for VC1/MP4 decoder, and stay false for AVC decoder. AVC  handles reference frame using DPB
+    OUTPUT_METHOD mOutputMethod;
+
+    int32_t mNumSurfaces;
+    VideoSurfaceBuffer *mSurfaceBuffers;
+    VideoSurfaceBuffer *mOutputHead; // head of output buffer list
+    VideoSurfaceBuffer *mOutputTail;  // tail of output buffer list
+    VASurfaceID *mSurfaces; // surfaces array
+    VASurfaceAttribExternalBuffers *mVASurfaceAttrib;
+    uint8_t **mSurfaceUserPtr; // mapped user space pointer
+    int32_t mSurfaceAcquirePos; // position of surface to start acquiring
+    int32_t mNextOutputPOC; // Picture order count of next output
+    _vbp_parser_type mParserType;
+    void *mParserHandle;
+    void *mSignalBufferPre[MAX_GRAPHIC_BUFFER_NUM];
+    uint32 mSignalBufferSize;
+    bool mUseGEN;
+protected:
+    void ManageReference(bool enable) {mManageReference = enable;}
+    void setOutputMethod(OUTPUT_METHOD method) {mOutputMethod = method;}
+    void setOutputWindowSize(int32_t size) {mOutputWindowSize = (size < OUTPUT_WINDOW_SIZE) ? size : OUTPUT_WINDOW_SIZE;}
+    void querySurfaceRenderStatus(VideoSurfaceBuffer* surface);
+    void enableLowDelayMode(bool enable) {mLowDelay = enable;}
+    void setRotationDegrees(int32_t rotationDegrees);
+    void setRenderRect(void);
+};
+
+
+#endif  // VIDEO_DECODER_BASE_H_
diff --git a/videodecoder/VideoDecoderDefs.h b/videodecoder/VideoDecoderDefs.h
new file mode 100644
index 0000000..c9b5d30
--- /dev/null
+++ b/videodecoder/VideoDecoderDefs.h
@@ -0,0 +1,263 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_DEFS_H_
+#define VIDEO_DECODER_DEFS_H_
+
+#include <va/va.h>
+#include <stdint.h>
+
+// format specific data, for future extension.
+struct VideoExtensionBuffer {
+    int32_t extType;
+    int32_t extSize;
+    uint8_t *extData;
+};
+
+typedef enum {
+    PACKED_FRAME_TYPE,
+} VIDEO_EXTENSION_TYPE;
+
+struct VideoFrameRawData {
+    int32_t width;
+    int32_t height;
+    int32_t pitch[3];
+    int32_t offset[3];
+    uint32_t fourcc;  //NV12
+    int32_t size;
+    uint8_t *data;
+    bool own; // own data or derived from surface. If true, the library will release the memory during clearnup
+};
+
+struct PackedFrameData {
+    int64_t timestamp;
+    int32_t offSet;
+};
+
+// flags for VideoDecodeBuffer, VideoConfigBuffer and VideoRenderBuffer
+typedef enum {
+    // indicates if sample has discontinuity in time stamp (happen after seeking usually)
+    HAS_DISCONTINUITY = 0x01,
+
+    // indicates wheter the sample contains a complete frame or end of frame.
+    HAS_COMPLETE_FRAME = 0x02,
+
+    // indicate whether surfaceNumber field  in the VideoConfigBuffer is valid
+    HAS_SURFACE_NUMBER = 0x04,
+
+    // indicate whether profile field in the VideoConfigBuffer is valid
+    HAS_VA_PROFILE = 0x08,
+
+    // indicate whether output order will be the same as decoder order
+    WANT_LOW_DELAY = 0x10, // make display order same as decoding order
+
+    // indicates whether error concealment algorithm should be enabled to automatically conceal error.
+    WANT_ERROR_CONCEALMENT = 0x20,
+
+    // indicate wheter raw data should be output.
+    WANT_RAW_OUTPUT = 0x40,
+
+    // indicate sample is decoded but should not be displayed.
+    WANT_DECODE_ONLY = 0x80,
+
+    // indicate surfaceNumber field is valid and it contains minimum surface number to allocate.
+    HAS_MINIMUM_SURFACE_NUMBER = 0x100,
+
+    // indicates surface created will be protected
+    WANT_SURFACE_PROTECTION = 0x400,
+
+    // indicates if extra data is appended at end of buffer
+    HAS_EXTRADATA = 0x800,
+
+    // indicates if buffer contains codec data
+    HAS_CODECDATA = 0x1000,
+
+    // indicate if it use graphic buffer.
+    USE_NATIVE_GRAPHIC_BUFFER = 0x2000,
+
+    // indicate whether it is a sync frame in container
+    IS_SYNC_FRAME = 0x4000,
+
+    // indicate whether video decoder buffer contains secure data
+    IS_SECURE_DATA = 0x8000,
+
+    // indicate it's the last output frame of the sequence
+    IS_EOS = 0x10000,
+
+    // indicate should allocate tiling surfaces
+    USE_TILING_MEMORY = 0x20000,
+
+     // indicate the frame has resolution change
+    IS_RESOLUTION_CHANGE = 0x40000,
+
+    // indicate whether video decoder buffer contains only one field
+    IS_SINGLE_FIELD = 0x80000,
+
+    // indicate adaptive playback mode
+    WANT_ADAPTIVE_PLAYBACK = 0x100000,
+
+    // indicate the modular drm type
+    IS_SUBSAMPLE_ENCRYPTION = 0x200000,
+
+} VIDEO_BUFFER_FLAG;
+
+typedef enum
+{
+        DecodeHeaderError   = 0,
+        DecodeMBError       = 1,
+        DecodeSliceMissing  = 2,
+        DecodeRefMissing    = 3,
+} VideoDecodeErrorType;
+
+#define MAX_ERR_NUM 10
+
+struct VideoDecodeBuffer {
+    uint8_t *data;
+    int32_t size;
+    int64_t timeStamp;
+    uint32_t flag;
+    uint32_t rotationDegrees;
+    VideoExtensionBuffer *ext;
+};
+
+
+//#define MAX_GRAPHIC_BUFFER_NUM  (16 + 1 + 11)  // max DPB + 1 + AVC_EXTRA_NUM
+#define MAX_GRAPHIC_BUFFER_NUM 64 // extended for VPP
+
+struct VideoConfigBuffer {
+    uint8_t *data;
+    int32_t size;
+    int32_t width;
+    int32_t height;
+    uint32_t surfaceNumber;
+    VAProfile profile;
+    uint32_t flag;
+    void *graphicBufferHandler[MAX_GRAPHIC_BUFFER_NUM];
+    uint32_t graphicBufferStride;
+    uint32_t graphicBufferColorFormat;
+    uint32_t graphicBufferWidth;
+    uint32_t graphicBufferHeight;
+    VideoExtensionBuffer *ext;
+    void* nativeWindow;
+    uint32_t rotationDegrees;
+#ifdef TARGET_HAS_VPP
+    uint32_t vppBufferNum;
+#endif
+};
+
+struct VideoErrorInfo {
+    VideoDecodeErrorType type;
+    uint32_t num_mbs;
+    union {
+        struct {uint32_t start_mb; uint32_t end_mb;} mb_pos;
+    } error_data;
+};
+
+struct VideoErrorBuffer {
+    uint32_t errorNumber;   // Error number should be no more than MAX_ERR_NUM
+	int64_t timeStamp;      // presentation time stamp
+    VideoErrorInfo errorArray[MAX_ERR_NUM];
+};
+
+struct VideoRenderBuffer {
+    VASurfaceID surface;
+    VADisplay display;
+    int32_t scanFormat;  //progressive,  top-field first, or bottom-field first
+    int64_t timeStamp;  // presentation time stamp
+    mutable volatile bool renderDone;  // indicated whether frame is rendered, this must be set to false by the client of this library once
+                                        // surface is rendered. Not setting this flag will lead to DECODE_NO_SURFACE error.
+    void * graphicBufferHandle;
+    int32_t graphicBufferIndex;  //the index in graphichandle array
+    uint32_t flag;
+    mutable volatile bool driverRenderDone;
+    VideoFrameRawData *rawData;
+
+    VideoErrorBuffer errBuf;
+};
+
+struct VideoSurfaceBuffer {
+    VideoRenderBuffer renderBuffer;
+    int32_t pictureOrder;  // picture order count, valid only for AVC format
+    bool referenceFrame;  // indicated whether frame associated with this surface is a reference I/P frame
+    bool asReferernce; // indicated wheter frame is used as reference (as a result surface can not be used for decoding)
+    VideoFrameRawData *mappedData;
+    VideoSurfaceBuffer *next;
+};
+
+struct VideoFormatInfo {
+    bool valid;  // indicates whether format info is valid. MimeType is always valid.
+    char *mimeType;
+    uint32_t width;
+    uint32_t height;
+    uint32_t surfaceWidth;
+    uint32_t surfaceHeight;
+    uint32_t surfaceNumber;
+    VASurfaceID *ctxSurfaces;
+    int32_t aspectX;
+    int32_t aspectY;
+    int32_t cropLeft;
+    int32_t cropRight;
+    int32_t cropTop;
+    int32_t cropBottom;
+    int32_t colorMatrix;
+    int32_t videoRange;
+    int32_t bitrate;
+    int32_t framerateNom;
+    int32_t framerateDenom;
+    uint32_t actualBufferNeeded;
+    int32_t flags; // indicate whether current picture is field or frame
+    VideoExtensionBuffer *ext;
+};
+
+// TODO: categorize the follow errors as fatal and non-fatal.
+typedef enum {
+    DECODE_NOT_STARTED = -10,
+    DECODE_NEED_RESTART = -9,
+    DECODE_NO_CONFIG = -8,
+    DECODE_NO_SURFACE = -7,
+    DECODE_NO_REFERENCE = -6,
+    DECODE_NO_PARSER = -5,
+    DECODE_INVALID_DATA = -4,
+    DECODE_DRIVER_FAIL = -3,
+    DECODE_PARSER_FAIL = -2,
+    DECODE_MEMORY_FAIL = -1,
+    DECODE_FAIL = 0,
+    DECODE_SUCCESS = 1,
+    DECODE_FORMAT_CHANGE = 2,
+    DECODE_FRAME_DROPPED = 3,
+    DECODE_MULTIPLE_FRAME = 4,
+} VIDEO_DECODE_STATUS;
+
+typedef int32_t Decode_Status;
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+inline bool checkFatalDecoderError(Decode_Status status) {
+    if (status == DECODE_NOT_STARTED ||
+        status == DECODE_NEED_RESTART ||
+        status == DECODE_NO_PARSER ||
+        status == DECODE_INVALID_DATA ||
+        status == DECODE_MEMORY_FAIL ||
+        status == DECODE_FAIL) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+#endif  // VIDEO_DECODER_DEFS_H_
diff --git a/videodecoder/VideoDecoderHost.cpp b/videodecoder/VideoDecoderHost.cpp
new file mode 100644
index 0000000..56f55d7
--- /dev/null
+++ b/videodecoder/VideoDecoderHost.cpp
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderWMV.h"
+#include "VideoDecoderMPEG4.h"
+#include "VideoDecoderAVC.h"
+
+#ifdef USE_INTEL_SECURE_AVC
+#include "VideoDecoderAVCSecure.h"
+#endif
+
+#ifdef USE_HW_VP8
+#include "VideoDecoderVP8.h"
+#endif
+#include "VideoDecoderHost.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+IVideoDecoder* createVideoDecoder(const char* mimeType) {
+    if (mimeType == NULL) {
+        ETRACE("NULL mime type.");
+        return NULL;
+    }
+
+    if (strcasecmp(mimeType, "video/wmv") == 0 ||
+        strcasecmp(mimeType, "video/vc1") == 0 ||
+        strcasecmp(mimeType, "video/x-ms-wmv") == 0) {
+        VideoDecoderWMV *p = new VideoDecoderWMV(mimeType);
+        return (IVideoDecoder *)p;
+    } else if (strcasecmp(mimeType, "video/avc") == 0 ||
+               strcasecmp(mimeType, "video/h264") == 0) {
+        VideoDecoderAVC *p = new VideoDecoderAVC(mimeType);
+        return (IVideoDecoder *)p;
+    } else if (strcasecmp(mimeType, "video/mp4v-es") == 0 ||
+               strcasecmp(mimeType, "video/mpeg4") == 0 ||
+               strcasecmp(mimeType, "video/h263") == 0 ||
+               strcasecmp(mimeType, "video/3gpp") == 0) {
+        VideoDecoderMPEG4 *p = new VideoDecoderMPEG4(mimeType);
+        return (IVideoDecoder *)p;
+    }
+#ifdef USE_INTEL_SECURE_AVC
+    else if (strcasecmp(mimeType, "video/avc-secure") == 0) {
+        VideoDecoderAVC *p = new VideoDecoderAVCSecure(mimeType);
+        return (IVideoDecoder *)p;
+    }
+#endif
+
+#ifdef USE_HW_VP8
+    else if (strcasecmp(mimeType, "video/vp8") == 0 ||
+        strcasecmp(mimeType, "video/x-vnd.on2.vp8") == 0) {
+        VideoDecoderVP8 *p = new VideoDecoderVP8(mimeType);
+        return (IVideoDecoder *)p;
+    }
+#endif
+
+    else {
+        ETRACE("Unknown mime type: %s", mimeType);
+    }
+    return NULL;
+}
+
+void releaseVideoDecoder(IVideoDecoder* p) {
+    if (p) {
+        const VideoFormatInfo *info  = p->getFormatInfo();
+        if (info && info->mimeType) {
+            ITRACE("Deleting decoder for %s", info->mimeType);
+        }
+    }
+    delete p;
+}
+
+
diff --git a/videodecoder/VideoDecoderHost.h b/videodecoder/VideoDecoderHost.h
new file mode 100644
index 0000000..1f053b6
--- /dev/null
+++ b/videodecoder/VideoDecoderHost.h
@@ -0,0 +1,29 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_HOST_H_
+#define VIDEO_DECODER_HOST_H_
+
+
+#include "VideoDecoderInterface.h"
+
+IVideoDecoder* createVideoDecoder(const char* mimeType);
+void releaseVideoDecoder(IVideoDecoder *p);
+
+
+
+#endif /* VIDEO_DECODER_HOST_H_ */
diff --git a/videodecoder/VideoDecoderInterface.h b/videodecoder/VideoDecoderInterface.h
new file mode 100644
index 0000000..fdc2c12
--- /dev/null
+++ b/videodecoder/VideoDecoderInterface.h
@@ -0,0 +1,40 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_INTERFACE_H_
+#define VIDEO_DECODER_INTERFACE_H_
+
+#include "VideoDecoderDefs.h"
+
+class IVideoDecoder {
+public:
+    virtual ~IVideoDecoder() {}
+    virtual Decode_Status start(VideoConfigBuffer *buffer) = 0;
+    virtual Decode_Status reset(VideoConfigBuffer *buffer) = 0;
+    virtual void stop(void) = 0;
+    virtual void flush() = 0;
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer) = 0;
+    virtual void freeSurfaceBuffers(void) = 0;
+    virtual const VideoRenderBuffer* getOutput(bool draining = false, VideoErrorBuffer *output_buf = NULL) = 0;
+    virtual const VideoFormatInfo* getFormatInfo(void) = 0;
+    virtual Decode_Status signalRenderDone(void * graphichandler) = 0;
+    virtual bool checkBufferAvail() = 0;
+    virtual Decode_Status getRawDataFromSurface(VideoRenderBuffer *renderBuffer = NULL, uint8_t *pRawData = NULL, uint32_t *pSize = NULL, bool internal = true) = 0;
+    virtual void enableErrorReport(bool enabled) = 0;
+};
+
+#endif /* VIDEO_DECODER_INTERFACE_H_ */
diff --git a/videodecoder/VideoDecoderMPEG4.cpp b/videodecoder/VideoDecoderMPEG4.cpp
new file mode 100644
index 0000000..b54afa9
--- /dev/null
+++ b/videodecoder/VideoDecoderMPEG4.cpp
@@ -0,0 +1,645 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderMPEG4.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+VideoDecoderMPEG4::VideoDecoderMPEG4(const char *mimeType)
+    : VideoDecoderBase(mimeType, VBP_MPEG4),
+      mLastVOPTimeIncrement(0),
+      mExpectingNVOP(false),
+      mSendIQMatrixBuf(false),
+      mLastVOPCodingType(MP4_VOP_TYPE_I),
+      mIsShortHeader(false) {
+}
+
+VideoDecoderMPEG4::~VideoDecoderMPEG4() {
+    stop();
+}
+
+Decode_Status VideoDecoderMPEG4::start(VideoConfigBuffer *buffer) {
+    Decode_Status status;
+
+    status = VideoDecoderBase::start(buffer);
+    CHECK_STATUS("VideoDecoderBase::start");
+
+    if (buffer->data == NULL || buffer->size == 0) {
+        WTRACE("No config data to start VA.");
+        return DECODE_SUCCESS;
+    }
+
+    vbp_data_mp42 *data = NULL;
+    status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
+    CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+    status = startVA(data);
+    return status;
+}
+
+void VideoDecoderMPEG4::stop(void) {
+    // drop the last frame and ignore return value
+    endDecodingFrame(true);
+    VideoDecoderBase::stop();
+
+    mLastVOPTimeIncrement = 0;
+    mExpectingNVOP = false;
+    mLastVOPCodingType = MP4_VOP_TYPE_I;
+}
+
+Decode_Status VideoDecoderMPEG4::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    vbp_data_mp42 *data = NULL;
+    bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+    if (buffer->flag & IS_SYNC_FRAME) {
+        mIsSyncFrame = true;
+    } else {
+        mIsSyncFrame = false;
+    }
+    buffer->ext = NULL;
+    status =  VideoDecoderBase::parseBuffer(
+            buffer->data,
+            buffer->size,
+            false,
+            (void**)&data);
+    CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+    if (!mVAStarted) {
+        status = startVA(data);
+        CHECK_STATUS("startVA");
+    }
+
+    if (mSizeChanged && !useGraphicbuffer) {
+        // some container has the incorrect width/height.
+        // send the format change to OMX to update the crop info.
+        mSizeChanged = false;
+        ITRACE("Video size is changed during startVA");
+        return DECODE_FORMAT_CHANGE;
+    }
+
+    if ((mVideoFormatInfo.width != (uint32_t)data->codec_data.video_object_layer_width ||
+        mVideoFormatInfo.height != (uint32_t)data->codec_data.video_object_layer_height) &&
+        data->codec_data.video_object_layer_width &&
+        data->codec_data.video_object_layer_height) {
+        // update  encoded image size
+        ITRACE("Video size is changed. from %dx%d to %dx%d\n",mVideoFormatInfo.width,mVideoFormatInfo.height,
+                data->codec_data.video_object_layer_width,data->codec_data.video_object_layer_height);
+        bool noNeedFlush = false;
+        mVideoFormatInfo.width = data->codec_data.video_object_layer_width;
+        mVideoFormatInfo.height = data->codec_data.video_object_layer_height;
+        if (useGraphicbuffer) {
+            noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
+                    && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
+        }
+        if (!noNeedFlush) {
+            flushSurfaceBuffers();
+            mSizeChanged = false;
+            return DECODE_FORMAT_CHANGE;
+        } else {
+            mSizeChanged = true;
+        }
+
+        setRenderRect();
+    }
+
+    status = decodeFrame(buffer, data);
+    CHECK_STATUS("decodeFrame");
+
+    return status;
+}
+
+void VideoDecoderMPEG4::flush(void) {
+    VideoDecoderBase::flush();
+
+    mExpectingNVOP = false;
+    mLastVOPTimeIncrement = 0;
+    mLastVOPCodingType = MP4_VOP_TYPE_I;
+}
+
+Decode_Status VideoDecoderMPEG4::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_mp42 *data) {
+    Decode_Status status;
+    // check if any slice is parsed, we may just receive configuration data
+    if (data->number_picture_data == 0) {
+        WTRACE("number_picture_data == 0");
+        return DECODE_SUCCESS;
+    }
+
+    // When the MPEG4 parser gets the invaild parameters, add the check
+    // and return error to OMX to avoid mediaserver crash.
+    if (data->picture_data && (data->picture_data->picture_param.vop_width == 0
+        || data->picture_data->picture_param.vop_height == 0)) {
+        return DECODE_PARSER_FAIL;
+    }
+
+    uint64_t lastPTS = mCurrentPTS;
+    mCurrentPTS = buffer->timeStamp;
+
+    if (lastPTS != mCurrentPTS) {
+        // finish decoding the last frame
+        status = endDecodingFrame(false);
+        CHECK_STATUS("endDecodingFrame");
+
+        // start decoding a new frame
+        status = beginDecodingFrame(data);
+        if (status == DECODE_MULTIPLE_FRAME) {
+            buffer->ext = &mExtensionBuffer;
+            mExtensionBuffer.extType = PACKED_FRAME_TYPE;
+            mExtensionBuffer.extSize = sizeof(mPackedFrame);
+            mExtensionBuffer.extData = (uint8_t*)&mPackedFrame;
+        } else if (status != DECODE_SUCCESS) {
+            endDecodingFrame(true);
+        }
+        CHECK_STATUS("beginDecodingFrame");
+    } else {
+        status = continueDecodingFrame(data);
+        if (status == DECODE_MULTIPLE_FRAME) {
+            buffer->ext = &mExtensionBuffer;
+            mExtensionBuffer.extType = PACKED_FRAME_TYPE;
+            mExtensionBuffer.extSize = sizeof(mPackedFrame);
+            mExtensionBuffer.extData = (uint8_t*)&mPackedFrame;
+        } else if (status != DECODE_SUCCESS) {
+            endDecodingFrame(true);
+        }
+        CHECK_STATUS("continueDecodingFrame");
+    }
+
+    if (buffer->flag & HAS_COMPLETE_FRAME) {
+        // finish decoding current frame
+        status = endDecodingFrame(false);
+        CHECK_STATUS("endDecodingFrame");
+    }
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderMPEG4::beginDecodingFrame(vbp_data_mp42 *data) {
+
+    Decode_Status status = DECODE_SUCCESS;
+    vbp_picture_data_mp42 *picData = data->picture_data;
+    VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param);
+    int codingType = picParam->vop_fields.bits.vop_coding_type;
+
+    // start sanity checking
+    if (mExpectingNVOP) {
+        // if we are waiting for n-vop for packed frame, and the new frame is coded, the coding type
+        // of this frame must be B
+        // for example: {PB} B N P B B P...
+        if (picData->vop_coded == 1 && codingType != MP4_VOP_TYPE_B) {
+            WTRACE("Invalid coding type while waiting for n-vop for packed frame.");
+            mExpectingNVOP = false;
+        }
+    }
+
+    // handle N-VOP picuture, it could be a skipped frame or a simple placeholder of packed frame
+    if (picData->vop_coded == 0) {
+        if (mLastReference == NULL) {
+            WTRACE("The last reference is unavailable to construct skipped frame.");
+            flush();
+            mExpectingNVOP = false;
+            // TODO: handle this case
+            return DECODE_SUCCESS;
+        }
+
+        if (mExpectingNVOP) {
+            // P frame is already in queue, just need to update time stamp.
+            mLastReference->renderBuffer.timeStamp = mCurrentPTS;
+            mExpectingNVOP = false;
+        }
+        else {
+            // Do nothing for skip frame as the last frame will be rendered agian by natively
+            // No needs to handle reference frame neither
+#if 0
+            // this is skipped frame, use the last reference frame as output
+            status = acquireSurfaceBuffer();
+            CHECK_STATUS("acquireSurfaceBuffer");
+            mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
+            mAcquiredBuffer->renderBuffer.flag = 0;
+            mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat;
+            mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface;
+            // No need to update mappedData for HW decoding
+            //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data;
+            mAcquiredBuffer->referenceFrame = true;
+            status = outputSurfaceBuffer();
+            CHECK_STATUS("outputSurfaceBuffer");
+#endif
+        }
+
+        if (data->number_picture_data > 1) {
+            WTRACE("Unexpected to have more picture data following a non-coded VOP.");
+            //picture data is thrown away. No issue if picture data is for N-VOP. if picture data is for
+            // coded picture, a frame is lost.
+            // TODO: handle this case
+            // return DECODE_FAIL;
+        }
+        return DECODE_SUCCESS;
+    }
+    else {
+        // Check if we have reference frame(s)  for decoding
+        if (codingType == MP4_VOP_TYPE_B)  {
+            if (mForwardReference ==  NULL ||
+                mLastReference == NULL) {
+                if (mIsShortHeader) {
+                    status = DECODE_SUCCESS;
+                    VTRACE("%s: No reference frame but keep decoding", __FUNCTION__);
+                } else
+                    return DECODE_NO_REFERENCE;
+            }
+        } else if (codingType == MP4_VOP_TYPE_P || codingType == MP4_VOP_TYPE_S) {
+            if (mLastReference == NULL && mIsSyncFrame == false) {
+                if (mIsShortHeader) {
+                    status = DECODE_SUCCESS;
+                    VTRACE("%s: No reference frame but keep decoding", __FUNCTION__);
+                } else
+                    return DECODE_NO_REFERENCE;
+            }
+        }
+        // all sanity checks pass, continue decoding through continueDecodingFrame
+        status = continueDecodingFrame(data);
+    }
+    return status;
+}
+
+Decode_Status VideoDecoderMPEG4::continueDecodingFrame(vbp_data_mp42 *data) {
+    Decode_Status status = DECODE_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+
+    /*
+         Packed Frame Assumption:
+
+         1. In one packed frame, there's only one P or I frame and only one B frame.
+         2. In packed frame, there's no skipped frame (vop_coded = 0)
+         3. For one packed frame, there will be one N-VOP frame to follow the packed frame (may not immediately).
+         4. N-VOP frame is the frame with vop_coded = 0.
+         5. The timestamp of  N-VOP frame will be used for P or I frame in the packed frame
+
+
+         I, P, {P, B}, B, N, P, N, I, ...
+         I, P, {P, B}, N, P, N, I, ...
+
+         The first N is placeholder for P frame in the packed frame
+         The second N is a skipped frame
+         */
+
+    vbp_picture_data_mp42 *picData = data->picture_data;
+    for (uint32_t i = 0; i < data->number_picture_data; i++, picData = picData->next_picture_data) {
+        // each slice has its own picture data, video_packet_header following resync_marker may reset picture header, see MP4 spec
+        VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param);
+        int codingType = picParam->vop_fields.bits.vop_coding_type;
+        if (codingType == MP4_VOP_TYPE_S && picParam->no_of_sprite_warping_points > 1) {
+            WTRACE("Hardware only supports up to one warping point (stationary or translation)");
+        }
+
+        if (picData->vop_coded == 0) {
+            ETRACE("Unexpected to have non-coded VOP.");
+            return DECODE_FAIL;
+        }
+        if (picData->new_picture_flag == 1 || mDecodingFrame == false) {
+            // either condition indicates start of a new frame
+            if (picData->new_picture_flag == 0) {
+                WTRACE("First slice of picture is lost!");
+                // TODO: handle this case
+            }
+            if (mDecodingFrame) {
+                if (codingType == MP4_VOP_TYPE_B){
+                    // this indicates the start of a new frame in the packed frame
+                    // Update timestamp for P frame in the packed frame as timestamp here is for the B frame!
+                    if (picParam->vop_time_increment_resolution){
+                        uint64_t increment = mLastVOPTimeIncrement - picData->vop_time_increment +
+                                picParam->vop_time_increment_resolution;
+                        increment = increment % picParam->vop_time_increment_resolution;
+                        // convert to micro-second
+                        // TODO: unit of time stamp varies on different frame work
+                        increment = increment * 1e6 / picParam->vop_time_increment_resolution;
+                        mAcquiredBuffer->renderBuffer.timeStamp += increment;
+                        if (useGraphicBuffer){
+                           mPackedFrame.timestamp = mCurrentPTS;
+                           mCurrentPTS = mAcquiredBuffer->renderBuffer.timeStamp;
+                        }
+                    }
+                } else {
+                    // this indicates the start of a new frame in the packed frame. no B frame int the packet
+                    // Update the timestamp according the increment
+                    if (picParam->vop_time_increment_resolution){
+                        int64_t increment = picData->vop_time_increment - mLastVOPTimeIncrement + picParam->vop_time_increment_resolution;
+                        increment = increment % picParam->vop_time_increment_resolution;
+                        //convert to micro-second
+                        increment = increment * 1e6 / picParam->vop_time_increment_resolution;
+                        if (useGraphicBuffer) {
+                            mPackedFrame.timestamp = mCurrentPTS + increment;
+                        }
+                        else {
+                            mCurrentPTS += increment;
+                        }
+
+                    } else {
+                        if (useGraphicBuffer) {
+                            mPackedFrame.timestamp = mCurrentPTS + 30000;
+                        }
+                        else {
+                            mCurrentPTS += 30000;
+                        }
+                    }
+                }
+                endDecodingFrame(false);
+                mExpectingNVOP = true;
+                if (codingType != MP4_VOP_TYPE_B) {
+                    mExpectingNVOP = false;
+                }
+                if (useGraphicBuffer) {
+                    int32_t count = i - 1;
+                    if (count < 0) {
+                        WTRACE("Shuld not be here!");
+                        return DECODE_SUCCESS;
+                    }
+                    vbp_picture_data_mp42 *lastpic = data->picture_data;
+                    for(int k = 0; k < count; k++ ) {
+                        lastpic = lastpic->next_picture_data;
+                    }
+                    mPackedFrame.offSet = lastpic->slice_data.slice_offset + lastpic->slice_data.slice_size;
+                    VTRACE("Report OMX to handle for Multiple frame offset=%d time=%lld",mPackedFrame.offSet,mPackedFrame.timestamp);
+                    return DECODE_MULTIPLE_FRAME;
+                }
+            }
+
+            // acquire a new surface buffer
+            status = acquireSurfaceBuffer();
+            CHECK_STATUS("acquireSurfaceBuffer");
+
+            // sprite is treated as P frame in the display order, so only B frame frame is not used as "reference"
+            mAcquiredBuffer->referenceFrame = (codingType != MP4_VOP_TYPE_B);
+            if (picData->picture_param.vol_fields.bits.interlaced) {
+                // only MPEG-4 studio profile can have field coding. All other profiles
+                // use frame coding only, i.e, there is no field VOP.  (see vop_structure in MP4 spec)
+                mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD | VA_TOP_FIELD;
+            } else {
+                mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
+            }
+            // TODO:  set discontinuity flag
+            mAcquiredBuffer->renderBuffer.flag = 0;
+            mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
+            if (mSizeChanged) {
+                mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
+                mSizeChanged = false;
+            }
+            if (codingType != MP4_VOP_TYPE_B) {
+                mLastVOPCodingType = codingType;
+                mLastVOPTimeIncrement = picData->vop_time_increment;
+            }
+
+            // start decoding a frame
+            vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+            CHECK_VA_STATUS("vaBeginPicture");
+
+            mDecodingFrame = true;
+            mSendIQMatrixBuf = true;
+        }
+
+        status = decodeSlice(data, picData);
+        CHECK_STATUS("decodeSlice");
+    }
+
+    return DECODE_SUCCESS;
+}
+
+
+Decode_Status VideoDecoderMPEG4::decodeSlice(vbp_data_mp42 *data, vbp_picture_data_mp42 *picData) {
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+    VABufferID bufferIDs[4];
+
+    VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param);
+    vbp_slice_data_mp42 *sliceData = &(picData->slice_data);
+    VASliceParameterBufferMPEG4 *sliceParam = &(sliceData->slice_param);
+
+    // send picture parametre for each slice
+    status = setReference(picParam);
+    CHECK_STATUS("setReference");
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VAPictureParameterBufferType,
+        sizeof(VAPictureParameterBufferMPEG4),
+        1,
+        picParam,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+
+    bufferIDCount++;
+    if (picParam->vol_fields.bits.quant_type && mSendIQMatrixBuf)
+    {
+        // only send IQ matrix for the first slice in the picture
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferMPEG4),
+            1,
+            &(data->iq_matrix_buffer),
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+
+        mSendIQMatrixBuf = false;
+        bufferIDCount++;
+    }
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferMPEG4),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+
+    bufferIDCount++;
+
+    //slice data buffer pointer
+    //Note that this is the original data buffer ptr;
+    // offset to the actual slice data is provided in
+    // slice_data_offset in VASliceParameterBufferMP42
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceDataBufferType,
+        sliceData->slice_size, //size
+        1,        //num_elements
+        sliceData->buffer_addr + sliceData->slice_offset,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderMPEG4::setReference(VAPictureParameterBufferMPEG4 *picParam) {
+    switch (picParam->vop_fields.bits.vop_coding_type) {
+        case MP4_VOP_TYPE_I:
+            picParam->forward_reference_picture = VA_INVALID_SURFACE;
+            picParam->backward_reference_picture = VA_INVALID_SURFACE;
+            break;
+        case MP4_VOP_TYPE_P:
+            if (mLastReference == NULL && mIsSyncFrame == false && !mIsShortHeader) {
+                return DECODE_NO_REFERENCE;
+            }
+            if (mLastReference != NULL) {
+                picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
+            } else {
+                VTRACE("%s: no reference frame, but keep decoding", __FUNCTION__);
+                picParam->forward_reference_picture = VA_INVALID_SURFACE;
+            }
+            picParam->backward_reference_picture = VA_INVALID_SURFACE;
+            break;
+        case MP4_VOP_TYPE_B:
+            picParam->vop_fields.bits.backward_reference_vop_coding_type = mLastVOPCodingType;
+            // WEIRD, CHECK AGAIN !!!!!!!
+            if (mIsShortHeader) {
+                if (mLastReference != NULL) {
+                    picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
+                } else {
+                    VTRACE("%s: no forward reference frame, but keep decoding", __FUNCTION__);
+                    picParam->forward_reference_picture = VA_INVALID_SURFACE;
+                }
+                if (mForwardReference != NULL) {
+                    picParam->backward_reference_picture = mForwardReference->renderBuffer.surface;
+                } else {
+                    VTRACE("%s: no backward reference frame, but keep decoding", __FUNCTION__);
+                    picParam->backward_reference_picture = VA_INVALID_SURFACE;
+                }
+            } else if (mLastReference == NULL || mForwardReference == NULL) {
+                return DECODE_NO_REFERENCE;
+            } else {
+                picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
+                picParam->backward_reference_picture = mForwardReference->renderBuffer.surface;
+            }
+            break;
+        case MP4_VOP_TYPE_S:
+            // WEIRD, CHECK AGAIN!!!! WAS using mForwardReference
+            if (mLastReference == NULL) {
+                return DECODE_NO_REFERENCE;
+            }
+            picParam->forward_reference_picture = mLastReference->renderBuffer.surface;
+            picParam->backward_reference_picture = VA_INVALID_SURFACE;
+            break;
+
+        default:
+            // Will never reach here;
+            return DECODE_PARSER_FAIL;
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderMPEG4::startVA(vbp_data_mp42 *data) {
+    updateFormatInfo(data);
+
+    VAProfile vaProfile;
+
+    if ((data->codec_data.profile_and_level_indication & 0xF8) == 0xF0) {
+        vaProfile = VAProfileMPEG4AdvancedSimple;
+    } else {
+        vaProfile = VAProfileMPEG4Simple;
+    }
+
+    mIsShortHeader = data->codec_data.short_video_header;
+
+    return VideoDecoderBase::setupVA(MP4_SURFACE_NUMBER, vaProfile);
+}
+
+void VideoDecoderMPEG4::updateFormatInfo(vbp_data_mp42 *data) {
+    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
+        mVideoFormatInfo.width, mVideoFormatInfo.height,
+        data->codec_data.video_object_layer_width,
+        data->codec_data.video_object_layer_height);
+
+    mVideoFormatInfo.cropBottom = data->codec_data.video_object_layer_height > mVideoFormatInfo.height ?
+                                                                          data->codec_data.video_object_layer_height - mVideoFormatInfo.height : 0;
+    mVideoFormatInfo.cropRight = data->codec_data.video_object_layer_width > mVideoFormatInfo.width ?
+                                                                     data->codec_data.video_object_layer_width - mVideoFormatInfo.width : 0;
+
+    if ((mVideoFormatInfo.width != (uint32_t)data->codec_data.video_object_layer_width ||
+        mVideoFormatInfo.height != (uint32_t)data->codec_data.video_object_layer_height) &&
+        data->codec_data.video_object_layer_width &&
+        data->codec_data.video_object_layer_height) {
+        // update  encoded image size
+        mVideoFormatInfo.width = data->codec_data.video_object_layer_width;
+        mVideoFormatInfo.height = data->codec_data.video_object_layer_height;
+        mSizeChanged = true;
+        ITRACE("Video size is changed.");
+    }
+
+    // video_range has default value of 0. Y ranges from 16 to 235.
+    mVideoFormatInfo.videoRange = data->codec_data.video_range;
+
+    switch (data->codec_data.matrix_coefficients) {
+        case 1:
+            mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
+            break;
+
+        // ITU-R Recommendation BT.470-6 System B, G (MP4), same as
+        // SMPTE 170M/BT601
+        case 5:
+        case 6:
+            mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
+            break;
+
+        default:
+            // unknown color matrix, set to 0 so color space flag will not be set.
+            mVideoFormatInfo.colorMatrix = 0;
+            break;
+    }
+
+    mVideoFormatInfo.aspectX = data->codec_data.par_width;
+    mVideoFormatInfo.aspectY = data->codec_data.par_height;
+    //mVideoFormatInfo.bitrate = data->codec_data.bit_rate;
+    mVideoFormatInfo.valid = true;
+
+    setRenderRect();
+}
+
+Decode_Status VideoDecoderMPEG4::checkHardwareCapability() {
+    VAStatus vaStatus;
+    VAConfigAttrib cfgAttribs[2];
+    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
+    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
+    vaStatus = vaGetConfigAttributes(mVADisplay,
+            mIsShortHeader ? VAProfileH263Baseline : VAProfileMPEG4AdvancedSimple,
+            VAEntrypointVLD, cfgAttribs, 2);
+    CHECK_VA_STATUS("vaGetConfigAttributes");
+    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
+        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
+                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
+        return DECODE_DRIVER_FAIL;
+    }
+
+    return DECODE_SUCCESS;
+}
diff --git a/videodecoder/VideoDecoderMPEG4.h b/videodecoder/VideoDecoderMPEG4.h
new file mode 100644
index 0000000..8fa319e
--- /dev/null
+++ b/videodecoder/VideoDecoderMPEG4.h
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_MPEG4_H_
+#define VIDEO_DECODER_MPEG4_H_
+
+#include "VideoDecoderBase.h"
+
+
+class VideoDecoderMPEG4 : public VideoDecoderBase {
+public:
+    VideoDecoderMPEG4(const char *mimeType);
+    virtual ~VideoDecoderMPEG4();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+    virtual void flush(void);
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+protected:
+    virtual Decode_Status checkHardwareCapability();
+
+private:
+    Decode_Status decodeFrame(VideoDecodeBuffer *buffer, vbp_data_mp42 *data);
+    Decode_Status beginDecodingFrame(vbp_data_mp42 *data);
+    Decode_Status continueDecodingFrame(vbp_data_mp42 *data);
+    Decode_Status decodeSlice(vbp_data_mp42 *data, vbp_picture_data_mp42 *picData);
+    Decode_Status setReference(VAPictureParameterBufferMPEG4 *picParam);
+    Decode_Status startVA(vbp_data_mp42 *data);
+    void updateFormatInfo(vbp_data_mp42 *data);
+
+private:
+    // Value of VOP type defined here follows MP4 spec
+    enum {
+        MP4_VOP_TYPE_I = 0,
+        MP4_VOP_TYPE_P = 1,
+        MP4_VOP_TYPE_B = 2,
+        MP4_VOP_TYPE_S = 3,
+    };
+
+    enum {
+        MP4_SURFACE_NUMBER = 10,
+    };
+
+    uint64_t mLastVOPTimeIncrement;
+    bool mExpectingNVOP; // indicate if future n-vop is a placeholder of a packed frame
+    bool mSendIQMatrixBuf; // indicate if iq_matrix_buffer is sent to driver
+    int32_t mLastVOPCodingType;
+    bool mIsSyncFrame; // indicate if it is SyncFrame in container
+    bool mIsShortHeader; // indicate if it is short header format
+    VideoExtensionBuffer mExtensionBuffer;
+    PackedFrameData mPackedFrame;
+};
+
+
+
+#endif /* VIDEO_DECODER_MPEG4_H_ */
diff --git a/videodecoder/VideoDecoderTrace.cpp b/videodecoder/VideoDecoderTrace.cpp
new file mode 100644
index 0000000..1075419
--- /dev/null
+++ b/videodecoder/VideoDecoderTrace.cpp
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderTrace.h"
+
+#ifdef ENABLE_VIDEO_DECODER_TRACE
+
+void TraceVideoDecoder(const char* cat, const char* fun, int line, const char* format, ...)
+{
+    if (NULL == cat || NULL == fun || NULL == format)
+        return;
+
+    printf("%s %s(#%d): ", cat, fun, line);
+    va_list args;
+    va_start(args, format);
+    vprintf(format, args);
+    va_end(args);
+    printf("\n");
+}
+
+#endif
+
diff --git a/videodecoder/VideoDecoderTrace.h b/videodecoder/VideoDecoderTrace.h
new file mode 100755
index 0000000..c4c1001
--- /dev/null
+++ b/videodecoder/VideoDecoderTrace.h
@@ -0,0 +1,96 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_TRACE_H_
+#define VIDEO_DECODER_TRACE_H_
+
+
+#define ENABLE_VIDEO_DECODER_TRACE
+//#define ANDROID
+
+
+#ifdef ENABLE_VIDEO_DECODER_TRACE
+
+#ifndef ANDROID
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern void TraceVideoDecoder(const char* cat, const char* fun, int line, const char* format, ...);
+#define VIDEO_DECODER_TRACE(cat, format, ...) \
+TraceVideoDecoder(cat, __FUNCTION__, __LINE__, format,  ##__VA_ARGS__)
+
+#define ETRACE(format, ...) VIDEO_DECODER_TRACE("ERROR:   ",  format, ##__VA_ARGS__)
+#define WTRACE(format, ...) VIDEO_DECODER_TRACE("WARNING: ",  format, ##__VA_ARGS__)
+#define ITRACE(format, ...) VIDEO_DECODER_TRACE("INFO:    ",  format, ##__VA_ARGS__)
+#define VTRACE(format, ...) VIDEO_DECODER_TRACE("VERBOSE: ",  format, ##__VA_ARGS__)
+
+#else
+// for Android OS
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "VideoDecoder"
+
+#include <wrs_omxil_core/log.h>
+#define ETRACE(...) LOGE(__VA_ARGS__)
+#define WTRACE(...) LOGW(__VA_ARGS__)
+#define ITRACE(...) LOGI(__VA_ARGS__)
+#define VTRACE(...) LOGV(__VA_ARGS__)
+
+#endif
+
+
+#else
+
+#define ETRACE(format, ...)
+#define WTRACE(format, ...)
+#define ITRACE(format, ...)
+#define VTRACE(format, ...)
+
+
+#endif /* ENABLE_VIDEO_DECODER_TRACE*/
+
+
+#define CHECK_STATUS(FUNC)\
+    if (status != DECODE_SUCCESS) {\
+        if (status > DECODE_SUCCESS) {\
+            WTRACE(FUNC" failed. status = %d", status);\
+        } else {\
+            ETRACE(FUNC" failed. status = %d", status);\
+        }\
+        return status;\
+     }
+
+#define CHECK_VA_STATUS(FUNC)\
+    if (vaStatus != VA_STATUS_SUCCESS) {\
+        ETRACE(FUNC" failed. vaStatus = 0x%x", vaStatus);\
+        return DECODE_DRIVER_FAIL;\
+    }
+
+#define CHECK_VBP_STATUS(FUNC)\
+    if (vbpStatus != VBP_OK) {\
+        ETRACE(FUNC" failed. vbpStatus = %d", (int)vbpStatus);\
+        if (vbpStatus == VBP_ERROR) {\
+            return DECODE_FAIL;\
+        }\
+        return DECODE_PARSER_FAIL;\
+    }
+
+#endif /*VIDEO_DECODER_TRACE_H_*/
+
+
diff --git a/videodecoder/VideoDecoderVP8.cpp b/videodecoder/VideoDecoderVP8.cpp
new file mode 100644
index 0000000..87249b4
--- /dev/null
+++ b/videodecoder/VideoDecoderVP8.cpp
@@ -0,0 +1,449 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderVP8.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+VideoDecoderVP8::VideoDecoderVP8(const char *mimeType)
+    : VideoDecoderBase(mimeType, VBP_VP8) {
+    invalidateReferenceFrames(0);
+    invalidateReferenceFrames(1);
+}
+
+VideoDecoderVP8::~VideoDecoderVP8() {
+    stop();
+}
+
+void VideoDecoderVP8::invalidateReferenceFrames(int toggle) {
+    ReferenceFrameBuffer *p = mRFBs[toggle];
+    for (int i = 0; i < VP8_REF_SIZE; i++) {
+        p->index = (uint32_t) -1;
+        p->surfaceBuffer = NULL;
+        p++;
+    }
+}
+
+void VideoDecoderVP8::clearAsReference(int toggle, int ref_type) {
+    ReferenceFrameBuffer ref = mRFBs[toggle][ref_type];
+    if (ref.surfaceBuffer) {
+        ref.surfaceBuffer->asReferernce = false;
+    }
+}
+
+void VideoDecoderVP8::updateFormatInfo(vbp_data_vp8 *data) {
+    uint32_t width = data->codec_data->frame_width;
+    uint32_t height = data->codec_data->frame_height;
+    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
+            mVideoFormatInfo.width, mVideoFormatInfo.height, width, height);
+
+    if ((mVideoFormatInfo.width != width ||
+            mVideoFormatInfo.height != height) &&
+            width && height) {
+        if ((VideoDecoderBase::alignMB(mVideoFormatInfo.width) != width) ||
+            (VideoDecoderBase::alignMB(mVideoFormatInfo.height) != height)) {
+            mSizeChanged = true;
+            ITRACE("Video size is changed.");
+        }
+        mVideoFormatInfo.width = width;
+        mVideoFormatInfo.height = height;
+    }
+
+    mVideoFormatInfo.cropLeft = data->codec_data->crop_left;
+    mVideoFormatInfo.cropRight = data->codec_data->crop_right;
+    mVideoFormatInfo.cropTop = data->codec_data->crop_top;
+    mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom;
+    ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d", data->codec_data->crop_left, data->codec_data->crop_top, data->codec_data->crop_right, data->codec_data->crop_bottom);
+
+    mVideoFormatInfo.valid = true;
+
+    setRenderRect();
+}
+
+Decode_Status VideoDecoderVP8::startVA(vbp_data_vp8 *data) {
+    updateFormatInfo(data);
+
+    VAProfile vaProfile = VAProfileVP8Version0_3;
+    if (data->codec_data->version_num > 3) {
+        return DECODE_PARSER_FAIL;
+    }
+
+    enableLowDelayMode(true);
+
+    return VideoDecoderBase::setupVA(VP8_SURFACE_NUMBER + VP8_REF_SIZE, vaProfile);
+}
+
+Decode_Status VideoDecoderVP8::start(VideoConfigBuffer *buffer) {
+    Decode_Status status;
+
+    status = VideoDecoderBase::start(buffer);
+    CHECK_STATUS("VideoDecoderBase::start");
+
+    // We don't want base class to manage reference.
+    VideoDecoderBase::ManageReference(false);
+
+    if (buffer->data == NULL || buffer->size == 0) {
+        WTRACE("No config data to start VA.");
+        return DECODE_SUCCESS;
+    }
+
+    vbp_data_vp8 *data = NULL;
+    status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
+    CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+    status = startVA(data);
+    return status;
+}
+
+void VideoDecoderVP8::stop(void) {
+    VideoDecoderBase::stop();
+
+    invalidateReferenceFrames(0);
+    invalidateReferenceFrames(1);
+}
+
+void VideoDecoderVP8::flush(void) {
+    VideoDecoderBase::flush();
+
+    invalidateReferenceFrames(0);
+    invalidateReferenceFrames(1);
+}
+
+Decode_Status VideoDecoderVP8::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    vbp_data_vp8 *data = NULL;
+    if (buffer == NULL) {
+        ETRACE("VideoDecodeBuffer is NULL.");
+        return DECODE_INVALID_DATA;
+    }
+
+    status = VideoDecoderBase::parseBuffer(
+                 buffer->data,
+                 buffer->size,
+                 false,
+                 (void**)&data);
+    CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+    mShowFrame = data->codec_data->show_frame;
+
+    if (!mVAStarted) {
+        status = startVA(data);
+        CHECK_STATUS("startVA");
+    }
+
+    VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees);
+
+    status = decodeFrame(buffer, data);
+
+    return status;
+}
+
+Decode_Status VideoDecoderVP8::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vp8 *data) {
+    Decode_Status status;
+    bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+    mCurrentPTS = buffer->timeStamp;
+    if (0 == data->num_pictures || NULL == data->pic_data) {
+        WTRACE("Number of pictures is 0.");
+        return DECODE_SUCCESS;
+    }
+
+    if (VP8_KEY_FRAME == data->codec_data->frame_type) {
+        if (mSizeChanged && !useGraphicbuffer){
+            mSizeChanged = false;
+            return DECODE_FORMAT_CHANGE;
+        } else {
+            updateFormatInfo(data);
+            bool noNeedFlush = false;
+            if (useGraphicbuffer) {
+                noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
+                        && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
+            }
+            if (mSizeChanged == true && !noNeedFlush) {
+                flushSurfaceBuffers();
+                mSizeChanged = false;
+                return DECODE_FORMAT_CHANGE;
+            }
+        }
+    }
+
+    if (data->codec_data->frame_type == VP8_SKIPPED_FRAME) {
+        // Do nothing for skip frame as the last frame will be rendered agian by natively
+        return DECODE_SUCCESS;
+    }
+
+    status = acquireSurfaceBuffer();
+    CHECK_STATUS("acquireSurfaceBuffer");
+
+    // set referenceFrame to true if frame decoded is I/P frame, false otherwise.
+    int frameType = data->codec_data->frame_type;
+    mAcquiredBuffer->referenceFrame = (frameType == VP8_KEY_FRAME || frameType == VP8_INTER_FRAME);
+    // assume it is frame picture.
+    mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
+    mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
+    mAcquiredBuffer->renderBuffer.flag = 0;
+    if (buffer->flag & WANT_DECODE_ONLY) {
+        mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
+    }
+    if (mSizeChanged) {
+        mSizeChanged = false;
+        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
+    }
+
+    // Here data->num_pictures is always equal to 1
+    for (uint32_t index = 0; index < data->num_pictures; index++) {
+        status = decodePicture(data, index);
+        if (status != DECODE_SUCCESS) {
+            endDecodingFrame(true);
+            return status;
+        }
+    }
+
+    if (frameType != VP8_SKIPPED_FRAME) {
+        updateReferenceFrames(data);
+    }
+
+    // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise
+    // call releaseSurfacebuffer();
+    status = outputSurfaceBuffer();
+    return status;
+}
+
+Decode_Status VideoDecoderVP8::decodePicture(vbp_data_vp8 *data, int32_t picIndex) {
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    Decode_Status status;
+    uint32_t bufferIDCount = 0;
+    VABufferID bufferIDs[5];
+
+    vbp_picture_data_vp8 *picData = &(data->pic_data[picIndex]);
+    VAPictureParameterBufferVP8 *picParams = picData->pic_parms;
+
+    status = setReference(picParams);
+    CHECK_STATUS("setReference");
+
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_VA_STATUS("vaBeginPicture");
+    // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
+    mDecodingFrame = true;
+
+    vaStatus = vaCreateBuffer(
+                   mVADisplay,
+                   mVAContext,
+                   VAPictureParameterBufferType,
+                   sizeof(VAPictureParameterBufferVP8),
+                   1,
+                   picParams,
+                   &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaCreateBuffer(
+                   mVADisplay,
+                   mVAContext,
+                   VAProbabilityBufferType,
+                   sizeof(VAProbabilityDataBufferVP8),
+                   1,
+                   data->prob_data,
+                   &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateProbabilityBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaCreateBuffer(
+                   mVADisplay,
+                   mVAContext,
+                   VAIQMatrixBufferType,
+                   sizeof(VAIQMatrixBufferVP8),
+                   1,
+                   data->IQ_matrix_buf,
+                   &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+    bufferIDCount++;
+
+    /* Here picData->num_slices is always equal to 1 */
+    for (uint32_t i = 0; i < picData->num_slices; i++) {
+        vaStatus = vaCreateBuffer(
+                       mVADisplay,
+                       mVAContext,
+                       VASliceParameterBufferType,
+                       sizeof(VASliceParameterBufferVP8),
+                       1,
+                       &(picData->slc_data[i].slc_parms),
+                       &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+                       mVADisplay,
+                       mVAContext,
+                       VASliceDataBufferType,
+                       picData->slc_data[i].slice_size, //size
+                       1,        //num_elements
+                       picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
+                       &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+        bufferIDCount++;
+    }
+
+    vaStatus = vaRenderPicture(
+                   mVADisplay,
+                   mVAContext,
+                   bufferIDs,
+                   bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    vaStatus = vaEndPicture(mVADisplay, mVAContext);
+    mDecodingFrame = false;
+    CHECK_VA_STATUS("vaEndPicture");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderVP8::setReference(VAPictureParameterBufferVP8 *picParam) {
+    int frameType = picParam->pic_fields.bits.key_frame;
+    switch (frameType) {
+    case VP8_KEY_FRAME:
+        picParam->last_ref_frame = VA_INVALID_SURFACE;
+        picParam->alt_ref_frame = VA_INVALID_SURFACE;
+        picParam->golden_ref_frame = VA_INVALID_SURFACE;
+        break;
+    case VP8_INTER_FRAME:
+        if (mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer   == NULL ||
+                mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer    == NULL ||
+                mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer == NULL) {
+            mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 1;
+            mAcquiredBuffer->renderBuffer.errBuf.errorArray[0].type = DecodeRefMissing;
+            return DECODE_NO_REFERENCE;
+        }
+        //mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mLastReference;
+        picParam->last_ref_frame = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->renderBuffer.surface;
+        picParam->alt_ref_frame = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->renderBuffer.surface;
+        picParam->golden_ref_frame = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->renderBuffer.surface;
+        break;
+    case VP8_SKIPPED_FRAME:
+        // will never happen here
+        break;
+    default:
+        return DECODE_PARSER_FAIL;
+    }
+
+    return DECODE_SUCCESS;
+}
+
+void VideoDecoderVP8::updateReferenceFrames(vbp_data_vp8 *data) {
+    /* Refresh last frame reference buffer using the currently reconstructed frame */
+    refreshLastReference(data);
+
+    /* Refresh golden frame reference buffer using the currently reconstructed frame */
+    refreshGoldenReference(data);
+
+    /* Refresh alternative frame reference buffer using the currently reconstructed frame */
+    refreshAltReference(data);
+
+    /* Update reference frames */
+    for (int i = 0; i < VP8_REF_SIZE; i++) {
+        VideoSurfaceBuffer *p = mRFBs[1][i].surfaceBuffer;
+        int j;
+        for (j = 0; j < VP8_REF_SIZE; j++) {
+            if (p == mRFBs[0][j].surfaceBuffer) {
+                break;
+            }
+        }
+        if (j == VP8_REF_SIZE) {
+            clearAsReference(1, i);
+        }
+    }
+}
+
+void VideoDecoderVP8::refreshLastReference(vbp_data_vp8 *data) {
+    /* Save previous last reference */
+    mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer;
+    mRFBs[1][VP8_LAST_REF_PIC].index = mRFBs[0][VP8_LAST_REF_PIC].index;
+
+    /* For key frame, this is always true */
+    if (data->codec_data->refresh_last_frame) {
+        mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mAcquiredBuffer;
+        mRFBs[0][VP8_LAST_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
+        mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->asReferernce = true;
+    }
+}
+
+void VideoDecoderVP8::refreshGoldenReference(vbp_data_vp8 *data) {
+    /* Save previous golden reference */
+    mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer;
+    mRFBs[1][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_GOLDEN_REF_PIC].index;
+
+    if (data->codec_data->golden_copied != BufferCopied_NoneToGolden) {
+        if (data->codec_data->golden_copied == BufferCopied_LastToGolden) {
+            /* LastFrame is copied to GoldenFrame */
+            mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
+            mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
+        } else if (data->codec_data->golden_copied == BufferCopied_AltRefToGolden) {
+            /* AltRefFrame is copied to GoldenFrame */
+            mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
+            mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
+        }
+    }
+
+    /* For key frame, this is always true */
+    if (data->codec_data->refresh_golden_frame) {
+        mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mAcquiredBuffer;
+        mRFBs[0][VP8_GOLDEN_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
+        mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->asReferernce = true;
+    }
+}
+
+void VideoDecoderVP8::refreshAltReference(vbp_data_vp8 *data) {
+    /* Save previous alternative reference */
+    mRFBs[1][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
+    mRFBs[1][VP8_ALT_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
+
+    if (data->codec_data->altref_copied != BufferCopied_NoneToAltRef) {
+        if (data->codec_data->altref_copied == BufferCopied_LastToAltRef) {
+            /* LastFrame is copied to AltRefFrame */
+            mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
+            mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
+        } else if (data->codec_data->altref_copied == BufferCopied_GoldenToAltRef) {
+            /* GoldenFrame is copied to AltRefFrame */
+            mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer;
+            mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_GOLDEN_REF_PIC].index;
+        }
+    }
+
+    /* For key frame, this is always true */
+    if (data->codec_data->refresh_alt_frame) {
+        mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mAcquiredBuffer;
+        mRFBs[0][VP8_ALT_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
+        mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->asReferernce = true;
+    }
+}
+
+
+Decode_Status VideoDecoderVP8::checkHardwareCapability() {
+    VAStatus vaStatus;
+    VAConfigAttrib cfgAttribs[2];
+    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
+    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
+    vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVP8Version0_3,
+            VAEntrypointVLD, cfgAttribs, 2);
+    CHECK_VA_STATUS("vaGetConfigAttributes");
+    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
+        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
+                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
+        return DECODE_DRIVER_FAIL;
+    }
+
+    return DECODE_SUCCESS;
+}
+
diff --git a/videodecoder/VideoDecoderVP8.h b/videodecoder/VideoDecoderVP8.h
new file mode 100644
index 0000000..1daecaf
--- /dev/null
+++ b/videodecoder/VideoDecoderVP8.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_VP8_H_
+#define VIDEO_DECODER_VP8_H_
+
+#include "VideoDecoderBase.h"
+
+
+class VideoDecoderVP8 : public VideoDecoderBase {
+public:
+    VideoDecoderVP8(const char *mimeType);
+    virtual ~VideoDecoderVP8();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+    virtual void flush(void);
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+protected:
+    virtual Decode_Status checkHardwareCapability();
+
+private:
+    Decode_Status decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vp8 *data);
+    Decode_Status decodePicture(vbp_data_vp8 *data, int32_t picIndex);
+    Decode_Status setReference(VAPictureParameterBufferVP8 *picParam);
+    Decode_Status startVA(vbp_data_vp8 *data);
+    void updateReferenceFrames(vbp_data_vp8 *data);
+    void refreshLastReference(vbp_data_vp8 *data);
+    void refreshGoldenReference(vbp_data_vp8 *data);
+    void refreshAltReference(vbp_data_vp8 *data);
+    void updateFormatInfo(vbp_data_vp8 *data);
+    void invalidateReferenceFrames(int toggle);
+    void clearAsReference(int toggle, int ref_type);
+
+private:
+    enum {
+        VP8_SURFACE_NUMBER = 9,
+        VP8_REF_SIZE = 3,
+    };
+
+    enum {
+        VP8_KEY_FRAME = 0,
+        VP8_INTER_FRAME,
+        VP8_SKIPPED_FRAME,
+    };
+
+    enum {
+        VP8_LAST_REF_PIC = 0,
+        VP8_GOLDEN_REF_PIC,
+        VP8_ALT_REF_PIC,
+    };
+
+    enum {
+        BufferCopied_NoneToGolden   = 0,
+        BufferCopied_LastToGolden   = 1,
+        BufferCopied_AltRefToGolden = 2
+    };
+
+    enum {
+        BufferCopied_NoneToAltRef   = 0,
+        BufferCopied_LastToAltRef   = 1,
+        BufferCopied_GoldenToAltRef = 2
+    };
+
+    struct ReferenceFrameBuffer {
+        VideoSurfaceBuffer *surfaceBuffer;
+        int32_t index;
+    };
+
+    //[2] : [0 for current each reference frame, 1 for the previous each reference frame]
+    //[VP8_REF_SIZE] : [0 for last ref pic, 1 for golden ref pic, 2 for alt ref pic]
+    ReferenceFrameBuffer mRFBs[2][VP8_REF_SIZE];
+};
+
+
+
+#endif /* VIDEO_DECODER_VP8_H_ */
diff --git a/videodecoder/VideoDecoderWMV.cpp b/videodecoder/VideoDecoderWMV.cpp
new file mode 100644
index 0000000..16c307a
--- /dev/null
+++ b/videodecoder/VideoDecoderWMV.cpp
@@ -0,0 +1,568 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderWMV.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+VideoDecoderWMV::VideoDecoderWMV(const char *mimeType)
+    : VideoDecoderBase(mimeType, VBP_VC1),
+      mBufferIDs(NULL),
+      mNumBufferIDs(0),
+      mConfigDataParsed(false),
+      mRangeMapped(false),
+      mDeblockedCurrPicIndex(0),
+      mDeblockedLastPicIndex(1),
+      mDeblockedForwardPicIndex(2) {
+}
+
+
+VideoDecoderWMV::~VideoDecoderWMV() {
+    stop();
+}
+
+Decode_Status VideoDecoderWMV::start(VideoConfigBuffer *buffer) {
+    Decode_Status status;
+
+    status = VideoDecoderBase::start(buffer);
+    CHECK_STATUS("VideoDecoderBase::start");
+
+    if (buffer->data == NULL || buffer->size == 0) {
+        WTRACE("No config data to start VA.");
+        return DECODE_SUCCESS;
+    }
+
+    vbp_data_vc1 *data = NULL;
+    status = parseBuffer(buffer->data, buffer->size, &data);
+    CHECK_STATUS("parseBuffer");
+
+    status = startVA(data);
+    return status;
+}
+
+void VideoDecoderWMV::stop(void) {
+    if (mBufferIDs) {
+        delete [] mBufferIDs;
+        mBufferIDs = NULL;
+    }
+    mNumBufferIDs = 0;
+    mConfigDataParsed = false;
+    mRangeMapped = false;
+
+    mDeblockedCurrPicIndex = 0;
+    mDeblockedLastPicIndex = 1;
+    mDeblockedForwardPicIndex = 2;
+
+    VideoDecoderBase::stop();
+}
+
+void VideoDecoderWMV::flush(void) {
+    VideoDecoderBase::flush();
+
+    mRangeMapped = false;
+    mDeblockedCurrPicIndex = 0;
+    mDeblockedLastPicIndex = 1;
+    mDeblockedForwardPicIndex = 2;
+}
+
+Decode_Status VideoDecoderWMV::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    vbp_data_vc1 *data = NULL;
+    bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+
+    status = parseBuffer(buffer->data, buffer->size, &data);
+    CHECK_STATUS("parseBuffer");
+
+    if (!mVAStarted) {
+        status = startVA(data);
+        CHECK_STATUS("startVA");
+    }
+
+    if (mSizeChanged && !useGraphicbuffer) {
+        mSizeChanged = false;
+        return DECODE_FORMAT_CHANGE;
+    }
+
+    if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH ||
+        mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) &&
+        data->se_data->CODED_WIDTH &&
+        data->se_data->CODED_HEIGHT) {
+        ITRACE("video size is changed from %dx%d to %dx%d", mVideoFormatInfo.width, mVideoFormatInfo.height,
+                data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT);
+        mVideoFormatInfo.width = data->se_data->CODED_WIDTH;
+        mVideoFormatInfo.height = data->se_data->CODED_HEIGHT;
+        bool noNeedFlush = false;
+        if (useGraphicbuffer) {
+            noNeedFlush = (mVideoFormatInfo.width <= mVideoFormatInfo.surfaceWidth)
+                    && (mVideoFormatInfo.height <= mVideoFormatInfo.surfaceHeight);
+        }
+
+        setRenderRect();
+
+        if (noNeedFlush) {
+            mSizeChanged = true;
+        } else {
+            flushSurfaceBuffers();
+            mSizeChanged = false;
+            return DECODE_FORMAT_CHANGE;
+        }
+    }
+
+    status = decodeFrame(buffer, data);
+    CHECK_STATUS("decodeFrame");
+    return status;
+}
+
+Decode_Status VideoDecoderWMV::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vc1 *data) {
+    Decode_Status status;
+    mCurrentPTS = buffer->timeStamp;
+    if (0 == data->num_pictures || NULL == data->pic_data) {
+        WTRACE("Number of pictures is 0, buffer contains configuration data only?");
+        return DECODE_SUCCESS;
+    }
+
+    if (data->pic_data[0].picture_is_skipped == VC1_PTYPE_SKIPPED) {
+
+        // Do nothing for skip frame as the last frame will be rendered agian by natively
+        // No needs to handle reference frame neither
+        return DECODE_SUCCESS;
+#if 0
+        //use the last P or I frame surface for skipped frame and treat it as P frame
+        if (mLastReference == NULL) {
+            // TODO: handle this case
+            WTRACE("The last reference is unavailable to construct skipped frame.");
+            return DECODE_SUCCESS;
+        }
+
+        status = acquireSurfaceBuffer();
+        CHECK_STATUS("acquireSurfaceBuffer");
+        mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
+        mAcquiredBuffer->renderBuffer.flag = 0;
+        mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat;
+        mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface;
+        // No need to update mappedData for HW decoding
+        //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data;
+        mAcquiredBuffer->referenceFrame = true;
+        // let outputSurfaceBuffer handle "asReference" for VC1
+        status = outputSurfaceBuffer();
+        return status;
+#endif
+    }
+
+    status = acquireSurfaceBuffer();
+    CHECK_STATUS("acquireSurfaceBuffer");
+
+    mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
+    if (buffer->flag & HAS_DISCONTINUITY) {
+        mAcquiredBuffer->renderBuffer.flag |= HAS_DISCONTINUITY;
+    }
+    if (buffer->flag & WANT_DECODE_ONLY) {
+        mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
+    }
+    if (mSizeChanged) {
+        mSizeChanged = false;
+        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
+    }
+
+    if (data->num_pictures > 1) {
+        if (data->pic_data[0].pic_parms->picture_fields.bits.is_first_field) {
+            mAcquiredBuffer->renderBuffer.scanFormat = VA_TOP_FIELD;
+        } else {
+            mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD;
+        }
+    } else {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
+    }
+
+    mRangeMapped = (data->se_data->RANGE_MAPY_FLAG || data->se_data->RANGE_MAPUV_FLAG || data->se_data->RANGERED);
+
+    int frameType = data->pic_data[0].pic_parms->picture_fields.bits.picture_type;
+    mAcquiredBuffer->referenceFrame = (frameType == VC1_PTYPE_I || frameType == VC1_PTYPE_P);
+
+    // TODO: handle multiple frames parsed from a sample buffer
+    int numPictures = (data->num_pictures > 1) ? 2 : 1;
+
+    for (int index = 0; index < numPictures; index++) {
+        status = decodePicture(data, index);
+        if (status != DECODE_SUCCESS) {
+            endDecodingFrame(true);
+            return status;
+        }
+    }
+
+    if (mRangeMapped) {
+        updateDeblockedPicIndexes(frameType);
+    }
+
+    // let outputSurfaceBuffer handle "asReference" for VC1
+    status = outputSurfaceBuffer();
+    return status;
+}
+
+
+Decode_Status VideoDecoderWMV::decodePicture(vbp_data_vc1 *data, int32_t picIndex) {
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    Decode_Status status;
+    int32_t bufferIDCount = 0;
+    vbp_picture_data_vc1 *picData = &(data->pic_data[picIndex]);
+    VAPictureParameterBufferVC1 *picParams = picData->pic_parms;
+
+    if (picParams == NULL) {
+        return DECODE_PARSER_FAIL;
+    }
+
+    status = allocateVABufferIDs(picData->num_slices * 2 + 2);
+    CHECK_STATUS("allocateVABufferIDs");
+
+    status = setReference(picParams, picIndex, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_STATUS("setReference");
+
+    if (mRangeMapped) {
+        // keep the destination surface for the picture after decoding and in-loop filtering
+        picParams->inloop_decoded_picture = mExtraSurfaces[mDeblockedCurrPicIndex];
+    } else {
+        picParams->inloop_decoded_picture = VA_INVALID_SURFACE;
+    }
+
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_VA_STATUS("vaBeginPicture");
+    // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
+    mDecodingFrame = true;
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferVC1),
+            1,
+            picParams,
+            &mBufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+    bufferIDCount++;
+
+    if (picParams->bitplane_present.value) {
+        vaStatus = vaCreateBuffer(
+                mVADisplay,
+                mVAContext,
+                VABitPlaneBufferType,
+                picData->size_bitplanes,
+                1,
+                picData->packed_bitplanes,
+                &mBufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateBitPlaneBuffer");
+        bufferIDCount++;
+    }
+
+    for (uint32_t i = 0; i < picData->num_slices; i++) {
+        vaStatus = vaCreateBuffer(
+                mVADisplay,
+                mVAContext,
+                VASliceParameterBufferType,
+                sizeof(VASliceParameterBufferVC1),
+                1,
+                &(picData->slc_data[i].slc_parms),
+                &mBufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+                mVADisplay,
+                mVAContext,
+                VASliceDataBufferType,
+                //size
+                picData->slc_data[i].slice_size,
+                //num_elements
+                1,
+                //slice data buffer pointer
+                //Note that this is the original data buffer ptr;
+                // offset to the actual slice data is provided in
+                // slice_data_offset in VASliceParameterBufferVC1
+                picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
+                &mBufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+        bufferIDCount++;
+    }
+
+    vaStatus = vaRenderPicture(
+            mVADisplay,
+            mVAContext,
+            mBufferIDs,
+            bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    vaStatus = vaEndPicture(mVADisplay, mVAContext);
+    mDecodingFrame = false;
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+}
+
+
+Decode_Status VideoDecoderWMV::setReference(
+        VAPictureParameterBufferVC1 *params,
+        int32_t picIndex,
+        VASurfaceID current) {
+    int frameType = params->picture_fields.bits.picture_type;
+    switch (frameType) {
+        case VC1_PTYPE_I:
+            params->forward_reference_picture = current;
+            params->backward_reference_picture = current;
+            break;
+        case VC1_PTYPE_P:
+            // check REFDIST in the picture parameter buffer
+            if (0 != params->reference_fields.bits.reference_distance_flag &&
+                0 != params->reference_fields.bits.reference_distance) {
+                /* The previous decoded frame (distance is up to 16 but not 0) is used
+                            for reference. Not supported here.
+                            */
+                return DECODE_NO_REFERENCE;
+            }
+            if (1 == picIndex) {
+                // handle interlace field coding case
+                if (1 == params->reference_fields.bits.num_reference_pictures ||
+                    1 == params->reference_fields.bits.reference_field_pic_indicator) {
+                    /*
+                                    two reference fields or the second closest I/P field is used for
+                                    prediction. Set forward reference picture to INVALID so it will be
+                                    updated to a valid previous reconstructed reference frame later.
+                                    */
+                    params->forward_reference_picture = VA_INVALID_SURFACE;
+                } else {
+                   /* the closest I/P is used for reference so it must be the
+                                  complementary field in the same surface.
+                                 */
+                    params->forward_reference_picture = current;
+                }
+            }
+            if (VA_INVALID_SURFACE == params->forward_reference_picture) {
+                if (mLastReference == NULL) {
+                    return DECODE_NO_REFERENCE;
+                }
+                params->forward_reference_picture = mLastReference->renderBuffer.surface;
+            }
+            params->backward_reference_picture = VA_INVALID_SURFACE;
+            break;
+        case VC1_PTYPE_B:
+            if (mForwardReference == NULL || mLastReference == NULL) {
+                return DECODE_NO_REFERENCE;
+            }
+            params->forward_reference_picture = mForwardReference->renderBuffer.surface;
+            params->backward_reference_picture = mLastReference->renderBuffer.surface;
+            break;
+        case VC1_PTYPE_BI:
+            params->forward_reference_picture = VA_INVALID_SURFACE;
+            params->backward_reference_picture = VA_INVALID_SURFACE;
+            break;
+        case VC1_PTYPE_SKIPPED:
+            //Will never happen here
+            break;
+        default:
+            break;
+    }
+    return DECODE_SUCCESS;
+}
+
+void VideoDecoderWMV::updateDeblockedPicIndexes(int frameType) {
+    int32_t curPicIndex = mDeblockedCurrPicIndex;
+
+    /* Out Loop (range map) buffers */
+    if (frameType != VC1_PTYPE_SKIPPED) {
+        if ((frameType == VC1_PTYPE_I) || (frameType == VC1_PTYPE_P)) {
+            mDeblockedCurrPicIndex = mDeblockedLastPicIndex;
+            mDeblockedLastPicIndex = curPicIndex;
+        } else {
+            mDeblockedCurrPicIndex = mDeblockedForwardPicIndex;
+            mDeblockedForwardPicIndex = curPicIndex;
+        }
+    }
+}
+
+Decode_Status VideoDecoderWMV::updateConfigData(
+        uint8_t *configData,
+        int32_t configDataLen,
+        uint8_t **newConfigData,
+        int32_t* newConfigDataLen) {
+    int32_t i = 0;
+    uint8_t *p = configData;
+
+    /* Check for start codes.  If one exist, then this is VC-1 and not WMV. */
+    while (i < configDataLen - 2) {
+        if ((p[i] == 0) &&
+            (p[i + 1] == 0) &&
+            (p[i + 2] == 1)) {
+            *newConfigData = NULL;
+            *newConfigDataLen = 0;
+            return DECODE_SUCCESS;
+        }
+        i++;
+    }
+
+    *newConfigDataLen = configDataLen + 9;
+    p = *newConfigData = new uint8_t [*newConfigDataLen];
+    if (!p) {
+       return DECODE_MEMORY_FAIL;
+    }
+
+    /* If we get here we have 4+ bytes of codec data that must be formatted */
+    /* to pass through as an RCV sequence header. */
+    p[0] = 0;
+    p[1] = 0;
+    p[2] = 1;
+    p[3] = 0x0f;  /* Start code. */
+    p[4] = (mVideoFormatInfo.width >> 8) & 0x0ff;
+    p[5] = mVideoFormatInfo.width & 0x0ff;
+    p[6] = (mVideoFormatInfo.height >> 8) & 0x0ff;
+    p[7] = mVideoFormatInfo.height & 0x0ff;
+
+    memcpy(p + 8, configData, configDataLen);
+    *(p + configDataLen + 8) = 0x80;
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderWMV::startVA(vbp_data_vc1 *data) {
+    updateFormatInfo(data);
+
+    VAProfile vaProfile;
+    switch (data->se_data->PROFILE) {
+        case 0:
+        vaProfile = VAProfileVC1Simple;
+        break;
+        case 1:
+        vaProfile = VAProfileVC1Main;
+        break;
+        default:
+        vaProfile = VAProfileVC1Advanced;
+        break;
+    }
+
+    return VideoDecoderBase::setupVA(VC1_SURFACE_NUMBER, vaProfile, VC1_EXTRA_SURFACE_NUMBER);
+}
+
+void VideoDecoderWMV::updateFormatInfo(vbp_data_vc1 *data) {
+    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
+        mVideoFormatInfo.width, mVideoFormatInfo.height,
+        data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT);
+
+    mVideoFormatInfo.cropBottom = data->se_data->CODED_HEIGHT > mVideoFormatInfo.height ?
+                                                                           data->se_data->CODED_HEIGHT - mVideoFormatInfo.height : 0;
+    mVideoFormatInfo.cropRight = data->se_data->CODED_WIDTH > mVideoFormatInfo.width ?
+                                                                      data->se_data->CODED_WIDTH - mVideoFormatInfo.width : 0;
+
+     if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH ||
+        mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) &&
+        data->se_data->CODED_WIDTH &&
+        data->se_data->CODED_HEIGHT) {
+        // encoded image size
+        mVideoFormatInfo.width = data->se_data->CODED_WIDTH;
+        mVideoFormatInfo.height = data->se_data->CODED_HEIGHT;
+        mSizeChanged = true;
+        ITRACE("Video size is changed.");
+    }
+
+    // scaling has been performed on the decoded image.
+    mVideoFormatInfo.videoRange = 1;
+
+    switch (data->se_data->MATRIX_COEF) {
+        case 1:
+            mVideoFormatInfo.colorMatrix = VA_SRC_BT709;
+            break;
+        // ITU-R BT.1700, ITU-R BT.601-5, and SMPTE 293M-1996.
+        case 6:
+            mVideoFormatInfo.colorMatrix = VA_SRC_BT601;
+            break;
+        default:
+            // unknown color matrix, set to 0 so color space flag will not be set.
+            mVideoFormatInfo.colorMatrix = 0;
+            break;
+    }
+
+    mVideoFormatInfo.aspectX = data->se_data->ASPECT_HORIZ_SIZE;
+    mVideoFormatInfo.aspectY = data->se_data->ASPECT_VERT_SIZE;
+    mVideoFormatInfo.bitrate = 0; //data->se_data->bitrate;
+    mVideoFormatInfo.valid = true;
+
+    setRenderRect();
+}
+
+Decode_Status VideoDecoderWMV::allocateVABufferIDs(int32_t number) {
+    if (mNumBufferIDs > number) {
+        return DECODE_SUCCESS;
+    }
+    if (mBufferIDs) {
+        delete [] mBufferIDs;
+    }
+    mBufferIDs = NULL;
+    mNumBufferIDs = 0;
+    mBufferIDs = new VABufferID [number];
+    if (mBufferIDs == NULL) {
+        return DECODE_MEMORY_FAIL;
+    }
+    mNumBufferIDs = number;
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderWMV::parseBuffer(uint8_t *data, int32_t size, vbp_data_vc1 **vbpData) {
+    Decode_Status status;
+
+    if (data == NULL || size == 0) {
+        return DECODE_INVALID_DATA;
+    }
+
+    if (mConfigDataParsed) {
+        status = VideoDecoderBase::parseBuffer(data, size, false, (void**)vbpData);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+    } else {
+        uint8_t *newData = NULL;
+        int32_t newSize = 0;
+        status = updateConfigData(data, size, &newData, &newSize);
+        CHECK_STATUS("updateConfigData");
+
+        if (newSize) {
+            status = VideoDecoderBase::parseBuffer(newData, newSize, true, (void**)vbpData);
+            delete [] newData;
+        } else {
+            status = VideoDecoderBase::parseBuffer(data, size, true, (void**)vbpData);
+        }
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+        mConfigDataParsed = true;
+    }
+    return DECODE_SUCCESS;
+}
+
+
+Decode_Status VideoDecoderWMV::checkHardwareCapability() {
+#ifndef USE_GEN_HW
+    VAStatus vaStatus;
+    VAConfigAttrib cfgAttribs[2];
+    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
+    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
+    vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVC1Advanced,
+            VAEntrypointVLD, cfgAttribs, 2);
+    CHECK_VA_STATUS("vaGetConfigAttributes");
+    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
+        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
+                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
+        return DECODE_DRIVER_FAIL;
+    }
+#endif
+    return DECODE_SUCCESS;
+}
+
+
diff --git a/videodecoder/VideoDecoderWMV.h b/videodecoder/VideoDecoderWMV.h
new file mode 100644
index 0000000..40e4a5c
--- /dev/null
+++ b/videodecoder/VideoDecoderWMV.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_WMV_H_
+#define VIDEO_DECODER_WMV_H_
+
+#include "VideoDecoderBase.h"
+
+
+class VideoDecoderWMV : public VideoDecoderBase {
+public:
+    VideoDecoderWMV(const char *mimeType);
+    virtual ~VideoDecoderWMV();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+    virtual void flush(void);
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+protected:
+    virtual Decode_Status checkHardwareCapability();
+
+
+private:
+    Decode_Status decodeFrame(VideoDecodeBuffer *buffer, vbp_data_vc1 *data);
+    Decode_Status decodePicture(vbp_data_vc1 *data, int32_t picIndex);
+    Decode_Status setReference(VAPictureParameterBufferVC1 *params, int32_t picIndex, VASurfaceID current);
+    void updateDeblockedPicIndexes(int frameType);
+    Decode_Status updateConfigData(uint8_t *configData, int32_t configDataLen, uint8_t **newConfigData, int32_t *newConfigDataLen);
+    Decode_Status startVA(vbp_data_vc1 *data);
+    void updateFormatInfo(vbp_data_vc1 *data);
+    inline Decode_Status allocateVABufferIDs(int32_t number);
+    Decode_Status parseBuffer(uint8_t *data, int32_t size, vbp_data_vc1 **vbpData);
+
+private:
+    enum {
+        VC1_SURFACE_NUMBER = 10,
+        VC1_EXTRA_SURFACE_NUMBER = 3,
+    };
+
+    VABufferID *mBufferIDs;
+    int32_t mNumBufferIDs;
+    bool mConfigDataParsed;
+    bool mRangeMapped;
+
+    int32_t mDeblockedCurrPicIndex;
+    int32_t mDeblockedLastPicIndex;
+    int32_t mDeblockedForwardPicIndex;
+};
+
+
+
+#endif /* VIDEO_DECODER_WMV_H_ */
diff --git a/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..52a5285
--- /dev/null
+++ b/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,367 @@
+/*
+* Copyright (c) 2009-2011 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 "va_private.h"
+#include "VideoDecoderAVCSecure.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+#define STARTCODE_PREFIX_LEN        3
+#define NALU_TYPE_MASK              0x1F
+#define MAX_NALU_HEADER_BUFFER      8192
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+    : VideoDecoderAVC(mimeType),
+      mNaluHeaderBuffer(NULL),
+      mSliceHeaderBuffer(NULL) {
+    setParserType(VBP_H264SECURE);
+}
+
+VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+    Decode_Status status = VideoDecoderAVC::start(buffer);
+    if (status != DECODE_SUCCESS) {
+        return status;
+    }
+
+    mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+
+    if (mNaluHeaderBuffer == NULL) {
+        ETRACE("Failed to allocate memory for mNaluHeaderBuffer");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    mSliceHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+    if (mSliceHeaderBuffer == NULL) {
+        ETRACE("Failed to allocate memory for mSliceHeaderBuffer");
+        if (mNaluHeaderBuffer) {
+            delete [] mNaluHeaderBuffer;
+            mNaluHeaderBuffer = NULL;
+        }
+        return DECODE_MEMORY_FAIL;
+    }
+
+    return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+    VideoDecoderAVC::stop();
+
+    if (mNaluHeaderBuffer) {
+        delete [] mNaluHeaderBuffer;
+        mNaluHeaderBuffer = NULL;
+    }
+
+    if (mSliceHeaderBuffer) {
+        delete [] mSliceHeaderBuffer;
+        mSliceHeaderBuffer = NULL;
+    }
+
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    int32_t sizeAccumulated = 0;
+    int32_t sliceHeaderSize = 0;
+    int32_t sizeLeft = 0;
+    int32_t sliceIdx = 0;
+    uint8_t naluType;
+    frame_info_t* pFrameInfo;
+
+    mFrameSize = 0;
+    if (buffer->flag & IS_SECURE_DATA) {
+        VTRACE("Decoding protected video ...");
+        mIsEncryptData = 1;
+    } else {
+        VTRACE("Decoding clear video ...");
+        mIsEncryptData = 0;
+        return VideoDecoderAVC::decode(buffer);
+    }
+
+    if (buffer->size != sizeof(frame_info_t)) {
+        ETRACE("Not enough data to read frame_info_t!");
+        return DECODE_INVALID_DATA;
+    }
+    pFrameInfo = (frame_info_t*) buffer->data;
+
+    mFrameSize = pFrameInfo->length;
+    VTRACE("mFrameSize = %d", mFrameSize);
+
+    memcpy(&mEncParam, pFrameInfo->pavp, sizeof(pavp_info_t));
+    for (int32_t i = 0; i < pFrameInfo->num_nalus; i++) {
+        naluType = pFrameInfo->nalus[i].type & NALU_TYPE_MASK;
+        if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &sliceIdx,
+                sizeof(int32_t));
+            sliceHeaderSize += 4;
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &pFrameInfo->data,
+                sizeof(uint8_t*));
+            sliceHeaderSize += sizeof(uint8_t*);
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &pFrameInfo->nalus[i].offset,
+                sizeof(uint32_t));
+            sliceHeaderSize += sizeof(uint32_t);
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &pFrameInfo->nalus[i].length,
+                sizeof(uint32_t));
+            sliceHeaderSize += sizeof(uint32_t);
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                pFrameInfo->nalus[i].slice_header,
+                sizeof(slice_header_t));
+            sliceHeaderSize += sizeof(slice_header_t);
+            if (pFrameInfo->nalus[i].type & 0x60) {
+                memcpy(mSliceHeaderBuffer+sliceHeaderSize, pFrameInfo->dec_ref_pic_marking, sizeof(dec_ref_pic_marking_t));
+            } else {
+                memset(mSliceHeaderBuffer+sliceHeaderSize, 0, sizeof(dec_ref_pic_marking_t));
+            }
+            sliceHeaderSize += sizeof(dec_ref_pic_marking_t);
+            sliceIdx++;
+        } else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
+            memcpy(mNaluHeaderBuffer + sizeAccumulated,
+                startcodePrefix,
+                STARTCODE_PREFIX_LEN);
+            sizeAccumulated += STARTCODE_PREFIX_LEN;
+            memcpy(mNaluHeaderBuffer + sizeAccumulated,
+                pFrameInfo->nalus[i].data,
+                pFrameInfo->nalus[i].length);
+            sizeAccumulated += pFrameInfo->nalus[i].length;
+        } else {
+            WTRACE("Failure: DECODE_FRAME_DROPPED");
+            return DECODE_FRAME_DROPPED;
+        }
+    }
+
+    vbp_data_h264 *data = NULL;
+    int new_sequence_to_handle = 0;
+
+    if (sizeAccumulated > 0) {
+        status =  VideoDecoderBase::parseBuffer(
+                mNaluHeaderBuffer,
+                sizeAccumulated,
+                false,
+                (void**)&data);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+
+        // [FIX DRC zoom issue] if one buffer contains more than one nalu
+        // for example SPS+PPS+IDR, new_sps/new_pps flags set in parseBuffer
+        // will be flushed in the following updateBuffer.
+        // So that handleNewSequence will not be handled in decodeFrame()
+        if (data->new_sps || data->new_pps) {
+            new_sequence_to_handle = 1;
+        }
+    }
+
+    if (sliceHeaderSize > 0) {
+        memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
+        sliceHeaderSize += 4;
+        status =  VideoDecoderBase::updateBuffer(
+                mSliceHeaderBuffer,
+                sliceHeaderSize,
+                (void**)&data);
+        CHECK_STATUS("VideoDecoderBase::updateBuffer");
+
+        // in case the flags were flushed but indeed new sequence needed to be handled.
+        if ((1 == new_sequence_to_handle) &&
+            ((data->new_sps == 0) || (data->new_pps == 0))) {
+            data->new_sps = 1;
+            data->new_pps = 1;
+        }
+    }
+
+    if (data == NULL) {
+        ETRACE("Invalid data returned by parser!");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    if (!mVAStarted) {
+         if (data->has_sps && data->has_pps) {
+            status = startVA(data);
+            CHECK_STATUS("startVA");
+        } else {
+            WTRACE("Can't start VA as either SPS or PPS is still not available.");
+            return DECODE_SUCCESS;
+        }
+    }
+    status = decodeFrame(buffer, data);
+    return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+    VABufferID bufferIDs[5];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+    VAEncryptionParameterBuffer encryptParam;
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+            // TODO: handle the first slice lost
+        }
+        if (mDecodingFrame) {
+            // interlace content, complete decoding the first field
+            vaStatus = vaEndPicture(mVADisplay, mVAContext);
+            CHECK_VA_STATUS("vaEndPicture");
+
+            // for interlace content, top field may be valid only after the second field is parsed
+            mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
+        }
+
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+        CHECK_VA_STATUS("vaBeginPicture");
+
+        // start decoding a frame
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+
+        if (mIsEncryptData) {
+            memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
+            encryptParam.pavpCounterMode = 4;
+            encryptParam.pavpEncryptionType = 2;
+            encryptParam.hostEncryptMode = 2;
+            encryptParam.pavpHasBeenEnabled = 1;
+            encryptParam.app_id = 0;
+            memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
+
+            vaStatus = vaCreateBuffer(
+                mVADisplay,
+                mVAContext,
+                (VABufferType)VAEncryptionParameterBufferType,
+                sizeof(VAEncryptionParameterBuffer),
+                1,
+                &encryptParam,
+                &bufferIDs[bufferIDCount]);
+            CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
+            bufferIDCount++;
+        }
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VASliceDataBufferType,
+            mFrameSize, //size
+            1,        //num_elements
+            sliceData->buffer_addr + sliceData->slice_offset,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+        bufferIDCount++;
+
+    }
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264Base),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
+    VAProfile profile, VAConfigID *config)
+{
+    VAStatus vaStatus;
+    VAConfigAttrib attrib[2];
+
+    if (config == NULL) {
+        ETRACE("Invalid parameter!");
+        return DECODE_FAIL;
+    }
+
+    attrib[0].type = VAConfigAttribRTFormat;
+    attrib[0].value = VA_RT_FORMAT_YUV420;
+    attrib[1].type = VAConfigAttribDecSliceMode;
+    attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+
+    vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
+
+    if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
+    {
+        ITRACE("AVC short format used");
+        attrib[1].value = VA_DEC_SLICE_MODE_BASE;
+    } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
+        ITRACE("AVC long format ssed");
+        attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+    } else {
+        ETRACE("Unsupported Decode Slice Mode!");
+        return DECODE_FAIL;
+    }
+
+    vaStatus = vaCreateConfig(
+            mVADisplay,
+            profile,
+            VAEntrypointVLD,
+            &attrib[0],
+            2,
+            config);
+    CHECK_VA_STATUS("vaCreateConfig");
+
+    return DECODE_SUCCESS;
+}
diff --git a/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.h b/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.h
new file mode 100644
index 0000000..2214075
--- /dev/null
+++ b/videodecoder/securevideo/baytrail/VideoDecoderAVCSecure.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_SECURE_H_
+#define VIDEO_DECODER_AVC_SECURE_H_
+
+#include "VideoDecoderAVC.h"
+#include "secvideoparser.h"
+
+class VideoDecoderAVCSecure : public VideoDecoderAVC {
+public:
+    VideoDecoderAVCSecure(const char *mimeType);
+    virtual ~VideoDecoderAVCSecure();
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+protected:
+    virtual Decode_Status getCodecSpecificConfigs(VAProfile profile, VAConfigID*config);
+
+private:
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+private:
+    pavp_info_t mEncParam;
+    uint8_t *mNaluHeaderBuffer;
+    uint8_t *mSliceHeaderBuffer;
+    uint32_t mIsEncryptData;
+    uint32_t mFrameSize;
+};
+
+#endif /* VIDEO_DECODER_AVC_SECURE_H_ */
diff --git a/videodecoder/securevideo/baytrail/secvideoparser.h b/videodecoder/securevideo/baytrail/secvideoparser.h
new file mode 100644
index 0000000..f27580a
--- /dev/null
+++ b/videodecoder/securevideo/baytrail/secvideoparser.h
@@ -0,0 +1,150 @@
+/*
+* Copyright (c) 2009-2011 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 SEC_VIDEO_PARSER_H_
+#define SEC_VIDEO_PARSER_H_
+
+#include <stdint.h>
+
+/* H264 start code values */
+typedef enum _h264_nal_unit_type
+{
+    h264_NAL_UNIT_TYPE_unspecified = 0,
+    h264_NAL_UNIT_TYPE_SLICE,
+    h264_NAL_UNIT_TYPE_DPA,
+    h264_NAL_UNIT_TYPE_DPB,
+    h264_NAL_UNIT_TYPE_DPC,
+    h264_NAL_UNIT_TYPE_IDR,
+    h264_NAL_UNIT_TYPE_SEI,
+    h264_NAL_UNIT_TYPE_SPS,
+    h264_NAL_UNIT_TYPE_PPS,
+    h264_NAL_UNIT_TYPE_Acc_unit_delimiter,
+    h264_NAL_UNIT_TYPE_EOSeq,
+    h264_NAL_UNIT_TYPE_EOstream,
+    h264_NAL_UNIT_TYPE_filler_data,
+    h264_NAL_UNIT_TYPE_SPS_extension,
+    h264_NAL_UNIT_TYPE_ACP = 19,
+    h264_NAL_UNIT_TYPE_Slice_extension = 20
+} h264_nal_unit_type_t;
+
+#define MAX_OP  16
+
+enum dec_ref_pic_marking_flags {
+    IDR_PIC_FLAG = 0,
+    NO_OUTPUT_OF_PRIOR_PICS_FLAG,
+    LONG_TERM_REFERENCE_FLAG,
+    ADAPTIVE_REF_PIC_MARKING_MODE_FLAG
+};
+
+typedef struct _dec_ref_pic_marking_t {
+    union {
+        uint8_t flags;
+        struct {
+            uint8_t idr_pic_flag:1;
+            uint8_t no_output_of_prior_pics_flag:1;
+            uint8_t long_term_reference_flag:1;
+            uint8_t adaptive_ref_pic_marking_mode_flag:1;
+        };
+    };
+    struct {
+        uint8_t memory_management_control_operation;
+        union {
+            struct {
+                uint8_t difference_of_pic_nums_minus1;
+            } op1;
+            struct {
+                uint8_t long_term_pic_num;
+            } op2;
+            struct {
+                uint8_t difference_of_pic_nums_minus1;
+                uint8_t long_term_frame_idx;
+            } op3;
+            struct {
+                uint8_t max_long_term_frame_idx_plus1;
+            } op4;
+            struct {
+                uint8_t long_term_frame_idx;
+            } op6;
+        };
+    } op[MAX_OP];
+} dec_ref_pic_marking_t;
+
+enum slice_header_flags {
+    FIELD_PIC_FLAG = 0,
+    BOTTOM_FIELD_FLAG
+};
+
+typedef struct _slice_header_t {
+    uint8_t nal_unit_type;
+    uint8_t pps_id;
+    uint8_t padding;    // TODO: padding needed because flags in secfw impl. is a big-endian uint16_t
+    union {
+        uint8_t flags;
+        struct {
+            uint8_t field_pic_flag:1;
+            uint8_t bottom_field_flag:1;
+        };
+    };
+    uint32_t first_mb_in_slice;
+    uint32_t frame_num;
+    uint16_t idr_pic_id;
+    uint16_t pic_order_cnt_lsb;
+    int32_t delta_pic_order_cnt[2];
+    int32_t delta_pic_order_cnt_bottom;
+} slice_header_t;
+
+typedef struct {
+    uint8_t type;
+    uint32_t offset;
+    uint8_t* data;
+    uint32_t length;
+    slice_header_t* slice_header;
+} nalu_info_t;
+
+typedef struct {
+    uint32_t iv[4];
+    uint32_t mode;
+    uint32_t app_id;
+} pavp_info_t;
+
+#define MAX_NUM_NALUS   20
+
+typedef struct {
+    uint8_t* data;
+    uint32_t length;
+    pavp_info_t* pavp;
+    dec_ref_pic_marking_t* dec_ref_pic_marking;
+    uint32_t num_nalus;
+    nalu_info_t nalus[MAX_NUM_NALUS];
+} frame_info_t;
+
+int parser_init(void);
+int parse_frame(uint8_t* frame, uint32_t frame_size, uint8_t* nalu_data, uint32_t* nalu_data_size);
+
+// DEBUG PRINTING
+void print_slice_header(slice_header_t* slice_header);
+void print_dec_ref_pic_marking(dec_ref_pic_marking_t* dec_ref_pic_marking);
+void print_data_bytes(uint8_t* data, uint32_t count);
+void print_nalu_data(uint8_t* nalu_data, uint32_t nalu_data_size);
+
+// BYTESWAPPING
+uint16_t byteswap_16(uint16_t word);
+uint32_t byteswap_32(uint32_t dword);
+void byteswap_slice_header(slice_header_t* slice_header);
+void byteswap_dec_ref_pic_marking(dec_ref_pic_marking_t* dec_ref_pic_marking);
+void byteswap_nalu_data(uint8_t* nalu_data, uint32_t nalu_data_size);
+
+#endif /* SEC_VIDEO_PARSER_H_ */
diff --git a/videodecoder/securevideo/baytrail/va_private.h b/videodecoder/securevideo/baytrail/va_private.h
new file mode 100644
index 0000000..34a4e1b
--- /dev/null
+++ b/videodecoder/securevideo/baytrail/va_private.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2009-2011 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 __VA_PRIVATE_H__
+#define __VA_PRIVATE_H__
+#include <va/va.h>
+#define ENABLE_PAVP_LINUX                   1
+// Misc parameter for encoder
+#define  VAEncMiscParameterTypePrivate     -2
+// encryption parameters for PAVP
+#define  VAEncryptionParameterBufferType   -3
+
+typedef struct _VAEncMiscParameterPrivate
+{
+    unsigned int target_usage; // Valid values 1-7 for AVC & MPEG2.
+    unsigned int reserved[7];  // Reserved for future use.
+} VAEncMiscParameterPrivate;
+
+/*VAEncrytpionParameterBuffer*/
+typedef struct _VAEncryptionParameterBuffer
+{
+    //Not used currently
+    unsigned int encryptionSupport;
+    //Not used currently
+    unsigned int hostEncryptMode;
+    // For IV, Counter input
+    unsigned int pavpAesCounter[2][4];
+    // not used currently
+    unsigned int pavpIndex;
+    // PAVP mode, CTR, CBC, DEDE etc
+    unsigned int pavpCounterMode;
+    unsigned int pavpEncryptionType;
+    // not used currently
+    unsigned int pavpInputSize[2];
+    // not used currently
+    unsigned int pavpBufferSize[2];
+    // not used currently
+    VABufferID   pvap_buf;
+    // set to TRUE if protected media
+    unsigned int pavpHasBeenEnabled;
+    // not used currently
+    unsigned int IntermmediatedBufReq;
+    // not used currently
+    unsigned int uiCounterIncrement;
+    // AppId: PAVP sessin Index from application
+    unsigned int app_id;
+
+} VAEncryptionParameterBuffer;
+
+#endif
diff --git a/videodecoder/securevideo/cherrytrail/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/cherrytrail/VideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..18c87b9
--- /dev/null
+++ b/videodecoder/securevideo/cherrytrail/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,351 @@
+/*
+* Copyright (c) 2009-2011 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 "va_private.h"
+#include "VideoDecoderAVCSecure.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+#define STARTCODE_PREFIX_LEN        3
+#define NALU_TYPE_MASK              0x1F
+#define MAX_NALU_HEADER_BUFFER      8192
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+    : VideoDecoderAVC(mimeType),
+      mNaluHeaderBuffer(NULL),
+      mSliceHeaderBuffer(NULL) {
+    setParserType(VBP_H264SECURE);
+}
+
+VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+    Decode_Status status = VideoDecoderAVC::start(buffer);
+    if (status != DECODE_SUCCESS) {
+        return status;
+    }
+
+    mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+
+    if (mNaluHeaderBuffer == NULL) {
+        ETRACE("Failed to allocate memory for mNaluHeaderBuffer");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    mSliceHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+    if (mSliceHeaderBuffer == NULL) {
+        ETRACE("Failed to allocate memory for mSliceHeaderBuffer");
+        if (mNaluHeaderBuffer) {
+            delete [] mNaluHeaderBuffer;
+            mNaluHeaderBuffer = NULL;
+        }
+        return DECODE_MEMORY_FAIL;
+    }
+
+    return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+    VideoDecoderAVC::stop();
+
+    if (mNaluHeaderBuffer) {
+        delete [] mNaluHeaderBuffer;
+        mNaluHeaderBuffer = NULL;
+    }
+
+    if (mSliceHeaderBuffer) {
+        delete [] mSliceHeaderBuffer;
+        mSliceHeaderBuffer = NULL;
+    }
+
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    int32_t sizeAccumulated = 0;
+    int32_t sliceHeaderSize = 0;
+    int32_t sizeLeft = 0;
+    int32_t sliceIdx = 0;
+    uint8_t naluType;
+    frame_info_t* pFrameInfo;
+
+    mFrameSize = 0;
+    if (buffer->flag & IS_SECURE_DATA) {
+        VTRACE("Decoding protected video ...");
+        mIsEncryptData = 1;
+    } else {
+        VTRACE("Decoding clear video ...");
+        mIsEncryptData = 0;
+        return VideoDecoderAVC::decode(buffer);
+    }
+
+    if (buffer->size != sizeof(frame_info_t)) {
+        ETRACE("Not enough data to read frame_info_t!");
+        return DECODE_INVALID_DATA;
+    }
+    pFrameInfo = (frame_info_t*) buffer->data;
+
+    mFrameSize = pFrameInfo->length;
+    VTRACE("mFrameSize = %d", mFrameSize);
+
+    memcpy(&mEncParam, pFrameInfo->pavp, sizeof(pavp_info_t));
+    for (int32_t i = 0; i < pFrameInfo->num_nalus; i++) {
+        naluType = pFrameInfo->nalus[i].type & NALU_TYPE_MASK;
+        if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &sliceIdx,
+                sizeof(int32_t));
+            sliceHeaderSize += 4;
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &pFrameInfo->data,
+                sizeof(uint8_t*));
+            sliceHeaderSize += sizeof(uint8_t*);
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &pFrameInfo->nalus[i].offset,
+                sizeof(uint32_t));
+            sliceHeaderSize += sizeof(uint32_t);
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                &pFrameInfo->nalus[i].length,
+                sizeof(uint32_t));
+            sliceHeaderSize += sizeof(uint32_t);
+
+            memcpy(mSliceHeaderBuffer + sliceHeaderSize,
+                pFrameInfo->nalus[i].slice_header,
+                sizeof(slice_header_t));
+            sliceHeaderSize += sizeof(slice_header_t);
+            if (pFrameInfo->nalus[i].type & 0x60) {
+                memcpy(mSliceHeaderBuffer+sliceHeaderSize, pFrameInfo->dec_ref_pic_marking, sizeof(dec_ref_pic_marking_t));
+            } else {
+                memset(mSliceHeaderBuffer+sliceHeaderSize, 0, sizeof(dec_ref_pic_marking_t));
+            }
+            sliceHeaderSize += sizeof(dec_ref_pic_marking_t);
+            sliceIdx++;
+        } else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
+            memcpy(mNaluHeaderBuffer + sizeAccumulated,
+                startcodePrefix,
+                STARTCODE_PREFIX_LEN);
+            sizeAccumulated += STARTCODE_PREFIX_LEN;
+            memcpy(mNaluHeaderBuffer + sizeAccumulated,
+                pFrameInfo->nalus[i].data,
+                pFrameInfo->nalus[i].length);
+            sizeAccumulated += pFrameInfo->nalus[i].length;
+        } else {
+            WTRACE("Failure: DECODE_FRAME_DROPPED");
+            return DECODE_FRAME_DROPPED;
+        }
+    }
+
+    vbp_data_h264 *data = NULL;
+
+    if (sizeAccumulated > 0) {
+        status =  VideoDecoderBase::parseBuffer(
+                mNaluHeaderBuffer,
+                sizeAccumulated,
+                false,
+                (void**)&data);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+    }
+
+    if (sliceHeaderSize > 0) {
+        memset(mSliceHeaderBuffer + sliceHeaderSize, 0xFF, 4);
+        sliceHeaderSize += 4;
+        status =  VideoDecoderBase::updateBuffer(
+                mSliceHeaderBuffer,
+                sliceHeaderSize,
+                (void**)&data);
+        CHECK_STATUS("VideoDecoderBase::updateBuffer");
+    }
+
+    if (data == NULL) {
+        ETRACE("Invalid data returned by parser!");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    if (!mVAStarted) {
+         if (data->has_sps && data->has_pps) {
+            status = startVA(data);
+            CHECK_STATUS("startVA");
+        } else {
+            WTRACE("Can't start VA as either SPS or PPS is still not available.");
+            return DECODE_SUCCESS;
+        }
+    }
+    status = decodeFrame(buffer, data);
+    return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+    VABufferID bufferIDs[5];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+    VAEncryptionParameterBuffer encryptParam;
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+            // TODO: handle the first slice lost
+        }
+        if (mDecodingFrame) {
+            // interlace content, complete decoding the first field
+            vaStatus = vaEndPicture(mVADisplay, mVAContext);
+            CHECK_VA_STATUS("vaEndPicture");
+
+            // for interlace content, top field may be valid only after the second field is parsed
+            mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
+        }
+
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+        CHECK_VA_STATUS("vaBeginPicture");
+
+        // start decoding a frame
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+
+        if (mIsEncryptData) {
+            memset(&encryptParam, 0, sizeof(VAEncryptionParameterBuffer));
+            encryptParam.pavpCounterMode = 4;
+            encryptParam.pavpEncryptionType = 2;
+            encryptParam.hostEncryptMode = 2;
+            encryptParam.pavpHasBeenEnabled = 1;
+            encryptParam.app_id = 0;
+            memcpy(encryptParam.pavpAesCounter, mEncParam.iv, 16);
+
+            vaStatus = vaCreateBuffer(
+                mVADisplay,
+                mVAContext,
+                (VABufferType)VAEncryptionParameterBufferType,
+                sizeof(VAEncryptionParameterBuffer),
+                1,
+                &encryptParam,
+                &bufferIDs[bufferIDCount]);
+            CHECK_VA_STATUS("vaCreateEncryptionParameterBuffer");
+            bufferIDCount++;
+        }
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VASliceDataBufferType,
+            mFrameSize, //size
+            1,        //num_elements
+            sliceData->buffer_addr + sliceData->slice_offset,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+        bufferIDCount++;
+
+    }
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264Base),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
+    VAProfile profile, VAConfigID *config)
+{
+    VAStatus vaStatus;
+    VAConfigAttrib attrib[2];
+
+    if (config == NULL) {
+        ETRACE("Invalid parameter!");
+        return DECODE_FAIL;
+    }
+
+    attrib[0].type = VAConfigAttribRTFormat;
+    attrib[0].value = VA_RT_FORMAT_YUV420;
+    attrib[1].type = VAConfigAttribDecSliceMode;
+    attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+
+    vaStatus = vaGetConfigAttributes(mVADisplay,profile,VAEntrypointVLD, &attrib[1], 1);
+
+    if (attrib[1].value & VA_DEC_SLICE_MODE_BASE)
+    {
+        ITRACE("AVC short format used");
+        attrib[1].value = VA_DEC_SLICE_MODE_BASE;
+    } else if (attrib[1].value & VA_DEC_SLICE_MODE_NORMAL) {
+        ITRACE("AVC long format ssed");
+        attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+    } else {
+        ETRACE("Unsupported Decode Slice Mode!");
+        return DECODE_FAIL;
+    }
+
+    vaStatus = vaCreateConfig(
+            mVADisplay,
+            profile,
+            VAEntrypointVLD,
+            &attrib[0],
+            2,
+            config);
+    CHECK_VA_STATUS("vaCreateConfig");
+
+    return DECODE_SUCCESS;
+}
diff --git a/videodecoder/securevideo/cherrytrail/VideoDecoderAVCSecure.h b/videodecoder/securevideo/cherrytrail/VideoDecoderAVCSecure.h
new file mode 100644
index 0000000..2214075
--- /dev/null
+++ b/videodecoder/securevideo/cherrytrail/VideoDecoderAVCSecure.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_SECURE_H_
+#define VIDEO_DECODER_AVC_SECURE_H_
+
+#include "VideoDecoderAVC.h"
+#include "secvideoparser.h"
+
+class VideoDecoderAVCSecure : public VideoDecoderAVC {
+public:
+    VideoDecoderAVCSecure(const char *mimeType);
+    virtual ~VideoDecoderAVCSecure();
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+protected:
+    virtual Decode_Status getCodecSpecificConfigs(VAProfile profile, VAConfigID*config);
+
+private:
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+private:
+    pavp_info_t mEncParam;
+    uint8_t *mNaluHeaderBuffer;
+    uint8_t *mSliceHeaderBuffer;
+    uint32_t mIsEncryptData;
+    uint32_t mFrameSize;
+};
+
+#endif /* VIDEO_DECODER_AVC_SECURE_H_ */
diff --git a/videodecoder/securevideo/cherrytrail/secvideoparser.h b/videodecoder/securevideo/cherrytrail/secvideoparser.h
new file mode 100644
index 0000000..f27580a
--- /dev/null
+++ b/videodecoder/securevideo/cherrytrail/secvideoparser.h
@@ -0,0 +1,150 @@
+/*
+* Copyright (c) 2009-2011 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 SEC_VIDEO_PARSER_H_
+#define SEC_VIDEO_PARSER_H_
+
+#include <stdint.h>
+
+/* H264 start code values */
+typedef enum _h264_nal_unit_type
+{
+    h264_NAL_UNIT_TYPE_unspecified = 0,
+    h264_NAL_UNIT_TYPE_SLICE,
+    h264_NAL_UNIT_TYPE_DPA,
+    h264_NAL_UNIT_TYPE_DPB,
+    h264_NAL_UNIT_TYPE_DPC,
+    h264_NAL_UNIT_TYPE_IDR,
+    h264_NAL_UNIT_TYPE_SEI,
+    h264_NAL_UNIT_TYPE_SPS,
+    h264_NAL_UNIT_TYPE_PPS,
+    h264_NAL_UNIT_TYPE_Acc_unit_delimiter,
+    h264_NAL_UNIT_TYPE_EOSeq,
+    h264_NAL_UNIT_TYPE_EOstream,
+    h264_NAL_UNIT_TYPE_filler_data,
+    h264_NAL_UNIT_TYPE_SPS_extension,
+    h264_NAL_UNIT_TYPE_ACP = 19,
+    h264_NAL_UNIT_TYPE_Slice_extension = 20
+} h264_nal_unit_type_t;
+
+#define MAX_OP  16
+
+enum dec_ref_pic_marking_flags {
+    IDR_PIC_FLAG = 0,
+    NO_OUTPUT_OF_PRIOR_PICS_FLAG,
+    LONG_TERM_REFERENCE_FLAG,
+    ADAPTIVE_REF_PIC_MARKING_MODE_FLAG
+};
+
+typedef struct _dec_ref_pic_marking_t {
+    union {
+        uint8_t flags;
+        struct {
+            uint8_t idr_pic_flag:1;
+            uint8_t no_output_of_prior_pics_flag:1;
+            uint8_t long_term_reference_flag:1;
+            uint8_t adaptive_ref_pic_marking_mode_flag:1;
+        };
+    };
+    struct {
+        uint8_t memory_management_control_operation;
+        union {
+            struct {
+                uint8_t difference_of_pic_nums_minus1;
+            } op1;
+            struct {
+                uint8_t long_term_pic_num;
+            } op2;
+            struct {
+                uint8_t difference_of_pic_nums_minus1;
+                uint8_t long_term_frame_idx;
+            } op3;
+            struct {
+                uint8_t max_long_term_frame_idx_plus1;
+            } op4;
+            struct {
+                uint8_t long_term_frame_idx;
+            } op6;
+        };
+    } op[MAX_OP];
+} dec_ref_pic_marking_t;
+
+enum slice_header_flags {
+    FIELD_PIC_FLAG = 0,
+    BOTTOM_FIELD_FLAG
+};
+
+typedef struct _slice_header_t {
+    uint8_t nal_unit_type;
+    uint8_t pps_id;
+    uint8_t padding;    // TODO: padding needed because flags in secfw impl. is a big-endian uint16_t
+    union {
+        uint8_t flags;
+        struct {
+            uint8_t field_pic_flag:1;
+            uint8_t bottom_field_flag:1;
+        };
+    };
+    uint32_t first_mb_in_slice;
+    uint32_t frame_num;
+    uint16_t idr_pic_id;
+    uint16_t pic_order_cnt_lsb;
+    int32_t delta_pic_order_cnt[2];
+    int32_t delta_pic_order_cnt_bottom;
+} slice_header_t;
+
+typedef struct {
+    uint8_t type;
+    uint32_t offset;
+    uint8_t* data;
+    uint32_t length;
+    slice_header_t* slice_header;
+} nalu_info_t;
+
+typedef struct {
+    uint32_t iv[4];
+    uint32_t mode;
+    uint32_t app_id;
+} pavp_info_t;
+
+#define MAX_NUM_NALUS   20
+
+typedef struct {
+    uint8_t* data;
+    uint32_t length;
+    pavp_info_t* pavp;
+    dec_ref_pic_marking_t* dec_ref_pic_marking;
+    uint32_t num_nalus;
+    nalu_info_t nalus[MAX_NUM_NALUS];
+} frame_info_t;
+
+int parser_init(void);
+int parse_frame(uint8_t* frame, uint32_t frame_size, uint8_t* nalu_data, uint32_t* nalu_data_size);
+
+// DEBUG PRINTING
+void print_slice_header(slice_header_t* slice_header);
+void print_dec_ref_pic_marking(dec_ref_pic_marking_t* dec_ref_pic_marking);
+void print_data_bytes(uint8_t* data, uint32_t count);
+void print_nalu_data(uint8_t* nalu_data, uint32_t nalu_data_size);
+
+// BYTESWAPPING
+uint16_t byteswap_16(uint16_t word);
+uint32_t byteswap_32(uint32_t dword);
+void byteswap_slice_header(slice_header_t* slice_header);
+void byteswap_dec_ref_pic_marking(dec_ref_pic_marking_t* dec_ref_pic_marking);
+void byteswap_nalu_data(uint8_t* nalu_data, uint32_t nalu_data_size);
+
+#endif /* SEC_VIDEO_PARSER_H_ */
diff --git a/videodecoder/securevideo/cherrytrail/va_private.h b/videodecoder/securevideo/cherrytrail/va_private.h
new file mode 100644
index 0000000..e53e31d
--- /dev/null
+++ b/videodecoder/securevideo/cherrytrail/va_private.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2009-2011 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 __VA_PRIVATE_H__
+#define __VA_PRIVATE_H__
+#include <va/va.h>
+#define ENABLE_PAVP_LINUX                   1
+// Misc parameter for encoder
+#define  VAEncMiscParameterTypePrivate     -2
+// encryption parameters for PAVP
+#define  VAEncryptionParameterBufferType   -3
+
+typedef struct _VAEncMiscParameterPrivate
+{
+    unsigned int target_usage; // Valid values 1-7 for AVC & MPEG2.
+    unsigned int reserved[7];  // Reserved for future use.
+} VAEncMiscParameterPrivate;
+
+/*VAEncrytpionParameterBuffer*/
+typedef struct _VAEncryptionParameterBuffer
+{
+    //Not used currently
+    unsigned int encryptionSupport;
+    //Not used currently
+    unsigned int hostEncryptMode;
+    // For IV, Counter input
+    unsigned int pavpAesCounter[2][4];
+    // not used currently
+    unsigned int pavpIndex;
+    // PAVP mode, CTR, CBC, DEDE etc
+    unsigned int pavpCounterMode;
+    unsigned int pavpEncryptionType;
+    // not used currently
+    unsigned int pavpInputSize[2];
+    // not used currently
+    unsigned int pavpBufferSize[2];
+    // not used currently
+    VABufferID   pvap_buf;
+    // set to TRUE if protected media
+    unsigned int pavpHasBeenEnabled;
+    // not used currently
+    unsigned int IntermmediatedBufReq;
+    // not used currently
+    unsigned int uiCounterIncrement;
+    // AppId: PAVP sessin Index from application
+    unsigned int app_id;
+
+} VAEncryptionParameterBuffer;
+
+#endif
diff --git a/videodecoder/securevideo/clovertrail/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/clovertrail/VideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..d9da2ac
--- /dev/null
+++ b/videodecoder/securevideo/clovertrail/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,507 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderAVCSecure.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+
+#define STARTCODE_00                0x00
+#define STARTCODE_01                0x01
+#define STARTCODE_PREFIX_LEN        3
+#define NALU_TYPE_MASK              0x1F
+
+
+// mask for little endian, to mast the second and fourth bytes in the byte stream
+#define STARTCODE_MASK0             0xFF000000 //0x00FF0000
+#define STARTCODE_MASK1             0x0000FF00  //0x000000FF
+
+
+typedef enum {
+    NAL_UNIT_TYPE_unspecified0 = 0,
+    NAL_UNIT_TYPE_SLICE,
+    NAL_UNIT_TYPE_DPA,
+    NAL_UNIT_TYPE_DPB,
+    NAL_UNIT_TYPE_DPC,
+    NAL_UNIT_TYPE_IDR,
+    NAL_UNIT_TYPE_SEI,
+    NAL_UNIT_TYPE_SPS,
+    NAL_UNIT_TYPE_PPS,
+    NAL_UNIT_TYPE_Acc_unit_delimiter,
+    NAL_UNIT_TYPE_EOSeq,
+    NAL_UNIT_TYPE_EOstream,
+    NAL_UNIT_TYPE_filler_data,
+    NAL_UNIT_TYPE_SPS_extension,
+    NAL_UNIT_TYPE_Reserved14,
+    NAL_UNIT_TYPE_Reserved15,
+    NAL_UNIT_TYPE_Reserved16,
+    NAL_UNIT_TYPE_Reserved17,
+    NAL_UNIT_TYPE_Reserved18,
+    NAL_UNIT_TYPE_ACP,
+    NAL_UNIT_TYPE_Reserved20,
+    NAL_UNIT_TYPE_Reserved21,
+    NAL_UNIT_TYPE_Reserved22,
+    NAL_UNIT_TYPE_Reserved23,
+    NAL_UNIT_TYPE_unspecified24,
+} NAL_UNIT_TYPE;
+
+#ifndef min
+#define min(X, Y)  ((X) <(Y) ? (X) : (Y))
+#endif
+
+
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+    : VideoDecoderAVC(mimeType),
+      mNaluHeaderBuffer(NULL),
+      mInputBuffer(NULL) {
+
+    memset(&mMetadata, 0, sizeof(NaluMetadata));
+    memset(&mByteStream, 0, sizeof(NaluByteStream));
+}
+
+VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+    Decode_Status status = VideoDecoderAVC::start(buffer);
+    if (status != DECODE_SUCCESS) {
+        return status;
+    }
+
+    mMetadata.naluInfo = new NaluInfo [MAX_NALU_NUMBER];
+    mByteStream.byteStream = new uint8_t [MAX_NALU_HEADER_BUFFER];
+    mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+
+    if (mMetadata.naluInfo == NULL ||
+        mByteStream.byteStream == NULL ||
+        mNaluHeaderBuffer == NULL) {
+        ETRACE("Failed to allocate memory.");
+        // TODO: release all allocated memory
+        return DECODE_MEMORY_FAIL;
+    }
+    return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+    VideoDecoderAVC::stop();
+
+    if (mMetadata.naluInfo) {
+        delete [] mMetadata.naluInfo;
+        mMetadata.naluInfo = NULL;
+    }
+
+    if (mByteStream.byteStream) {
+        delete [] mByteStream.byteStream;
+        mByteStream.byteStream = NULL;
+    }
+
+    if (mNaluHeaderBuffer) {
+        delete [] mNaluHeaderBuffer;
+        mNaluHeaderBuffer = NULL;
+    }
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    int32_t sizeAccumulated = 0;
+    int32_t sizeLeft = 0;
+    uint8_t *pByteStream = NULL;
+    NaluInfo *pNaluInfo = mMetadata.naluInfo;
+
+    if (buffer->flag & IS_SECURE_DATA) {
+        pByteStream = buffer->data;
+        sizeLeft = buffer->size;
+        mInputBuffer = NULL;
+    } else {
+        status = parseAnnexBStream(buffer->data, buffer->size, &mByteStream);
+        CHECK_STATUS("parseAnnexBStream");
+        pByteStream = mByteStream.byteStream;
+        sizeLeft = mByteStream.streamPos;
+        mInputBuffer = buffer->data;
+    }
+    if (sizeLeft < 4) {
+        ETRACE("Not enough data to read number of NALU.");
+        return DECODE_INVALID_DATA;
+    }
+
+    // read number of NALU
+    memcpy(&(mMetadata.naluNumber), pByteStream, sizeof(int32_t));
+    pByteStream += 4;
+    sizeLeft -= 4;
+
+    if (mMetadata.naluNumber == 0) {
+        WTRACE("Number of NALU is ZERO!");
+        return DECODE_SUCCESS;
+    }
+
+    for (int32_t i = 0; i < mMetadata.naluNumber; i++) {
+        if (sizeLeft < 12) {
+            ETRACE("Not enough data to parse NALU offset, size, header length for NALU %d, left = %d", i, sizeLeft);
+            return DECODE_INVALID_DATA;
+        }
+        sizeLeft -= 12;
+        // read NALU offset
+        memcpy(&(pNaluInfo->naluOffset), pByteStream, sizeof(int32_t));
+        pByteStream += 4;
+
+        // read NALU size
+        memcpy(&(pNaluInfo->naluLen), pByteStream, sizeof(int32_t));
+        pByteStream += 4;
+
+        // read NALU header length
+        memcpy(&(pNaluInfo->naluHeaderLen), pByteStream, sizeof(int32_t));
+        pByteStream += 4;
+
+        if (sizeLeft < pNaluInfo->naluHeaderLen) {
+            ETRACE("Not enough data to copy NALU header for %d, left = %d, header len = %d", i, sizeLeft, pNaluInfo->naluHeaderLen);
+            return DECODE_INVALID_DATA;
+        }
+
+        sizeLeft -=  pNaluInfo->naluHeaderLen;
+
+        if (pNaluInfo->naluHeaderLen) {
+            // copy start code prefix to buffer
+            memcpy(mNaluHeaderBuffer + sizeAccumulated,
+                startcodePrefix,
+                STARTCODE_PREFIX_LEN);
+            sizeAccumulated += STARTCODE_PREFIX_LEN;
+
+            // copy NALU header
+            memcpy(mNaluHeaderBuffer + sizeAccumulated, pByteStream, pNaluInfo->naluHeaderLen);
+            pByteStream += pNaluInfo->naluHeaderLen;
+
+            sizeAccumulated += pNaluInfo->naluHeaderLen;
+        } else {
+            WTRACE("header len is zero for NALU %d", i);
+        }
+
+        // for next NALU
+        pNaluInfo++;
+    }
+
+    buffer->data = mNaluHeaderBuffer;
+    buffer->size = sizeAccumulated;
+
+    return VideoDecoderAVC::decode(buffer);
+}
+
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+    VABufferID bufferIDs[4];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+            // TODO: handle the first slice lost
+        }
+        if (mDecodingFrame) {
+            // interlace content, complete decoding the first field
+            vaStatus = vaEndPicture(mVADisplay, mVAContext);
+            CHECK_VA_STATUS("vaEndPicture");
+
+            // for interlace content, top field may be valid only after the second field is parsed
+            mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
+        }
+
+        // Check there is no reference frame loss before decoding a frame
+
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+        //We have to provide a hacked DPB rather than complete DPB for libva as workaround
+        status = updateReferenceFrames(picData);
+        CHECK_STATUS("updateReferenceFrames");
+
+        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+        CHECK_VA_STATUS("vaBeginPicture");
+
+        // start decoding a frame
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+    }
+
+    status = setReference(sliceParam);
+    CHECK_STATUS("setReference");
+
+    // find which naluinfo is correlated to current slice
+    int naluIndex = 0;
+    uint32_t accumulatedHeaderLen = 0;
+    uint32_t headerLen = 0;
+    for (; naluIndex < mMetadata.naluNumber; naluIndex++)  {
+        headerLen = mMetadata.naluInfo[naluIndex].naluHeaderLen;
+        if (headerLen == 0) {
+            WTRACE("lenght of current NAL unit is 0.");
+            continue;
+        }
+        accumulatedHeaderLen += STARTCODE_PREFIX_LEN;
+        if (accumulatedHeaderLen + headerLen > sliceData->slice_offset) {
+            break;
+        }
+        accumulatedHeaderLen += headerLen;
+    }
+
+    if (sliceData->slice_offset != accumulatedHeaderLen) {
+        WTRACE("unexpected slice offset %d, accumulatedHeaderLen = %d", sliceData->slice_offset, accumulatedHeaderLen);
+    }
+
+    sliceParam->slice_data_size = mMetadata.naluInfo[naluIndex].naluLen;
+    sliceData->slice_size = sliceParam->slice_data_size;
+
+    // no need to update:
+    // sliceParam->slice_data_offset - 0 always
+    // sliceParam->slice_data_bit_offset - relative to  sliceData->slice_offset
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    // sliceData->slice_offset - accumulatedHeaderLen is the absolute offset to start codes of current NAL unit
+    // offset points to first byte of NAL unit
+    uint32_t sliceOffset = mMetadata.naluInfo[naluIndex].naluOffset;
+    if (mInputBuffer != NULL) {
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VASliceDataBufferType,
+            sliceData->slice_size, //size
+            1,        //num_elements
+            mInputBuffer  + sliceOffset,
+            &bufferIDs[bufferIDCount]);
+    } else {
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAProtectedSliceDataBufferType,
+            sliceData->slice_size, //size
+            1,        //num_elements
+            (uint8_t*)sliceOffset, // IMR offset
+            &bufferIDs[bufferIDCount]);
+    }
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+}
+
+
+// Parse byte string pattern "0x000001" (3 bytes)  in the current buffer.
+// Returns offset of position following  the pattern in the buffer if pattern is found or -1 if not found.
+int32_t VideoDecoderAVCSecure::findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length) {
+    uint8_t *ptr;
+    uint32_t left = 0, data = 0, phase = 0;
+    uint8_t mask1 = 0, mask2 = 0;
+
+    /* Meaning of phase:
+        0: initial status, "0x000001" bytes are not found so far;
+        1: one "0x00" byte is found;
+        2: two or more consecutive "0x00" bytes" are found;
+        3: "0x000001" patten is found ;
+        4: if there is one more byte after "0x000001";
+       */
+
+    left = length;
+    ptr = (uint8_t *) (stream + offset);
+    phase = 0;
+
+    // parse until there is more data and start code not found
+    while ((left > 0) && (phase < 3)) {
+        // Check if the address is 32-bit aligned & phase=0, if thats the case we can check 4 bytes instead of one byte at a time.
+        if (((((uint32_t)ptr) & 0x3) == 0) && (phase == 0)) {
+            while (left > 3) {
+                data = *((uint32_t *)ptr);
+                mask1 = (STARTCODE_00 != (data & STARTCODE_MASK0));
+                mask2 = (STARTCODE_00 != (data & STARTCODE_MASK1));
+                // If second byte and fourth byte are not zero's then we cannot have a start code here,
+                //  as we need two consecutive zero bytes for a start code pattern.
+                if (mask1 && mask2) {
+                    // skip 4 bytes and start over
+                    ptr += 4;
+                    left -=4;
+                    continue;
+                } else {
+                    break;
+                }
+            }
+        }
+
+        // At this point either data is not on a 32-bit boundary or phase > 0 so we look at one byte at a time
+        if (left > 0) {
+            if (*ptr == STARTCODE_00) {
+                phase++;
+                if (phase > 2) {
+                    // more than 2 consecutive '0x00' bytes is found
+                    phase = 2;
+                }
+            } else if ((*ptr == STARTCODE_01) && (phase == 2)) {
+                // start code is found
+                phase = 3;
+            } else {
+                // reset lookup
+                phase = 0;
+            }
+            ptr++;
+            left--;
+        }
+    }
+
+    if ((left > 0) && (phase == 3)) {
+        phase = 4;
+        // return offset of position following the pattern in the buffer which matches "0x000001" byte string
+        return (int32_t)(ptr - stream);
+    }
+    return -1;
+}
+
+
+Decode_Status VideoDecoderAVCSecure::copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream) {
+    uint8_t naluType;
+    int32_t naluHeaderLen;
+
+    naluType = *(uint8_t *)(stream + naluStream->naluOffset);
+    naluType &= NALU_TYPE_MASK;
+    // first update nalu header length based on nalu type
+    if (naluType >= NAL_UNIT_TYPE_SLICE && naluType <= NAL_UNIT_TYPE_IDR) {
+        // coded slice, return only up to MAX_SLICE_HEADER_SIZE bytes
+        naluHeaderLen = min(naluStream->naluLen, MAX_SLICE_HEADER_SIZE);
+    } else if (naluType >= NAL_UNIT_TYPE_SEI && naluType <= NAL_UNIT_TYPE_PPS) {
+        //sps, pps, sei, etc, return the entire NAL unit in clear
+        naluHeaderLen = naluStream->naluLen;
+    } else {
+        return DECODE_FRAME_DROPPED;
+    }
+
+    memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluOffset), sizeof(int32_t));
+    naluStream->streamPos += 4;
+
+    memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluLen), sizeof(int32_t));
+    naluStream->streamPos += 4;
+
+    memcpy(naluStream->byteStream + naluStream->streamPos, &naluHeaderLen, sizeof(int32_t));
+    naluStream->streamPos += 4;
+
+    if (naluHeaderLen) {
+        memcpy(naluStream->byteStream + naluStream->streamPos, (uint8_t*)(stream + naluStream->naluOffset), naluHeaderLen);
+        naluStream->streamPos += naluHeaderLen;
+    }
+    return DECODE_SUCCESS;
+}
+
+
+// parse start-code prefixed stream, also knowns as Annex B byte stream, commonly used in AVI, ES, MPEG2 TS container
+Decode_Status VideoDecoderAVCSecure::parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream) {
+    int32_t naluOffset, offset, left;
+    NaluInfo *info;
+    uint32_t ret = DECODE_SUCCESS;
+
+    naluOffset = 0;
+    offset = 0;
+    left = length;
+
+    // leave 4 bytes to copy nalu count
+    naluStream->streamPos = 4;
+    naluStream->naluCount = 0;
+    memset(naluStream->byteStream, 0, MAX_NALU_HEADER_BUFFER);
+
+    for (; ;) {
+        naluOffset = findNalUnitOffset(stream, offset, left);
+        if (naluOffset == -1) {
+            break;
+        }
+
+        if (naluStream->naluCount == 0) {
+            naluStream->naluOffset = naluOffset;
+        } else {
+            naluStream->naluLen = naluOffset - naluStream->naluOffset - STARTCODE_PREFIX_LEN;
+            ret = copyNaluHeader(stream, naluStream);
+            if (ret != DECODE_SUCCESS && ret != DECODE_FRAME_DROPPED) {
+                LOGW("copyNaluHeader returned %d", ret);
+                return ret;
+            }
+            // starting position for next NALU
+            naluStream->naluOffset = naluOffset;
+        }
+
+        if (ret == DECODE_SUCCESS) {
+            naluStream->naluCount++;
+        }
+
+        // update next lookup position and length
+        offset = naluOffset + 1; // skip one byte of NAL unit type
+        left = length - offset;
+    }
+
+    if (naluStream->naluCount > 0) {
+        naluStream->naluLen = length - naluStream->naluOffset;
+        memcpy(naluStream->byteStream, &(naluStream->naluCount), sizeof(int32_t));
+        // ignore return value, either DECODE_SUCCESS or DECODE_FRAME_DROPPED
+        copyNaluHeader(stream, naluStream);
+        return DECODE_SUCCESS;
+    }
+
+    LOGW("number of valid NALU is 0!");
+    return DECODE_SUCCESS;
+}
+
diff --git a/videodecoder/securevideo/clovertrail/VideoDecoderAVCSecure.h b/videodecoder/securevideo/clovertrail/VideoDecoderAVCSecure.h
new file mode 100644
index 0000000..ee16073
--- /dev/null
+++ b/videodecoder/securevideo/clovertrail/VideoDecoderAVCSecure.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_SECURE_H_
+#define VIDEO_DECODER_AVC_SECURE_H_
+
+#include "VideoDecoderAVC.h"
+
+
+class VideoDecoderAVCSecure : public VideoDecoderAVC {
+public:
+    VideoDecoderAVCSecure(const char *mimeType);
+    virtual ~VideoDecoderAVCSecure();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+
+    // data in the decoded buffer is all encrypted.
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+private:
+    enum {
+        MAX_SLICE_HEADER_SIZE  = 30,
+        MAX_NALU_HEADER_BUFFER = 8192,
+        MAX_NALU_NUMBER = 400,  // > 4096/12
+    };
+
+    // Information of Network Abstraction Layer Unit
+    struct NaluInfo {
+        int32_t naluOffset;                        // offset of NAL unit in the firewalled buffer
+        int32_t naluLen;                           // length of NAL unit
+        int32_t naluHeaderLen;                     // length of NAL unit header
+    };
+
+    struct NaluMetadata {
+        NaluInfo *naluInfo;
+        int32_t naluNumber;  // number of NAL units
+    };
+
+    struct NaluByteStream {
+        int32_t naluOffset;
+        int32_t naluLen;
+        int32_t streamPos;
+        uint8_t *byteStream;   // 4 bytes of naluCount, 4 bytes of naluOffset, 4 bytes of naulLen, 4 bytes of naluHeaderLen, followed by naluHeaderData
+        int32_t naluCount;
+    };
+
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+    int32_t findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length);
+    Decode_Status copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream);
+    Decode_Status parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream);
+
+private:
+    NaluMetadata mMetadata;
+    NaluByteStream mByteStream;
+    uint8_t *mNaluHeaderBuffer;
+    uint8_t *mInputBuffer;
+};
+
+
+
+#endif /* VIDEO_DECODER_AVC_SECURE_H_ */
diff --git a/videodecoder/securevideo/merrifield/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/merrifield/VideoDecoderAVCSecure.cpp
new file mode 100755
index 0000000..649402d
--- /dev/null
+++ b/videodecoder/securevideo/merrifield/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,858 @@
+/*
+* Copyright (c) 2009-2011 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 <va/va.h>
+#include "VideoDecoderBase.h"
+#include "VideoDecoderAVC.h"
+#include "VideoDecoderTrace.h"
+#include "vbp_loader.h"
+#include "VideoDecoderAVCSecure.h"
+#include "VideoFrameInfo.h"
+
+#define MAX_SLICEHEADER_BUFFER_SIZE 4096
+#define STARTCODE_PREFIX_LEN        3
+#define NALU_TYPE_MASK              0x1F
+#define MAX_NALU_HEADER_BUFFER      8192
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+/* H264 start code values */
+typedef enum _h264_nal_unit_type
+{
+    h264_NAL_UNIT_TYPE_unspecified = 0,
+    h264_NAL_UNIT_TYPE_SLICE,
+    h264_NAL_UNIT_TYPE_DPA,
+    h264_NAL_UNIT_TYPE_DPB,
+    h264_NAL_UNIT_TYPE_DPC,
+    h264_NAL_UNIT_TYPE_IDR,
+    h264_NAL_UNIT_TYPE_SEI,
+    h264_NAL_UNIT_TYPE_SPS,
+    h264_NAL_UNIT_TYPE_PPS,
+    h264_NAL_UNIT_TYPE_Acc_unit_delimiter,
+    h264_NAL_UNIT_TYPE_EOSeq,
+    h264_NAL_UNIT_TYPE_EOstream,
+    h264_NAL_UNIT_TYPE_filler_data,
+    h264_NAL_UNIT_TYPE_SPS_extension,
+    h264_NAL_UNIT_TYPE_ACP = 19,
+    h264_NAL_UNIT_TYPE_Slice_extension = 20
+} h264_nal_unit_type_t;
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+    : VideoDecoderAVC(mimeType){
+    mFrameSize     = 0;
+    mFrameData     = NULL;
+    mIsEncryptData = 0;
+    mClearData     = NULL;
+    mCachedHeader  = NULL;
+    setParserType(VBP_H264SECURE);
+    mFrameIdx = 0;
+    mModularMode = 0;
+    mSliceNum = 0;
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+    VTRACE("VideoDecoderAVCSecure::start");
+
+    Decode_Status status = VideoDecoderAVC::start(buffer);
+    if (status != DECODE_SUCCESS) {
+        return status;
+    }
+
+    mClearData = new uint8_t [MAX_NALU_HEADER_BUFFER];
+    if (mClearData == NULL) {
+        ETRACE("Failed to allocate memory for mClearData");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    mCachedHeader= new uint8_t [MAX_SLICEHEADER_BUFFER_SIZE];
+    if (mCachedHeader == NULL) {
+        ETRACE("Failed to allocate memory for mCachedHeader");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+    VTRACE("VideoDecoderAVCSecure::stop");
+    VideoDecoderAVC::stop();
+
+    if (mClearData) {
+        delete [] mClearData;
+        mClearData = NULL;
+    }
+
+    if (mCachedHeader) {
+        delete [] mCachedHeader;
+        mCachedHeader = NULL;
+    }
+}
+Decode_Status VideoDecoderAVCSecure::processModularInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data)
+{
+    VTRACE("processModularInputBuffer +++");
+    Decode_Status status;
+    int32_t clear_data_size = 0;
+    uint8_t *clear_data = NULL;
+
+    int32_t nalu_num = 0;
+    uint8_t nalu_type = 0;
+    int32_t nalu_offset = 0;
+    uint32_t nalu_size = 0;
+    uint8_t naluType = 0;
+    uint8_t *nalu_data = NULL;
+    uint32_t sliceidx = 0;
+
+    frame_info_t *pFrameInfo = NULL;
+    mSliceNum = 0;
+    memset(&mSliceInfo, 0, sizeof(mSliceInfo));
+    mIsEncryptData = 0;
+
+    if (buffer->flag & IS_SECURE_DATA) {
+        VTRACE("Decoding protected video ...");
+        pFrameInfo = (frame_info_t *) buffer->data;
+        if (pFrameInfo == NULL) {
+            ETRACE("Invalid parameter: pFrameInfo is NULL!");
+            return DECODE_MEMORY_FAIL;
+        }
+
+        mFrameData = pFrameInfo->data;
+        mFrameSize = pFrameInfo->size;
+        VTRACE("mFrameData = %p, mFrameSize = %d", mFrameData, mFrameSize);
+
+        nalu_num  = pFrameInfo->num_nalus;
+        VTRACE("nalu_num = %d", nalu_num);
+
+        if (nalu_num <= 0 || nalu_num >= MAX_NUM_NALUS) {
+            ETRACE("Invalid parameter: nalu_num = %d", nalu_num);
+            return DECODE_MEMORY_FAIL;
+        }
+
+        for (int32_t i = 0; i < nalu_num; i++) {
+
+            nalu_size = pFrameInfo->nalus[i].length;
+            nalu_type = pFrameInfo->nalus[i].type;
+            nalu_offset = pFrameInfo->nalus[i].offset;
+            nalu_data = pFrameInfo->nalus[i].data;
+            naluType  = nalu_type & NALU_TYPE_MASK;
+
+            VTRACE("nalu_type = 0x%x, nalu_size = %d, nalu_offset = 0x%x", nalu_type, nalu_size, nalu_offset);
+
+            if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+
+                mIsEncryptData = 1;
+                VTRACE("slice idx = %d", sliceidx);
+                mSliceInfo[sliceidx].sliceHeaderByte = nalu_type;
+                mSliceInfo[sliceidx].sliceStartOffset = (nalu_offset >> 4) << 4;
+                mSliceInfo[sliceidx].sliceByteOffset = nalu_offset - mSliceInfo[sliceidx].sliceStartOffset;
+                mSliceInfo[sliceidx].sliceLength = mSliceInfo[sliceidx].sliceByteOffset + nalu_size;
+                mSliceInfo[sliceidx].sliceSize = (mSliceInfo[sliceidx].sliceByteOffset + nalu_size + 0xF) & ~0xF;
+                VTRACE("sliceHeaderByte = 0x%x", mSliceInfo[sliceidx].sliceHeaderByte);
+                VTRACE("sliceStartOffset = %d", mSliceInfo[sliceidx].sliceStartOffset);
+                VTRACE("sliceByteOffset = %d", mSliceInfo[sliceidx].sliceByteOffset);
+                VTRACE("sliceSize = %d", mSliceInfo[sliceidx].sliceSize);
+                VTRACE("sliceLength = %d", mSliceInfo[sliceidx].sliceLength);
+#if 0
+                uint32_t testsize;
+                uint8_t *testdata;
+                testsize = mSliceInfo[sliceidx].sliceSize > 64 ? 64 : mSliceInfo[sliceidx].sliceSize ;
+                testdata = (uint8_t *)(mFrameData);
+                for (int i = 0; i < testsize; i++) {
+                    VTRACE("testdata[%d] = 0x%x", i, testdata[i]);
+                }
+#endif
+                sliceidx++;
+
+            } else if (naluType == h264_NAL_UNIT_TYPE_SPS || naluType == h264_NAL_UNIT_TYPE_PPS) {
+                if (nalu_data == NULL) {
+                    ETRACE("Invalid parameter: nalu_data = NULL for naluType 0x%x", naluType);
+                    return DECODE_MEMORY_FAIL;
+                }
+                memcpy(mClearData + clear_data_size,
+                    nalu_data,
+                    nalu_size);
+                clear_data_size += nalu_size;
+            } else {
+                ITRACE("Nalu type = 0x%x is skipped", naluType);
+                continue;
+            }
+        }
+        clear_data = mClearData;
+        mSliceNum = sliceidx;
+
+    } else {
+        VTRACE("Decoding clear video ...");
+        mIsEncryptData = 0;
+        mFrameSize = buffer->size;
+        mFrameData = buffer->data;
+        clear_data = buffer->data;
+        clear_data_size = buffer->size;
+    }
+
+    if (clear_data_size > 0) {
+        status =  VideoDecoderBase::parseBuffer(
+                clear_data,
+                clear_data_size,
+                false,
+                (void**)data);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+    } else {
+        status =  VideoDecoderBase::queryBuffer((void**)data);
+        CHECK_STATUS("VideoDecoderBase::queryBuffer");
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::processClassicInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data)
+{
+    Decode_Status status;
+    int32_t clear_data_size = 0;
+    uint8_t *clear_data = NULL;
+    uint8_t naluType = 0;
+
+    int32_t num_nalus;
+    int32_t nalu_offset;
+    int32_t offset;
+    uint8_t *data_src;
+    uint8_t *nalu_data;
+    uint32_t nalu_size;
+
+    if (buffer->flag & IS_SECURE_DATA) {
+        VTRACE("Decoding protected video ...");
+        mIsEncryptData = 1;
+
+        mFrameData = buffer->data;
+        mFrameSize = buffer->size;
+        VTRACE("mFrameData = %p, mFrameSize = %d", mFrameData, mFrameSize);
+        num_nalus  = *(uint32_t *)(buffer->data + buffer->size + sizeof(uint32_t));
+        VTRACE("num_nalus = %d", num_nalus);
+        offset = 4;
+        for (int32_t i = 0; i < num_nalus; i++) {
+            VTRACE("%d nalu, offset = %d", i, offset);
+            data_src = buffer->data + buffer->size + sizeof(uint32_t) + offset;
+            nalu_size = *(uint32_t *)(data_src + 2 * sizeof(uint32_t));
+            nalu_size = (nalu_size + 0x03) & (~0x03);
+
+            nalu_data = data_src + 3 *sizeof(uint32_t);
+            naluType  = nalu_data[0] & NALU_TYPE_MASK;
+            offset += nalu_size + 3 *sizeof(uint32_t);
+            VTRACE("naluType = 0x%x", naluType);
+            VTRACE("nalu_size = %d, nalu_data = %p", nalu_size, nalu_data);
+
+            if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+                ETRACE("Slice NALU received!");
+                return DECODE_INVALID_DATA;
+            }
+
+            else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
+                memcpy(mClearData + clear_data_size,
+                    startcodePrefix,
+                    STARTCODE_PREFIX_LEN);
+                clear_data_size += STARTCODE_PREFIX_LEN;
+                memcpy(mClearData + clear_data_size,
+                    nalu_data,
+                    nalu_size);
+                clear_data_size += nalu_size;
+            } else {
+                ETRACE("Failure: DECODE_FRAME_DROPPED");
+                return DECODE_FRAME_DROPPED;
+            }
+        }
+        clear_data = mClearData;
+    } else {
+        VTRACE("Decoding clear video ...");
+        mIsEncryptData = 0;
+        mFrameSize = buffer->size;
+        mFrameData = buffer->data;
+        clear_data = buffer->data;
+        clear_data_size = buffer->size;
+    }
+
+    if (clear_data_size > 0) {
+        status =  VideoDecoderBase::parseBuffer(
+                clear_data,
+                clear_data_size,
+                false,
+                (void**)data);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+    } else {
+        status =  VideoDecoderBase::queryBuffer((void**)data);
+        CHECK_STATUS("VideoDecoderBase::queryBuffer");
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+    VTRACE("VideoDecoderAVCSecure::decode");
+    Decode_Status status;
+    vbp_data_h264 *data = NULL;
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+
+#if 0
+    uint32_t testsize;
+    uint8_t *testdata;
+    testsize = buffer->size > 16 ? 16:buffer->size ;
+    testdata = (uint8_t *)(buffer->data);
+    for (int i = 0; i < 16; i++) {
+        VTRACE("testdata[%d] = 0x%x", i, testdata[i]);
+    }
+#endif
+    if (buffer->flag & IS_SUBSAMPLE_ENCRYPTION) {
+        mModularMode = 1;
+    }
+
+    if (mModularMode) {
+        status = processModularInputBuffer(buffer,&data);
+        CHECK_STATUS("processModularInputBuffer");
+    }
+    else {
+        status = processClassicInputBuffer(buffer,&data);
+        CHECK_STATUS("processClassicInputBuffer");
+    }
+
+    if (!mVAStarted) {
+         if (data->has_sps && data->has_pps) {
+            status = startVA(data);
+            CHECK_STATUS("startVA");
+        } else {
+            WTRACE("Can't start VA as either SPS or PPS is still not available.");
+            return DECODE_SUCCESS;
+        }
+    }
+
+    status = decodeFrame(buffer, data);
+
+    return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_h264 *data) {
+    VTRACE("VideoDecoderAVCSecure::decodeFrame");
+    Decode_Status status;
+    VTRACE("data->has_sps = %d, data->has_pps = %d", data->has_sps, data->has_pps);
+
+#if 0
+    // Don't remove the following codes, it can be enabled for debugging DPB.
+    for (unsigned int i = 0; i < data->num_pictures; i++) {
+        VAPictureH264 &pic = data->pic_data[i].pic_parms->CurrPic;
+        VTRACE("%d: decoding frame %.2f, poc top = %d, poc bottom = %d, flags = %d,  reference = %d",
+                i,
+                buffer->timeStamp/1E6,
+                pic.TopFieldOrderCnt,
+                pic.BottomFieldOrderCnt,
+                pic.flags,
+                (pic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+                (pic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE));
+    }
+#endif
+
+    if (data->new_sps || data->new_pps) {
+        status = handleNewSequence(data);
+        CHECK_STATUS("handleNewSequence");
+    }
+
+    if (mModularMode && (!mIsEncryptData)) {
+        if (data->pic_data[0].num_slices == 0) {
+            ITRACE("No slice available for decoding.");
+            status = mSizeChanged ? DECODE_FORMAT_CHANGE : DECODE_SUCCESS;
+            mSizeChanged = false;
+            return status;
+        }
+    }
+
+    uint64_t lastPTS = mCurrentPTS;
+    mCurrentPTS = buffer->timeStamp;
+
+    // start decoding a new frame
+    status = acquireSurfaceBuffer();
+    CHECK_STATUS("acquireSurfaceBuffer");
+
+    if (mModularMode) {
+        parseModularSliceHeader(buffer,data);
+    }
+    else {
+        parseClassicSliceHeader(buffer,data);
+    }
+
+    if (status != DECODE_SUCCESS) {
+        endDecodingFrame(true);
+        return status;
+    }
+
+    status = beginDecodingFrame(data);
+    CHECK_STATUS("beginDecodingFrame");
+
+   // finish decoding the last frame
+    status = endDecodingFrame(false);
+    CHECK_STATUS("endDecodingFrame");
+
+    if (isNewFrame(data, lastPTS == mCurrentPTS) == 0) {
+        ETRACE("Can't handle interlaced frames yet");
+        return DECODE_FAIL;
+    }
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::beginDecodingFrame(vbp_data_h264 *data) {
+    VTRACE("VideoDecoderAVCSecure::beginDecodingFrame");
+    Decode_Status status;
+    VAPictureH264 *picture = &(data->pic_data[0].pic_parms->CurrPic);
+    if ((picture->flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+        (picture->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)) {
+        mAcquiredBuffer->referenceFrame = true;
+    } else {
+        mAcquiredBuffer->referenceFrame = false;
+    }
+
+    if (picture->flags & VA_PICTURE_H264_TOP_FIELD) {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD | VA_TOP_FIELD;
+    } else {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
+    }
+
+    mAcquiredBuffer->renderBuffer.flag = 0;
+    mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
+    mAcquiredBuffer->pictureOrder = getPOC(picture);
+
+    if (mSizeChanged) {
+        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
+        mSizeChanged = false;
+    }
+
+    status  = continueDecodingFrame(data);
+    return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::continueDecodingFrame(vbp_data_h264 *data) {
+    VTRACE("VideoDecoderAVCSecure::continueDecodingFrame");
+    Decode_Status status;
+    vbp_picture_data_h264 *picData = data->pic_data;
+
+    if (mAcquiredBuffer == NULL || mAcquiredBuffer->renderBuffer.surface == VA_INVALID_SURFACE) {
+        ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
+        return DECODE_FAIL;
+    }
+    VTRACE("data->num_pictures = %d", data->num_pictures);
+    for (uint32_t picIndex = 0; picIndex < data->num_pictures; picIndex++, picData++) {
+        if (picData == NULL || picData->pic_parms == NULL || picData->slc_data == NULL || picData->num_slices == 0) {
+            return DECODE_PARSER_FAIL;
+        }
+
+        if (picIndex > 0 &&
+            (picData->pic_parms->CurrPic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) == 0) {
+            ETRACE("Packed frame is not supported yet!");
+            return DECODE_FAIL;
+        }
+        VTRACE("picData->num_slices = %d", picData->num_slices);
+        for (uint32_t sliceIndex = 0; sliceIndex < picData->num_slices; sliceIndex++) {
+            status = decodeSlice(data, picIndex, sliceIndex);
+            if (status != DECODE_SUCCESS) {
+                endDecodingFrame(true);
+                // remove current frame from DPB as it can't be decoded.
+                removeReferenceFromDPB(picData->pic_parms);
+                return status;
+            }
+        }
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::parseClassicSliceHeader(VideoDecodeBuffer *buffer, vbp_data_h264 *data) {
+    Decode_Status status;
+    VAStatus vaStatus;
+
+    VABufferID sliceheaderbufferID;
+    VABufferID pictureparameterparsingbufferID;
+    VABufferID mSlicebufferID;
+
+    if (mFrameSize <= 0) {
+        return DECODE_SUCCESS;
+    }
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_VA_STATUS("vaBeginPicture");
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VAParseSliceHeaderGroupBufferType,
+        MAX_SLICEHEADER_BUFFER_SIZE,
+        1,
+        NULL,
+        &sliceheaderbufferID);
+    CHECK_VA_STATUS("vaCreateSliceHeaderGroupBuffer");
+
+    void *sliceheaderbuf;
+    vaStatus = vaMapBuffer(
+        mVADisplay,
+        sliceheaderbufferID,
+        &sliceheaderbuf);
+    CHECK_VA_STATUS("vaMapBuffer");
+
+    memset(sliceheaderbuf, 0, MAX_SLICEHEADER_BUFFER_SIZE);
+
+    vaStatus = vaUnmapBuffer(
+        mVADisplay,
+        sliceheaderbufferID);
+    CHECK_VA_STATUS("vaUnmapBuffer");
+
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceDataBufferType,
+        mFrameSize, //size
+        1,        //num_elements
+        mFrameData,
+        &mSlicebufferID);
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+    data->pic_parse_buffer->frame_buf_id = mSlicebufferID;
+    data->pic_parse_buffer->slice_headers_buf_id = sliceheaderbufferID;
+    data->pic_parse_buffer->frame_size = mFrameSize;
+    data->pic_parse_buffer->slice_headers_size = MAX_SLICEHEADER_BUFFER_SIZE;
+
+#if 0
+
+    VTRACE("flags.bits.frame_mbs_only_flag = %d", data->pic_parse_buffer->flags.bits.frame_mbs_only_flag);
+    VTRACE("flags.bits.pic_order_present_flag = %d", data->pic_parse_buffer->flags.bits.pic_order_present_flag);
+    VTRACE("flags.bits.delta_pic_order_always_zero_flag = %d", data->pic_parse_buffer->flags.bits.delta_pic_order_always_zero_flag);
+    VTRACE("flags.bits.redundant_pic_cnt_present_flag = %d", data->pic_parse_buffer->flags.bits.redundant_pic_cnt_present_flag);
+    VTRACE("flags.bits.weighted_pred_flag = %d", data->pic_parse_buffer->flags.bits.weighted_pred_flag);
+    VTRACE("flags.bits.entropy_coding_mode_flag = %d", data->pic_parse_buffer->flags.bits.entropy_coding_mode_flag);
+    VTRACE("flags.bits.deblocking_filter_control_present_flag = %d", data->pic_parse_buffer->flags.bits.deblocking_filter_control_present_flag);
+    VTRACE("flags.bits.weighted_bipred_idc = %d", data->pic_parse_buffer->flags.bits.weighted_bipred_idc);
+
+    VTRACE("pic_parse_buffer->expected_pic_parameter_set_id = %d", data->pic_parse_buffer->expected_pic_parameter_set_id);
+    VTRACE("pic_parse_buffer->num_slice_groups_minus1 = %d", data->pic_parse_buffer->num_slice_groups_minus1);
+    VTRACE("pic_parse_buffer->chroma_format_idc = %d", data->pic_parse_buffer->chroma_format_idc);
+    VTRACE("pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4 = %d", data->pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4);
+    VTRACE("pic_parse_buffer->pic_order_cnt_type = %d", data->pic_parse_buffer->pic_order_cnt_type);
+    VTRACE("pic_parse_buffer->residual_colour_transform_flag = %d", data->pic_parse_buffer->residual_colour_transform_flag);
+    VTRACE("pic_parse_buffer->num_ref_idc_l0_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l0_active_minus1);
+    VTRACE("pic_parse_buffer->num_ref_idc_l1_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l1_active_minus1);
+#endif
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VAParsePictureParameterBufferType,
+        sizeof(VAParsePictureParameterBuffer),
+        1,
+        data->pic_parse_buffer,
+        &pictureparameterparsingbufferID);
+    CHECK_VA_STATUS("vaCreatePictureParameterParsingBuffer");
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        &pictureparameterparsingbufferID,
+        1);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    vaStatus = vaMapBuffer(
+        mVADisplay,
+        sliceheaderbufferID,
+        &sliceheaderbuf);
+    CHECK_VA_STATUS("vaMapBuffer");
+
+    status = updateSliceParameter(data,sliceheaderbuf);
+    CHECK_STATUS("processSliceHeader");
+
+    vaStatus = vaUnmapBuffer(
+        mVADisplay,
+        sliceheaderbufferID);
+    CHECK_VA_STATUS("vaUnmapBuffer");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::parseModularSliceHeader(VideoDecodeBuffer *buffer, vbp_data_h264 *data) {
+    Decode_Status status;
+    VAStatus vaStatus;
+
+    VABufferID sliceheaderbufferID;
+    VABufferID pictureparameterparsingbufferID;
+    VABufferID mSlicebufferID;
+    int32_t sliceIdx;
+
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_VA_STATUS("vaBeginPicture");
+
+    if (mFrameSize <= 0 || mSliceNum <=0) {
+        return DECODE_SUCCESS;
+    }
+    void *sliceheaderbuf;
+    memset(mCachedHeader, 0, MAX_SLICEHEADER_BUFFER_SIZE);
+    int32_t offset = 0;
+    int32_t size = 0;
+
+    for (sliceIdx = 0; sliceIdx < mSliceNum; sliceIdx++) {
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAParseSliceHeaderGroupBufferType,
+            MAX_SLICEHEADER_BUFFER_SIZE,
+            1,
+            NULL,
+            &sliceheaderbufferID);
+        CHECK_VA_STATUS("vaCreateSliceHeaderGroupBuffer");
+
+        vaStatus = vaMapBuffer(
+            mVADisplay,
+            sliceheaderbufferID,
+            &sliceheaderbuf);
+        CHECK_VA_STATUS("vaMapBuffer");
+
+        memset(sliceheaderbuf, 0, MAX_SLICEHEADER_BUFFER_SIZE);
+
+        vaStatus = vaUnmapBuffer(
+            mVADisplay,
+            sliceheaderbufferID);
+        CHECK_VA_STATUS("vaUnmapBuffer");
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VASliceDataBufferType,
+            mSliceInfo[sliceIdx].sliceSize, //size
+            1,        //num_elements
+            mFrameData + mSliceInfo[sliceIdx].sliceStartOffset,
+            &mSlicebufferID);
+        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+        data->pic_parse_buffer->frame_buf_id = mSlicebufferID;
+        data->pic_parse_buffer->slice_headers_buf_id = sliceheaderbufferID;
+        data->pic_parse_buffer->frame_size = mSliceInfo[sliceIdx].sliceLength;
+        data->pic_parse_buffer->slice_headers_size = MAX_SLICEHEADER_BUFFER_SIZE;
+        data->pic_parse_buffer->nalu_header.value = mSliceInfo[sliceIdx].sliceHeaderByte;
+        data->pic_parse_buffer->slice_offset = mSliceInfo[sliceIdx].sliceByteOffset;
+
+#if 0
+        VTRACE("data->pic_parse_buffer->slice_offset = 0x%x", data->pic_parse_buffer->slice_offset);
+        VTRACE("pic_parse_buffer->nalu_header.value = %x", data->pic_parse_buffer->nalu_header.value = mSliceInfo[sliceIdx].sliceHeaderByte);
+        VTRACE("flags.bits.frame_mbs_only_flag = %d", data->pic_parse_buffer->flags.bits.frame_mbs_only_flag);
+        VTRACE("flags.bits.pic_order_present_flag = %d", data->pic_parse_buffer->flags.bits.pic_order_present_flag);
+        VTRACE("flags.bits.delta_pic_order_always_zero_flag = %d", data->pic_parse_buffer->flags.bits.delta_pic_order_always_zero_flag);
+        VTRACE("flags.bits.redundant_pic_cnt_present_flag = %d", data->pic_parse_buffer->flags.bits.redundant_pic_cnt_present_flag);
+        VTRACE("flags.bits.weighted_pred_flag = %d", data->pic_parse_buffer->flags.bits.weighted_pred_flag);
+        VTRACE("flags.bits.entropy_coding_mode_flag = %d", data->pic_parse_buffer->flags.bits.entropy_coding_mode_flag);
+        VTRACE("flags.bits.deblocking_filter_control_present_flag = %d", data->pic_parse_buffer->flags.bits.deblocking_filter_control_present_flag);
+        VTRACE("flags.bits.weighted_bipred_idc = %d", data->pic_parse_buffer->flags.bits.weighted_bipred_idc);
+        VTRACE("pic_parse_buffer->expected_pic_parameter_set_id = %d", data->pic_parse_buffer->expected_pic_parameter_set_id);
+        VTRACE("pic_parse_buffer->num_slice_groups_minus1 = %d", data->pic_parse_buffer->num_slice_groups_minus1);
+        VTRACE("pic_parse_buffer->chroma_format_idc = %d", data->pic_parse_buffer->chroma_format_idc);
+        VTRACE("pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4 = %d", data->pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4);
+        VTRACE("pic_parse_buffer->pic_order_cnt_type = %d", data->pic_parse_buffer->pic_order_cnt_type);
+        VTRACE("pic_parse_buffer->residual_colour_transform_flag = %d", data->pic_parse_buffer->residual_colour_transform_flag);
+        VTRACE("pic_parse_buffer->num_ref_idc_l0_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l0_active_minus1);
+        VTRACE("pic_parse_buffer->num_ref_idc_l1_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l1_active_minus1);
+#endif
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAParsePictureParameterBufferType,
+            sizeof(VAParsePictureParameterBuffer),
+            1,
+            data->pic_parse_buffer,
+            &pictureparameterparsingbufferID);
+        CHECK_VA_STATUS("vaCreatePictureParameterParsingBuffer");
+
+        vaStatus = vaRenderPicture(
+            mVADisplay,
+            mVAContext,
+            &pictureparameterparsingbufferID,
+            1);
+        CHECK_VA_STATUS("vaRenderPicture");
+
+        vaStatus = vaMapBuffer(
+            mVADisplay,
+            sliceheaderbufferID,
+            &sliceheaderbuf);
+        CHECK_VA_STATUS("vaMapBuffer");
+
+        size = *(uint32 *)((uint8 *)sliceheaderbuf + 4) + 4;
+        VTRACE("slice header size = 0x%x, offset = 0x%x", size, offset);
+        if (offset + size <= MAX_SLICEHEADER_BUFFER_SIZE - 4) {
+            memcpy(mCachedHeader+offset, sliceheaderbuf, size);
+            offset += size;
+        } else {
+            WTRACE("Cached slice header is not big enough!");
+        }
+        vaStatus = vaUnmapBuffer(
+            mVADisplay,
+            sliceheaderbufferID);
+        CHECK_VA_STATUS("vaUnmapBuffer");
+    }
+    memset(mCachedHeader + offset, 0xFF, 4);
+    status = updateSliceParameter(data,mCachedHeader);
+    CHECK_STATUS("processSliceHeader");
+    return DECODE_SUCCESS;
+}
+
+
+Decode_Status VideoDecoderAVCSecure::updateSliceParameter(vbp_data_h264 *data, void *sliceheaderbuf) {
+    VTRACE("VideoDecoderAVCSecure::updateSliceParameter");
+    Decode_Status status;
+    status =  VideoDecoderBase::updateBuffer(
+            (uint8_t *)sliceheaderbuf,
+            MAX_SLICEHEADER_BUFFER_SIZE,
+            (void**)&data);
+    CHECK_STATUS("updateBuffer");
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 3 buffers to render a slice: picture parameter, IQMatrix, slice parameter
+    VABufferID bufferIDs[3];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+    uint32_t slice_data_size = 0;
+    uint8_t* slice_data_addr = NULL;
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+        }
+        VTRACE("Current frameidx = %d", mFrameIdx++);
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+        //We have to provide a hacked DPB rather than complete DPB for libva as workaround
+        status = updateReferenceFrames(picData);
+        CHECK_STATUS("updateReferenceFrames");
+
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+    }
+
+    status = setReference(sliceParam);
+    CHECK_STATUS("setReference");
+
+    if (mModularMode) {
+        if (mIsEncryptData) {
+            sliceParam->slice_data_size = mSliceInfo[sliceIndex].sliceSize;
+            slice_data_size = mSliceInfo[sliceIndex].sliceSize;
+            slice_data_addr = mFrameData + mSliceInfo[sliceIndex].sliceStartOffset;
+        } else {
+            slice_data_size = sliceData->slice_size;
+            slice_data_addr = sliceData->buffer_addr + sliceData->slice_offset;
+        }
+    } else {
+        sliceParam->slice_data_size = mFrameSize;
+        slice_data_size = mFrameSize;
+        slice_data_addr = mFrameData;
+    }
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    VABufferID slicebufferID;
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceDataBufferType,
+        slice_data_size, //size
+        1,        //num_elements
+        slice_data_addr,
+        &slicebufferID);
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        &slicebufferID,
+        1);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+
+}
+
+Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
+    VAProfile profile, VAConfigID *config)
+{
+    VAStatus vaStatus;
+    VAConfigAttrib attrib[2];
+
+    if (config == NULL) {
+        ETRACE("Invalid parameter!");
+        return DECODE_FAIL;
+    }
+
+    attrib[0].type = VAConfigAttribRTFormat;
+    attrib[0].value = VA_RT_FORMAT_YUV420;
+    attrib[1].type = VAConfigAttribDecSliceMode;
+    attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+    if (mModularMode) {
+        attrib[1].value = VA_DEC_SLICE_MODE_SUBSAMPLE;
+    }
+
+    vaStatus = vaCreateConfig(
+            mVADisplay,
+            profile,
+            VAEntrypointVLD,
+            &attrib[0],
+            2,
+            config);
+    CHECK_VA_STATUS("vaCreateConfig");
+
+    return DECODE_SUCCESS;
+}
diff --git a/videodecoder/securevideo/merrifield/VideoDecoderAVCSecure.h b/videodecoder/securevideo/merrifield/VideoDecoderAVCSecure.h
new file mode 100755
index 0000000..d4a9f15
--- /dev/null
+++ b/videodecoder/securevideo/merrifield/VideoDecoderAVCSecure.h
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_SECURE_H
+#define VIDEO_DECODER_AVC_SECURE_H
+
+#include "VideoDecoderBase.h"
+#include "VideoDecoderAVC.h"
+#include "VideoDecoderDefs.h"
+
+class VideoDecoderAVCSecure : public VideoDecoderAVC {
+public:
+    VideoDecoderAVCSecure(const char *mimeType);
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+
+    // data in the decoded buffer is all encrypted.
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+protected:
+    virtual Decode_Status decodeFrame(VideoDecodeBuffer *buffer, vbp_data_h264 *data);
+    virtual Decode_Status continueDecodingFrame(vbp_data_h264 *data);
+    virtual Decode_Status beginDecodingFrame(vbp_data_h264 *data);
+    virtual Decode_Status getCodecSpecificConfigs(VAProfile profile, VAConfigID*config);
+    Decode_Status parseClassicSliceHeader(VideoDecodeBuffer *buffer, vbp_data_h264 *data);
+    Decode_Status parseModularSliceHeader(VideoDecodeBuffer *buffer, vbp_data_h264 *data);
+
+    Decode_Status updateSliceParameter(vbp_data_h264 *data, void *sliceheaderbuf);
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+private:
+    Decode_Status processClassicInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data);
+    Decode_Status processModularInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data);
+    int32_t     mIsEncryptData;
+    int32_t     mFrameSize;
+    uint8_t*    mFrameData;
+    uint8_t*    mClearData;
+    uint8_t*    mCachedHeader;
+    int32_t     mFrameIdx;
+    int32_t     mModularMode;
+
+    enum {
+        MAX_SLICE_HEADER_NUM  = 256,
+    };
+    int32_t     mSliceNum;
+    // Information of Slices in the Modular DRM Mode
+    struct SliceInfo {
+        uint8_t     sliceHeaderByte;             //  first byte of the slice header
+        uint32_t    sliceStartOffset;            // offset of Slice unit in the firewalled buffer
+        uint32_t    sliceByteOffset;             // extra offset from the blockAligned slice offset
+        uint32_t    sliceSize;                   // block aligned length of slice unit
+        uint32_t    sliceLength;                 // actual size of the slice
+    };
+
+    SliceInfo mSliceInfo[MAX_SLICE_HEADER_NUM];
+};
+
+#endif
diff --git a/videodecoder/securevideo/merrifield/VideoFrameInfo.h b/videodecoder/securevideo/merrifield/VideoFrameInfo.h
new file mode 100755
index 0000000..485b0da
--- /dev/null
+++ b/videodecoder/securevideo/merrifield/VideoFrameInfo.h
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_FRAME_INFO_H_
+#define VIDEO_FRAME_INFO_H_
+
+#define MAX_NUM_NALUS 16
+
+typedef struct {
+    uint8_t  type;      // nalu type + nal_ref_idc
+    uint32_t offset;    // offset to the pointer of the encrypted data
+    uint8_t* data;      // if the nalu is encrypted, this field is useless; if current NALU is SPS/PPS, data is the pointer to clear SPS/PPS data
+    uint32_t length;    // nalu length
+} nalu_info_t;
+
+typedef struct {
+    uint8_t* data;      // pointer to the encrypted data
+    uint32_t size;      // encrypted data size
+    uint32_t num_nalus; // number of NALU
+    nalu_info_t nalus[MAX_NUM_NALUS];
+} frame_info_t;
+
+#endif
diff --git a/videodecoder/securevideo/merrplus/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/merrplus/VideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..38039e2
--- /dev/null
+++ b/videodecoder/securevideo/merrplus/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,510 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoDecoderAVCSecure.h"
+#include "VideoDecoderTrace.h"
+#include <string.h>
+
+
+#define STARTCODE_00                0x00
+#define STARTCODE_01                0x01
+#define STARTCODE_PREFIX_LEN        3
+#define NALU_TYPE_MASK              0x1F
+
+
+// mask for little endian, to mast the second and fourth bytes in the byte stream
+#define STARTCODE_MASK0             0xFF000000 //0x00FF0000
+#define STARTCODE_MASK1             0x0000FF00  //0x000000FF
+
+
+typedef enum {
+    NAL_UNIT_TYPE_unspecified0 = 0,
+    NAL_UNIT_TYPE_SLICE,
+    NAL_UNIT_TYPE_DPA,
+    NAL_UNIT_TYPE_DPB,
+    NAL_UNIT_TYPE_DPC,
+    NAL_UNIT_TYPE_IDR,
+    NAL_UNIT_TYPE_SEI,
+    NAL_UNIT_TYPE_SPS,
+    NAL_UNIT_TYPE_PPS,
+    NAL_UNIT_TYPE_Acc_unit_delimiter,
+    NAL_UNIT_TYPE_EOSeq,
+    NAL_UNIT_TYPE_EOstream,
+    NAL_UNIT_TYPE_filler_data,
+    NAL_UNIT_TYPE_SPS_extension,
+    NAL_UNIT_TYPE_Reserved14,
+    NAL_UNIT_TYPE_Reserved15,
+    NAL_UNIT_TYPE_Reserved16,
+    NAL_UNIT_TYPE_Reserved17,
+    NAL_UNIT_TYPE_Reserved18,
+    NAL_UNIT_TYPE_ACP,
+    NAL_UNIT_TYPE_Reserved20,
+    NAL_UNIT_TYPE_Reserved21,
+    NAL_UNIT_TYPE_Reserved22,
+    NAL_UNIT_TYPE_Reserved23,
+    NAL_UNIT_TYPE_unspecified24,
+} NAL_UNIT_TYPE;
+
+#ifndef min
+#define min(X, Y)  ((X) <(Y) ? (X) : (Y))
+#endif
+
+
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+    : VideoDecoderAVC(mimeType),
+      mNaluHeaderBuffer(NULL),
+      mInputBuffer(NULL) {
+
+    memset(&mMetadata, 0, sizeof(NaluMetadata));
+    memset(&mByteStream, 0, sizeof(NaluByteStream));
+}
+
+VideoDecoderAVCSecure::~VideoDecoderAVCSecure() {
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+    Decode_Status status = VideoDecoderAVC::start(buffer);
+    if (status != DECODE_SUCCESS) {
+        return status;
+    }
+
+    mMetadata.naluInfo = new NaluInfo [MAX_NALU_NUMBER];
+    mByteStream.byteStream = new uint8_t [MAX_NALU_HEADER_BUFFER];
+    mNaluHeaderBuffer = new uint8_t [MAX_NALU_HEADER_BUFFER];
+
+    if (mMetadata.naluInfo == NULL ||
+        mByteStream.byteStream == NULL ||
+        mNaluHeaderBuffer == NULL) {
+        ETRACE("Failed to allocate memory.");
+        // TODO: release all allocated memory
+        return DECODE_MEMORY_FAIL;
+    }
+    return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+    VideoDecoderAVC::stop();
+
+    if (mMetadata.naluInfo) {
+        delete [] mMetadata.naluInfo;
+        mMetadata.naluInfo = NULL;
+    }
+
+    if (mByteStream.byteStream) {
+        delete [] mByteStream.byteStream;
+        mByteStream.byteStream = NULL;
+    }
+
+    if (mNaluHeaderBuffer) {
+        delete [] mNaluHeaderBuffer;
+        mNaluHeaderBuffer = NULL;
+    }
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+    Decode_Status status;
+    int32_t sizeAccumulated = 0;
+    int32_t sizeLeft = 0;
+    uint8_t *pByteStream = NULL;
+    NaluInfo *pNaluInfo = mMetadata.naluInfo;
+
+    if (buffer->flag & IS_SECURE_DATA) {
+        // NALU headers are appended to encrypted video bitstream
+        // |...encrypted video bitstream (16 bytes aligned)...| 4 bytes of header size |...NALU headers..|
+        pByteStream = buffer->data + buffer->size + 4;
+        sizeLeft = *(int32_t *)(buffer->data + buffer->size);
+        VTRACE("%s sizeLeft: %d buffer->size: %#x", __func__, sizeLeft, buffer->size);
+        mInputBuffer = buffer->data;
+    } else {
+        status = parseAnnexBStream(buffer->data, buffer->size, &mByteStream);
+        CHECK_STATUS("parseAnnexBStream");
+        pByteStream = mByteStream.byteStream;
+        sizeLeft = mByteStream.streamPos;
+        mInputBuffer = buffer->data;
+    }
+    if (sizeLeft < 4) {
+        ETRACE("Not enough data to read number of NALU.");
+        return DECODE_INVALID_DATA;
+    }
+
+    // read number of NALU
+    memcpy(&(mMetadata.naluNumber), pByteStream, sizeof(int32_t));
+    pByteStream += 4;
+    sizeLeft -= 4;
+
+    if (mMetadata.naluNumber == 0) {
+        WTRACE("Number of NALU is ZERO!");
+        return DECODE_SUCCESS;
+    }
+
+    for (int32_t i = 0; i < mMetadata.naluNumber; i++) {
+        if (sizeLeft < 12) {
+            ETRACE("Not enough data to parse NALU offset, size, header length for NALU %d, left = %d", i, sizeLeft);
+            return DECODE_INVALID_DATA;
+        }
+        sizeLeft -= 12;
+        // read NALU offset
+        memcpy(&(pNaluInfo->naluOffset), pByteStream, sizeof(int32_t));
+        pByteStream += 4;
+
+        // read NALU size
+        memcpy(&(pNaluInfo->naluLen), pByteStream, sizeof(int32_t));
+        pByteStream += 4;
+
+        // read NALU header length
+        memcpy(&(pNaluInfo->naluHeaderLen), pByteStream, sizeof(int32_t));
+        pByteStream += 4;
+
+
+        if (sizeLeft < pNaluInfo->naluHeaderLen) {
+            ETRACE("Not enough data to copy NALU header for %d, left = %d, header len = %d", i, sizeLeft, pNaluInfo->naluHeaderLen);
+            return DECODE_INVALID_DATA;
+        }
+
+        sizeLeft -=  pNaluInfo->naluHeaderLen;
+
+        if (pNaluInfo->naluHeaderLen) {
+            // copy start code prefix to buffer
+            memcpy(mNaluHeaderBuffer + sizeAccumulated,
+                startcodePrefix,
+                STARTCODE_PREFIX_LEN);
+            sizeAccumulated += STARTCODE_PREFIX_LEN;
+
+            // copy NALU header
+            memcpy(mNaluHeaderBuffer + sizeAccumulated, pByteStream, pNaluInfo->naluHeaderLen);
+            pByteStream += pNaluInfo->naluHeaderLen;
+
+            sizeAccumulated += pNaluInfo->naluHeaderLen;
+        } else {
+            WTRACE("header len is zero for NALU %d", i);
+        }
+
+        // for next NALU
+        pNaluInfo++;
+    }
+
+    buffer->data = mNaluHeaderBuffer;
+    buffer->size = sizeAccumulated;
+
+    return VideoDecoderAVC::decode(buffer);
+}
+
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data
+    VABufferID bufferIDs[4];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+            // TODO: handle the first slice lost
+        }
+        if (mDecodingFrame) {
+            // interlace content, complete decoding the first field
+            vaStatus = vaEndPicture(mVADisplay, mVAContext);
+            CHECK_VA_STATUS("vaEndPicture");
+
+            // for interlace content, top field may be valid only after the second field is parsed
+            mAcquiredBuffer->pictureOrder= picParam->CurrPic.TopFieldOrderCnt;
+        }
+
+        // Check there is no reference frame loss before decoding a frame
+
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+        //We have to provide a hacked DPB rather than complete DPB for libva as workaround
+        status = updateReferenceFrames(picData);
+        CHECK_STATUS("updateReferenceFrames");
+
+        vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+        CHECK_VA_STATUS("vaBeginPicture");
+
+        // start decoding a frame
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+    }
+
+    status = setReference(sliceParam);
+    CHECK_STATUS("setReference");
+
+    // find which naluinfo is correlated to current slice
+    int naluIndex = 0;
+    uint32_t accumulatedHeaderLen = 0;
+    uint32_t headerLen = 0;
+    for (; naluIndex < mMetadata.naluNumber; naluIndex++)  {
+        headerLen = mMetadata.naluInfo[naluIndex].naluHeaderLen;
+        if (headerLen == 0) {
+            WTRACE("lenght of current NAL unit is 0.");
+            continue;
+        }
+        accumulatedHeaderLen += STARTCODE_PREFIX_LEN;
+        if (accumulatedHeaderLen + headerLen > sliceData->slice_offset) {
+            break;
+        }
+        accumulatedHeaderLen += headerLen;
+    }
+
+    if (sliceData->slice_offset != accumulatedHeaderLen) {
+        WTRACE("unexpected slice offset %d, accumulatedHeaderLen = %d", sliceData->slice_offset, accumulatedHeaderLen);
+    }
+
+    sliceParam->slice_data_size = mMetadata.naluInfo[naluIndex].naluLen;
+    uint32_t sliceOffset = mMetadata.naluInfo[naluIndex].naluOffset;
+    uint32_t slice_offset_shift =  sliceOffset % 16;
+    sliceParam->slice_data_offset += slice_offset_shift;
+    sliceData->slice_size = (sliceParam->slice_data_size + slice_offset_shift + 0xF) & ~0xF;
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    // sliceData->slice_offset - accumulatedHeaderLen is the absolute offset to start codes of current NAL unit
+    // offset points to first byte of NAL unit
+
+    if (mInputBuffer != NULL) {
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VASliceDataBufferType,
+            sliceData->slice_size,  //Slice size
+            1,                      // num_elements
+            mInputBuffer + sliceOffset - slice_offset_shift,
+            &bufferIDs[bufferIDCount]);
+    } else {
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAProtectedSliceDataBufferType,
+            sliceData->slice_size, //size
+            1,        //num_elements
+            (uint8_t*)sliceOffset, // IMR offset
+            &bufferIDs[bufferIDCount]);
+    }
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+}
+
+
+// Parse byte string pattern "0x000001" (3 bytes)  in the current buffer.
+// Returns offset of position following  the pattern in the buffer if pattern is found or -1 if not found.
+int32_t VideoDecoderAVCSecure::findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length) {
+    uint8_t *ptr;
+    uint32_t left = 0, data = 0, phase = 0;
+    uint8_t mask1 = 0, mask2 = 0;
+
+    /* Meaning of phase:
+        0: initial status, "0x000001" bytes are not found so far;
+        1: one "0x00" byte is found;
+        2: two or more consecutive "0x00" bytes" are found;
+        3: "0x000001" patten is found ;
+        4: if there is one more byte after "0x000001";
+       */
+
+    left = length;
+    ptr = (uint8_t *) (stream + offset);
+    phase = 0;
+
+    // parse until there is more data and start code not found
+    while ((left > 0) && (phase < 3)) {
+        // Check if the address is 32-bit aligned & phase=0, if thats the case we can check 4 bytes instead of one byte at a time.
+        if (((((uint32_t)ptr) & 0x3) == 0) && (phase == 0)) {
+            while (left > 3) {
+                data = *((uint32_t *)ptr);
+                mask1 = (STARTCODE_00 != (data & STARTCODE_MASK0));
+                mask2 = (STARTCODE_00 != (data & STARTCODE_MASK1));
+                // If second byte and fourth byte are not zero's then we cannot have a start code here,
+                //  as we need two consecutive zero bytes for a start code pattern.
+                if (mask1 && mask2) {
+                    // skip 4 bytes and start over
+                    ptr += 4;
+                    left -=4;
+                    continue;
+                } else {
+                    break;
+                }
+            }
+        }
+
+        // At this point either data is not on a 32-bit boundary or phase > 0 so we look at one byte at a time
+        if (left > 0) {
+            if (*ptr == STARTCODE_00) {
+                phase++;
+                if (phase > 2) {
+                    // more than 2 consecutive '0x00' bytes is found
+                    phase = 2;
+                }
+            } else if ((*ptr == STARTCODE_01) && (phase == 2)) {
+                // start code is found
+                phase = 3;
+            } else {
+                // reset lookup
+                phase = 0;
+            }
+            ptr++;
+            left--;
+        }
+    }
+
+    if ((left > 0) && (phase == 3)) {
+        phase = 4;
+        // return offset of position following the pattern in the buffer which matches "0x000001" byte string
+        return (int32_t)(ptr - stream);
+    }
+    return -1;
+}
+
+
+Decode_Status VideoDecoderAVCSecure::copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream) {
+    uint8_t naluType;
+    int32_t naluHeaderLen;
+
+    naluType = *(uint8_t *)(stream + naluStream->naluOffset);
+    naluType &= NALU_TYPE_MASK;
+    // first update nalu header length based on nalu type
+    if (naluType >= NAL_UNIT_TYPE_SLICE && naluType <= NAL_UNIT_TYPE_IDR) {
+        // coded slice, return only up to MAX_SLICE_HEADER_SIZE bytes
+        naluHeaderLen = min(naluStream->naluLen, MAX_SLICE_HEADER_SIZE);
+    } else if (naluType >= NAL_UNIT_TYPE_SEI && naluType <= NAL_UNIT_TYPE_PPS) {
+        //sps, pps, sei, etc, return the entire NAL unit in clear
+        naluHeaderLen = naluStream->naluLen;
+    } else {
+        return DECODE_FRAME_DROPPED;
+    }
+
+    memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluOffset), sizeof(int32_t));
+    naluStream->streamPos += 4;
+
+    memcpy(naluStream->byteStream + naluStream->streamPos, &(naluStream->naluLen), sizeof(int32_t));
+    naluStream->streamPos += 4;
+
+    memcpy(naluStream->byteStream + naluStream->streamPos, &naluHeaderLen, sizeof(int32_t));
+    naluStream->streamPos += 4;
+
+    if (naluHeaderLen) {
+        memcpy(naluStream->byteStream + naluStream->streamPos, (uint8_t*)(stream + naluStream->naluOffset), naluHeaderLen);
+        naluStream->streamPos += naluHeaderLen;
+    }
+    return DECODE_SUCCESS;
+}
+
+
+// parse start-code prefixed stream, also knowns as Annex B byte stream, commonly used in AVI, ES, MPEG2 TS container
+Decode_Status VideoDecoderAVCSecure::parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream) {
+    int32_t naluOffset, offset, left;
+    NaluInfo *info;
+    uint32_t ret = DECODE_SUCCESS;
+
+    naluOffset = 0;
+    offset = 0;
+    left = length;
+
+    // leave 4 bytes to copy nalu count
+    naluStream->streamPos = 4;
+    naluStream->naluCount = 0;
+    memset(naluStream->byteStream, 0, MAX_NALU_HEADER_BUFFER);
+
+    for (; ;) {
+        naluOffset = findNalUnitOffset(stream, offset, left);
+        if (naluOffset == -1) {
+            break;
+        }
+
+        if (naluStream->naluCount == 0) {
+            naluStream->naluOffset = naluOffset;
+        } else {
+            naluStream->naluLen = naluOffset - naluStream->naluOffset - STARTCODE_PREFIX_LEN;
+            ret = copyNaluHeader(stream, naluStream);
+            if (ret != DECODE_SUCCESS && ret != DECODE_FRAME_DROPPED) {
+                LOGW("copyNaluHeader returned %d", ret);
+                return ret;
+            }
+            // starting position for next NALU
+            naluStream->naluOffset = naluOffset;
+        }
+
+        if (ret == DECODE_SUCCESS) {
+            naluStream->naluCount++;
+        }
+
+        // update next lookup position and length
+        offset = naluOffset + 1; // skip one byte of NAL unit type
+        left = length - offset;
+    }
+
+    if (naluStream->naluCount > 0) {
+        naluStream->naluLen = length - naluStream->naluOffset;
+        memcpy(naluStream->byteStream, &(naluStream->naluCount), sizeof(int32_t));
+        // ignore return value, either DECODE_SUCCESS or DECODE_FRAME_DROPPED
+        copyNaluHeader(stream, naluStream);
+        return DECODE_SUCCESS;
+    }
+
+    LOGW("number of valid NALU is 0!");
+    return DECODE_SUCCESS;
+}
+
diff --git a/videodecoder/securevideo/merrplus/VideoDecoderAVCSecure.h b/videodecoder/securevideo/merrplus/VideoDecoderAVCSecure.h
new file mode 100644
index 0000000..ee16073
--- /dev/null
+++ b/videodecoder/securevideo/merrplus/VideoDecoderAVCSecure.h
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_SECURE_H_
+#define VIDEO_DECODER_AVC_SECURE_H_
+
+#include "VideoDecoderAVC.h"
+
+
+class VideoDecoderAVCSecure : public VideoDecoderAVC {
+public:
+    VideoDecoderAVCSecure(const char *mimeType);
+    virtual ~VideoDecoderAVCSecure();
+
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+
+    // data in the decoded buffer is all encrypted.
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+
+private:
+    enum {
+        MAX_SLICE_HEADER_SIZE  = 30,
+        MAX_NALU_HEADER_BUFFER = 8192,
+        MAX_NALU_NUMBER = 400,  // > 4096/12
+    };
+
+    // Information of Network Abstraction Layer Unit
+    struct NaluInfo {
+        int32_t naluOffset;                        // offset of NAL unit in the firewalled buffer
+        int32_t naluLen;                           // length of NAL unit
+        int32_t naluHeaderLen;                     // length of NAL unit header
+    };
+
+    struct NaluMetadata {
+        NaluInfo *naluInfo;
+        int32_t naluNumber;  // number of NAL units
+    };
+
+    struct NaluByteStream {
+        int32_t naluOffset;
+        int32_t naluLen;
+        int32_t streamPos;
+        uint8_t *byteStream;   // 4 bytes of naluCount, 4 bytes of naluOffset, 4 bytes of naulLen, 4 bytes of naluHeaderLen, followed by naluHeaderData
+        int32_t naluCount;
+    };
+
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+    int32_t findNalUnitOffset(uint8_t *stream, int32_t offset, int32_t length);
+    Decode_Status copyNaluHeader(uint8_t *stream, NaluByteStream *naluStream);
+    Decode_Status parseAnnexBStream(uint8_t *stream, int32_t length, NaluByteStream *naluStream);
+
+private:
+    NaluMetadata mMetadata;
+    NaluByteStream mByteStream;
+    uint8_t *mNaluHeaderBuffer;
+    uint8_t *mInputBuffer;
+};
+
+
+
+#endif /* VIDEO_DECODER_AVC_SECURE_H_ */
diff --git a/videodecoder/securevideo/moorefield/VideoDecoderAVCSecure.cpp b/videodecoder/securevideo/moorefield/VideoDecoderAVCSecure.cpp
new file mode 100644
index 0000000..2867ad9
--- /dev/null
+++ b/videodecoder/securevideo/moorefield/VideoDecoderAVCSecure.cpp
@@ -0,0 +1,861 @@
+/*
+* Copyright (c) 2009-2011 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 <va/va.h>
+#include "VideoDecoderBase.h"
+#include "VideoDecoderAVC.h"
+#include "VideoDecoderTrace.h"
+#include "vbp_loader.h"
+#include "VideoDecoderAVCSecure.h"
+#include "VideoFrameInfo.h"
+
+#define MAX_SLICEHEADER_BUFFER_SIZE 4096
+#define STARTCODE_PREFIX_LEN        3
+#define NALU_TYPE_MASK              0x1F
+#define MAX_NALU_HEADER_BUFFER      8192
+static const uint8_t startcodePrefix[STARTCODE_PREFIX_LEN] = {0x00, 0x00, 0x01};
+
+/* H264 start code values */
+typedef enum _h264_nal_unit_type
+{
+    h264_NAL_UNIT_TYPE_unspecified = 0,
+    h264_NAL_UNIT_TYPE_SLICE,
+    h264_NAL_UNIT_TYPE_DPA,
+    h264_NAL_UNIT_TYPE_DPB,
+    h264_NAL_UNIT_TYPE_DPC,
+    h264_NAL_UNIT_TYPE_IDR,
+    h264_NAL_UNIT_TYPE_SEI,
+    h264_NAL_UNIT_TYPE_SPS,
+    h264_NAL_UNIT_TYPE_PPS,
+    h264_NAL_UNIT_TYPE_Acc_unit_delimiter,
+    h264_NAL_UNIT_TYPE_EOSeq,
+    h264_NAL_UNIT_TYPE_EOstream,
+    h264_NAL_UNIT_TYPE_filler_data,
+    h264_NAL_UNIT_TYPE_SPS_extension,
+    h264_NAL_UNIT_TYPE_ACP = 19,
+    h264_NAL_UNIT_TYPE_Slice_extension = 20
+} h264_nal_unit_type_t;
+
+VideoDecoderAVCSecure::VideoDecoderAVCSecure(const char *mimeType)
+    : VideoDecoderAVC(mimeType){
+    mFrameSize     = 0;
+    mFrameData     = NULL;
+    mIsEncryptData = 0;
+    mClearData     = NULL;
+    mCachedHeader  = NULL;
+    setParserType(VBP_H264SECURE);
+    mFrameIdx = 0;
+    mModularMode = 0;
+    mSliceNum = 0;
+}
+
+Decode_Status VideoDecoderAVCSecure::start(VideoConfigBuffer *buffer) {
+    VTRACE("VideoDecoderAVCSecure::start");
+
+    Decode_Status status = VideoDecoderAVC::start(buffer);
+    if (status != DECODE_SUCCESS) {
+        return status;
+    }
+
+    mClearData = new uint8_t [MAX_NALU_HEADER_BUFFER];
+    if (mClearData == NULL) {
+        ETRACE("Failed to allocate memory for mClearData");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    mCachedHeader= new uint8_t [MAX_SLICEHEADER_BUFFER_SIZE];
+    if (mCachedHeader == NULL) {
+        ETRACE("Failed to allocate memory for mCachedHeader");
+        return DECODE_MEMORY_FAIL;
+    }
+
+    return status;
+}
+
+void VideoDecoderAVCSecure::stop(void) {
+    VTRACE("VideoDecoderAVCSecure::stop");
+    VideoDecoderAVC::stop();
+
+    if (mClearData) {
+        delete [] mClearData;
+        mClearData = NULL;
+    }
+
+    if (mCachedHeader) {
+        delete [] mCachedHeader;
+        mCachedHeader = NULL;
+    }
+}
+Decode_Status VideoDecoderAVCSecure::processModularInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data)
+{
+    VTRACE("processModularInputBuffer +++");
+    Decode_Status status;
+    int32_t clear_data_size = 0;
+    uint8_t *clear_data = NULL;
+
+    int32_t nalu_num = 0;
+    uint8_t nalu_type = 0;
+    int32_t nalu_offset = 0;
+    uint32_t nalu_size = 0;
+    uint8_t naluType = 0;
+    uint8_t *nalu_data = NULL;
+    uint32_t sliceidx = 0;
+
+    frame_info_t *pFrameInfo = NULL;
+    mSliceNum = 0;
+    memset(&mSliceInfo, 0, sizeof(mSliceInfo));
+    mIsEncryptData = 0;
+
+    if (buffer->flag & IS_SECURE_DATA) {
+        VTRACE("Decoding protected video ...");
+        pFrameInfo = (frame_info_t *) buffer->data;
+        if (pFrameInfo == NULL) {
+            ETRACE("Invalid parameter: pFrameInfo is NULL!");
+            return DECODE_MEMORY_FAIL;
+        }
+
+        mFrameData = pFrameInfo->data;
+        mFrameSize = pFrameInfo->size;
+        VTRACE("mFrameData = %p, mFrameSize = %d", mFrameData, mFrameSize);
+
+        nalu_num  = pFrameInfo->num_nalus;
+        VTRACE("nalu_num = %d", nalu_num);
+
+        if (nalu_num <= 0 || nalu_num >= MAX_NUM_NALUS) {
+            ETRACE("Invalid parameter: nalu_num = %d", nalu_num);
+            return DECODE_MEMORY_FAIL;
+        }
+
+        for (int32_t i = 0; i < nalu_num; i++) {
+
+            nalu_size = pFrameInfo->nalus[i].length;
+            nalu_type = pFrameInfo->nalus[i].type;
+            nalu_offset = pFrameInfo->nalus[i].offset;
+            nalu_data = pFrameInfo->nalus[i].data;
+            naluType  = nalu_type & NALU_TYPE_MASK;
+
+            VTRACE("nalu_type = 0x%x, nalu_size = %d, nalu_offset = 0x%x", nalu_type, nalu_size, nalu_offset);
+
+            if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+
+                mIsEncryptData = 1;
+                VTRACE("slice idx = %d", sliceidx);
+                mSliceInfo[sliceidx].sliceHeaderByte = nalu_type;
+                mSliceInfo[sliceidx].sliceStartOffset = (nalu_offset >> 4) << 4;
+                mSliceInfo[sliceidx].sliceByteOffset = nalu_offset - mSliceInfo[sliceidx].sliceStartOffset;
+                mSliceInfo[sliceidx].sliceLength = mSliceInfo[sliceidx].sliceByteOffset + nalu_size;
+                mSliceInfo[sliceidx].sliceSize = (mSliceInfo[sliceidx].sliceByteOffset + nalu_size + 0xF) & ~0xF;
+                VTRACE("sliceHeaderByte = 0x%x", mSliceInfo[sliceidx].sliceHeaderByte);
+                VTRACE("sliceStartOffset = %d", mSliceInfo[sliceidx].sliceStartOffset);
+                VTRACE("sliceByteOffset = %d", mSliceInfo[sliceidx].sliceByteOffset);
+                VTRACE("sliceSize = %d", mSliceInfo[sliceidx].sliceSize);
+                VTRACE("sliceLength = %d", mSliceInfo[sliceidx].sliceLength);
+
+#if 0
+                uint32_t testsize;
+                uint8_t *testdata;
+                testsize = mSliceInfo[sliceidx].sliceSize > 64 ? 64 : mSliceInfo[sliceidx].sliceSize ;
+                testdata = (uint8_t *)(mFrameData);
+                for (int i = 0; i < testsize; i++) {
+                    VTRACE("testdata[%d] = 0x%x", i, testdata[i]);
+                }
+#endif
+                sliceidx++;
+
+            } else if (naluType == h264_NAL_UNIT_TYPE_SPS || naluType == h264_NAL_UNIT_TYPE_PPS) {
+                if (nalu_data == NULL) {
+                    ETRACE("Invalid parameter: nalu_data = NULL for naluType 0x%x", naluType);
+                    return DECODE_MEMORY_FAIL;
+                }
+                memcpy(mClearData + clear_data_size,
+                    nalu_data,
+                    nalu_size);
+                clear_data_size += nalu_size;
+            } else {
+                ITRACE("Nalu type = 0x%x is skipped", naluType);
+                continue;
+            }
+        }
+        clear_data = mClearData;
+        mSliceNum = sliceidx;
+
+    } else {
+        VTRACE("Decoding clear video ...");
+        mIsEncryptData = 0;
+        mFrameSize = buffer->size;
+        mFrameData = buffer->data;
+        clear_data = buffer->data;
+        clear_data_size = buffer->size;
+    }
+
+    if (clear_data_size > 0) {
+        status =  VideoDecoderBase::parseBuffer(
+                clear_data,
+                clear_data_size,
+                false,
+                (void**)data);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+    } else {
+        status =  VideoDecoderBase::queryBuffer((void**)data);
+        CHECK_STATUS("VideoDecoderBase::queryBuffer");
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::processClassicInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data)
+{
+    Decode_Status status;
+    int32_t clear_data_size = 0;
+    uint8_t *clear_data = NULL;
+    uint8_t naluType = 0;
+
+    int32_t num_nalus;
+    int32_t nalu_offset;
+    int32_t offset;
+    uint8_t *data_src;
+    uint8_t *nalu_data;
+    uint32_t nalu_size;
+
+    if (buffer->flag & IS_SECURE_DATA) {
+        VTRACE("Decoding protected video ...");
+        mIsEncryptData = 1;
+
+        mFrameData = buffer->data;
+        mFrameSize = buffer->size;
+        VTRACE("mFrameData = %p, mFrameSize = %d", mFrameData, mFrameSize);
+        num_nalus  = *(uint32_t *)(buffer->data + buffer->size + sizeof(uint32_t));
+        VTRACE("num_nalus = %d", num_nalus);
+        offset = 4;
+        for (int32_t i = 0; i < num_nalus; i++) {
+            VTRACE("%d nalu, offset = %d", i, offset);
+            data_src = buffer->data + buffer->size + sizeof(uint32_t) + offset;
+            nalu_size = *(uint32_t *)(data_src + 2 * sizeof(uint32_t));
+            nalu_size = (nalu_size + 0x03) & (~0x03);
+
+            nalu_data = data_src + 3 *sizeof(uint32_t);
+            naluType  = nalu_data[0] & NALU_TYPE_MASK;
+            offset += nalu_size + 3 *sizeof(uint32_t);
+            VTRACE("naluType = 0x%x", naluType);
+            VTRACE("nalu_size = %d, nalu_data = %p", nalu_size, nalu_data);
+
+            if (naluType >= h264_NAL_UNIT_TYPE_SLICE && naluType <= h264_NAL_UNIT_TYPE_IDR) {
+                ETRACE("Slice NALU received!");
+                return DECODE_INVALID_DATA;
+            }
+
+            else if (naluType >= h264_NAL_UNIT_TYPE_SEI && naluType <= h264_NAL_UNIT_TYPE_PPS) {
+                memcpy(mClearData + clear_data_size,
+                    startcodePrefix,
+                    STARTCODE_PREFIX_LEN);
+                clear_data_size += STARTCODE_PREFIX_LEN;
+                memcpy(mClearData + clear_data_size,
+                    nalu_data,
+                    nalu_size);
+                clear_data_size += nalu_size;
+            } else {
+                ETRACE("Failure: DECODE_FRAME_DROPPED");
+                return DECODE_FRAME_DROPPED;
+            }
+        }
+        clear_data = mClearData;
+    } else {
+        VTRACE("Decoding clear video ...");
+        mIsEncryptData = 0;
+        mFrameSize = buffer->size;
+        mFrameData = buffer->data;
+        clear_data = buffer->data;
+        clear_data_size = buffer->size;
+    }
+
+    if (clear_data_size > 0) {
+        status =  VideoDecoderBase::parseBuffer(
+                clear_data,
+                clear_data_size,
+                false,
+                (void**)data);
+        CHECK_STATUS("VideoDecoderBase::parseBuffer");
+    } else {
+        status =  VideoDecoderBase::queryBuffer((void**)data);
+        CHECK_STATUS("VideoDecoderBase::queryBuffer");
+    }
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::decode(VideoDecodeBuffer *buffer) {
+    VTRACE("VideoDecoderAVCSecure::decode");
+    Decode_Status status;
+    vbp_data_h264 *data = NULL;
+    if (buffer == NULL) {
+        return DECODE_INVALID_DATA;
+    }
+
+#if 0
+    uint32_t testsize;
+    uint8_t *testdata;
+    testsize = buffer->size > 16 ? 16:buffer->size ;
+    testdata = (uint8_t *)(buffer->data);
+    for (int i = 0; i < 16; i++) {
+        VTRACE("testdata[%d] = 0x%x", i, testdata[i]);
+    }
+#endif
+    if (buffer->flag & IS_SUBSAMPLE_ENCRYPTION) {
+        mModularMode = 1;
+    }
+
+    if (mModularMode) {
+        status = processModularInputBuffer(buffer,&data);
+        CHECK_STATUS("processModularInputBuffer");
+    }
+    else {
+        status = processClassicInputBuffer(buffer,&data);
+        CHECK_STATUS("processClassicInputBuffer");
+    }
+
+    if (!mVAStarted) {
+         if (data->has_sps && data->has_pps) {
+            status = startVA(data);
+            CHECK_STATUS("startVA");
+        } else {
+            WTRACE("Can't start VA as either SPS or PPS is still not available.");
+            return DECODE_SUCCESS;
+        }
+    }
+
+    status = decodeFrame(buffer, data);
+
+    return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_h264 *data) {
+    VTRACE("VideoDecoderAVCSecure::decodeFrame");
+    Decode_Status status;
+    VTRACE("data->has_sps = %d, data->has_pps = %d", data->has_sps, data->has_pps);
+
+#if 0
+    // Don't remove the following codes, it can be enabled for debugging DPB.
+    for (unsigned int i = 0; i < data->num_pictures; i++) {
+        VAPictureH264 &pic = data->pic_data[i].pic_parms->CurrPic;
+        VTRACE("%d: decoding frame %.2f, poc top = %d, poc bottom = %d, flags = %d,  reference = %d",
+                i,
+                buffer->timeStamp/1E6,
+                pic.TopFieldOrderCnt,
+                pic.BottomFieldOrderCnt,
+                pic.flags,
+                (pic.flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+                (pic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE));
+    }
+#endif
+
+    if (data->new_sps || data->new_pps) {
+        status = handleNewSequence(data);
+        CHECK_STATUS("handleNewSequence");
+    }
+
+    if (mModularMode && (!mIsEncryptData)) {
+        if (data->pic_data[0].num_slices == 0) {
+            ITRACE("No slice available for decoding.");
+            status = mSizeChanged ? DECODE_FORMAT_CHANGE : DECODE_SUCCESS;
+            mSizeChanged = false;
+            return status;
+        }
+    }
+
+    uint64_t lastPTS = mCurrentPTS;
+    mCurrentPTS = buffer->timeStamp;
+
+    // start decoding a new frame
+    status = acquireSurfaceBuffer();
+    CHECK_STATUS("acquireSurfaceBuffer");
+
+    if (mModularMode) {
+        parseModularSliceHeader(data);
+    }
+    else {
+        parseClassicSliceHeader(data);
+    }
+
+    if (status != DECODE_SUCCESS) {
+        endDecodingFrame(true);
+        return status;
+    }
+
+    status = beginDecodingFrame(data);
+    CHECK_STATUS("beginDecodingFrame");
+
+   // finish decoding the last frame
+    status = endDecodingFrame(false);
+    CHECK_STATUS("endDecodingFrame");
+
+    if (isNewFrame(data, lastPTS == mCurrentPTS) == 0) {
+        ETRACE("Can't handle interlaced frames yet");
+        return DECODE_FAIL;
+    }
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::beginDecodingFrame(vbp_data_h264 *data) {
+    VTRACE("VideoDecoderAVCSecure::beginDecodingFrame");
+    Decode_Status status;
+    VAPictureH264 *picture = &(data->pic_data[0].pic_parms->CurrPic);
+    if ((picture->flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) ||
+        (picture->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)) {
+        mAcquiredBuffer->referenceFrame = true;
+    } else {
+        mAcquiredBuffer->referenceFrame = false;
+    }
+
+    if (picture->flags & VA_PICTURE_H264_TOP_FIELD) {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD | VA_TOP_FIELD;
+    } else {
+        mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
+    }
+
+    mAcquiredBuffer->renderBuffer.flag = 0;
+    mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS;
+    mAcquiredBuffer->pictureOrder = getPOC(picture);
+
+    if (mSizeChanged) {
+        mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE;
+        mSizeChanged = false;
+    }
+
+    status  = continueDecodingFrame(data);
+    return status;
+}
+
+Decode_Status VideoDecoderAVCSecure::continueDecodingFrame(vbp_data_h264 *data) {
+    VTRACE("VideoDecoderAVCSecure::continueDecodingFrame");
+    Decode_Status status;
+    vbp_picture_data_h264 *picData = data->pic_data;
+
+    if (mAcquiredBuffer == NULL || mAcquiredBuffer->renderBuffer.surface == VA_INVALID_SURFACE) {
+        ETRACE("mAcquiredBuffer is NULL. Implementation bug.");
+        return DECODE_FAIL;
+    }
+    VTRACE("data->num_pictures = %d", data->num_pictures);
+    for (uint32_t picIndex = 0; picIndex < data->num_pictures; picIndex++, picData++) {
+        if (picData == NULL || picData->pic_parms == NULL || picData->slc_data == NULL || picData->num_slices == 0) {
+            return DECODE_PARSER_FAIL;
+        }
+
+        if (picIndex > 0 &&
+            (picData->pic_parms->CurrPic.flags & (VA_PICTURE_H264_TOP_FIELD | VA_PICTURE_H264_BOTTOM_FIELD)) == 0) {
+            ETRACE("Packed frame is not supported yet!");
+            return DECODE_FAIL;
+        }
+        VTRACE("picData->num_slices = %d", picData->num_slices);
+        for (uint32_t sliceIndex = 0; sliceIndex < picData->num_slices; sliceIndex++) {
+            status = decodeSlice(data, picIndex, sliceIndex);
+            if (status != DECODE_SUCCESS) {
+                endDecodingFrame(true);
+                // remove current frame from DPB as it can't be decoded.
+                removeReferenceFromDPB(picData->pic_parms);
+                return status;
+            }
+        }
+    }
+    mDecodingFrame = true;
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::parseClassicSliceHeader(vbp_data_h264 *data) {
+    Decode_Status status;
+    VAStatus vaStatus;
+
+    VABufferID sliceheaderbufferID;
+    VABufferID pictureparameterparsingbufferID;
+    VABufferID mSlicebufferID;
+
+    if (mFrameSize <= 0) {
+        return DECODE_SUCCESS;
+    }
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_VA_STATUS("vaBeginPicture");
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VAParseSliceHeaderGroupBufferType,
+        MAX_SLICEHEADER_BUFFER_SIZE,
+        1,
+        NULL,
+        &sliceheaderbufferID);
+    CHECK_VA_STATUS("vaCreateSliceHeaderGroupBuffer");
+
+    void *sliceheaderbuf;
+    vaStatus = vaMapBuffer(
+        mVADisplay,
+        sliceheaderbufferID,
+        &sliceheaderbuf);
+    CHECK_VA_STATUS("vaMapBuffer");
+
+    memset(sliceheaderbuf, 0, MAX_SLICEHEADER_BUFFER_SIZE);
+
+    vaStatus = vaUnmapBuffer(
+        mVADisplay,
+        sliceheaderbufferID);
+    CHECK_VA_STATUS("vaUnmapBuffer");
+
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceDataBufferType,
+        mFrameSize, //size
+        1,        //num_elements
+        mFrameData,
+        &mSlicebufferID);
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+    data->pic_parse_buffer->frame_buf_id = mSlicebufferID;
+    data->pic_parse_buffer->slice_headers_buf_id = sliceheaderbufferID;
+    data->pic_parse_buffer->frame_size = mFrameSize;
+    data->pic_parse_buffer->slice_headers_size = MAX_SLICEHEADER_BUFFER_SIZE;
+
+#if 0
+
+    VTRACE("flags.bits.frame_mbs_only_flag = %d", data->pic_parse_buffer->flags.bits.frame_mbs_only_flag);
+    VTRACE("flags.bits.pic_order_present_flag = %d", data->pic_parse_buffer->flags.bits.pic_order_present_flag);
+    VTRACE("flags.bits.delta_pic_order_always_zero_flag = %d", data->pic_parse_buffer->flags.bits.delta_pic_order_always_zero_flag);
+    VTRACE("flags.bits.redundant_pic_cnt_present_flag = %d", data->pic_parse_buffer->flags.bits.redundant_pic_cnt_present_flag);
+    VTRACE("flags.bits.weighted_pred_flag = %d", data->pic_parse_buffer->flags.bits.weighted_pred_flag);
+    VTRACE("flags.bits.entropy_coding_mode_flag = %d", data->pic_parse_buffer->flags.bits.entropy_coding_mode_flag);
+    VTRACE("flags.bits.deblocking_filter_control_present_flag = %d", data->pic_parse_buffer->flags.bits.deblocking_filter_control_present_flag);
+    VTRACE("flags.bits.weighted_bipred_idc = %d", data->pic_parse_buffer->flags.bits.weighted_bipred_idc);
+
+    VTRACE("pic_parse_buffer->expected_pic_parameter_set_id = %d", data->pic_parse_buffer->expected_pic_parameter_set_id);
+    VTRACE("pic_parse_buffer->num_slice_groups_minus1 = %d", data->pic_parse_buffer->num_slice_groups_minus1);
+    VTRACE("pic_parse_buffer->chroma_format_idc = %d", data->pic_parse_buffer->chroma_format_idc);
+    VTRACE("pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4 = %d", data->pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4);
+    VTRACE("pic_parse_buffer->pic_order_cnt_type = %d", data->pic_parse_buffer->pic_order_cnt_type);
+    VTRACE("pic_parse_buffer->residual_colour_transform_flag = %d", data->pic_parse_buffer->residual_colour_transform_flag);
+    VTRACE("pic_parse_buffer->num_ref_idc_l0_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l0_active_minus1);
+    VTRACE("pic_parse_buffer->num_ref_idc_l1_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l1_active_minus1);
+#endif
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VAParsePictureParameterBufferType,
+        sizeof(VAParsePictureParameterBuffer),
+        1,
+        data->pic_parse_buffer,
+        &pictureparameterparsingbufferID);
+    CHECK_VA_STATUS("vaCreatePictureParameterParsingBuffer");
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        &pictureparameterparsingbufferID,
+        1);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    vaStatus = vaMapBuffer(
+        mVADisplay,
+        sliceheaderbufferID,
+        &sliceheaderbuf);
+    CHECK_VA_STATUS("vaMapBuffer");
+
+    status = updateSliceParameter(data,sliceheaderbuf);
+    CHECK_STATUS("processSliceHeader");
+
+    vaStatus = vaUnmapBuffer(
+        mVADisplay,
+        sliceheaderbufferID);
+    CHECK_VA_STATUS("vaUnmapBuffer");
+
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::parseModularSliceHeader(vbp_data_h264 *data) {
+    Decode_Status status;
+    VAStatus vaStatus;
+
+    VABufferID sliceheaderbufferID;
+    VABufferID pictureparameterparsingbufferID;
+    VABufferID mSlicebufferID;
+    int32_t sliceIdx;
+
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
+    CHECK_VA_STATUS("vaBeginPicture");
+
+    if (mFrameSize <= 0 || mSliceNum <=0) {
+        return DECODE_SUCCESS;
+    }
+    void *sliceheaderbuf;
+    memset(mCachedHeader, 0, MAX_SLICEHEADER_BUFFER_SIZE);
+    int32_t offset = 0;
+    int32_t size = 0;
+
+    for (sliceIdx = 0; sliceIdx < mSliceNum; sliceIdx++) {
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAParseSliceHeaderGroupBufferType,
+            MAX_SLICEHEADER_BUFFER_SIZE,
+            1,
+            NULL,
+            &sliceheaderbufferID);
+        CHECK_VA_STATUS("vaCreateSliceHeaderGroupBuffer");
+
+        vaStatus = vaMapBuffer(
+            mVADisplay,
+            sliceheaderbufferID,
+            &sliceheaderbuf);
+        CHECK_VA_STATUS("vaMapBuffer");
+
+        memset(sliceheaderbuf, 0, MAX_SLICEHEADER_BUFFER_SIZE);
+
+        vaStatus = vaUnmapBuffer(
+            mVADisplay,
+            sliceheaderbufferID);
+        CHECK_VA_STATUS("vaUnmapBuffer");
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VASliceDataBufferType,
+            mSliceInfo[sliceIdx].sliceSize, //size
+            1,        //num_elements
+            mFrameData + mSliceInfo[sliceIdx].sliceStartOffset,
+            &mSlicebufferID);
+        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+        data->pic_parse_buffer->frame_buf_id = mSlicebufferID;
+        data->pic_parse_buffer->slice_headers_buf_id = sliceheaderbufferID;
+        data->pic_parse_buffer->frame_size = mSliceInfo[sliceIdx].sliceLength;
+        data->pic_parse_buffer->slice_headers_size = MAX_SLICEHEADER_BUFFER_SIZE;
+        data->pic_parse_buffer->nalu_header.value = mSliceInfo[sliceIdx].sliceHeaderByte;
+        data->pic_parse_buffer->slice_offset = mSliceInfo[sliceIdx].sliceByteOffset;
+
+#if 0
+        VTRACE("data->pic_parse_buffer->slice_offset = 0x%x", data->pic_parse_buffer->slice_offset);
+        VTRACE("pic_parse_buffer->nalu_header.value = %x", data->pic_parse_buffer->nalu_header.value = mSliceInfo[sliceIdx].sliceHeaderByte);
+        VTRACE("flags.bits.frame_mbs_only_flag = %d", data->pic_parse_buffer->flags.bits.frame_mbs_only_flag);
+        VTRACE("flags.bits.pic_order_present_flag = %d", data->pic_parse_buffer->flags.bits.pic_order_present_flag);
+        VTRACE("flags.bits.delta_pic_order_always_zero_flag = %d", data->pic_parse_buffer->flags.bits.delta_pic_order_always_zero_flag);
+        VTRACE("flags.bits.redundant_pic_cnt_present_flag = %d", data->pic_parse_buffer->flags.bits.redundant_pic_cnt_present_flag);
+        VTRACE("flags.bits.weighted_pred_flag = %d", data->pic_parse_buffer->flags.bits.weighted_pred_flag);
+        VTRACE("flags.bits.entropy_coding_mode_flag = %d", data->pic_parse_buffer->flags.bits.entropy_coding_mode_flag);
+        VTRACE("flags.bits.deblocking_filter_control_present_flag = %d", data->pic_parse_buffer->flags.bits.deblocking_filter_control_present_flag);
+        VTRACE("flags.bits.weighted_bipred_idc = %d", data->pic_parse_buffer->flags.bits.weighted_bipred_idc);
+        VTRACE("pic_parse_buffer->expected_pic_parameter_set_id = %d", data->pic_parse_buffer->expected_pic_parameter_set_id);
+        VTRACE("pic_parse_buffer->num_slice_groups_minus1 = %d", data->pic_parse_buffer->num_slice_groups_minus1);
+        VTRACE("pic_parse_buffer->chroma_format_idc = %d", data->pic_parse_buffer->chroma_format_idc);
+        VTRACE("pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4 = %d", data->pic_parse_buffer->log2_max_pic_order_cnt_lsb_minus4);
+        VTRACE("pic_parse_buffer->pic_order_cnt_type = %d", data->pic_parse_buffer->pic_order_cnt_type);
+        VTRACE("pic_parse_buffer->residual_colour_transform_flag = %d", data->pic_parse_buffer->residual_colour_transform_flag);
+        VTRACE("pic_parse_buffer->num_ref_idc_l0_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l0_active_minus1);
+        VTRACE("pic_parse_buffer->num_ref_idc_l1_active_minus1 = %d", data->pic_parse_buffer->num_ref_idc_l1_active_minus1);
+#endif
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAParsePictureParameterBufferType,
+            sizeof(VAParsePictureParameterBuffer),
+            1,
+            data->pic_parse_buffer,
+            &pictureparameterparsingbufferID);
+        CHECK_VA_STATUS("vaCreatePictureParameterParsingBuffer");
+
+        vaStatus = vaRenderPicture(
+            mVADisplay,
+            mVAContext,
+            &pictureparameterparsingbufferID,
+            1);
+        CHECK_VA_STATUS("vaRenderPicture");
+
+        vaStatus = vaMapBuffer(
+            mVADisplay,
+            sliceheaderbufferID,
+            &sliceheaderbuf);
+        CHECK_VA_STATUS("vaMapBuffer");
+
+        size = *(uint32 *)((uint8 *)sliceheaderbuf + 4) + 4;
+        VTRACE("slice header size = 0x%x, offset = 0x%x", size, offset);
+        if (offset + size <= MAX_SLICEHEADER_BUFFER_SIZE - 4) {
+            memcpy(mCachedHeader+offset, sliceheaderbuf, size);
+            offset += size;
+        } else {
+            WTRACE("Cached slice header is not big enough!");
+        }
+        vaStatus = vaUnmapBuffer(
+            mVADisplay,
+            sliceheaderbufferID);
+        CHECK_VA_STATUS("vaUnmapBuffer");
+    }
+    memset(mCachedHeader + offset, 0xFF, 4);
+    status = updateSliceParameter(data,mCachedHeader);
+    CHECK_STATUS("processSliceHeader");
+    return DECODE_SUCCESS;
+}
+
+
+Decode_Status VideoDecoderAVCSecure::updateSliceParameter(vbp_data_h264 *data, void *sliceheaderbuf) {
+    VTRACE("VideoDecoderAVCSecure::updateSliceParameter");
+    Decode_Status status;
+    status =  VideoDecoderBase::updateBuffer(
+            (uint8_t *)sliceheaderbuf,
+            MAX_SLICEHEADER_BUFFER_SIZE,
+            (void**)&data);
+    CHECK_STATUS("updateBuffer");
+    return DECODE_SUCCESS;
+}
+
+Decode_Status VideoDecoderAVCSecure::decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex) {
+    Decode_Status status;
+    VAStatus vaStatus;
+    uint32_t bufferIDCount = 0;
+    // maximum 3 buffers to render a slice: picture parameter, IQMatrix, slice parameter
+    VABufferID bufferIDs[3];
+
+    vbp_picture_data_h264 *picData = &(data->pic_data[picIndex]);
+    vbp_slice_data_h264 *sliceData = &(picData->slc_data[sliceIndex]);
+    VAPictureParameterBufferH264 *picParam = picData->pic_parms;
+    VASliceParameterBufferH264 *sliceParam = &(sliceData->slc_parms);
+    uint32_t slice_data_size = 0;
+    uint8_t* slice_data_addr = NULL;
+
+    if (sliceParam->first_mb_in_slice == 0 || mDecodingFrame == false) {
+        // either condition indicates start of a new frame
+        if (sliceParam->first_mb_in_slice != 0) {
+            WTRACE("The first slice is lost.");
+        }
+        VTRACE("Current frameidx = %d", mFrameIdx++);
+        // Update  the reference frames and surface IDs for DPB and current frame
+        status = updateDPB(picParam);
+        CHECK_STATUS("updateDPB");
+
+        //We have to provide a hacked DPB rather than complete DPB for libva as workaround
+        status = updateReferenceFrames(picData);
+        CHECK_STATUS("updateReferenceFrames");
+
+        mDecodingFrame = true;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAPictureParameterBufferType,
+            sizeof(VAPictureParameterBufferH264),
+            1,
+            picParam,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
+        bufferIDCount++;
+
+        vaStatus = vaCreateBuffer(
+            mVADisplay,
+            mVAContext,
+            VAIQMatrixBufferType,
+            sizeof(VAIQMatrixBufferH264),
+            1,
+            data->IQ_matrix_buf,
+            &bufferIDs[bufferIDCount]);
+        CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
+        bufferIDCount++;
+    }
+
+    status = setReference(sliceParam);
+    CHECK_STATUS("setReference");
+
+    if (mModularMode) {
+        if (mIsEncryptData) {
+            sliceParam->slice_data_size = mSliceInfo[sliceIndex].sliceSize;
+            slice_data_size = mSliceInfo[sliceIndex].sliceSize;
+            slice_data_addr = mFrameData + mSliceInfo[sliceIndex].sliceStartOffset;
+        } else {
+            slice_data_size = sliceData->slice_size;
+            slice_data_addr = sliceData->buffer_addr + sliceData->slice_offset;
+        }
+    } else {
+        sliceParam->slice_data_size = mFrameSize;
+        slice_data_size = mFrameSize;
+        slice_data_addr = mFrameData;
+    }
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceParameterBufferType,
+        sizeof(VASliceParameterBufferH264),
+        1,
+        sliceParam,
+        &bufferIDs[bufferIDCount]);
+    CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
+    bufferIDCount++;
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        bufferIDs,
+        bufferIDCount);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    VABufferID slicebufferID;
+
+    vaStatus = vaCreateBuffer(
+        mVADisplay,
+        mVAContext,
+        VASliceDataBufferType,
+        slice_data_size, //size
+        1,        //num_elements
+        slice_data_addr,
+        &slicebufferID);
+    CHECK_VA_STATUS("vaCreateSliceDataBuffer");
+
+    vaStatus = vaRenderPicture(
+        mVADisplay,
+        mVAContext,
+        &slicebufferID,
+        1);
+    CHECK_VA_STATUS("vaRenderPicture");
+
+    return DECODE_SUCCESS;
+
+}
+
+Decode_Status VideoDecoderAVCSecure::getCodecSpecificConfigs(
+    VAProfile profile, VAConfigID *config)
+{
+    VAStatus vaStatus;
+    VAConfigAttrib attrib[2];
+
+    if (config == NULL) {
+        ETRACE("Invalid parameter!");
+        return DECODE_FAIL;
+    }
+
+    attrib[0].type = VAConfigAttribRTFormat;
+    attrib[0].value = VA_RT_FORMAT_YUV420;
+    attrib[1].type = VAConfigAttribDecSliceMode;
+    attrib[1].value = VA_DEC_SLICE_MODE_NORMAL;
+    if (mModularMode) {
+        attrib[1].value = VA_DEC_SLICE_MODE_SUBSAMPLE;
+    }
+
+    vaStatus = vaCreateConfig(
+            mVADisplay,
+            profile,
+            VAEntrypointVLD,
+            &attrib[0],
+            2,
+            config);
+    CHECK_VA_STATUS("vaCreateConfig");
+
+    return DECODE_SUCCESS;
+}
diff --git a/videodecoder/securevideo/moorefield/VideoDecoderAVCSecure.h b/videodecoder/securevideo/moorefield/VideoDecoderAVCSecure.h
new file mode 100644
index 0000000..f66d7b8
--- /dev/null
+++ b/videodecoder/securevideo/moorefield/VideoDecoderAVCSecure.h
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_DECODER_AVC_SECURE_H
+#define VIDEO_DECODER_AVC_SECURE_H
+
+#include "VideoDecoderBase.h"
+#include "VideoDecoderAVC.h"
+#include "VideoDecoderDefs.h"
+
+class VideoDecoderAVCSecure : public VideoDecoderAVC {
+public:
+    VideoDecoderAVCSecure(const char *mimeType);
+    virtual Decode_Status start(VideoConfigBuffer *buffer);
+    virtual void stop(void);
+
+    // data in the decoded buffer is all encrypted.
+    virtual Decode_Status decode(VideoDecodeBuffer *buffer);
+protected:
+    virtual Decode_Status decodeFrame(VideoDecodeBuffer *buffer, vbp_data_h264 *data);
+    virtual Decode_Status continueDecodingFrame(vbp_data_h264 *data);
+    virtual Decode_Status beginDecodingFrame(vbp_data_h264 *data);
+    virtual Decode_Status getCodecSpecificConfigs(VAProfile profile, VAConfigID*config);
+    Decode_Status parseClassicSliceHeader(vbp_data_h264 *data);
+    Decode_Status parseModularSliceHeader(vbp_data_h264 *data);
+
+    Decode_Status updateSliceParameter(vbp_data_h264 *data, void *sliceheaderbuf);
+    virtual Decode_Status decodeSlice(vbp_data_h264 *data, uint32_t picIndex, uint32_t sliceIndex);
+private:
+    Decode_Status processClassicInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data);
+    Decode_Status processModularInputBuffer(VideoDecodeBuffer *buffer, vbp_data_h264 **data);
+    int32_t     mIsEncryptData;
+    int32_t     mFrameSize;
+    uint8_t*    mFrameData;
+    uint8_t*    mClearData;
+    uint8_t*    mCachedHeader;
+    int32_t     mFrameIdx;
+    int32_t     mModularMode;
+
+    enum {
+        MAX_SLICE_HEADER_NUM  = 256,
+    };
+    int32_t     mSliceNum;
+    // Information of Slices in the Modular DRM Mode
+    struct SliceInfo {
+        uint8_t     sliceHeaderByte;             //  first byte of the slice header
+        uint32_t    sliceStartOffset;            // offset of Slice unit in the firewalled buffer
+        uint32_t    sliceByteOffset;             // extra offset from the blockAligned slice offset
+        uint32_t    sliceSize;                   // block aligned length of slice unit
+        uint32_t    sliceLength;                 // actual size of the slice
+    };
+
+    SliceInfo mSliceInfo[MAX_SLICE_HEADER_NUM];
+};
+
+#endif
diff --git a/videodecoder/securevideo/moorefield/VideoFrameInfo.h b/videodecoder/securevideo/moorefield/VideoFrameInfo.h
new file mode 100755
index 0000000..485b0da
--- /dev/null
+++ b/videodecoder/securevideo/moorefield/VideoFrameInfo.h
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_FRAME_INFO_H_
+#define VIDEO_FRAME_INFO_H_
+
+#define MAX_NUM_NALUS 16
+
+typedef struct {
+    uint8_t  type;      // nalu type + nal_ref_idc
+    uint32_t offset;    // offset to the pointer of the encrypted data
+    uint8_t* data;      // if the nalu is encrypted, this field is useless; if current NALU is SPS/PPS, data is the pointer to clear SPS/PPS data
+    uint32_t length;    // nalu length
+} nalu_info_t;
+
+typedef struct {
+    uint8_t* data;      // pointer to the encrypted data
+    uint32_t size;      // encrypted data size
+    uint32_t num_nalus; // number of NALU
+    nalu_info_t nalus[MAX_NUM_NALUS];
+} frame_info_t;
+
+#endif
diff --git a/videodecoder/use_util_sse4.h b/videodecoder/use_util_sse4.h
new file mode 100644
index 0000000..454099d
--- /dev/null
+++ b/videodecoder/use_util_sse4.h
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2009-2011 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 <emmintrin.h>
+#include <x86intrin.h>
+
+inline void stream_memcpy(void* dst_buff, const void* src_buff, size_t size)
+{
+    bool isAligned = (((size_t)(src_buff) | (size_t)(dst_buff)) & 0xF) == 0;
+    if (!isAligned) {
+        memcpy(dst_buff, src_buff, size);
+        return;
+    }
+
+    static const size_t regs_count = 8;
+
+    __m128i xmm_data0, xmm_data1, xmm_data2, xmm_data3;
+    __m128i xmm_data4, xmm_data5, xmm_data6, xmm_data7;
+
+    size_t remain_data = size & (regs_count * sizeof(xmm_data0) - 1);
+    size_t end_position = 0;
+
+    __m128i* pWb_buff = (__m128i*)dst_buff;
+    __m128i* pWb_buff_end = pWb_buff + ((size - remain_data) >> 4);
+    __m128i* pWc_buff = (__m128i*)src_buff;
+
+    /*sync the wc memory data*/
+    _mm_mfence();
+
+    while (pWb_buff < pWb_buff_end)
+    {
+        xmm_data0  = _mm_stream_load_si128(pWc_buff);
+        xmm_data1  = _mm_stream_load_si128(pWc_buff + 1);
+        xmm_data2  = _mm_stream_load_si128(pWc_buff + 2);
+        xmm_data3  = _mm_stream_load_si128(pWc_buff + 3);
+        xmm_data4  = _mm_stream_load_si128(pWc_buff + 4);
+        xmm_data5  = _mm_stream_load_si128(pWc_buff + 5);
+        xmm_data6  = _mm_stream_load_si128(pWc_buff + 6);
+        xmm_data7  = _mm_stream_load_si128(pWc_buff + 7);
+
+        pWc_buff += regs_count;
+        _mm_store_si128(pWb_buff, xmm_data0);
+        _mm_store_si128(pWb_buff + 1, xmm_data1);
+        _mm_store_si128(pWb_buff + 2, xmm_data2);
+        _mm_store_si128(pWb_buff + 3, xmm_data3);
+        _mm_store_si128(pWb_buff + 4, xmm_data4);
+        _mm_store_si128(pWb_buff + 5, xmm_data5);
+        _mm_store_si128(pWb_buff + 6, xmm_data6);
+        _mm_store_si128(pWb_buff + 7, xmm_data7);
+
+        pWb_buff += regs_count;
+    }
+
+    /*copy data by 16 bytes step from the remainder*/
+    if (remain_data >= 16)
+    {
+        size = remain_data;
+        remain_data = size & 15;
+        end_position = size >> 4;
+        for (size_t i = 0; i < end_position; ++i)
+        {
+            pWb_buff[i] = _mm_stream_load_si128(pWc_buff + i);
+        }
+    }
+
+    /*copy the remainder data, if it still existed*/
+    if (remain_data)
+    {
+        __m128i temp_data = _mm_stream_load_si128(pWc_buff + end_position);
+
+        char* psrc_buf = (char*)(&temp_data);
+        char* pdst_buf = (char*)(pWb_buff + end_position);
+
+        for (size_t i = 0; i < remain_data; ++i)
+        {
+            pdst_buf[i] = psrc_buf[i];
+        }
+    }
+
+}
diff --git a/videoencoder/Android.mk b/videoencoder/Android.mk
new file mode 100644
index 0000000..1fc4d9a
--- /dev/null
+++ b/videoencoder/Android.mk
@@ -0,0 +1,110 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+ifeq ($(ENABLE_IMG_GRAPHICS),)
+LOCAL_CFLAGS += \
+    -DBX_RC \
+    -DOSCL_IMPORT_REF= \
+    -DOSCL_UNUSED_ARG= \
+    -DOSCL_EXPORT_REF=
+
+LOCAL_STATIC_LIBRARIES := \
+    libstagefright_m4vh263enc
+endif
+
+LOCAL_SRC_FILES := \
+    VideoEncoderBase.cpp \
+    VideoEncoderAVC.cpp \
+    VideoEncoderH263.cpp \
+    VideoEncoderMP4.cpp \
+    VideoEncoderVP8.cpp \
+    VideoEncoderUtils.cpp \
+    VideoEncoderHost.cpp
+
+ifeq ($(ENABLE_IMG_GRAPHICS),)
+    LOCAL_SRC_FILES += PVSoftMPEG4Encoder.cpp
+endif
+
+LOCAL_C_INCLUDES := \
+    $(TARGET_OUT_HEADERS)/libva \
+    $(call include-path-for, frameworks-native) \
+    $(TARGET_OUT_HEADERS)/pvr
+
+ifeq ($(ENABLE_IMG_GRAPHICS),)
+LOCAL_C_INCLUDES += \
+    frameworks/av/media/libstagefright/codecs/m4v_h263/enc/include \
+    frameworks/av/media/libstagefright/codecs/m4v_h263/enc/src \
+    frameworks/av/media/libstagefright/codecs/common/include \
+    frameworks/native/include/media/openmax \
+    frameworks/native/include/media/hardware \
+    frameworks/av/media/libstagefright/include
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libva \
+    libva-android \
+    libva-tpi \
+    libui \
+    libutils \
+    libhardware \
+    libintelmetadatabuffer
+
+LOCAL_COPY_HEADERS_TO  := libmix_videoencoder
+
+LOCAL_COPY_HEADERS := \
+    VideoEncoderHost.h \
+    VideoEncoderInterface.h \
+    VideoEncoderDef.h
+
+ifeq ($(VIDEO_ENC_LOG_ENABLE),true)
+LOCAL_CPPFLAGS += -DVIDEO_ENC_LOG_ENABLE
+endif
+
+ifeq ($(NO_BUFFER_SHARE),true)
+LOCAL_CPPFLAGS += -DNO_BUFFER_SHARE
+endif
+
+ifeq ($(VIDEO_ENC_STATISTICS_ENABLE),true)
+LOCAL_CPPFLAGS += -DVIDEO_ENC_STATISTICS_ENABLE
+endif
+
+ifeq ($(ENABLE_IMG_GRAPHICS),true)
+    LOCAL_CFLAGS += -DIMG_GFX
+
+    ifeq ($(ENABLE_MRFL_GRAPHICS),true)
+        LOCAL_CFLAGS += -DMRFLD_GFX
+    endif
+endif
+
+LOCAL_CFLAGS += -Werror
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libva_videoencoder
+
+include $(BUILD_SHARED_LIBRARY)
+
+# For libintelmetadatabuffer
+# =====================================================
+
+include $(CLEAR_VARS)
+
+VIDEO_ENC_LOG_ENABLE := true
+
+LOCAL_SRC_FILES := \
+    IntelMetadataBuffer.cpp
+
+LOCAL_COPY_HEADERS_TO  := libmix_videoencoder
+
+LOCAL_COPY_HEADERS := \
+    IntelMetadataBuffer.h
+
+ifeq ($(INTEL_VIDEO_XPROC_SHARING),true)
+LOCAL_SHARED_LIBRARIES := liblog libutils libbinder libgui \
+                          libui libcutils libhardware
+endif
+LOCAL_CFLAGS += -Werror
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libintelmetadatabuffer
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/videoencoder/IntelMetadataBuffer.cpp b/videoencoder/IntelMetadataBuffer.cpp
new file mode 100644
index 0000000..28f8e63
--- /dev/null
+++ b/videoencoder/IntelMetadataBuffer.cpp
@@ -0,0 +1,832 @@
+/*
+* Copyright (c) 2009-2011 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IntelMetadataBuffer"
+#include <wrs_omxil_core/log.h>
+
+#include "IntelMetadataBuffer.h"
+#include <string.h>
+#include <stdio.h>
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+#include <binder/IServiceManager.h>
+#include <binder/MemoryBase.h>
+#include <binder/Parcel.h>
+#include <utils/List.h>
+#include <utils/threads.h>
+#include <ui/GraphicBuffer.h>
+
+//#define TEST
+
+struct ShareMemMap {
+    uint32_t sessionflag;
+    intptr_t value;
+    intptr_t value_backup;
+    uint32_t type;
+    sp<MemoryBase> membase;
+    sp<GraphicBuffer> gbuffer;
+};
+
+List <ShareMemMap *> gShareMemMapList;
+Mutex gShareMemMapListLock;
+
+enum {
+    SHARE_MEM = IBinder::FIRST_CALL_TRANSACTION,
+    GET_MEM,
+    CLEAR_MEM,
+};
+
+enum {
+    ST_MEMBASE = 0,
+    ST_GFX,
+    ST_MAX,
+};
+
+#define REMOTE_PROVIDER 0x80000000
+#define REMOTE_CONSUMER 0x40000000
+
+static ShareMemMap* ReadMemObjFromBinder(const Parcel& data, uint32_t sessionflag, intptr_t value) {
+
+    uint32_t type = data.readInt32();
+    if (type >= ST_MAX)
+        return NULL;
+
+    ShareMemMap* map = new ShareMemMap;
+    map->sessionflag = sessionflag;
+    map->type = type;
+    map->value_backup = value;
+    map->membase = NULL;
+    map->gbuffer= NULL;
+
+//    LOGI("ReadMemObjFromBinder");
+
+    if (type == ST_MEMBASE) /*offset, size, heap*/
+    {
+        ssize_t offset = data.readInt32();
+        size_t size = data.readInt32();
+
+        sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
+
+        sp<MemoryBase> mem = new MemoryBase(heap, offset, size);
+        if (mem == NULL)
+        {
+            delete map;
+            return NULL;
+        }
+
+        map->value = (intptr_t)( mem->pointer() + 0x0FFF) & ~0x0FFF;
+        map->membase = mem;
+
+#ifdef TEST
+        ALOGI("membase heapID:%d, pointer:%x data:%x, aligned value:%x", \
+           heap->getHeapID(), mem->pointer(), *((intptr_t *)(mem->pointer())), map->value);
+#endif
+
+    }
+    else if (type == ST_GFX) /*graphicbuffer*/
+    {
+        sp<GraphicBuffer> buffer = new GraphicBuffer();
+        if (buffer == NULL)
+        {
+            delete map;
+            return NULL;
+        }
+        data.read(*buffer);
+
+        map->value = (intptr_t)buffer->handle;
+        map->gbuffer = buffer;
+
+#ifdef TEST
+        void* usrptr[3];
+        buffer->lock(GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_READ_OFTEN, &usrptr[0]);
+        buffer->unlock();
+        ALOGI("gfx handle:%p data:%x", (intptr_t)buffer->handle, *((intptr_t *)usrptr[0]));
+#endif
+    }
+
+    gShareMemMapListLock.lock();
+    gShareMemMapList.push_back(map);
+    gShareMemMapListLock.unlock();
+    return map;
+}
+
+static status_t WriteMemObjToBinder(Parcel& data, ShareMemMap* smem) {
+
+    if (smem->type >= ST_MAX)
+        return BAD_VALUE;
+
+//    LOGI("WriteMemObjToBinder");
+
+    data.writeInt32(smem->type);
+
+    if (smem->type == ST_MEMBASE) /*offset, size, heap*/
+    {
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = smem->membase->getMemory(&offset, &size);
+        data.writeInt32(offset);
+        data.writeInt32(size);
+        data.writeStrongBinder(heap->asBinder());
+#ifdef TEST
+        ALOGI("membase heapID:%d pointer:%x data:%x", \
+            heap->getHeapID(), smem->membase->pointer(), *((int *)(smem->membase->pointer())));
+#endif
+    }
+    else if (smem->type == ST_GFX) /*graphicbuffer*/
+        data.write(*(smem->gbuffer));
+
+    return NO_ERROR;
+}
+
+static void ClearLocalMem(uint32_t sessionflag)
+{
+    List<ShareMemMap *>::iterator node;
+
+    gShareMemMapListLock.lock();
+
+    for(node = gShareMemMapList.begin(); node != gShareMemMapList.end(); )
+    {
+        if ((*node)->sessionflag == sessionflag) //remove all buffers belong to this session
+        {
+            (*node)->membase = NULL;
+            (*node)->gbuffer = NULL;
+            delete (*node);
+            node = gShareMemMapList.erase(node);
+        }
+        else
+            node ++;
+    }
+
+    gShareMemMapListLock.unlock();
+}
+
+static ShareMemMap* FindShareMem(uint32_t sessionflag, intptr_t value, bool isBackup)
+{
+    List<ShareMemMap *>::iterator node;
+
+    gShareMemMapListLock.lock();
+    for(node = gShareMemMapList.begin(); node !=  gShareMemMapList.end(); node++)
+    {
+        if (isBackup)
+        {
+            if ((*node)->sessionflag == sessionflag && (*node)->value_backup == value)
+            {
+                gShareMemMapListLock.unlock();
+                return (*node);
+            }
+        }
+        else if ((*node)->sessionflag == sessionflag && (*node)->value == value)
+        {
+            gShareMemMapListLock.unlock();
+            return (*node);
+        }
+    }
+    gShareMemMapListLock.unlock();
+
+    return NULL;
+}
+
+static ShareMemMap* PopShareMem(uint32_t sessionflag, intptr_t value)
+{
+    List<ShareMemMap *>::iterator node;
+
+    gShareMemMapListLock.lock();
+    for(node = gShareMemMapList.begin(); node != gShareMemMapList.end(); node++)
+    {
+        if ((*node)->sessionflag == sessionflag && (*node)->value == value)
+        {
+            gShareMemMapList.erase(node);
+            gShareMemMapListLock.unlock();
+            return (*node);
+        }
+    }
+    gShareMemMapListLock.unlock();
+
+    return NULL;
+}
+
+static void PushShareMem(ShareMemMap* &smem)
+{
+    gShareMemMapListLock.lock();
+    gShareMemMapList.push_back(smem);
+    gShareMemMapListLock.unlock();
+}
+
+static sp<IBinder> GetIntelBufferSharingService() {
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->checkService(String16("media.IntelBufferSharing"));
+
+    if (binder == 0)
+        ALOGE("media.IntelBufferSharing service is not published");
+
+    return binder;
+}
+
+IntelBufferSharingService* IntelBufferSharingService::gBufferService = NULL;
+
+status_t IntelBufferSharingService::instantiate(){
+    status_t ret = NO_ERROR;
+
+    if (gBufferService == NULL) {
+        gBufferService = new IntelBufferSharingService();
+        ret = defaultServiceManager()->addService(String16("media.IntelBufferSharing"), gBufferService);
+        LOGI("IntelBufferSharingService::instantiate() ret = %d\n", ret);
+    }
+
+    return ret;
+}
+
+status_t IntelBufferSharingService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+
+    //TODO: if pid is int32?
+    pid_t pid = data.readInt32();
+    uint32_t sessionflag = data.readInt32();
+
+    switch(code)
+    {
+        case SHARE_MEM:
+        {
+
+            if (pid == getpid()) //in same process, should not use binder
+            {
+                ALOGE("onTransact in same process, wrong sessionflag?");
+                return UNKNOWN_ERROR;
+            }
+
+            intptr_t value = data.readIntPtr();
+
+//            LOGI("onTransact SHARE_MEM value=%x", value);
+
+            //different process
+            ShareMemMap* map = ReadMemObjFromBinder(data, sessionflag, value);
+            if (map == NULL)
+                return UNKNOWN_ERROR;
+
+            reply->writeIntPtr(map->value);
+
+            return NO_ERROR;
+        }
+        case CLEAR_MEM:
+        {
+//            LOGI("onTransact CLEAR_MEM sessionflag=%x", sessionflag);
+
+            if (pid == getpid()) //in same process, should not use binder
+            {
+                //same process, return same pointer in data
+                ALOGE("onTransact CLEAR_MEM in same process, wrong sessionflag?");
+                return UNKNOWN_ERROR;
+            }
+
+            ClearLocalMem(sessionflag);
+            return NO_ERROR;
+        }
+        case GET_MEM:
+        {
+
+            if (pid == getpid()) //in same process, should not use binder
+            {
+                ALOGE("onTransact GET_MEM in same process, wrong sessionflag?");
+                return UNKNOWN_ERROR;
+            }
+
+            intptr_t value = data.readIntPtr();
+
+//            LOGI("onTransact GET_MEM value=%x", value);
+
+            ShareMemMap* smem = FindShareMem(sessionflag, value, false);
+            if (smem && (NO_ERROR == WriteMemObjToBinder(*reply, smem)))
+                return NO_ERROR;
+            else
+                ALOGE("onTransact GET_MEM: Not find mem");
+
+            return UNKNOWN_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+
+    }
+    return NO_ERROR;
+}
+#endif
+
+IntelMetadataBuffer::IntelMetadataBuffer()
+{
+    mType = IntelMetadataBufferTypeCameraSource;
+    mValue = 0;
+    mInfo = NULL;
+    mExtraValues = NULL;
+    mExtraValues_Count = 0;
+    mBytes = NULL;
+    mSize = 0;
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    mSessionFlag = 0;
+#endif
+}
+
+IntelMetadataBuffer::IntelMetadataBuffer(IntelMetadataBufferType type, intptr_t value)
+{
+    mType = type;
+    mValue = value;
+    mInfo = NULL;
+    mExtraValues = NULL;
+    mExtraValues_Count = 0;
+    mBytes = NULL;
+    mSize = 0;
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    mSessionFlag = 0;
+#endif
+}
+
+IntelMetadataBuffer::~IntelMetadataBuffer()
+{
+    if (mInfo)
+        delete mInfo;
+
+    if (mExtraValues)
+        delete[] mExtraValues;
+
+    if (mBytes)
+        delete[] mBytes;
+}
+
+
+IntelMetadataBuffer::IntelMetadataBuffer(const IntelMetadataBuffer& imb)
+     :mType(imb.mType), mValue(imb.mValue), mInfo(NULL), mExtraValues(NULL),
+      mExtraValues_Count(imb.mExtraValues_Count), mBytes(NULL), mSize(imb.mSize)
+#ifdef INTEL_VIDEO_XPROC_SHARING
+      ,mSessionFlag(imb.mSessionFlag)
+#endif
+{
+    if (imb.mInfo)
+        mInfo = new ValueInfo(*imb.mInfo);
+
+    if (imb.mExtraValues)
+    {
+        mExtraValues = new intptr_t[mExtraValues_Count];
+        memcpy(mExtraValues, imb.mExtraValues, sizeof(mValue) * mExtraValues_Count);
+    }
+
+    if (imb.mBytes)
+    {
+        mBytes = new uint8_t[mSize];
+        memcpy(mBytes, imb.mBytes, mSize);
+    }
+}
+
+const IntelMetadataBuffer& IntelMetadataBuffer::operator=(const IntelMetadataBuffer& imb)
+{
+    mType = imb.mType;
+    mValue = imb.mValue;
+    mInfo = NULL;
+    mExtraValues = NULL;
+    mExtraValues_Count = imb.mExtraValues_Count;
+    mBytes = NULL;
+    mSize = imb.mSize;
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    mSessionFlag = imb.mSessionFlag;
+#endif
+
+    if (imb.mInfo)
+        mInfo = new ValueInfo(*imb.mInfo);
+
+    if (imb.mExtraValues)
+    {
+        mExtraValues = new intptr_t[mExtraValues_Count];
+        memcpy(mExtraValues, imb.mExtraValues, sizeof(mValue) * mExtraValues_Count);
+    }
+
+    if (imb.mBytes)
+    {
+        mBytes = new uint8_t[mSize];
+        memcpy(mBytes, imb.mBytes, mSize);
+    }
+
+    return *this;
+}
+
+IMB_Result IntelMetadataBuffer::GetType(IntelMetadataBufferType& type)
+{
+    type = mType;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::SetType(IntelMetadataBufferType type)
+{
+    if (type < IntelMetadataBufferTypeLast)
+        mType = type;
+    else
+        return IMB_INVAL_PARAM;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::GetValue(intptr_t& value)
+{
+    value = mValue;
+
+#ifndef INTEL_VIDEO_XPROC_SHARING
+    return IMB_SUCCESS;
+#else
+    if ((mSessionFlag & REMOTE_CONSUMER) == 0) //no sharing or is local consumer
+        return IMB_SUCCESS;
+
+    //try to find if it is already cached.
+    ShareMemMap* smem = FindShareMem(mSessionFlag, mValue, true);
+    if(smem)
+    {
+        value = smem->value;
+        return IMB_SUCCESS;
+    }
+
+    //is remote provider and not find from cache, then pull from service
+    sp<IBinder> binder = GetIntelBufferSharingService();
+    if (binder == 0)
+        return IMB_NO_SERVICE;
+
+    //Detect IntelBufferSharingService, share mem to service
+    Parcel data, reply;
+
+    //send pid, sessionflag, and memtype
+    pid_t pid = getpid();
+    //TODO: if pid is int32?
+    data.writeInt32(pid);
+    data.writeInt32(mSessionFlag);
+    data.writeIntPtr(mValue);
+
+    //do transcation
+    if (binder->transact(GET_MEM, data, &reply) != NO_ERROR)
+        return IMB_SERVICE_FAIL;
+
+    //get type/Mem OBJ
+    smem = ReadMemObjFromBinder(reply, mSessionFlag, mValue);
+    if (smem)
+        value = smem->value;
+    else
+        return IMB_SERVICE_FAIL;
+
+    return IMB_SUCCESS;
+#endif
+}
+
+IMB_Result IntelMetadataBuffer::SetValue(intptr_t value)
+{
+    mValue = value;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::GetValueInfo(ValueInfo* &info)
+{
+    info = mInfo;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::SetValueInfo(ValueInfo* info)
+{
+    if (info)
+    {
+        if (mInfo == NULL)
+            mInfo = new ValueInfo;
+
+        memcpy(mInfo, info, sizeof(ValueInfo));
+    }
+    else
+        return IMB_INVAL_PARAM;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::GetExtraValues(intptr_t* &values, uint32_t& num)
+{
+    values = mExtraValues;
+    num = mExtraValues_Count;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::SetExtraValues(intptr_t* values, uint32_t num)
+{
+    if (values && num > 0)
+    {
+        if (mExtraValues && mExtraValues_Count != num)
+        {
+            delete[] mExtraValues;
+            mExtraValues = NULL;
+        }
+
+        if (mExtraValues == NULL)
+            mExtraValues = new intptr_t[num];
+
+        memcpy(mExtraValues, values, sizeof(intptr_t) * num);
+        mExtraValues_Count = num;
+    }
+    else
+        return IMB_INVAL_PARAM;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::UnSerialize(uint8_t* data, uint32_t size)
+{
+    if (!data || size == 0)
+        return IMB_INVAL_PARAM;
+
+    IntelMetadataBufferType type;
+    intptr_t value;
+    uint32_t extrasize = size - sizeof(type) - sizeof(value);
+    ValueInfo* info = NULL;
+    intptr_t* ExtraValues = NULL;
+    uint32_t ExtraValues_Count = 0;
+
+    memcpy(&type, data, sizeof(type));
+    data += sizeof(type);
+    memcpy(&value, data, sizeof(value));
+    data += sizeof(value);
+
+    switch (type)
+    {
+        case IntelMetadataBufferTypeCameraSource:
+        case IntelMetadataBufferTypeEncoder:
+        case IntelMetadataBufferTypeUser:
+        {
+            if (extrasize >0 && extrasize < sizeof(ValueInfo))
+                return IMB_INVAL_BUFFER;
+
+            if (extrasize > sizeof(ValueInfo)) //has extravalues
+            {
+                if ( (extrasize - sizeof(ValueInfo)) % sizeof(mValue) != 0 )
+                    return IMB_INVAL_BUFFER;
+                ExtraValues_Count = (extrasize - sizeof(ValueInfo)) / sizeof(mValue);
+            }
+
+            if (extrasize > 0)
+            {
+                info = new ValueInfo;
+                memcpy(info, data, sizeof(ValueInfo));
+                data += sizeof(ValueInfo);
+            }
+
+            if (ExtraValues_Count > 0)
+            {
+                ExtraValues = new intptr_t[ExtraValues_Count];
+                memcpy(ExtraValues, data, ExtraValues_Count * sizeof(mValue));
+            }
+
+            break;
+        }
+        case IntelMetadataBufferTypeGrallocSource:
+            if (extrasize > 0)
+                return IMB_INVAL_BUFFER;
+
+            break;
+        default:
+            return IMB_INVAL_BUFFER;
+    }
+
+    //store data
+    mType = type;
+    mValue = value;
+    if (mInfo)
+        delete mInfo;
+    mInfo = info;
+    if (mExtraValues)
+        delete[] mExtraValues;
+    mExtraValues = ExtraValues;
+    mExtraValues_Count = ExtraValues_Count;
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    if (mInfo != NULL)
+        mSessionFlag = mInfo->sessionFlag;
+#endif
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::Serialize(uint8_t* &data, uint32_t& size)
+{
+    if (mBytes == NULL)
+    {
+        if (mType == IntelMetadataBufferTypeGrallocSource && mInfo)
+            return IMB_INVAL_PARAM;
+
+        //assemble bytes according members
+        mSize = sizeof(mType) + sizeof(mValue);
+        if (mInfo)
+        {
+            mSize += sizeof(ValueInfo);
+            if (mExtraValues)
+                mSize += sizeof(mValue) * mExtraValues_Count;
+        }
+
+        mBytes = new uint8_t[mSize];
+        uint8_t *ptr = mBytes;
+        memcpy(ptr, &mType, sizeof(mType));
+        ptr += sizeof(mType);
+        memcpy(ptr, &mValue, sizeof(mValue));
+        ptr += sizeof(mValue);
+
+        if (mInfo)
+        {
+        #ifdef INTEL_VIDEO_XPROC_SHARING
+            mInfo->sessionFlag = mSessionFlag;
+        #endif
+            memcpy(ptr, mInfo, sizeof(ValueInfo));
+            ptr += sizeof(ValueInfo);
+
+            if (mExtraValues)
+                memcpy(ptr, mExtraValues, mExtraValues_Count * sizeof(mValue));
+        }
+    }
+
+    data = mBytes;
+    size = mSize;
+
+    return IMB_SUCCESS;
+}
+
+uint32_t IntelMetadataBuffer::GetMaxBufferSize()
+{
+    return 256;
+}
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+IMB_Result IntelMetadataBuffer::GetSessionFlag(uint32_t& sessionflag)
+{
+    sessionflag = mSessionFlag;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::SetSessionFlag(uint32_t sessionflag)
+{
+    mSessionFlag = sessionflag;
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::ShareValue(sp<MemoryBase> mem)
+{
+    mValue = (intptr_t)((intptr_t) ( mem->pointer() + 0x0FFF) & ~0x0FFF);
+
+    if ( !(mSessionFlag & REMOTE_PROVIDER) && !(mSessionFlag & REMOTE_CONSUMER)) //no sharing
+        return IMB_SUCCESS;
+
+    if (mSessionFlag & REMOTE_PROVIDER) //is remote provider
+    {
+        sp<IBinder> binder = GetIntelBufferSharingService();
+        if (binder == 0)
+            return IMB_NO_SERVICE;
+
+        //Detect IntelBufferSharingService, share mem to service
+        Parcel data, reply;
+
+        //send pid, sessionflag, and value
+        pid_t pid = getpid();
+        //TODO: if pid is int32?
+        data.writeInt32(pid);
+        data.writeInt32(mSessionFlag);
+        data.writeIntPtr(mValue);
+
+        //send type/obj (offset/size/MemHeap)
+        ShareMemMap smem;
+        smem.membase = mem;
+        smem.type = ST_MEMBASE;
+        if (WriteMemObjToBinder(data, &smem) != NO_ERROR)
+            return IMB_SERVICE_FAIL;
+
+        //do transcation
+        if (binder->transact(SHARE_MEM, data, &reply) != NO_ERROR)
+            return IMB_SERVICE_FAIL;
+
+        //set new value gotten from peer
+        mValue = reply.readIntPtr();
+//        LOGI("ShareValue(membase) Get reply from sevice, new value:%x\n", mValue);
+    }
+    else  //is local provider , direct access list
+    {
+        ShareMemMap* smem = new ShareMemMap;
+        smem->sessionflag = mSessionFlag;
+        smem->value = mValue;
+        smem->value_backup = mValue;
+        smem->type = ST_MEMBASE;
+        smem->membase = mem;
+        smem->gbuffer = NULL;
+        PushShareMem(smem);
+    }
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::ShareValue(sp<GraphicBuffer> gbuffer)
+{
+    mValue = (intptr_t)gbuffer->handle;
+
+    if ( !(mSessionFlag & REMOTE_PROVIDER) && !(mSessionFlag & REMOTE_CONSUMER)) //no sharing
+        return IMB_SUCCESS;
+
+    if (mSessionFlag & REMOTE_PROVIDER == 0) //is remote provider
+    {
+        sp<IBinder> binder = GetIntelBufferSharingService();
+        if (binder == 0)
+            return IMB_NO_SERVICE;
+
+        Parcel data, reply;
+
+        //send pid, sessionflag, and memtype
+        pid_t pid = getpid();
+        //TODO: if pid is int32 ?
+        data.writeInt32(pid);
+        data.writeInt32(mSessionFlag);
+        data.writeIntPtr(mValue);
+
+        //send value/graphicbuffer obj
+        ShareMemMap smem;
+        smem.gbuffer = gbuffer;
+        smem.type = ST_GFX;
+        if (WriteMemObjToBinder(data, &smem) != NO_ERROR)
+            return IMB_SERVICE_FAIL;
+
+        //do transcation
+        if (binder->transact(SHARE_MEM, data, &reply) != NO_ERROR)
+            return IMB_SERVICE_FAIL;
+
+        //set new value gotten from peer
+        mValue = reply.readIntPtr();
+//        LOGI("ShareValue(gfx) Get reply from sevice, new value:%x\n", mValue);
+    }
+    else //is local provider, direct access list
+    {
+        ShareMemMap* smem = new ShareMemMap;
+        smem->sessionflag = mSessionFlag;
+        smem->value = mValue;
+        smem->value_backup = mValue;
+        smem->type = ST_GFX;
+        smem->membase = NULL;
+        smem->gbuffer = gbuffer;
+        PushShareMem(smem);
+    }
+
+    return IMB_SUCCESS;
+}
+
+IMB_Result IntelMetadataBuffer::ClearContext(uint32_t sessionflag, bool isProvider)
+{
+    if ( !(sessionflag & REMOTE_PROVIDER) && !(sessionflag & REMOTE_CONSUMER)) //no sharing
+        return IMB_SUCCESS;
+
+    //clear local firstly
+    ClearLocalMem(sessionflag);
+
+    //clear mem on service if it is remote user
+    if ((isProvider && (sessionflag & REMOTE_PROVIDER)) || (!isProvider && (sessionflag & REMOTE_CONSUMER)))
+    {
+//        LOGI("CLEAR_MEM sessionflag=%x", sessionflag);
+
+        sp<IBinder> binder = GetIntelBufferSharingService();
+        if (binder == 0)
+            return IMB_NO_SERVICE;
+
+        //Detect IntelBufferSharingService, unshare mem from service
+        Parcel data, reply;
+
+        //send pid and sessionflag
+        pid_t pid = getpid();
+        //TODO: if pid is int32?
+        data.writeInt32(pid);
+        data.writeInt32(sessionflag);
+
+        if (binder->transact(CLEAR_MEM, data, &reply) != NO_ERROR)
+            return IMB_SERVICE_FAIL;
+    }
+
+    return IMB_SUCCESS;
+}
+
+uint32_t IntelMetadataBuffer::MakeSessionFlag(bool romoteProvider, bool remoteConsumer, uint16_t sindex)
+{
+    uint32_t sessionflag = 0;
+
+    if (romoteProvider)
+        sessionflag |= REMOTE_PROVIDER;
+
+    if (remoteConsumer)
+        sessionflag |= REMOTE_CONSUMER;
+
+    return sessionflag + sindex;
+}
+#endif
diff --git a/videoencoder/IntelMetadataBuffer.h b/videoencoder/IntelMetadataBuffer.h
new file mode 100644
index 0000000..20a9590
--- /dev/null
+++ b/videoencoder/IntelMetadataBuffer.h
@@ -0,0 +1,162 @@
+/*
+* Copyright (c) 2009-2011 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 _INTEL_METADATA_BUFFER_H_
+#define _INTEL_METADATA_BUFFER_H_
+
+#include <stdint.h>
+
+//#define INTEL_VIDEO_XPROC_SHARING
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+#include <binder/MemoryBase.h>
+#include <ui/GraphicBuffer.h>
+
+using namespace android;
+#endif
+#define STRING_TO_FOURCC(format) ((uint32_t)(((format)[0])|((format)[1]<<8)|((format)[2]<<16)|((format)[3]<<24)))
+
+typedef enum {
+    IMB_SUCCESS = 0,
+    IMB_INVAL_PARAM = 1,
+    IMB_INVAL_BUFFER = 2,
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    IMB_NO_SERVICE = 3,
+    IMB_SERVICE_FAIL = 4,
+#endif
+}IMB_Result;
+
+typedef enum {
+    MEM_MODE_MALLOC = 1,
+    MEM_MODE_CI = 2,
+    MEM_MODE_V4L2 = 4,
+    MEM_MODE_SURFACE = 8,
+    MEM_MODE_USRPTR = 16,
+    MEM_MODE_GFXHANDLE = 32,
+    MEM_MODE_KBUFHANDLE = 64,
+    MEM_MODE_ION = 128,
+    MEM_MODE_NONECACHE_USRPTR = 256,
+}MemMode;
+
+typedef struct {
+        MemMode mode; 			//memory type, vasurface/malloc/gfx/ion/v4l2/ci etc
+        intptr_t handle;		//handle
+        uint32_t size;      		//memory size
+        uint32_t width;			//picture width
+        uint32_t height;		//picture height
+        uint32_t lumaStride;		//picture luma stride
+        uint32_t chromStride;		//picture chrom stride
+        uint32_t format;		//color format
+        uint32_t s3dformat;		//S3D format
+#ifdef INTEL_VIDEO_XPROC_SHARING
+        uint32_t sessionFlag;     //for buffer sharing session
+#endif
+}ValueInfo;
+
+typedef enum {
+    IntelMetadataBufferTypeCameraSource = 0,   //same with kMetadataBufferTypeCameraSource in framework
+    IntelMetadataBufferTypeGrallocSource = 1,  //same with kMetadataBufferTypeGrallocSource in framework
+
+    IntelMetadataBufferTypeExtension = 0xFF,   //intel extended type
+    IntelMetadataBufferTypeEncoder = IntelMetadataBufferTypeExtension,        //for WiDi clone mode
+    IntelMetadataBufferTypeUser = IntelMetadataBufferTypeExtension + 1,       //for WiDi user mode
+    IntelMetadataBufferTypeLast = IntelMetadataBufferTypeExtension + 2,       //type number
+}IntelMetadataBufferType;
+
+class IntelMetadataBuffer {
+public:
+    IntelMetadataBuffer();                                          //for generator
+    IntelMetadataBuffer(IntelMetadataBufferType type, intptr_t value);    //for quick generator
+    ~IntelMetadataBuffer();
+
+    IntelMetadataBuffer(const IntelMetadataBuffer& imb);
+    const IntelMetadataBuffer& operator=(const IntelMetadataBuffer& imb);
+
+    IMB_Result GetType(IntelMetadataBufferType &type);
+    IMB_Result SetType(IntelMetadataBufferType type);
+    IMB_Result GetValue(intptr_t &value);
+    IMB_Result SetValue(intptr_t value);
+    IMB_Result GetValueInfo(ValueInfo* &info);
+    IMB_Result SetValueInfo(ValueInfo *info);
+    IMB_Result GetExtraValues(intptr_t* &values, uint32_t &num);
+    IMB_Result SetExtraValues(intptr_t *values, uint32_t num);
+
+    //New API for bytes input/ouput, UnSerialize=SetBytes, Serialize=GetBytes
+    IMB_Result UnSerialize(uint8_t* data, uint32_t size);
+    IMB_Result Serialize(uint8_t* &data, uint32_t& size);
+
+    //Static, for get max IntelMetadataBuffer size
+    static uint32_t GetMaxBufferSize();
+
+private:
+    IntelMetadataBufferType mType;
+    intptr_t mValue;
+    ValueInfo* mInfo;
+
+    intptr_t* mExtraValues;
+    uint32_t mExtraValues_Count;
+
+    uint8_t* mBytes;
+    uint32_t mSize;
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+public:
+    IMB_Result ShareValue(sp<MemoryBase> mem);
+    IMB_Result ShareValue(sp<GraphicBuffer> gbuffer);
+
+    IMB_Result GetSessionFlag(uint32_t &sessionflag);
+    IMB_Result SetSessionFlag(uint32_t sessionflag);
+
+    //Static, for clear context
+    static IMB_Result ClearContext(uint32_t sessionflag, bool isProvider = true);
+
+    static const uint16_t CAMERA_BASE =    0x0000;
+    static const uint16_t WIDI_BASE =      0x1000;
+    static const uint16_t WEBRTC_BASE =    0x2000;
+    static const uint16_t VIDEOEDIT_BASE = 0x3000;
+
+   static uint32_t MakeSessionFlag(bool romoteProvider, bool remoteConsumer, uint16_t sindex);
+
+private:
+    uint32_t mSessionFlag;
+#endif
+
+};
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+
+class IntelBufferSharingService : public BBinder
+{
+private:
+    static IntelBufferSharingService *gBufferService;
+
+public:
+    static status_t instantiate();
+
+    IntelBufferSharingService(){
+        ALOGI("IntelBufferSharingService instance is created");
+    }
+
+    ~IntelBufferSharingService(){
+        ALOGI("IntelBufferSharingService instance is destroyed");
+    }
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+};
+#endif
+
+#endif
+
diff --git a/videoencoder/PVSoftMPEG4Encoder.cpp b/videoencoder/PVSoftMPEG4Encoder.cpp
new file mode 100644
index 0000000..6b893df
--- /dev/null
+++ b/videoencoder/PVSoftMPEG4Encoder.cpp
@@ -0,0 +1,513 @@
+/*
+* Copyright (c) 2009-2011 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PVSoftMPEG4Encoder"
+#include <wrs_omxil_core/log.h>
+
+#include "mp4enc_api.h"
+#include "OMX_Video.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <ui/GraphicBufferMapper.h>
+#include <ui/Rect.h>
+
+#include "PVSoftMPEG4Encoder.h"
+#include "VideoEncoderLog.h"
+
+#define ALIGN(x, align)                  (((x) + (align) - 1) & (~((align) - 1)))
+
+inline static void ConvertYUV420SemiPlanarToYUV420Planar(
+        uint8_t *inyuv, uint8_t* outyuv,
+        int32_t width, int32_t height) {
+
+    int32_t outYsize = width * height;
+    uint32_t *outy =  (uint32_t *) outyuv;
+    uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
+    uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
+
+    /* Y copying */
+    memcpy(outy, inyuv, outYsize);
+
+    /* U & V copying */
+    uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
+    for (int32_t i = height >> 1; i > 0; --i) {
+        for (int32_t j = width >> 2; j > 0; --j) {
+            uint32_t temp = *inyuv_4++;
+            uint32_t tempU = temp & 0xFF;
+            tempU = tempU | ((temp >> 8) & 0xFF00);
+
+            uint32_t tempV = (temp >> 8) & 0xFF;
+            tempV = tempV | ((temp >> 16) & 0xFF00);
+
+            // Flip U and V
+            *outcb++ = tempU;
+            *outcr++ = tempV;
+        }
+    }
+}
+
+inline static void trimBuffer(uint8_t *dataIn, uint8_t *dataOut,
+        int32_t width, int32_t height,
+        int32_t alignedHeight, int32_t stride) {
+    int32_t h;
+    uint8_t *y_start, *uv_start, *_y_start, *_uv_start;
+    y_start = dataOut;
+    uv_start = dataOut + width * height;
+    _y_start = dataIn;
+    _uv_start = dataIn + stride * alignedHeight;
+
+    for (h = 0; h < height; h++)
+        memcpy(y_start + h * width, _y_start + h * stride, width);
+    for (h = 0; h < height / 2; h++)
+        memcpy(uv_start + h * width,
+                _uv_start + h * stride, width);
+}
+
+PVSoftMPEG4Encoder::PVSoftMPEG4Encoder(const char *name)
+    :  mEncodeMode(COMBINE_MODE_WITH_ERR_RES),
+      mVideoWidth(176),
+      mVideoHeight(144),
+      mVideoFrameRate(30),
+      mVideoBitRate(192000),
+      mVideoColorFormat(OMX_COLOR_FormatYUV420SemiPlanar),
+      mStoreMetaDataInBuffers(false),
+      mIDRFrameRefreshIntervalInSec(1),
+      mNumInputFrames(-1),
+      mStarted(false),
+      mSawInputEOS(false),
+      mSignalledError(false),
+      mHandle(new tagvideoEncControls),
+      mEncParams(new tagvideoEncOptions),
+      mInputFrameData(NULL)
+{
+
+    if (!strcmp(name, "OMX.google.h263.encoder")) {
+        mEncodeMode = H263_MODE;
+        LOG_I("construct h263 encoder");
+    } else {
+        CHECK(!strcmp(name, "OMX.google.mpeg4.encoder"));
+        LOG_I("construct mpeg4 encoder");
+    }
+
+    setDefaultParams();
+#if NO_BUFFER_SHARE
+    mVASurfaceMappingAction |= MAPACT_COPY;
+#endif
+
+    LOG_I("Construct PVSoftMPEG4Encoder");
+
+}
+
+PVSoftMPEG4Encoder::~PVSoftMPEG4Encoder() {
+    LOG_I("Destruct PVSoftMPEG4Encoder");
+    releaseEncoder();
+
+}
+
+void PVSoftMPEG4Encoder::setDefaultParams() {
+
+    // Set default value for input parameters
+    mComParams.profile = VAProfileH264Baseline;
+    mComParams.level = 41;
+    mComParams.rawFormat = RAW_FORMAT_NV12;
+    mComParams.frameRate.frameRateNum = 30;
+    mComParams.frameRate.frameRateDenom = 1;
+    mComParams.resolution.width = 0;
+    mComParams.resolution.height = 0;
+    mComParams.intraPeriod = 30;
+    mComParams.rcMode = RATE_CONTROL_NONE;
+    mComParams.rcParams.initQP = 15;
+    mComParams.rcParams.minQP = 0;
+    mComParams.rcParams.bitRate = 640000;
+    mComParams.rcParams.targetPercentage= 0;
+    mComParams.rcParams.windowSize = 0;
+    mComParams.rcParams.disableFrameSkip = 0;
+    mComParams.rcParams.disableBitsStuffing = 1;
+    mComParams.cyclicFrameInterval = 30;
+    mComParams.refreshType = VIDEO_ENC_NONIR;
+    mComParams.airParams.airMBs = 0;
+    mComParams.airParams.airThreshold = 0;
+    mComParams.airParams.airAuto = 1;
+    mComParams.disableDeblocking = 2;
+    mComParams.syncEncMode = false;
+    mComParams.codedBufNum = 2;
+
+}
+
+Encode_Status PVSoftMPEG4Encoder::initEncParams() {
+    CHECK(mHandle != NULL);
+    memset(mHandle, 0, sizeof(tagvideoEncControls));
+
+    CHECK(mEncParams != NULL);
+    memset(mEncParams, 0, sizeof(tagvideoEncOptions));
+    if (!PVGetDefaultEncOption(mEncParams, 0)) {
+        LOG_E("Failed to get default encoding parameters");
+        return ENCODE_FAIL;
+    }
+    mEncParams->encMode = mEncodeMode;
+    mEncParams->encWidth[0] = mVideoWidth;
+    mEncParams->encHeight[0] = mVideoHeight;
+    mEncParams->encFrameRate[0] = mVideoFrameRate;
+    mEncParams->rcType = VBR_1;
+    mEncParams->vbvDelay = 5.0f;
+
+    // FIXME:
+    // Add more profile and level support for MPEG4 encoder
+    mEncParams->profile_level = CORE_PROFILE_LEVEL2;
+    mEncParams->packetSize = 32;
+    mEncParams->rvlcEnable = PV_OFF;
+    mEncParams->numLayers = 1;
+    mEncParams->timeIncRes = 1000;
+    mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
+
+    mEncParams->bitRate[0] = mVideoBitRate <= 2000000 ? mVideoBitRate : 2000000;
+    mEncParams->iQuant[0] = 15;
+    mEncParams->pQuant[0] = 12;
+    mEncParams->quantType[0] = 0;
+    mEncParams->noFrameSkipped = PV_OFF;
+
+    mTrimedInputData =
+        (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+    CHECK(mTrimedInputData != NULL);
+
+    if (mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
+        // Color conversion is needed.
+        CHECK(mInputFrameData == NULL);
+        mInputFrameData =
+            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+        CHECK(mInputFrameData != NULL);
+    }
+
+    // PV's MPEG4 encoder requires the video dimension of multiple
+    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+        LOG_E("Video frame size %dx%d must be a multiple of 16",
+            mVideoWidth, mVideoHeight);
+        return ENCODE_INVALID_PARAMS;
+    }
+
+    // Set IDR frame refresh interval
+    if (mIDRFrameRefreshIntervalInSec < 0) {
+        mEncParams->intraPeriod = -1;
+    } else if (mIDRFrameRefreshIntervalInSec == 0) {
+        mEncParams->intraPeriod = 1;  // All I frames
+    } else {
+        mEncParams->intraPeriod =
+            (mIDRFrameRefreshIntervalInSec * mVideoFrameRate);
+    }
+
+    mEncParams->numIntraMB = 0;
+    mEncParams->sceneDetect = PV_ON;
+    mEncParams->searchRange = 16;
+    mEncParams->mv8x8Enable = PV_OFF;
+    mEncParams->gobHeaderInterval = 0;
+    mEncParams->useACPred = PV_ON;
+    mEncParams->intraDCVlcTh = 0;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status PVSoftMPEG4Encoder::initEncoder() {
+    LOG_V("Begin\n");
+
+    CHECK(!mStarted);
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    if (ENCODE_SUCCESS != (ret = initEncParams())) {
+        LOG_E("Failed to initialized encoder params");
+        mSignalledError = true;
+        return ret;
+    }
+
+    if (!PVInitVideoEncoder(mHandle, mEncParams)) {
+        LOG_E("Failed to initialize the encoder");
+        mSignalledError = true;
+        return ENCODE_FAIL;
+    }
+
+    mNumInputFrames = -1;  // 1st buffer for codec specific data
+    mStarted = true;
+    mCurTimestampUs = 0;
+    mLastTimestampUs = 0;
+    mVolHeaderLength = 256;
+
+    LOG_V("End\n");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status PVSoftMPEG4Encoder::releaseEncoder() {
+    LOG_V("Begin\n");
+
+    if (!mStarted) {
+        return ENCODE_SUCCESS;
+    }
+
+    PVCleanUpVideoEncoder(mHandle);
+
+    delete mTrimedInputData;
+    mTrimedInputData = NULL;
+
+    delete mInputFrameData;
+    mInputFrameData = NULL;
+
+    delete mEncParams;
+    mEncParams = NULL;
+
+    delete mHandle;
+    mHandle = NULL;
+
+    mStarted = false;
+
+    LOG_V("End\n");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status PVSoftMPEG4Encoder::setParameters(
+        VideoParamConfigSet *videoEncParams)
+{
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+    LOG_I("Config type = %d\n", (int)videoEncParams->type);
+
+    if (mStarted) {
+        LOG_E("Encoder has been initialized, should use setConfig to change configurations\n");
+        return ENCODE_ALREADY_INIT;
+    }
+
+    switch (videoEncParams->type) {
+        case VideoParamsTypeCommon: {
+
+            VideoParamsCommon *paramsCommon =
+                    reinterpret_cast <VideoParamsCommon *> (videoEncParams);
+            if (paramsCommon->size != sizeof (VideoParamsCommon)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            if(paramsCommon->codedBufNum < 2)
+                paramsCommon->codedBufNum =2;
+            mComParams = *paramsCommon;
+
+            mVideoWidth = mComParams.resolution.width;
+            mVideoHeight = mComParams.resolution.height;
+            mVideoFrameRate =  mComParams.frameRate.frameRateNum / \
+                               mComParams.frameRate.frameRateDenom;
+            mVideoBitRate = mComParams.rcParams.bitRate;
+            mVideoColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+            break;
+        }
+
+        case VideoParamsTypeStoreMetaDataInBuffers: {
+            VideoParamsStoreMetaDataInBuffers *metadata =
+                    reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
+
+            if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mStoreMetaDataInBuffers = metadata->isEnabled;
+
+            break;
+        }
+
+        default: {
+            LOG_I ("Wrong ParamType here\n");
+            break;
+        }
+    }
+
+    return ret;
+}
+
+Encode_Status PVSoftMPEG4Encoder::getParameters(
+        VideoParamConfigSet *videoEncParams) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+    LOG_I("Config type = %d\n", (int)videoEncParams->type);
+
+    switch (videoEncParams->type) {
+        case VideoParamsTypeCommon: {
+
+            VideoParamsCommon *paramsCommon =
+                    reinterpret_cast <VideoParamsCommon *> (videoEncParams);
+
+            if (paramsCommon->size != sizeof (VideoParamsCommon)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            *paramsCommon = mComParams;
+            break;
+        }
+
+        case VideoParamsTypeStoreMetaDataInBuffers: {
+            VideoParamsStoreMetaDataInBuffers *metadata =
+                    reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
+
+            if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            metadata->isEnabled = mStoreMetaDataInBuffers;
+
+            break;
+        }
+
+        default: {
+            LOG_I ("Wrong ParamType here\n");
+            break;
+        }
+
+    }
+    return ret;
+}
+
+Encode_Status PVSoftMPEG4Encoder::encode(VideoEncRawBuffer *inBuffer, uint32_t timeout)
+{
+    LOG_V("Begin\n");
+
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    if (mCurTimestampUs <= inBuffer->timeStamp) {
+        mLastTimestampUs = mCurTimestampUs;
+        mCurTimestampUs = inBuffer->timeStamp;
+    }
+
+    if (mNumInputFrames < 0) {
+        if (!PVGetVolHeader(mHandle, mVolHeader, &mVolHeaderLength, 0)) {
+            LOG_E("Failed to get VOL header");
+            mSignalledError = true;
+            return ENCODE_FAIL;
+        }
+        LOG_I("Output VOL header: %d bytes", mVolHeaderLength);
+        mNumInputFrames++;
+        //return ENCODE_SUCCESS;
+    }
+
+    if (mStoreMetaDataInBuffers) {
+        IntelMetadataBuffer imb;
+        int32_t type;
+        int32_t value;
+        uint8_t *img;
+        const android::Rect rect(mVideoWidth, mVideoHeight);
+        android::status_t res;
+        ValueInfo vinfo;
+        ValueInfo *pvinfo = &vinfo;
+        CHECK(IMB_SUCCESS == imb.UnSerialize(inBuffer->data, inBuffer->size));
+        imb.GetType((::IntelMetadataBufferType&)type);
+        imb.GetValue(value);
+        imb.GetValueInfo(pvinfo);
+        if(pvinfo == NULL) {
+            res = android::GraphicBufferMapper::get().lock((buffer_handle_t)value,
+                    GRALLOC_USAGE_SW_READ_MASK,
+                    rect, (void**)&img);
+        } else {
+            img = (uint8_t*)value;
+        }
+        if (pvinfo != NULL)
+            trimBuffer(img, mTrimedInputData, pvinfo->width, pvinfo->height,
+                   pvinfo->height, pvinfo->lumaStride);
+        else {
+            //NV12 Y-TILED
+            trimBuffer(img, mTrimedInputData, mVideoWidth, mVideoHeight,
+                    ALIGN(mVideoHeight, 32), ALIGN(mVideoWidth, 128));
+            android::GraphicBufferMapper::get().unlock((buffer_handle_t)value);
+        }
+    } else {
+        memcpy(mTrimedInputData, inBuffer->data,
+                (mVideoWidth * mVideoHeight * 3 ) >> 1);
+    }
+
+    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+        ConvertYUV420SemiPlanarToYUV420Planar(
+                mTrimedInputData, mInputFrameData, mVideoWidth, mVideoHeight);
+    } else {
+        memcpy(mTrimedInputData, mInputFrameData,
+                (mVideoWidth * mVideoHeight * 3 ) >> 1);
+    }
+
+    LOG_V("End\n");
+
+    return ret;
+}
+
+Encode_Status PVSoftMPEG4Encoder::getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout)
+{
+    LOG_V("Begin\n");
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    uint8_t *outPtr = outBuffer->data;
+    int32_t dataLength = outBuffer->bufferSize;
+    outBuffer->flag = 0;
+
+    if ((mEncodeMode == COMBINE_MODE_WITH_ERR_RES) &&
+            (outBuffer->format == OUTPUT_CODEC_DATA)) {
+        memcpy(outPtr, mVolHeader, mVolHeaderLength);
+        ++mNumInputFrames;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_CODECCONFIG;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
+        outBuffer->dataSize = mVolHeaderLength;
+        outBuffer->remainingSize = 0;
+        return ENCODE_SUCCESS;
+    }
+
+    outBuffer->timeStamp = mCurTimestampUs;
+    LOG_I("info.mTimeUs %lld\n", outBuffer->timeStamp);
+
+    VideoEncFrameIO vin, vout;
+    memset(&vin, 0, sizeof(vin));
+    memset(&vout, 0, sizeof(vout));
+    vin.height = ((mVideoHeight  + 15) >> 4) << 4;
+    vin.pitch = ((mVideoWidth + 15) >> 4) << 4;
+    vin.timestamp = (outBuffer->timeStamp + 500) / 1000;  // in ms
+    vin.yChan = mInputFrameData;
+    vin.uChan = vin.yChan + vin.height * vin.pitch;
+    vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
+
+    unsigned long modTimeMs = 0;
+    int32_t nLayer = 0;
+    MP4HintTrack hintTrack;
+    if (!PVEncodeVideoFrame(mHandle, &vin, &vout,
+                &modTimeMs, outPtr, &dataLength, &nLayer) ||
+            !PVGetHintTrack(mHandle, &hintTrack)) {
+        LOG_E("Failed to encode frame or get hink track at frame %lld",
+                mNumInputFrames);
+        mSignalledError = true;
+        hintTrack.CodeType = 0;
+        ret = ENCODE_FAIL;
+    }
+    LOG_I("dataLength %d\n", dataLength);
+    CHECK(NULL == PVGetOverrunBuffer(mHandle));
+    if (hintTrack.CodeType == 0) {  // I-frame serves as sync frame
+        outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
+    }
+
+    ++mNumInputFrames;
+
+    outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+    outBuffer->dataSize = dataLength;
+
+    LOG_V("End\n");
+
+    return ret;
+}
+
diff --git a/videoencoder/PVSoftMPEG4Encoder.h b/videoencoder/PVSoftMPEG4Encoder.h
new file mode 100644
index 0000000..5d34e9f
--- /dev/null
+++ b/videoencoder/PVSoftMPEG4Encoder.h
@@ -0,0 +1,84 @@
+/*
+* Copyright (c) 2009-2011 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 __PV_SOFT_MPEG4_ENCODER__
+#define __PV_SOFT_MPEG4_ENCODER__
+
+#include <va/va.h>
+#include <va/va_tpi.h>
+#include "VideoEncoderDef.h"
+#include "VideoEncoderInterface.h"
+#include "IntelMetadataBuffer.h"
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/foundation/ABase.h>
+#include "SimpleSoftOMXComponent.h"
+#include "mp4enc_api.h"
+
+class PVSoftMPEG4Encoder : IVideoEncoder {
+
+public:
+    PVSoftMPEG4Encoder(const char *name);
+    virtual ~PVSoftMPEG4Encoder();
+
+    virtual Encode_Status start(void) {return initEncoder();}
+    virtual void flush(void) { }
+    virtual Encode_Status stop(void) {return releaseEncoder();}
+    virtual Encode_Status encode(VideoEncRawBuffer *inBuffer, uint32_t timeout);
+
+    virtual Encode_Status getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout);
+
+    virtual Encode_Status getParameters(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status setParameters(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status setConfig(VideoParamConfigSet *videoEncConfig) {return ENCODE_SUCCESS;}
+    virtual Encode_Status getConfig(VideoParamConfigSet *videoEncConfig) {return ENCODE_SUCCESS;}
+    virtual Encode_Status getMaxOutSize(uint32_t *maxSize) {return ENCODE_SUCCESS;}
+
+private:
+    void setDefaultParams(void);
+    VideoParamsCommon mComParams;
+
+    MP4EncodingMode mEncodeMode;
+    int32_t  mVideoWidth;
+    int32_t  mVideoHeight;
+    int32_t  mVideoFrameRate;
+    int32_t  mVideoBitRate;
+    int32_t  mVideoColorFormat;
+    bool     mStoreMetaDataInBuffers;
+    int32_t  mIDRFrameRefreshIntervalInSec;
+
+    int64_t  mNumInputFrames;
+    bool     mStarted;
+    bool     mSawInputEOS;
+    bool     mSignalledError;
+    int64_t mCurTimestampUs;
+    int64_t mLastTimestampUs;
+
+    tagvideoEncControls   *mHandle;
+    tagvideoEncOptions    *mEncParams;
+    uint8_t               *mInputFrameData;
+    uint8_t               *mTrimedInputData;
+    uint8_t mVolHeader[256];
+    int32_t mVolHeaderLength;
+
+    Encode_Status initEncParams();
+    Encode_Status initEncoder();
+    Encode_Status releaseEncoder();
+
+    DISALLOW_EVIL_CONSTRUCTORS(PVSoftMPEG4Encoder);
+};
+
+#endif
diff --git a/videoencoder/VideoEncoderAVC.cpp b/videoencoder/VideoEncoderAVC.cpp
new file mode 100644
index 0000000..47d8174
--- /dev/null
+++ b/videoencoder/VideoEncoderAVC.cpp
@@ -0,0 +1,1377 @@
+/*
+* Copyright (c) 2009-2011 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 <string.h>
+#include <stdlib.h>
+#include "VideoEncoderLog.h"
+#include "VideoEncoderAVC.h"
+#include <va/va_tpi.h>
+#include <va/va_enc_h264.h>
+#include <bitstream.h>
+
+VideoEncoderAVC::VideoEncoderAVC()
+    :VideoEncoderBase() {
+    if(VideoEncoderBase::queryProfileLevelConfig(mVADisplay, VAProfileH264High) == ENCODE_SUCCESS){
+        mComParams.profile = VAProfileH264High;
+        mComParams.level = 42;
+    }else if(VideoEncoderBase::queryProfileLevelConfig(mVADisplay, VAProfileH264Main) == ENCODE_SUCCESS){
+        mComParams.profile = VAProfileH264Main;
+        mComParams.level = 41;
+    }
+    mVideoParamsAVC.basicUnitSize = 0;
+    mVideoParamsAVC.VUIFlag = 0;
+    mVideoParamsAVC.sliceNum.iSliceNum = 2;
+    mVideoParamsAVC.sliceNum.pSliceNum = 2;
+    mVideoParamsAVC.idrInterval = 2;
+    mVideoParamsAVC.ipPeriod = 1;
+    mVideoParamsAVC.maxSliceSize = 0;
+    mVideoParamsAVC.delimiterType = AVC_DELIMITER_ANNEXB;
+    mSliceNum = 2;
+    mVideoParamsAVC.crop.LeftOffset = 0;
+    mVideoParamsAVC.crop.RightOffset = 0;
+    mVideoParamsAVC.crop.TopOffset = 0;
+    mVideoParamsAVC.crop.BottomOffset = 0;
+    mVideoParamsAVC.SAR.SarWidth = 0;
+    mVideoParamsAVC.SAR.SarHeight = 0;
+    mVideoParamsAVC.bEntropyCodingCABAC = 0;
+    mVideoParamsAVC.bWeightedPPrediction = 0;
+    mVideoParamsAVC.bDirect8x8Inference = 0;
+    mVideoParamsAVC.bConstIpred = 0;
+    mAutoReferenceSurfaceNum = 4;
+
+    packed_seq_header_param_buf_id = VA_INVALID_ID;
+    packed_seq_buf_id = VA_INVALID_ID;
+    packed_pic_header_param_buf_id = VA_INVALID_ID;
+    packed_pic_buf_id = VA_INVALID_ID;
+    packed_sei_header_param_buf_id = VA_INVALID_ID;   /* the SEI buffer */
+    packed_sei_buf_id = VA_INVALID_ID;
+}
+
+Encode_Status VideoEncoderAVC::start() {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    LOG_V( "Begin\n");
+
+    if (mComParams.rcMode == VA_RC_VCM) {
+        // If we are in VCM, we will set slice num to max value
+        // mVideoParamsAVC.sliceNum.iSliceNum = (mComParams.resolution.height + 15) / 16;
+        // mVideoParamsAVC.sliceNum.pSliceNum = mVideoParamsAVC.sliceNum.iSliceNum;
+    }
+
+    ret = VideoEncoderBase::start ();
+    CHECK_ENCODE_STATUS_RETURN("VideoEncoderBase::start");
+
+    LOG_V( "end\n");
+    return ret;
+}
+
+Encode_Status VideoEncoderAVC::derivedSetParams(VideoParamConfigSet *videoEncParams) {
+
+    CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+    VideoParamsAVC *encParamsAVC = reinterpret_cast <VideoParamsAVC *> (videoEncParams);
+
+    // AVC parames
+    if (encParamsAVC->size != sizeof (VideoParamsAVC)) {
+        return ENCODE_INVALID_PARAMS;
+    }
+
+    if(encParamsAVC->ipPeriod == 0 || encParamsAVC->ipPeriod >4)
+        return ENCODE_INVALID_PARAMS;
+
+    if((mComParams.intraPeriod >1)&&(mComParams.intraPeriod % encParamsAVC->ipPeriod !=0))
+        return ENCODE_INVALID_PARAMS;
+
+    mVideoParamsAVC = *encParamsAVC;
+    if(mComParams.profile == VAProfileH264Baseline){
+        mVideoParamsAVC.bEntropyCodingCABAC = 0;
+        mVideoParamsAVC.bDirect8x8Inference = 0;
+        mVideoParamsAVC.bWeightedPPrediction = 0;
+    }
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC:: derivedGetParams(VideoParamConfigSet *videoEncParams) {
+
+    CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+    VideoParamsAVC *encParamsAVC = reinterpret_cast <VideoParamsAVC *> (videoEncParams);
+
+    // AVC parames
+    if (encParamsAVC->size != sizeof (VideoParamsAVC)) {
+        return ENCODE_INVALID_PARAMS;
+    }
+
+    *encParamsAVC = mVideoParamsAVC;
+    return ENCODE_SUCCESS;
+
+}
+
+Encode_Status VideoEncoderAVC::derivedSetConfig(VideoParamConfigSet *videoEncConfig) {
+
+    CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
+    LOG_I("Config type = %d\n", (int)videoEncConfig->type);
+
+    switch (videoEncConfig->type) {
+        case VideoConfigTypeAVCIntraPeriod: {
+
+            VideoConfigAVCIntraPeriod *configAVCIntraPeriod =
+                    reinterpret_cast <VideoConfigAVCIntraPeriod *> (videoEncConfig);
+            // Config Intra Peroid
+            if (configAVCIntraPeriod->size != sizeof (VideoConfigAVCIntraPeriod)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            if(configAVCIntraPeriod->ipPeriod == 0 || configAVCIntraPeriod->ipPeriod >4)
+                return ENCODE_INVALID_PARAMS;
+            if((configAVCIntraPeriod->intraPeriod >1)&&(configAVCIntraPeriod->intraPeriod % configAVCIntraPeriod->ipPeriod !=0))
+                return ENCODE_INVALID_PARAMS;
+
+            mVideoParamsAVC.idrInterval = configAVCIntraPeriod->idrInterval;
+            mVideoParamsAVC.ipPeriod = configAVCIntraPeriod->ipPeriod;
+            mComParams.intraPeriod = configAVCIntraPeriod->intraPeriod;
+            mNewHeader = true;
+            break;
+        }
+        case VideoConfigTypeNALSize: {
+            // Config MTU
+            VideoConfigNALSize *configNALSize =
+                    reinterpret_cast <VideoConfigNALSize *> (videoEncConfig);
+            if (configNALSize->size != sizeof (VideoConfigNALSize)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mVideoParamsAVC.maxSliceSize = configNALSize->maxSliceSize;
+            mRenderMaxSliceSize = true;
+            break;
+        }
+        case VideoConfigTypeIDRRequest: {
+            if(mVideoParamsAVC.ipPeriod >1)
+                return ENCODE_FAIL;
+            else
+                mNewHeader = true;
+            break;
+        }
+        case VideoConfigTypeSliceNum: {
+
+            VideoConfigSliceNum *configSliceNum =
+                    reinterpret_cast <VideoConfigSliceNum *> (videoEncConfig);
+            // Config Slice size
+            if (configSliceNum->size != sizeof (VideoConfigSliceNum)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mVideoParamsAVC.sliceNum = configSliceNum->sliceNum;
+            break;
+        }
+        default: {
+            LOG_E ("Invalid Config Type");
+            break;
+        }
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC:: derivedGetConfig(
+        VideoParamConfigSet *videoEncConfig) {
+
+    CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
+    LOG_I("Config type = %d\n", (int)videoEncConfig->type);
+
+    switch (videoEncConfig->type) {
+
+        case VideoConfigTypeAVCIntraPeriod: {
+
+            VideoConfigAVCIntraPeriod *configAVCIntraPeriod =
+                    reinterpret_cast <VideoConfigAVCIntraPeriod *> (videoEncConfig);
+            if (configAVCIntraPeriod->size != sizeof (VideoConfigAVCIntraPeriod)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configAVCIntraPeriod->idrInterval = mVideoParamsAVC.idrInterval;
+            configAVCIntraPeriod->intraPeriod = mComParams.intraPeriod;
+            configAVCIntraPeriod->ipPeriod = mVideoParamsAVC.ipPeriod;
+
+            break;
+        }
+        case VideoConfigTypeNALSize: {
+
+            VideoConfigNALSize *configNALSize =
+                    reinterpret_cast <VideoConfigNALSize *> (videoEncConfig);
+            if (configNALSize->size != sizeof (VideoConfigNALSize)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configNALSize->maxSliceSize = mVideoParamsAVC.maxSliceSize;
+            break;
+        }
+        case VideoConfigTypeIDRRequest: {
+            break;
+
+        }
+        case VideoConfigTypeSliceNum: {
+
+            VideoConfigSliceNum *configSliceNum =
+                    reinterpret_cast <VideoConfigSliceNum *> (videoEncConfig);
+            if (configSliceNum->size != sizeof (VideoConfigSliceNum)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configSliceNum->sliceNum = mVideoParamsAVC.sliceNum;
+            break;
+        }
+        default: {
+            LOG_E ("Invalid Config Type");
+            break;
+        }
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::updateFrameInfo(EncodeTask* task) {
+    uint32_t idrPeroid = mComParams.intraPeriod * mVideoParamsAVC.idrInterval;
+    FrameType frametype;
+    uint32_t frame_num = mFrameNum;
+    uint32_t intraPeriod = mComParams.intraPeriod;
+
+    if (idrPeroid != 0) {
+        if(mVideoParamsAVC.ipPeriod > 1)
+            frame_num = frame_num % (idrPeroid + 1);
+        else
+            frame_num = frame_num % idrPeroid ;
+    }else{
+        if (mComParams.intraPeriod == 0)
+            intraPeriod = 0xFFFFFFFF;
+    }
+
+
+    if(frame_num ==0){
+        frametype = FTYPE_IDR;
+    }else if(intraPeriod ==1)
+        // only I frame need intraPeriod=idrInterval=ipPeriod=0
+        frametype = FTYPE_I;
+    else if(mVideoParamsAVC.ipPeriod == 1){ // no B frame
+        if((frame_num >  1) &&((frame_num -1)%intraPeriod == 0))
+            frametype = FTYPE_I;
+        else
+            frametype = FTYPE_P;
+    } else {
+        if(((frame_num-1)%intraPeriod == 0)&&(frame_num >intraPeriod))
+            frametype = FTYPE_I;
+        else{
+            frame_num = frame_num%intraPeriod;
+            if(frame_num == 0)
+                frametype = FTYPE_B;
+            else if((frame_num-1)%mVideoParamsAVC.ipPeriod == 0)
+                frametype = FTYPE_P;
+            else
+                frametype = FTYPE_B;
+        }
+    }
+
+    if (frametype == FTYPE_IDR || frametype == FTYPE_I)
+        task->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
+
+    if (frametype != task->type) {
+        const char* FrameTypeStr[10] = {"UNKNOWN", "I", "P", "B", "SI", "SP", "EI", "EP", "S", "IDR"};
+        if ((uint32_t) task->type < 9)
+            LOG_V("libMIX thinks it is %s Frame, the input is %s Frame", FrameTypeStr[frametype], FrameTypeStr[task->type]);
+        else
+            LOG_V("Wrong Frame type %d, type may not be initialized ?\n", task->type);
+    }
+
+//temparily comment out to avoid uninitialize error
+//    if (task->type == FTYPE_UNKNOWN || (uint32_t) task->type > 9)
+        task->type = frametype;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::getExtFormatOutput(VideoEncOutputBuffer *outBuffer) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    LOG_V("Begin\n");
+
+    switch (outBuffer->format) {
+        case OUTPUT_CODEC_DATA: {
+            // Output the codec data
+            ret = outputCodecData(outBuffer);
+            CHECK_ENCODE_STATUS_CLEANUP("outputCodecData");
+            break;
+        }
+
+        case OUTPUT_ONE_NAL: {
+            // Output only one NAL unit
+            ret = outputOneNALU(outBuffer, true);
+            CHECK_ENCODE_STATUS_CLEANUP("outputOneNALU");
+            break;
+        }
+
+        case OUTPUT_ONE_NAL_WITHOUT_STARTCODE: {
+            ret = outputOneNALU(outBuffer, false);
+            CHECK_ENCODE_STATUS_CLEANUP("outputOneNALU");
+            break;
+        }
+
+        case OUTPUT_LENGTH_PREFIXED: {
+            // Output length prefixed
+            ret = outputLengthPrefixed(outBuffer);
+            CHECK_ENCODE_STATUS_CLEANUP("outputLengthPrefixed");
+            break;
+        }
+
+        case OUTPUT_NALULENGTHS_PREFIXED: {
+            // Output nalu lengths ahead of bitstream
+            ret = outputNaluLengthsPrefixed(outBuffer);
+            CHECK_ENCODE_STATUS_CLEANUP("outputNaluLengthsPrefixed");
+            break;
+        }
+
+        default:
+            LOG_E("Invalid buffer mode\n");
+            ret = ENCODE_FAIL;
+            break;
+    }
+
+    LOG_I("out size is = %d\n", outBuffer->dataSize);
+
+
+CLEAN_UP:
+
+
+    LOG_V("End\n");
+    return ret;
+}
+
+Encode_Status VideoEncoderAVC::getOneNALUnit(
+        uint8_t *inBuffer, uint32_t bufSize, uint32_t *nalSize,
+        uint32_t *nalType, uint32_t *nalOffset, uint32_t status) {
+    uint32_t pos = 0;
+    uint32_t zeroByteCount = 0;
+    uint32_t singleByteTable[3][2] = {{1,0},{2,0},{2,3}};
+    uint32_t dataRemaining = 0;
+    uint8_t *dataPtr;
+
+    // Don't need to check parameters here as we just checked by caller
+    while ((inBuffer[pos++] == 0x00)) {
+        zeroByteCount ++;
+        if (pos >= bufSize)  //to make sure the buffer to be accessed is valid
+            break;
+    }
+
+    if (inBuffer[pos - 1] != 0x01 || zeroByteCount < 2) {
+        LOG_E("The stream is not AnnexB format \n");
+        LOG_E("segment status is %x \n", status);
+        return ENCODE_FAIL; //not AnnexB, we won't process it
+    }
+
+    *nalType = (*(inBuffer + pos)) & 0x1F;
+    LOG_I ("NAL type = 0x%x\n", *nalType);
+
+    zeroByteCount = 0;
+    *nalOffset = pos;
+
+    if (status & VA_CODED_BUF_STATUS_SINGLE_NALU) {
+        *nalSize = bufSize - pos;
+        return ENCODE_SUCCESS;
+    }
+
+    dataPtr  = inBuffer + pos;
+    dataRemaining = bufSize - pos + 1;
+
+    while ((dataRemaining > 0) && (zeroByteCount < 3)) {
+        if (((((intptr_t)dataPtr) & 0xF ) == 0) && (0 == zeroByteCount)
+               && (dataRemaining > 0xF)) {
+
+            __asm__  (
+                //Data input
+                "movl %1, %%ecx\n\t"//data_ptr=>ecx
+                "movl %0, %%eax\n\t"//data_remaing=>eax
+                //Main compare loop
+                //
+                "0:\n\t"   //MATCH_8_ZERO:
+                "pxor %%xmm0,%%xmm0\n\t"//set 0=>xmm0
+                "pcmpeqb (%%ecx),%%xmm0\n\t"//data_ptr=xmm0,(byte==0)?0xFF:0x00
+                "pmovmskb %%xmm0, %%edx\n\t"//edx[0]=xmm0[7],edx[1]=xmm0[15],...,edx[15]=xmm0[127]
+                "test $0xAAAA, %%edx\n\t"//edx& 1010 1010 1010 1010b
+                "jnz 2f\n\t"//Not equal to zero means that at least one byte 0x00
+
+                "1:\n\t"  //PREPARE_NEXT_MATCH:
+                "sub $0x10, %%eax\n\t"//16 + ecx --> ecx
+                "add $0x10, %%ecx\n\t"//eax-16 --> eax
+                "cmp $0x10, %%eax\n\t"
+                "jge 0b\n\t"//search next 16 bytes
+
+                "2:\n\t"   //DATA_RET:
+                "movl %%ecx, %1\n\t"//output ecx->data_ptr
+                "movl %%eax, %0\n\t"//output eax->data_remaining
+                : "+m"(dataRemaining), "+m"(dataPtr)
+                :
+                :"eax", "ecx", "edx", "xmm0"
+                );
+            if (0 >= dataRemaining) {
+                break;
+            }
+
+        }
+        //check the value of each byte
+        if ((*dataPtr) >= 2) {
+
+            zeroByteCount = 0;
+
+        }
+        else {
+            zeroByteCount = singleByteTable[zeroByteCount][*dataPtr];
+         }
+
+        dataPtr ++;
+        dataRemaining --;
+    }
+
+    if ((3 == zeroByteCount) && (dataRemaining > 0)) {
+
+        *nalSize =  bufSize - dataRemaining - *nalOffset - 3;
+
+    } else if (0 == dataRemaining) {
+
+        *nalSize = bufSize - *nalOffset;
+    }
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::getHeader(
+        uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize, uint32_t status) {
+
+    uint32_t nalType = 0;
+    uint32_t nalSize = 0;
+    uint32_t nalOffset = 0;
+    uint32_t size = 0;
+    uint8_t *buf = inBuffer;
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    *headerSize = 0;
+    CHECK_NULL_RETURN_IFFAIL(inBuffer);
+
+    if (bufSize == 0) {
+        //bufSize shoule not be 0, error happens
+        LOG_E("Buffer size is 0\n");
+        return ENCODE_FAIL;
+    }
+
+    while (1) {
+        nalType = nalSize = nalOffset = 0;
+        ret = getOneNALUnit(buf, bufSize, &nalSize, &nalType, &nalOffset, status);
+        CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
+
+        LOG_I("NAL type = %d, NAL size = %d, offset = %d\n", nalType, nalSize, nalOffset);
+        size = nalSize + nalOffset;
+
+        // Codec_data should be SPS or PPS
+        if (nalType == 7 || nalType == 8) {
+            *headerSize += size;
+            buf += size;
+            bufSize -= size;
+        } else {
+            LOG_V("No header found or no header anymore\n");
+            break;
+        }
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::outputCodecData(
+        VideoEncOutputBuffer *outBuffer) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    uint32_t headerSize = 0;
+
+    ret = getHeader((uint8_t *)mCurSegment->buf + mOffsetInSeg,
+            mCurSegment->size - mOffsetInSeg, &headerSize, mCurSegment->status);
+    CHECK_ENCODE_STATUS_RETURN("getHeader");
+    if (headerSize == 0) {
+        outBuffer->dataSize = 0;
+        mCurSegment = NULL;
+        return ENCODE_NO_REQUEST_DATA;
+    }
+
+    if (headerSize <= outBuffer->bufferSize) {
+        memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, headerSize);
+        mTotalSizeCopied += headerSize;
+        mOffsetInSeg += headerSize;
+        outBuffer->dataSize = headerSize;
+        outBuffer->remainingSize = 0;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_CODECCONFIG;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
+    } else {
+        // we need a big enough buffer, otherwise we won't output anything
+        outBuffer->dataSize = 0;
+        outBuffer->remainingSize = headerSize;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
+        LOG_E("Buffer size too small\n");
+        return ENCODE_BUFFER_TOO_SMALL;
+    }
+
+    return ret;
+}
+
+Encode_Status VideoEncoderAVC::outputOneNALU(
+        VideoEncOutputBuffer *outBuffer, bool startCode) {
+
+    uint32_t nalType = 0;
+    uint32_t nalSize = 0;
+    uint32_t nalOffset = 0;
+    uint32_t sizeToBeCopied = 0;
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
+
+    ret = getOneNALUnit((uint8_t *)mCurSegment->buf + mOffsetInSeg,
+            mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
+    CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
+
+    // check if we need startcode along with the payload
+    if (startCode) {
+        sizeToBeCopied = nalSize + nalOffset;
+    } else {
+        sizeToBeCopied = nalSize;
+    }
+
+    if (sizeToBeCopied <= outBuffer->bufferSize) {
+        if (startCode) {
+            memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, sizeToBeCopied);
+        } else {
+            memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg + nalOffset,
+                   sizeToBeCopied);
+        }
+        mTotalSizeCopied += sizeToBeCopied;
+        mOffsetInSeg += (nalSize + nalOffset);
+        outBuffer->dataSize = sizeToBeCopied;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
+        outBuffer->remainingSize = 0;
+    } else {
+        // if nothing to be copied out, set flag to invalid
+        outBuffer->dataSize = 0;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
+        outBuffer->remainingSize = sizeToBeCopied;
+        LOG_W("Buffer size too small\n");
+        return ENCODE_BUFFER_TOO_SMALL;
+    }
+
+    // check if all data in current segment has been copied out
+    if (mCurSegment->size == mOffsetInSeg) {
+        if (mCurSegment->next != NULL) {
+            mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
+            mOffsetInSeg = 0;
+        } else {
+            LOG_V("End of stream\n");
+            outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+            mCurSegment = NULL;
+        }
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::outputLengthPrefixed(VideoEncOutputBuffer *outBuffer) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    uint32_t nalType = 0;
+    uint32_t nalSize = 0;
+    uint32_t nalOffset = 0;
+    uint32_t sizeCopiedHere = 0;
+
+    CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
+
+    while (1) {
+
+        if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
+            LOG_E("mCurSegment->size < mOffsetInSeg  || outBuffer->bufferSize < sizeCopiedHere\n");
+            return ENCODE_FAIL;
+        }
+
+        // we need to handle the whole bitstream NAL by NAL
+        ret = getOneNALUnit(
+                (uint8_t *)mCurSegment->buf + mOffsetInSeg,
+                mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
+        CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
+
+        if (nalSize + 4 <= outBuffer->bufferSize - sizeCopiedHere) {
+            // write the NAL length to bit stream
+            outBuffer->data[sizeCopiedHere] = (nalSize >> 24) & 0xff;
+            outBuffer->data[sizeCopiedHere + 1] = (nalSize >> 16) & 0xff;
+            outBuffer->data[sizeCopiedHere + 2] = (nalSize >> 8)  & 0xff;
+            outBuffer->data[sizeCopiedHere + 3] = nalSize   & 0xff;
+
+            sizeCopiedHere += 4;
+            mTotalSizeCopied += 4;
+
+            memcpy(outBuffer->data + sizeCopiedHere,
+                   (uint8_t *)mCurSegment->buf + mOffsetInSeg + nalOffset, nalSize);
+
+            sizeCopiedHere += nalSize;
+            mTotalSizeCopied += nalSize;
+            mOffsetInSeg += (nalSize + nalOffset);
+
+        } else {
+            outBuffer->dataSize = sizeCopiedHere;
+            // In case the start code is 3-byte length but we use 4-byte for length prefixed
+            // so the remainingSize size may larger than the remaining data size
+            outBuffer->remainingSize = mTotalSize - mTotalSizeCopied + 100;
+            outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
+            LOG_E("Buffer size too small\n");
+            return ENCODE_BUFFER_TOO_SMALL;
+        }
+
+        // check if all data in current segment has been copied out
+        if (mCurSegment->size == mOffsetInSeg) {
+            if (mCurSegment->next != NULL) {
+                mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
+                mOffsetInSeg = 0;
+            } else {
+                LOG_V("End of stream\n");
+                outBuffer->dataSize = sizeCopiedHere;
+                outBuffer->remainingSize = 0;
+                outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+                mCurSegment = NULL;
+                break;
+            }
+        }
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::outputNaluLengthsPrefixed(VideoEncOutputBuffer *outBuffer) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    uint32_t nalType = 0;
+    uint32_t nalSize = 0;
+    uint32_t nalOffset = 0;
+    uint32_t sizeCopiedHere = 0;
+    const uint32_t NALUINFO_OFFSET = 256;
+    uint32_t nalNum = 0;
+
+    CHECK_NULL_RETURN_IFFAIL(mCurSegment->buf);
+
+    while (1) {
+
+        if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
+            LOG_E("mCurSegment->size < mOffsetInSeg  || outBuffer->bufferSize < sizeCopiedHere\n");
+            return ENCODE_FAIL;
+        }
+
+        // we need to handle the whole bitstream NAL by NAL
+        ret = getOneNALUnit(
+                (uint8_t *)mCurSegment->buf + mOffsetInSeg,
+                mCurSegment->size - mOffsetInSeg, &nalSize, &nalType, &nalOffset, mCurSegment->status);
+        CHECK_ENCODE_STATUS_RETURN("getOneNALUnit");
+
+        if (nalSize + 4 <= outBuffer->bufferSize - NALUINFO_OFFSET - sizeCopiedHere) {
+
+            memcpy(outBuffer->data + NALUINFO_OFFSET + sizeCopiedHere,
+                   (uint8_t *)mCurSegment->buf + mOffsetInSeg, nalSize + nalOffset);
+
+            sizeCopiedHere += nalSize + nalOffset;
+            mTotalSizeCopied += nalSize + nalOffset;
+            mOffsetInSeg += (nalSize + nalOffset);
+
+        } else {
+            outBuffer->dataSize = sizeCopiedHere;
+            // In case the start code is 3-byte length but we use 4-byte for length prefixed
+            // so the remainingSize size may larger than the remaining data size
+            outBuffer->remainingSize = mTotalSize - mTotalSizeCopied + 100;
+            outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
+            LOG_E("Buffer size too small\n");
+            return ENCODE_BUFFER_TOO_SMALL;
+        }
+
+        nalNum ++;
+        uint32_t *nalLength = (uint32_t *) (outBuffer->data + (nalNum+1) * 4);
+
+        *nalLength = nalSize + nalOffset;
+
+        // check if all data in current segment has been copied out
+        if (mCurSegment->size == mOffsetInSeg) {
+            if (mCurSegment->next != NULL) {
+                mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
+                mOffsetInSeg = 0;
+            } else {
+                LOG_V("End of stream\n");
+                outBuffer->dataSize = sizeCopiedHere;
+                outBuffer->remainingSize = 0;
+                outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+                mCurSegment = NULL;
+                break;
+            }
+        }
+    }
+
+    outBuffer->offset = NALUINFO_OFFSET;
+    uint32_t *nalHead = (uint32_t *) outBuffer->data;
+    *nalHead = 0x4E414C4C; //'nall'
+    *(++nalHead) = nalNum;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::sendEncodeCommand(EncodeTask *task) {
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    LOG_V( "Begin\n");
+
+    if (mFrameNum == 0 || mNewHeader) {
+        if (mRenderHrd) {
+            ret = renderHrd();
+            mRenderHrd = false;
+            CHECK_ENCODE_STATUS_RETURN("renderHrd");
+        }
+
+        mFrameNum = 0;
+        ret = renderSequenceParams(task);
+        CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
+        if (mNewHeader) {
+            mNewHeader = false; //Set to require new header filed to false
+            mFrameNum = 0; //reset mFrameNum to 0
+            updateFrameInfo(task); //recalculate frame info if mNewHeader is set true after PrepareFrameInfo in encode()
+        }
+    }
+
+    if (mRenderMaxSliceSize && mVideoParamsAVC.maxSliceSize != 0) {
+        ret = renderMaxSliceSize();
+        CHECK_ENCODE_STATUS_RETURN("renderMaxSliceSize");
+        mRenderMaxSliceSize = false;
+    }
+
+    if (mComParams.rcParams.enableIntraFrameQPControl && (task->type == FTYPE_IDR || task->type == FTYPE_I))
+        mRenderBitRate = true;
+
+    if (mRenderBitRate) {
+        ret = VideoEncoderBase::renderDynamicBitrate(task);
+        CHECK_ENCODE_STATUS_RETURN("renderDynamicBitrate");
+    }
+
+    if (mRenderAIR &&
+        (mComParams.refreshType == VIDEO_ENC_AIR ||
+        mComParams.refreshType == VIDEO_ENC_BOTH)) {
+
+        ret = renderAIR();
+        CHECK_ENCODE_STATUS_RETURN("renderAIR");
+
+        mRenderAIR = false;
+    }
+    
+    if (mRenderCIR) {
+
+        ret = renderCIR();
+        CHECK_ENCODE_STATUS_RETURN("renderCIR");
+
+        mRenderCIR = false;
+    }
+
+    if (mRenderFrameRate) {
+
+        ret = VideoEncoderBase::renderDynamicFrameRate();
+        CHECK_ENCODE_STATUS_RETURN("renderDynamicFrameRate");
+
+        mRenderFrameRate = false;
+    }
+
+    ret = renderPictureParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
+
+    if (mFrameNum == 0 && (mEncPackedHeaders != VA_ATTRIB_NOT_SUPPORTED)) {
+        ret = renderPackedSequenceParams(task);
+        CHECK_ENCODE_STATUS_RETURN("renderPackedSequenceParams");
+
+        ret = renderPackedPictureParams(task);
+        CHECK_ENCODE_STATUS_RETURN("renderPackedPictureParams");
+    }
+
+    ret = renderSliceParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderSliceParams");
+
+    LOG_V( "End\n");
+    return ENCODE_SUCCESS;
+}
+
+
+Encode_Status VideoEncoderAVC::renderMaxSliceSize() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    LOG_V( "Begin\n\n");
+
+    if (mComParams.rcMode != RATE_CONTROL_VCM) {
+        LOG_W ("Not in VCM mode, but call send_max_slice_size\n");
+        return ENCODE_SUCCESS;
+    }
+
+    VAEncMiscParameterBuffer *miscEncParamBuf;
+    VAEncMiscParameterMaxSliceSize *maxSliceSizeParam;
+    VABufferID miscParamBufferID;
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterMaxSliceSize),
+            1, NULL, &miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    miscEncParamBuf->type = VAEncMiscParameterTypeMaxSliceSize;
+    maxSliceSizeParam = (VAEncMiscParameterMaxSliceSize *)miscEncParamBuf->data;
+
+    maxSliceSizeParam->max_slice_size = mVideoParamsAVC.maxSliceSize;
+
+    vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    LOG_I( "max slice size = %d\n", maxSliceSizeParam->max_slice_size);
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::renderCIR(){
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    LOG_I( "%s Begin\n", __FUNCTION__);
+
+    VABufferID miscParamBufferCIRid;
+    VAEncMiscParameterBuffer *misc_param;
+    VAEncMiscParameterCIR *misc_cir_param;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterCIR),
+            1,
+            NULL,
+            &miscParamBufferCIRid);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaMapBuffer(mVADisplay, miscParamBufferCIRid,  (void **)&misc_param);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    misc_param->type = VAEncMiscParameterTypeCIR;
+    misc_cir_param = (VAEncMiscParameterCIR *)misc_param->data;
+    misc_cir_param->cir_num_mbs = mComParams.cirParams.cir_num_mbs;
+    LOG_I( "cir_num_mbs %d \n", misc_cir_param->cir_num_mbs);
+
+    vaUnmapBuffer(mVADisplay, miscParamBufferCIRid);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferCIRid, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::renderAIR() {
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    LOG_V( "Begin\n\n");
+
+    VAEncMiscParameterBuffer   *miscEncParamBuf;
+    VAEncMiscParameterAIR *airParams;
+    VABufferID miscParamBufferID;
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterAIR),
+            1, NULL, &miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    miscEncParamBuf->type = VAEncMiscParameterTypeAIR;
+    airParams = (VAEncMiscParameterAIR *)miscEncParamBuf->data;
+
+    airParams->air_num_mbs = mComParams.airParams.airMBs;
+    airParams->air_threshold= mComParams.airParams.airThreshold;
+    airParams->air_auto = mComParams.airParams.airAuto;
+
+    vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_I( "airThreshold = %d\n", airParams->air_threshold);
+    return ENCODE_SUCCESS;
+}
+
+int VideoEncoderAVC::calcLevel(int numMbs) {
+    int level = 30;
+
+    if (numMbs < 1620) {
+        level = 30;
+    } else if (numMbs < 3600) {
+        level = 31;
+    } else if (numMbs < 5120) {
+        level = 32;
+    } else if (numMbs < 8192) {
+        level = 41;
+    } else if (numMbs < 8704) {
+        level = 42;
+    } else if (numMbs < 22080) {
+        level = 50;
+    } else if (numMbs < 36864) {
+        level = 51;
+    } else {
+        LOG_W("No such level can support that resolution");
+        level = 51;
+    }
+    return level;
+}
+
+Encode_Status VideoEncoderAVC::renderSequenceParams(EncodeTask *) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncSequenceParameterBufferH264 avcSeqParams = VAEncSequenceParameterBufferH264();
+    VAEncMiscParameterBuffer   *miscEncRCParamBuf;
+    VAEncMiscParameterBuffer   *miscEncFrameRateParamBuf;
+    VAEncMiscParameterRateControl *rcMiscParam;
+    VAEncMiscParameterFrameRate *framerateParam;
+    int level;
+    uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
+    uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
+
+    LOG_V( "Begin\n\n");
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterRateControl),
+            1, NULL,
+            &mRcParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+    vaStatus = vaMapBuffer(mVADisplay, mRcParamBuf, (void **)&miscEncRCParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterFrameRate),
+            1, NULL,
+            &mFrameRateParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+    vaStatus = vaMapBuffer(mVADisplay, mFrameRateParamBuf, (void **)&miscEncFrameRateParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    miscEncRCParamBuf->type = VAEncMiscParameterTypeRateControl;
+    rcMiscParam = (VAEncMiscParameterRateControl  *)miscEncRCParamBuf->data;
+    miscEncFrameRateParamBuf->type = VAEncMiscParameterTypeFrameRate;
+    framerateParam = (VAEncMiscParameterFrameRate *)miscEncFrameRateParamBuf->data;
+    // set up the sequence params for HW
+    // avcSeqParams.level_idc = mLevel;
+    avcSeqParams.intra_period = mComParams.intraPeriod;
+    avcSeqParams.intra_idr_period = mVideoParamsAVC.idrInterval;
+    avcSeqParams.ip_period = mVideoParamsAVC.ipPeriod;
+    avcSeqParams.picture_width_in_mbs = (mComParams.resolution.width + 15) / 16;
+    avcSeqParams.picture_height_in_mbs = (mComParams.resolution.height + 15) / 16;
+
+    level = calcLevel (avcSeqParams.picture_width_in_mbs * avcSeqParams.picture_height_in_mbs);
+    avcSeqParams.level_idc = level;
+    avcSeqParams.bits_per_second = mComParams.rcParams.bitRate;
+    framerateParam->framerate =
+            (unsigned int) (frameRateNum + frameRateDenom /2 ) / frameRateDenom;
+    rcMiscParam->initial_qp = mComParams.rcParams.initQP;
+    rcMiscParam->min_qp = mComParams.rcParams.minQP;
+    rcMiscParam->max_qp = mComParams.rcParams.maxQP;
+    if (mComParams.rcParams.enableIntraFrameQPControl) {
+        rcMiscParam->min_qp = mComParams.rcParams.I_minQP;
+        rcMiscParam->max_qp = mComParams.rcParams.I_maxQP;
+    }
+    rcMiscParam->window_size = mComParams.rcParams.windowSize;
+    //target bitrate is sent to libva through Sequence Parameter Buffer
+    rcMiscParam->bits_per_second = 0;
+    rcMiscParam->basic_unit_size = mVideoParamsAVC.basicUnitSize; //for rate control usage
+    avcSeqParams.intra_period = mComParams.intraPeriod;
+    //avcSeqParams.vui_flag = 248;
+    avcSeqParams.vui_parameters_present_flag = mVideoParamsAVC.VUIFlag;
+    avcSeqParams.num_units_in_tick = frameRateDenom;
+    avcSeqParams.time_scale = 2 * frameRateNum;
+    avcSeqParams.seq_parameter_set_id = 0;
+    if (mVideoParamsAVC.crop.LeftOffset ||
+            mVideoParamsAVC.crop.RightOffset ||
+            mVideoParamsAVC.crop.TopOffset ||
+            mVideoParamsAVC.crop.BottomOffset) {
+        avcSeqParams.frame_cropping_flag = true;
+        avcSeqParams.frame_crop_left_offset = mVideoParamsAVC.crop.LeftOffset;
+        avcSeqParams.frame_crop_right_offset = mVideoParamsAVC.crop.RightOffset;
+        avcSeqParams.frame_crop_top_offset = mVideoParamsAVC.crop.TopOffset;
+        avcSeqParams.frame_crop_bottom_offset = mVideoParamsAVC.crop.BottomOffset;
+    } else {
+        avcSeqParams.frame_cropping_flag = false;
+
+        if (mComParams.resolution.width & 0xf) {
+            avcSeqParams.frame_cropping_flag = true;
+            uint32_t AWidth = (mComParams.resolution.width + 0xf) & (~0xf);
+            avcSeqParams.frame_crop_right_offset = ( AWidth - mComParams.resolution.width ) / 2;
+        }
+
+        if (mComParams.resolution.height & 0xf) {
+            avcSeqParams.frame_cropping_flag = true;
+            uint32_t AHeight = (mComParams.resolution.height + 0xf) & (~0xf);
+            avcSeqParams.frame_crop_bottom_offset = ( AHeight - mComParams.resolution.height ) / 2;
+        }
+    }
+
+    if(avcSeqParams.vui_parameters_present_flag && (mVideoParamsAVC.SAR.SarWidth || mVideoParamsAVC.SAR.SarHeight)) {
+        avcSeqParams.vui_fields.bits.aspect_ratio_info_present_flag = true;
+        avcSeqParams.aspect_ratio_idc = 0xff /* Extended_SAR */;
+        avcSeqParams.sar_width = mVideoParamsAVC.SAR.SarWidth;
+        avcSeqParams.sar_height = mVideoParamsAVC.SAR.SarHeight;
+    }
+
+    avcSeqParams.max_num_ref_frames = 1;
+
+    if(avcSeqParams.ip_period > 1)
+        avcSeqParams.max_num_ref_frames = 2; 
+
+    LOG_V("===h264 sequence params===\n");
+    LOG_I( "seq_parameter_set_id = %d\n", (uint32_t)avcSeqParams.seq_parameter_set_id);
+    LOG_I( "level_idc = %d\n", (uint32_t)avcSeqParams.level_idc);
+    LOG_I( "intra_period = %d\n", avcSeqParams.intra_period);
+    LOG_I( "idr_interval = %d\n", avcSeqParams.intra_idr_period);
+    LOG_I( "picture_width_in_mbs = %d\n", avcSeqParams.picture_width_in_mbs);
+    LOG_I( "picture_height_in_mbs = %d\n", avcSeqParams.picture_height_in_mbs);
+    LOG_I( "bitrate = %d\n", rcMiscParam->bits_per_second);
+    LOG_I( "frame_rate = %d\n", framerateParam->framerate);
+    LOG_I( "initial_qp = %d\n", rcMiscParam->initial_qp);
+    LOG_I( "min_qp = %d\n", rcMiscParam->min_qp);
+    LOG_I( "basic_unit_size = %d\n", rcMiscParam->basic_unit_size);
+    LOG_I( "bDirect8x8Inference = %d\n",mVideoParamsAVC.bDirect8x8Inference);
+
+    // Not sure whether these settings work for all drivers
+    avcSeqParams.seq_fields.bits.frame_mbs_only_flag = 1;
+    avcSeqParams.seq_fields.bits.pic_order_cnt_type = 0;
+    avcSeqParams.seq_fields.bits.direct_8x8_inference_flag = mVideoParamsAVC.bDirect8x8Inference;
+
+    avcSeqParams.seq_fields.bits.log2_max_frame_num_minus4 = 0;
+    avcSeqParams.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 2;
+//    avcSeqParams.time_scale = 900;
+//    avcSeqParams.num_units_in_tick = 15;			/* Tc = num_units_in_tick / time_sacle */
+    // Not sure whether these settings work for all drivers
+
+    vaStatus = vaUnmapBuffer(mVADisplay, mRcParamBuf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+    vaStatus = vaUnmapBuffer(mVADisplay, mFrameRateParamBuf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSequenceParameterBufferType,
+            sizeof(avcSeqParams), 1, &avcSeqParams,
+            &mSeqParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mFrameRateParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mRcParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::renderPackedSequenceParams(EncodeTask *) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncSequenceParameterBufferH264 *avcSeqParams;
+    VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
+    unsigned char *packed_seq_buffer = NULL;
+    unsigned int length_in_bits, offset_in_bytes;
+
+    LOG_V("Begin\n");
+
+    vaStatus = vaMapBuffer(mVADisplay, mSeqParamBuf, (void **)&avcSeqParams);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    length_in_bits = build_packed_seq_buffer(&packed_seq_buffer, mComParams.profile, avcSeqParams);
+    packed_header_param_buffer.type = VAEncPackedHeaderSequence;
+    packed_header_param_buffer.bit_length = length_in_bits;
+    packed_header_param_buffer.has_emulation_bytes = 0;
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncPackedHeaderParameterBufferType,
+            sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
+            &packed_seq_header_param_buf_id);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncPackedHeaderDataBufferType,
+            (length_in_bits + 7) / 8, 1, packed_seq_buffer,
+            &packed_seq_buf_id);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_seq_header_param_buf_id, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_seq_buf_id, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    vaStatus = vaUnmapBuffer(mVADisplay, mSeqParamBuf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    free(packed_seq_buffer);
+
+    LOG_V("End\n");
+
+    return vaStatus;
+}
+
+Encode_Status VideoEncoderAVC::renderPictureParams(EncodeTask *task) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncPictureParameterBufferH264 avcPicParams = VAEncPictureParameterBufferH264();
+    uint32_t RefFrmIdx;
+
+    LOG_V( "Begin\n\n");
+    // set picture params for HW
+    if (mAutoReference == false) {
+        for (RefFrmIdx = 0; RefFrmIdx < 16; RefFrmIdx++) {
+            avcPicParams.ReferenceFrames[RefFrmIdx].picture_id = VA_INVALID_ID;
+            avcPicParams.ReferenceFrames[RefFrmIdx].flags = VA_PICTURE_H264_INVALID;
+        }
+        avcPicParams.ReferenceFrames[0].picture_id= task->ref_surface;
+        avcPicParams.ReferenceFrames[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+        avcPicParams.CurrPic.picture_id= task->rec_surface;
+        // Not sure whether these settings work for all drivers
+        avcPicParams.CurrPic.TopFieldOrderCnt = mFrameNum * 2;
+
+        avcPicParams.pic_fields.bits.transform_8x8_mode_flag = 0;
+        avcPicParams.seq_parameter_set_id = 0;
+        avcPicParams.pic_parameter_set_id = 0;
+
+        avcPicParams.last_picture = 0;
+        avcPicParams.frame_num = 0;
+
+        avcPicParams.pic_init_qp = 26;
+        avcPicParams.num_ref_idx_l0_active_minus1 = 0;
+        avcPicParams.num_ref_idx_l1_active_minus1 = 0;
+
+        avcPicParams.pic_fields.bits.idr_pic_flag = 0;
+        avcPicParams.pic_fields.bits.reference_pic_flag = 0;
+        avcPicParams.pic_fields.bits.entropy_coding_mode_flag = 0;
+        avcPicParams.pic_fields.bits.weighted_pred_flag = 0;
+        avcPicParams.pic_fields.bits.weighted_bipred_idc = 0;
+        avcPicParams.pic_fields.bits.transform_8x8_mode_flag = 0;
+        avcPicParams.pic_fields.bits.deblocking_filter_control_present_flag = 1;
+
+        avcPicParams.frame_num = mFrameNum;
+        avcPicParams.pic_fields.bits.reference_pic_flag = 1;
+        // Not sure whether these settings work for all drivers
+    }else {
+        avcPicParams.CurrPic.picture_id= VA_INVALID_SURFACE;
+        for(uint32_t i =0; i< mAutoReferenceSurfaceNum; i++)
+            avcPicParams.ReferenceFrames[i].picture_id = mAutoRefSurfaces[i];
+    }
+
+    avcPicParams.pic_fields.bits.idr_pic_flag = (mFrameNum == 0);
+    avcPicParams.pic_fields.bits.entropy_coding_mode_flag = mVideoParamsAVC.bEntropyCodingCABAC;
+    avcPicParams.coded_buf = task->coded_buffer;
+    avcPicParams.last_picture = 0;
+
+    LOG_V("======h264 picture params======\n");
+    LOG_I( "reference_picture = 0x%08x\n", avcPicParams.ReferenceFrames[0].picture_id);
+    LOG_I( "reconstructed_picture = 0x%08x\n", avcPicParams.CurrPic.picture_id);
+    LOG_I( "coded_buf = 0x%08x\n", avcPicParams.coded_buf);
+    //LOG_I( "picture_width = %d\n", avcPicParams.picture_width);
+    //LOG_I( "picture_height = %d\n\n", avcPicParams.picture_height);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncPictureParameterBufferType,
+            sizeof(avcPicParams),
+            1,&avcPicParams,
+            &mPicParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderAVC::renderPackedPictureParams(EncodeTask *) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncPictureParameterBufferH264 *avcPicParams;
+    VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
+    unsigned char *packed_pic_buffer = NULL;
+    unsigned int length_in_bits, offset_in_bytes;
+
+    LOG_V("Begin\n");
+
+    vaStatus = vaMapBuffer(mVADisplay, mPicParamBuf, (void **)&avcPicParams);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    length_in_bits = build_packed_pic_buffer(&packed_pic_buffer, avcPicParams);
+    packed_header_param_buffer.type = VAEncPackedHeaderPicture;
+    packed_header_param_buffer.bit_length = length_in_bits;
+    packed_header_param_buffer.has_emulation_bytes = 0;
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncPackedHeaderParameterBufferType,
+            sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
+            &packed_pic_header_param_buf_id);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncPackedHeaderDataBufferType,
+            (length_in_bits + 7) / 8, 1, packed_pic_buffer,
+            &packed_pic_buf_id);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_pic_header_param_buf_id, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &packed_pic_buf_id, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    vaStatus = vaUnmapBuffer(mVADisplay, mSeqParamBuf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    free(packed_pic_buffer);
+
+    LOG_V("End\n");
+
+    return vaStatus;
+}
+
+Encode_Status VideoEncoderAVC::renderSliceParams(EncodeTask *task) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    uint32_t sliceNum = 0;
+    uint32_t sliceIndex = 0;
+    uint32_t sliceHeightInMB = 0;
+    uint32_t maxSliceNum = 0;
+    uint32_t minSliceNum = 0;
+    uint32_t actualSliceHeightInMB = 0;
+    uint32_t startRowInMB = 0;
+    uint32_t modulus = 0;
+    uint32_t RefFrmIdx;
+
+    LOG_V( "Begin\n\n");
+
+    maxSliceNum = (mComParams.resolution.height + 15) / 16;
+    minSliceNum = 1;
+
+    if (task->type == FTYPE_I || task->type == FTYPE_IDR) {
+        sliceNum = mVideoParamsAVC.sliceNum.iSliceNum;
+    } else {
+        sliceNum = mVideoParamsAVC.sliceNum.pSliceNum;
+    }
+
+    if (sliceNum < minSliceNum) {
+        LOG_W("Slice Number is too small");
+        sliceNum = minSliceNum;
+    }
+
+    if (sliceNum > maxSliceNum) {
+        LOG_W("Slice Number is too big");
+        sliceNum = maxSliceNum;
+    }
+
+    mSliceNum= sliceNum;
+    modulus = maxSliceNum % sliceNum;
+    sliceHeightInMB = (maxSliceNum - modulus) / sliceNum ;
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSliceParameterBufferType,
+            sizeof(VAEncSliceParameterBufferH264),
+            sliceNum, NULL,
+            &mSliceParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    VAEncSliceParameterBufferH264 *sliceParams, *currentSlice;
+
+    vaStatus = vaMapBuffer(mVADisplay, mSliceParamBuf, (void **)&sliceParams);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+    if(!sliceParams)
+        return ENCODE_NULL_PTR;
+    memset(sliceParams, 0 , sizeof(VAEncSliceParameterBufferH264));
+    if(!sliceParams)
+        return ENCODE_NULL_PTR;
+
+    currentSlice = sliceParams;
+    startRowInMB = 0;
+    for (sliceIndex = 0; sliceIndex < sliceNum; sliceIndex++) {
+        currentSlice = sliceParams + sliceIndex;
+        actualSliceHeightInMB = sliceHeightInMB;
+        if (sliceIndex < modulus) {
+            actualSliceHeightInMB ++;
+        }
+
+        // starting MB row number for this slice, suppose macroblock 16x16
+        currentSlice->macroblock_address = startRowInMB * ((mComParams.resolution.width + 0xf) & ~0xf) / 16;
+        // slice height measured in MB
+        currentSlice->num_macroblocks = actualSliceHeightInMB * ((mComParams.resolution.width + 0xf) & ~0xf) / 16;
+        if(task->type == FTYPE_I||task->type == FTYPE_IDR)
+            currentSlice->slice_type = 2;
+        else if(task->type == FTYPE_P)
+            currentSlice->slice_type = 0;
+        else if(task->type == FTYPE_B)
+            currentSlice->slice_type = 1;
+        currentSlice->disable_deblocking_filter_idc = mComParams.disableDeblocking;
+
+        // This is a temporary fix suggested by Binglin for bad encoding quality issue
+        // TODO: We need a long term design for this field
+        //currentSlice->slice_flags.bits.uses_long_term_ref = 0;
+        //currentSlice->slice_flags.bits.is_long_term_ref = 0;
+
+        LOG_V("======AVC slice params======\n");
+        LOG_I( "slice_index = %d\n", (int) sliceIndex);
+        LOG_I( "macroblock_address = %d\n", (int) currentSlice->macroblock_address);
+        LOG_I( "slice_height_in_mb = %d\n", (int) currentSlice->num_macroblocks);
+        LOG_I( "slice.type = %d\n", (int) currentSlice->slice_type);
+        LOG_I("disable_deblocking_filter_idc = %d\n\n", (int) currentSlice->disable_deblocking_filter_idc);
+
+        // Not sure whether these settings work for all drivers
+        currentSlice->pic_parameter_set_id = 0;
+        currentSlice->pic_order_cnt_lsb = mFrameNum * 2;
+        currentSlice->direct_spatial_mv_pred_flag = 0;
+        currentSlice->num_ref_idx_l0_active_minus1 = 0;      /* FIXME: ??? */
+        currentSlice->num_ref_idx_l1_active_minus1 = 0;
+        currentSlice->cabac_init_idc = 0;
+        currentSlice->slice_qp_delta = 0;
+        currentSlice->disable_deblocking_filter_idc = 0;
+        currentSlice->slice_alpha_c0_offset_div2 = 2;
+        currentSlice->slice_beta_offset_div2 = 2;
+        currentSlice->idr_pic_id = 0;
+        for (RefFrmIdx = 0; RefFrmIdx < 32; RefFrmIdx++) {
+            currentSlice->RefPicList0[RefFrmIdx].picture_id = VA_INVALID_ID;
+            currentSlice->RefPicList0[RefFrmIdx].flags = VA_PICTURE_H264_INVALID;
+        }
+        currentSlice->RefPicList0[0].picture_id = task->ref_surface;
+        currentSlice->RefPicList0[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+        // Not sure whether these settings work for all drivers
+
+        startRowInMB += actualSliceHeightInMB;
+    }
+
+    vaStatus = vaUnmapBuffer(mVADisplay, mSliceParamBuf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSliceParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
diff --git a/videoencoder/VideoEncoderAVC.h b/videoencoder/VideoEncoderAVC.h
new file mode 100644
index 0000000..87c9407
--- /dev/null
+++ b/videoencoder/VideoEncoderAVC.h
@@ -0,0 +1,73 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_AVC_H__
+#define __VIDEO_ENCODER_AVC_H__
+
+#include "VideoEncoderBase.h"
+
+class VideoEncoderAVC : public VideoEncoderBase {
+
+public:
+    VideoEncoderAVC();
+    ~VideoEncoderAVC() {};
+
+    virtual Encode_Status start();
+
+    virtual Encode_Status derivedSetParams(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status derivedGetParams(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status derivedGetConfig(VideoParamConfigSet *videoEncConfig);
+    virtual Encode_Status derivedSetConfig(VideoParamConfigSet *videoEncConfig);
+
+protected:
+
+    virtual Encode_Status sendEncodeCommand(EncodeTask *task);
+    virtual Encode_Status getExtFormatOutput(VideoEncOutputBuffer *outBuffer);
+    virtual Encode_Status updateFrameInfo(EncodeTask* task);
+private:
+    // Local Methods
+
+    Encode_Status getOneNALUnit(uint8_t *inBuffer, uint32_t bufSize, uint32_t *nalSize, uint32_t *nalType, uint32_t *nalOffset, uint32_t status);
+    Encode_Status getHeader(uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize, uint32_t status);
+    Encode_Status outputCodecData(VideoEncOutputBuffer *outBuffer);
+    Encode_Status outputOneNALU(VideoEncOutputBuffer *outBuffer, bool startCode);
+    Encode_Status outputLengthPrefixed(VideoEncOutputBuffer *outBuffer);
+    Encode_Status outputNaluLengthsPrefixed(VideoEncOutputBuffer *outBuffer);
+
+    Encode_Status renderMaxSliceSize();
+    Encode_Status renderAIR();
+    Encode_Status renderCIR();
+    Encode_Status renderSequenceParams(EncodeTask *task);
+    Encode_Status renderPictureParams(EncodeTask *task);
+    Encode_Status renderSliceParams(EncodeTask *task);
+    int calcLevel(int numMbs);
+    Encode_Status renderPackedSequenceParams(EncodeTask *task);
+    Encode_Status renderPackedPictureParams(EncodeTask *task);
+
+public:
+
+    VideoParamsAVC mVideoParamsAVC;
+    uint32_t mSliceNum;
+    VABufferID packed_seq_header_param_buf_id;
+    VABufferID packed_seq_buf_id;
+    VABufferID packed_pic_header_param_buf_id;
+    VABufferID packed_pic_buf_id;
+    VABufferID packed_sei_header_param_buf_id;   /* the SEI buffer */
+    VABufferID packed_sei_buf_id;
+
+};
+
+#endif /* __VIDEO_ENCODER_AVC_H__ */
diff --git a/videoencoder/VideoEncoderBase.cpp b/videoencoder/VideoEncoderBase.cpp
new file mode 100644
index 0000000..b3fd3c2
--- /dev/null
+++ b/videoencoder/VideoEncoderBase.cpp
@@ -0,0 +1,1928 @@
+/*
+* Copyright (c) 2009-2011 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 <string.h>
+#include "VideoEncoderLog.h"
+#include "VideoEncoderBase.h"
+#include "IntelMetadataBuffer.h"
+#include <va/va_tpi.h>
+#include <va/va_android.h>
+
+VideoEncoderBase::VideoEncoderBase()
+    :mInitialized(true)
+    ,mStarted(false)
+    ,mVADisplay(NULL)
+    ,mVAContext(VA_INVALID_ID)
+    ,mVAConfig(VA_INVALID_ID)
+    ,mVAEntrypoint(VAEntrypointEncSlice)
+    ,mNewHeader(false)
+    ,mRenderMaxSliceSize(false)
+    ,mRenderQP (false)
+    ,mRenderAIR(false)
+    ,mRenderCIR(false)
+    ,mRenderFrameRate(false)
+    ,mRenderBitRate(false)
+    ,mRenderHrd(false)
+    ,mRenderMultiTemporal(false)
+    ,mForceKFrame(false)
+    ,mSeqParamBuf(0)
+    ,mPicParamBuf(0)
+    ,mSliceParamBuf(0)
+    ,mAutoRefSurfaces(NULL)
+    ,mRefSurface(VA_INVALID_SURFACE)
+    ,mRecSurface(VA_INVALID_SURFACE)
+    ,mFrameNum(0)
+    ,mCodedBufSize(0)
+    ,mAutoReference(false)
+    ,mAutoReferenceSurfaceNum(4)
+    ,mEncPackedHeaders(VA_ATTRIB_NOT_SUPPORTED)
+    ,mSliceSizeOverflow(false)
+    ,mCurOutputTask(NULL)
+    ,mOutCodedBuffer(0)
+    ,mOutCodedBufferPtr(NULL)
+    ,mCurSegment(NULL)
+    ,mOffsetInSeg(0)
+    ,mTotalSize(0)
+    ,mTotalSizeCopied(0)
+    ,mFrameSkipped(false)
+    ,mSupportedSurfaceMemType(0)
+    ,mVASurfaceMappingAction(0)
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    ,mSessionFlag(0)
+#endif
+    {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    // here the display can be any value, use following one
+    // just for consistence purpose, so don't define it
+    unsigned int display = 0x18C34078;
+    int majorVersion = -1;
+    int minorVersion = -1;
+
+    setDefaultParams();
+
+    LOG_V("vaGetDisplay \n");
+    mVADisplay = vaGetDisplay(&display);
+    if (mVADisplay == NULL) {
+        LOG_E("vaGetDisplay failed.");
+    }
+
+    vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
+    LOG_V("vaInitialize \n");
+    if (vaStatus != VA_STATUS_SUCCESS) {
+        LOG_E( "Failed vaInitialize, vaStatus = %d\n", vaStatus);
+        mInitialized = false;
+    }
+}
+
+VideoEncoderBase::~VideoEncoderBase() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    stop();
+
+    vaStatus = vaTerminate(mVADisplay);
+    LOG_V( "vaTerminate\n");
+    if (vaStatus != VA_STATUS_SUCCESS) {
+        LOG_W( "Failed vaTerminate, vaStatus = %d\n", vaStatus);
+    } else {
+        mVADisplay = NULL;
+    }
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    IntelMetadataBuffer::ClearContext(mSessionFlag, false);
+#endif
+}
+
+Encode_Status VideoEncoderBase::start() {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    if (!mInitialized) {
+        LOGE("Encoder Initialize fail can not start");
+        return ENCODE_DRIVER_FAIL;
+    }
+
+    if (mStarted) {
+        LOG_V("Encoder has been started\n");
+        return ENCODE_ALREADY_INIT;
+    }
+
+    if (mComParams.rawFormat != RAW_FORMAT_NV12)
+#ifdef IMG_GFX
+        mVASurfaceMappingAction |= MAP_ACTION_COLORCONVERT;
+#else
+        return ENCODE_NOT_SUPPORTED;
+#endif
+
+    if (mComParams.resolution.width > 2048 || mComParams.resolution.height > 2048){
+        LOGE("Unsupported resolution width %d, height %d\n",
+            mComParams.resolution.width, mComParams.resolution.height);
+        return ENCODE_NOT_SUPPORTED;
+    }
+    queryAutoReferenceConfig(mComParams.profile);
+
+    VAConfigAttrib vaAttrib_tmp[6],vaAttrib[VAConfigAttribTypeMax];
+    int vaAttribNumber = 0;
+    vaAttrib_tmp[0].type = VAConfigAttribRTFormat;
+    vaAttrib_tmp[1].type = VAConfigAttribRateControl;
+    vaAttrib_tmp[2].type = VAConfigAttribEncAutoReference;
+    vaAttrib_tmp[3].type = VAConfigAttribEncPackedHeaders;
+    vaAttrib_tmp[4].type = VAConfigAttribEncMaxRefFrames;
+    vaAttrib_tmp[5].type = VAConfigAttribEncRateControlExt;
+
+    vaStatus = vaGetConfigAttributes(mVADisplay, mComParams.profile,
+            VAEntrypointEncSlice, &vaAttrib_tmp[0], 6);
+    CHECK_VA_STATUS_RETURN("vaGetConfigAttributes");
+
+    if((vaAttrib_tmp[0].value & VA_RT_FORMAT_YUV420) != 0)
+    {
+        vaAttrib[vaAttribNumber].type = VAConfigAttribRTFormat;
+        vaAttrib[vaAttribNumber].value = VA_RT_FORMAT_YUV420;
+        vaAttribNumber++;
+    }
+
+    vaAttrib[vaAttribNumber].type = VAConfigAttribRateControl;
+    vaAttrib[vaAttribNumber].value = mComParams.rcMode;
+    vaAttribNumber++;
+
+    vaAttrib[vaAttribNumber].type = VAConfigAttribEncAutoReference;
+    vaAttrib[vaAttribNumber].value = mAutoReference ? 1 : VA_ATTRIB_NOT_SUPPORTED;
+    vaAttribNumber++;
+
+    if(vaAttrib_tmp[3].value != VA_ATTRIB_NOT_SUPPORTED)
+    {
+        vaAttrib[vaAttribNumber].type = VAConfigAttribEncPackedHeaders;
+        vaAttrib[vaAttribNumber].value = vaAttrib[3].value;
+        vaAttribNumber++;
+        mEncPackedHeaders = vaAttrib[3].value;
+    }
+
+    if(vaAttrib_tmp[4].value != VA_ATTRIB_NOT_SUPPORTED)
+    {
+        vaAttrib[vaAttribNumber].type = VAConfigAttribEncMaxRefFrames;
+        vaAttrib[vaAttribNumber].value = vaAttrib[4].value;
+        vaAttribNumber++;
+        mEncMaxRefFrames = vaAttrib[4].value;
+    }
+
+    if(vaAttrib_tmp[5].value != VA_ATTRIB_NOT_SUPPORTED)
+    {
+        vaAttrib[vaAttribNumber].type = VAConfigAttribEncRateControlExt;
+        vaAttrib[vaAttribNumber].value = mComParams.numberOfLayer;
+        vaAttribNumber++;
+    }
+
+    LOG_V( "======VA Configuration======\n");
+    LOG_I( "profile = %d\n", mComParams.profile);
+    LOG_I( "mVAEntrypoint = %d\n", mVAEntrypoint);
+    LOG_I( "vaAttrib[0].type = %d\n", vaAttrib[0].type);
+    LOG_I( "vaAttrib[1].type = %d\n", vaAttrib[1].type);
+    LOG_I( "vaAttrib[2].type = %d\n", vaAttrib[2].type);
+    LOG_I( "vaAttrib[0].value (Format) = %d\n", vaAttrib[0].value);
+    LOG_I( "vaAttrib[1].value (RC mode) = %d\n", vaAttrib[1].value);
+    LOG_I( "vaAttrib[2].value (AutoReference) = %d\n", vaAttrib[2].value);
+    LOG_I( "vaAttribNumber is %d\n", vaAttribNumber);
+    LOG_I( "mComParams.numberOfLayer is %d\n", mComParams.numberOfLayer);
+
+    LOG_V( "vaCreateConfig\n");
+
+    vaStatus = vaCreateConfig(
+            mVADisplay, mComParams.profile, mVAEntrypoint,
+            &vaAttrib[0], vaAttribNumber, &(mVAConfig));
+//            &vaAttrib[0], 3, &(mVAConfig));  //uncomment this after psb_video supports
+    CHECK_VA_STATUS_RETURN("vaCreateConfig");
+
+    querySupportedSurfaceMemTypes();
+
+    if (mComParams.rcMode == VA_RC_VCM) {
+        // Following three features are only enabled in VCM mode
+        mRenderMaxSliceSize = true;
+        mRenderAIR = true;
+        mRenderBitRate = true;
+    }
+
+    LOG_V( "======VA Create Surfaces for Rec/Ref frames ======\n");
+
+    uint32_t stride_aligned, height_aligned;
+    if(mAutoReference == false){
+        stride_aligned = (mComParams.resolution.width + 15) & ~15;
+        height_aligned = (mComParams.resolution.height + 15) & ~15;
+    }else{
+        // this alignment is used for AVC. For vp8 encode, driver will handle the alignment
+        if(mComParams.profile == VAProfileVP8Version0_3)
+        {
+            stride_aligned = mComParams.resolution.width;
+            height_aligned = mComParams.resolution.height;
+            mVASurfaceMappingAction |= MAP_ACTION_COPY;
+        }
+        else
+        {
+            stride_aligned = (mComParams.resolution.width + 63) & ~63;  //on Merr, stride must be 64 aligned.
+            height_aligned = (mComParams.resolution.height + 31) & ~31;
+            mVASurfaceMappingAction |= MAP_ACTION_ALIGN64;
+        }
+    }
+
+    if(mAutoReference == false){
+        mRefSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
+        mRecSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
+
+    }else {
+        mAutoRefSurfaces = new VASurfaceID [mAutoReferenceSurfaceNum];
+        for(uint32_t i = 0; i < mAutoReferenceSurfaceNum; i ++)
+            mAutoRefSurfaces[i] = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
+    }
+    CHECK_VA_STATUS_RETURN("vaCreateSurfaces");
+
+    //Prepare all Surfaces to be added into Context
+    uint32_t contextSurfaceCnt;
+    if(mAutoReference == false )
+        contextSurfaceCnt = 2 + mSrcSurfaceMapList.size();
+    else
+        contextSurfaceCnt = mAutoReferenceSurfaceNum + mSrcSurfaceMapList.size();
+
+    VASurfaceID *contextSurfaces = new VASurfaceID[contextSurfaceCnt];
+    int32_t index = -1;
+    android::List<VASurfaceMap *>::iterator map_node;
+
+    for(map_node = mSrcSurfaceMapList.begin(); map_node !=  mSrcSurfaceMapList.end(); map_node++)
+    {
+        contextSurfaces[++index] = (*map_node)->getVASurface();
+        (*map_node)->setTracked();
+    }
+
+    if(mAutoReference == false){
+        contextSurfaces[++index] = mRefSurface;
+        contextSurfaces[++index] = mRecSurface;
+    } else {
+        for (uint32_t i=0; i < mAutoReferenceSurfaceNum; i++)
+            contextSurfaces[++index] = mAutoRefSurfaces[i];
+    }
+
+    //Initialize and save the VA context ID
+    LOG_V( "vaCreateContext\n");
+    vaStatus = vaCreateContext(mVADisplay, mVAConfig,
+#ifdef IMG_GFX
+            mComParams.resolution.width,
+            mComParams.resolution.height,
+#else
+            stride_aligned,
+            height_aligned,
+#endif
+            VA_PROGRESSIVE, contextSurfaces, contextSurfaceCnt,
+            &(mVAContext));
+    CHECK_VA_STATUS_RETURN("vaCreateContext");
+
+    delete [] contextSurfaces;
+
+    LOG_I("Success to create libva context width %d, height %d\n",
+          mComParams.resolution.width, mComParams.resolution.height);
+
+    uint32_t maxSize = 0;
+    ret = getMaxOutSize(&maxSize);
+    CHECK_ENCODE_STATUS_RETURN("getMaxOutSize");
+
+    // Create CodedBuffer for output
+    VABufferID VACodedBuffer;
+
+    for(uint32_t i = 0; i <mComParams.codedBufNum; i++) {
+            vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                    VAEncCodedBufferType,
+                    mCodedBufSize,
+                    1, NULL,
+                    &VACodedBuffer);
+            CHECK_VA_STATUS_RETURN("vaCreateBuffer::VAEncCodedBufferType");
+
+            mVACodedBufferList.push_back(VACodedBuffer);
+    }
+
+    if (ret == ENCODE_SUCCESS)
+        mStarted = true;
+
+    LOG_V( "end\n");
+    return ret;
+}
+
+Encode_Status VideoEncoderBase::encode(VideoEncRawBuffer *inBuffer, uint32_t timeout) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    if (!mStarted) {
+        LOG_E("Encoder has not initialized yet\n");
+        return ENCODE_NOT_INIT;
+    }
+
+    CHECK_NULL_RETURN_IFFAIL(inBuffer);
+
+    //======Prepare all resources encoder needed=====.
+
+    //Prepare encode vaSurface
+    VASurfaceID sid = VA_INVALID_SURFACE;
+    ret = manageSrcSurface(inBuffer, &sid);
+    CHECK_ENCODE_STATUS_RETURN("manageSrcSurface");
+
+    //Prepare CodedBuffer
+    mCodedBuffer_Lock.lock();
+    if(mVACodedBufferList.empty()){
+        if(timeout == FUNC_BLOCK)
+            mCodedBuffer_Cond.wait(mCodedBuffer_Lock);
+        else if (timeout > 0) {
+            if(NO_ERROR != mEncodeTask_Cond.waitRelative(mCodedBuffer_Lock, 1000000*timeout)){
+                mCodedBuffer_Lock.unlock();
+                LOG_E("Time out wait for Coded buffer.\n");
+                return ENCODE_DEVICE_BUSY;
+            }
+        }
+        else {//Nonblock
+            mCodedBuffer_Lock.unlock();
+            LOG_E("Coded buffer is not ready now.\n");
+            return ENCODE_DEVICE_BUSY;
+        }
+    }
+
+    if(mVACodedBufferList.empty()){
+        mCodedBuffer_Lock.unlock();
+        return ENCODE_DEVICE_BUSY;
+    }
+    VABufferID coded_buf = (VABufferID) *(mVACodedBufferList.begin());
+    mVACodedBufferList.erase(mVACodedBufferList.begin());
+    mCodedBuffer_Lock.unlock();
+
+    LOG_V("CodedBuffer ID 0x%08x\n", coded_buf);
+
+    //All resources are ready, start to assemble EncodeTask
+    EncodeTask* task = new EncodeTask();
+
+    task->completed = false;
+    task->enc_surface = sid;
+    task->coded_buffer = coded_buf;
+    task->timestamp = inBuffer->timeStamp;
+    task->priv = inBuffer->priv;
+
+    //Setup frame info, like flag ( SYNCFRAME), frame number, type etc
+    task->type = inBuffer->type;
+    task->flag = inBuffer->flag;
+    PrepareFrameInfo(task);
+
+    if(mAutoReference == false){
+        //Setup ref /rec frames
+        //TODO: B frame support, temporary use same logic
+        switch (inBuffer->type) {
+            case FTYPE_UNKNOWN:
+            case FTYPE_IDR:
+            case FTYPE_I:
+            case FTYPE_P:
+            {
+                if(!mFrameSkipped) {
+                    VASurfaceID tmpSurface = mRecSurface;
+                    mRecSurface = mRefSurface;
+                    mRefSurface = tmpSurface;
+                }
+
+                task->ref_surface = mRefSurface;
+                task->rec_surface = mRecSurface;
+
+                break;
+            }
+            case FTYPE_B:
+            default:
+                LOG_V("Something wrong, B frame may not be supported in this mode\n");
+                ret = ENCODE_NOT_SUPPORTED;
+                goto CLEAN_UP;
+        }
+    }else {
+        task->ref_surface = VA_INVALID_SURFACE;
+        task->rec_surface = VA_INVALID_SURFACE;
+    }
+    //======Start Encoding, add task to list======
+    LOG_V("Start Encoding vaSurface=0x%08x\n", task->enc_surface);
+
+    vaStatus = vaBeginPicture(mVADisplay, mVAContext, task->enc_surface);
+    CHECK_VA_STATUS_GOTO_CLEANUP("vaBeginPicture");
+
+    ret = sendEncodeCommand(task);
+    CHECK_ENCODE_STATUS_CLEANUP("sendEncodeCommand");
+
+    vaStatus = vaEndPicture(mVADisplay, mVAContext);
+    CHECK_VA_STATUS_GOTO_CLEANUP("vaEndPicture");
+
+    LOG_V("Add Task %p into Encode Task list\n", task);
+    mEncodeTask_Lock.lock();
+    mEncodeTaskList.push_back(task);
+    mEncodeTask_Cond.signal();
+    mEncodeTask_Lock.unlock();
+
+    mFrameNum ++;
+
+    LOG_V("encode return Success\n");
+
+    return ENCODE_SUCCESS;
+
+CLEAN_UP:
+
+    delete task;
+    mCodedBuffer_Lock.lock();
+    mVACodedBufferList.push_back(coded_buf); //push to CodedBuffer pool again since it is not used
+    mCodedBuffer_Cond.signal();
+    mCodedBuffer_Lock.unlock();
+
+    LOG_V("encode return error=%x\n", ret);
+
+    return ret;
+}
+
+/*
+  1. Firstly check if one task is outputting data, if yes, continue outputting, if not try to get one from list.
+  2. Due to block/non-block/block with timeout 3 modes, if task is not completed, then sync surface, if yes,
+    start output data
+  3. Use variable curoutputtask to record task which is getOutput() working on to avoid push again when get failure
+    on non-block/block with timeout modes.
+  4. if complete all output data, curoutputtask should be set NULL
+*/
+Encode_Status VideoEncoderBase::getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    bool useLocalBuffer = false;
+
+    CHECK_NULL_RETURN_IFFAIL(outBuffer);
+
+    if (mCurOutputTask == NULL) {
+        mEncodeTask_Lock.lock();
+        if(mEncodeTaskList.empty()) {
+            LOG_V("getOutput CurrentTask is NULL\n");
+            if(timeout == FUNC_BLOCK) {
+                LOG_V("waiting for task....\n");
+                mEncodeTask_Cond.wait(mEncodeTask_Lock);
+            } else if (timeout > 0) {
+                LOG_V("waiting for task in %i ms....\n", timeout);
+                if(NO_ERROR != mEncodeTask_Cond.waitRelative(mEncodeTask_Lock, 1000000*timeout)) {
+                    mEncodeTask_Lock.unlock();
+                    LOG_E("Time out wait for encode task.\n");
+                    return ENCODE_NO_REQUEST_DATA;
+                }
+            } else {//Nonblock
+                mEncodeTask_Lock.unlock();
+                return ENCODE_NO_REQUEST_DATA;
+            }
+        }
+
+        if(mEncodeTaskList.empty()){
+            mEncodeTask_Lock.unlock();
+            return ENCODE_DATA_NOT_READY;
+        }
+        mCurOutputTask =  *(mEncodeTaskList.begin());
+        mEncodeTaskList.erase(mEncodeTaskList.begin());
+        mEncodeTask_Lock.unlock();
+    }
+
+    //sync/query/wait task if not completed
+    if (mCurOutputTask->completed == false) {
+        VASurfaceStatus vaSurfaceStatus;
+
+        if (timeout == FUNC_BLOCK) {
+            //block mode, direct sync surface to output data
+
+            mOutCodedBuffer = mCurOutputTask->coded_buffer;
+
+            // Check frame skip
+            // Need encoding to be completed before calling query surface below to
+            // get the right skip frame flag for current frame
+            // It is a requirement of video driver
+            // vaSyncSurface syncs the wrong frame when rendering the same surface multiple times,
+            // so use vaMapbuffer instead
+            LOG_I ("block mode, vaMapBuffer ID = 0x%08x\n", mOutCodedBuffer);
+            if (mOutCodedBufferPtr == NULL) {
+                vaStatus = vaMapBuffer (mVADisplay, mOutCodedBuffer, (void **)&mOutCodedBufferPtr);
+                CHECK_VA_STATUS_GOTO_CLEANUP("vaMapBuffer");
+                CHECK_NULL_RETURN_IFFAIL(mOutCodedBufferPtr);
+            }
+
+            vaStatus = vaQuerySurfaceStatus(mVADisplay, mCurOutputTask->enc_surface,  &vaSurfaceStatus);
+            CHECK_VA_STATUS_RETURN("vaQuerySurfaceStatus");
+            mFrameSkipped = vaSurfaceStatus & VASurfaceSkipped;
+
+            mCurOutputTask->completed = true;
+
+        } else {
+            //For both block with timeout and non-block mode, query surface, if ready, output data
+            LOG_I ("non-block mode, vaQuerySurfaceStatus ID = 0x%08x\n", mCurOutputTask->enc_surface);
+
+            vaStatus = vaQuerySurfaceStatus(mVADisplay, mCurOutputTask->enc_surface,  &vaSurfaceStatus);
+            if (vaSurfaceStatus & VASurfaceReady) {
+                mOutCodedBuffer = mCurOutputTask->coded_buffer;
+                mFrameSkipped = vaSurfaceStatus & VASurfaceSkipped;
+                mCurOutputTask->completed = true;
+                //if need to call SyncSurface again ?
+
+            }  else {//not encode complet yet, but keep all context and return directly
+                return ENCODE_DATA_NOT_READY;
+            }
+
+        }
+
+    }
+
+    //start to output data
+    ret = prepareForOutput(outBuffer, &useLocalBuffer);
+    CHECK_ENCODE_STATUS_CLEANUP("prepareForOutput");
+
+    //copy all flags to outBuffer
+    outBuffer->offset = 0;
+    outBuffer->flag = mCurOutputTask->flag;
+    outBuffer->type = mCurOutputTask->type;
+    outBuffer->timeStamp = mCurOutputTask->timestamp;
+    outBuffer->priv = mCurOutputTask->priv;
+
+    if (outBuffer->format == OUTPUT_EVERYTHING || outBuffer->format == OUTPUT_FRAME_DATA) {
+        ret = outputAllData(outBuffer);
+        CHECK_ENCODE_STATUS_CLEANUP("outputAllData");
+    }else {
+        ret = getExtFormatOutput(outBuffer);
+        CHECK_ENCODE_STATUS_CLEANUP("getExtFormatOutput");
+    }
+
+    LOG_I("out size for this getOutput call = %d\n", outBuffer->dataSize);
+
+    ret = cleanupForOutput();
+    CHECK_ENCODE_STATUS_CLEANUP("cleanupForOutput");
+
+    LOG_V("getOutput return Success, Frame skip is %d\n", mFrameSkipped);
+
+    return ENCODE_SUCCESS;
+
+CLEAN_UP:
+
+    if (outBuffer->data && (useLocalBuffer == true)) {
+        delete[] outBuffer->data;
+        outBuffer->data = NULL;
+        useLocalBuffer = false;
+    }
+
+    if (mOutCodedBufferPtr != NULL) {
+        vaStatus = vaUnmapBuffer(mVADisplay, mOutCodedBuffer);
+        mOutCodedBufferPtr = NULL;
+        mCurSegment = NULL;
+    }
+
+    delete mCurOutputTask;
+    mCurOutputTask = NULL;
+    mCodedBuffer_Lock.lock();
+    mVACodedBufferList.push_back(mOutCodedBuffer);
+    mCodedBuffer_Cond.signal();
+    mCodedBuffer_Lock.unlock();
+
+    LOG_V("getOutput return error=%x\n", ret);
+    return ret;
+}
+
+void VideoEncoderBase::flush() {
+
+    LOG_V( "Begin\n");
+
+    // reset the properities
+    mFrameNum = 0;
+
+    LOG_V( "end\n");
+}
+
+Encode_Status VideoEncoderBase::stop() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    LOG_V( "Begin\n");
+
+    // It is possible that above pointers have been allocated
+    // before we set mStarted to true
+    if (!mStarted) {
+        LOG_V("Encoder has been stopped\n");
+        return ENCODE_SUCCESS;
+    }
+    if (mAutoRefSurfaces) {
+        delete[] mAutoRefSurfaces;
+        mAutoRefSurfaces = NULL;
+    }
+
+    mCodedBuffer_Lock.lock();
+    mVACodedBufferList.clear();
+    mCodedBuffer_Lock.unlock();
+    mCodedBuffer_Cond.broadcast();
+
+    //Delete all uncompleted tasks
+    mEncodeTask_Lock.lock();
+    while(! mEncodeTaskList.empty())
+    {
+        delete *mEncodeTaskList.begin();
+        mEncodeTaskList.erase(mEncodeTaskList.begin());
+    }
+    mEncodeTask_Lock.unlock();
+    mEncodeTask_Cond.broadcast();
+
+    //Release Src Surface Buffer Map, destroy surface manually since it is not added into context
+    LOG_V( "Rlease Src Surface Map\n");
+    while(! mSrcSurfaceMapList.empty())
+    {
+        delete (*mSrcSurfaceMapList.begin());
+        mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
+    }
+
+    LOG_V( "vaDestroyContext\n");
+    if (mVAContext != VA_INVALID_ID) {
+        vaStatus = vaDestroyContext(mVADisplay, mVAContext);
+        CHECK_VA_STATUS_GOTO_CLEANUP("vaDestroyContext");
+    }
+
+    LOG_V( "vaDestroyConfig\n");
+    if (mVAConfig != VA_INVALID_ID) {
+        vaStatus = vaDestroyConfig(mVADisplay, mVAConfig);
+        CHECK_VA_STATUS_GOTO_CLEANUP("vaDestroyConfig");
+    }
+
+CLEAN_UP:
+
+    mStarted = false;
+    mSliceSizeOverflow = false;
+    mCurOutputTask= NULL;
+    mOutCodedBuffer = 0;
+    mCurSegment = NULL;
+    mOffsetInSeg =0;
+    mTotalSize = 0;
+    mTotalSizeCopied = 0;
+    mFrameSkipped = false;
+    mSupportedSurfaceMemType = 0;
+
+    LOG_V( "end\n");
+    return ret;
+}
+
+Encode_Status VideoEncoderBase::prepareForOutput(
+        VideoEncOutputBuffer *outBuffer, bool *useLocalBuffer) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VACodedBufferSegment *vaCodedSeg = NULL;
+    uint32_t status = 0;
+
+    LOG_V( "begin\n");
+    // Won't check parameters here as the caller already checked them
+    // mCurSegment is NULL means it is first time to be here after finishing encoding a frame
+    if (mCurSegment == NULL) {
+        if (mOutCodedBufferPtr == NULL) {
+            vaStatus = vaMapBuffer (mVADisplay, mOutCodedBuffer, (void **)&mOutCodedBufferPtr);
+            CHECK_VA_STATUS_RETURN("vaMapBuffer");
+            CHECK_NULL_RETURN_IFFAIL(mOutCodedBufferPtr);
+        }
+
+        LOG_I ("Coded Buffer ID been mapped = 0x%08x\n", mOutCodedBuffer);
+
+        mTotalSize = 0;
+        mOffsetInSeg = 0;
+        mTotalSizeCopied = 0;
+        vaCodedSeg = (VACodedBufferSegment *)mOutCodedBufferPtr;
+        mCurSegment = (VACodedBufferSegment *)mOutCodedBufferPtr;
+
+        while (1) {
+
+            mTotalSize += vaCodedSeg->size;
+            status = vaCodedSeg->status;
+#ifndef IMG_GFX
+            uint8_t *pTemp;
+            uint32_t ii;
+            pTemp = (uint8_t*)vaCodedSeg->buf;
+            for(ii = 0; ii < 16;){
+                if (*(pTemp + ii) == 0xFF)
+                    ii++;
+                else
+                    break;
+            }
+            if (ii > 0) {
+                mOffsetInSeg = ii;
+            }
+#endif
+            if (!mSliceSizeOverflow) {
+                mSliceSizeOverflow = status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
+            }
+
+            if (vaCodedSeg->next == NULL)
+                break;
+
+            vaCodedSeg = (VACodedBufferSegment *)vaCodedSeg->next;
+        }
+    }
+
+    // We will support two buffer allocation mode,
+    // one is application allocates the buffer and passes to encode,
+    // the other is encode allocate memory
+
+    //means  app doesn't allocate the buffer, so _encode will allocate it.
+    if (outBuffer->data == NULL) {
+        *useLocalBuffer = true;
+        outBuffer->data = new  uint8_t[mTotalSize - mTotalSizeCopied + 100];
+        if (outBuffer->data == NULL) {
+            LOG_E( "outBuffer->data == NULL\n");
+            return ENCODE_NO_MEMORY;
+        }
+        outBuffer->bufferSize = mTotalSize + 100;
+        outBuffer->dataSize = 0;
+    }
+
+    // Clear all flag for every call
+    outBuffer->flag = 0;
+    if (mSliceSizeOverflow) outBuffer->flag |= ENCODE_BUFFERFLAG_SLICEOVERFOLOW;
+
+    if (!mCurSegment)
+        return ENCODE_FAIL;
+
+    if (mCurSegment->size < mOffsetInSeg) {
+        LOG_E("mCurSegment->size < mOffsetInSeg\n");
+        return ENCODE_FAIL;
+    }
+
+    // Make sure we have data in current segment
+    if (mCurSegment->size == mOffsetInSeg) {
+        if (mCurSegment->next != NULL) {
+            mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
+            mOffsetInSeg = 0;
+        } else {
+            LOG_V("No more data available\n");
+            outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
+            outBuffer->dataSize = 0;
+            mCurSegment = NULL;
+            return ENCODE_NO_REQUEST_DATA;
+        }
+    }
+
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::cleanupForOutput() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    //mCurSegment is NULL means all data has been copied out
+    if (mCurSegment == NULL && mOutCodedBufferPtr) {
+        vaStatus = vaUnmapBuffer(mVADisplay, mOutCodedBuffer);
+        CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+        mOutCodedBufferPtr = NULL;
+        mTotalSize = 0;
+        mOffsetInSeg = 0;
+        mTotalSizeCopied = 0;
+
+        delete mCurOutputTask;
+        mCurOutputTask = NULL;
+        mCodedBuffer_Lock.lock();
+        mVACodedBufferList.push_back(mOutCodedBuffer);
+        mCodedBuffer_Cond.signal();
+        mCodedBuffer_Lock.unlock();
+
+        LOG_V("All data has been outputted, return CodedBuffer 0x%08x to pool\n", mOutCodedBuffer);
+    }
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::queryProfileLevelConfig(VADisplay dpy, VAProfile profile) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEntrypoint entryPtr[8];
+    int i, entryPtrNum;
+
+    if(profile ==  VAProfileH264Main) //need to be fixed
+        return ENCODE_NOT_SUPPORTED;
+
+    vaStatus = vaQueryConfigEntrypoints(dpy, profile, entryPtr, &entryPtrNum);
+    CHECK_VA_STATUS_RETURN("vaQueryConfigEntrypoints");
+
+    for(i=0; i<entryPtrNum; i++){
+        if(entryPtr[i] == VAEntrypointEncSlice)
+            return ENCODE_SUCCESS;
+    }
+
+    return ENCODE_NOT_SUPPORTED;
+}
+
+Encode_Status VideoEncoderBase::queryAutoReferenceConfig(VAProfile profile) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAConfigAttrib attrib_list;
+    attrib_list.type = VAConfigAttribEncAutoReference;
+    attrib_list.value = VA_ATTRIB_NOT_SUPPORTED;
+
+    vaStatus = vaGetConfigAttributes(mVADisplay, profile, VAEntrypointEncSlice, &attrib_list, 1);
+    if(attrib_list.value == VA_ATTRIB_NOT_SUPPORTED )
+        mAutoReference = false;
+    else
+        mAutoReference = true;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::querySupportedSurfaceMemTypes() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    unsigned int num = 0;
+
+    VASurfaceAttrib* attribs = NULL;
+
+    //get attribs number
+    vaStatus = vaQuerySurfaceAttributes(mVADisplay, mVAConfig, attribs, &num);
+    CHECK_VA_STATUS_RETURN("vaGetSurfaceAttributes");
+
+    if (num == 0)
+        return ENCODE_SUCCESS;
+
+    attribs = new VASurfaceAttrib[num];
+
+    vaStatus = vaQuerySurfaceAttributes(mVADisplay, mVAConfig, attribs, &num);
+    CHECK_VA_STATUS_RETURN("vaGetSurfaceAttributes");
+
+    for(uint32_t i = 0; i < num; i ++) {
+        if (attribs[i].type == VASurfaceAttribMemoryType) {
+            mSupportedSurfaceMemType = attribs[i].value.value.i;
+            break;
+        }
+        else
+            continue;
+    }
+
+    delete attribs;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::outputAllData(VideoEncOutputBuffer *outBuffer) {
+
+    // Data size been copied for every single call
+    uint32_t sizeCopiedHere = 0;
+    uint32_t sizeToBeCopied = 0;
+
+    CHECK_NULL_RETURN_IFFAIL(outBuffer->data);
+
+    while (1) {
+
+        LOG_I("mCurSegment->size = %d, mOffsetInSeg = %d\n", mCurSegment->size, mOffsetInSeg);
+        LOG_I("outBuffer->bufferSize = %d, sizeCopiedHere = %d, mTotalSizeCopied = %d\n",
+              outBuffer->bufferSize, sizeCopiedHere, mTotalSizeCopied);
+
+        if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
+            LOG_E("mCurSegment->size < mOffsetInSeg  || outBuffer->bufferSize < sizeCopiedHere\n");
+            return ENCODE_FAIL;
+        }
+
+        if ((mCurSegment->size - mOffsetInSeg) <= outBuffer->bufferSize - sizeCopiedHere) {
+            sizeToBeCopied = mCurSegment->size - mOffsetInSeg;
+            memcpy(outBuffer->data + sizeCopiedHere,
+                   (uint8_t *)mCurSegment->buf + mOffsetInSeg, sizeToBeCopied);
+            sizeCopiedHere += sizeToBeCopied;
+            mTotalSizeCopied += sizeToBeCopied;
+            mOffsetInSeg = 0;
+        } else {
+            sizeToBeCopied = outBuffer->bufferSize - sizeCopiedHere;
+            memcpy(outBuffer->data + sizeCopiedHere,
+                   (uint8_t *)mCurSegment->buf + mOffsetInSeg, outBuffer->bufferSize - sizeCopiedHere);
+            mTotalSizeCopied += sizeToBeCopied;
+            mOffsetInSeg += sizeToBeCopied;
+            outBuffer->dataSize = outBuffer->bufferSize;
+            outBuffer->remainingSize = mTotalSize - mTotalSizeCopied;
+            outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
+            return ENCODE_BUFFER_TOO_SMALL;
+        }
+
+        if (mCurSegment->next == NULL) {
+            outBuffer->dataSize = sizeCopiedHere;
+            outBuffer->remainingSize = 0;
+            outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+            mCurSegment = NULL;
+            return ENCODE_SUCCESS;
+        }
+
+        mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
+        mOffsetInSeg = 0;
+    }
+}
+
+void VideoEncoderBase::setDefaultParams() {
+
+    // Set default value for input parameters
+    mComParams.profile = VAProfileH264Baseline;
+    mComParams.level = 41;
+    mComParams.rawFormat = RAW_FORMAT_NV12;
+    mComParams.frameRate.frameRateNum = 30;
+    mComParams.frameRate.frameRateDenom = 1;
+    mComParams.resolution.width = 0;
+    mComParams.resolution.height = 0;
+    mComParams.intraPeriod = 30;
+    mComParams.rcMode = RATE_CONTROL_NONE;
+    mComParams.rcParams.initQP = 15;
+    mComParams.rcParams.minQP = 0;
+    mComParams.rcParams.maxQP = 0;
+    mComParams.rcParams.I_minQP = 0;
+    mComParams.rcParams.I_maxQP = 0;
+    mComParams.rcParams.bitRate = 640000;
+    mComParams.rcParams.targetPercentage= 0;
+    mComParams.rcParams.windowSize = 0;
+    mComParams.rcParams.disableFrameSkip = 0;
+    mComParams.rcParams.disableBitsStuffing = 1;
+    mComParams.rcParams.enableIntraFrameQPControl = 0;
+    mComParams.rcParams.temporalFrameRate = 0;
+    mComParams.rcParams.temporalID = 0;
+    mComParams.cyclicFrameInterval = 30;
+    mComParams.refreshType = VIDEO_ENC_NONIR;
+    mComParams.airParams.airMBs = 0;
+    mComParams.airParams.airThreshold = 0;
+    mComParams.airParams.airAuto = 1;
+    mComParams.disableDeblocking = 2;
+    mComParams.syncEncMode = false;
+    mComParams.codedBufNum = 2;
+    mComParams.numberOfLayer = 1;
+    mComParams.nPeriodicity = 0;
+    memset(mComParams.nLayerID,0,32*sizeof(uint32_t));
+
+    mHrdParam.bufferSize = 0;
+    mHrdParam.initBufferFullness = 0;
+
+    mStoreMetaDataInBuffers.isEnabled = false;
+}
+
+Encode_Status VideoEncoderBase::setParameters(
+        VideoParamConfigSet *videoEncParams) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+    LOG_I("Config type = %x\n", (int)videoEncParams->type);
+
+    if (mStarted) {
+        LOG_E("Encoder has been initialized, should use setConfig to change configurations\n");
+        return ENCODE_ALREADY_INIT;
+    }
+
+    switch (videoEncParams->type) {
+        case VideoParamsTypeCommon: {
+
+            VideoParamsCommon *paramsCommon =
+                    reinterpret_cast <VideoParamsCommon *> (videoEncParams);
+            if (paramsCommon->size != sizeof (VideoParamsCommon)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            if(paramsCommon->codedBufNum < 2)
+                paramsCommon->codedBufNum =2;
+            mComParams = *paramsCommon;
+            break;
+        }
+
+        case VideoParamsTypeUpSteamBuffer: {
+
+            VideoParamsUpstreamBuffer *upStreamBuffer =
+                    reinterpret_cast <VideoParamsUpstreamBuffer *> (videoEncParams);
+
+            if (upStreamBuffer->size != sizeof (VideoParamsUpstreamBuffer)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            ret = setUpstreamBuffer(upStreamBuffer);
+            break;
+        }
+
+        case VideoParamsTypeUsrptrBuffer: {
+
+            // usrptr only can be get
+            // this case should not happen
+            break;
+        }
+
+        case VideoParamsTypeHRD: {
+            VideoParamsHRD *hrd =
+                    reinterpret_cast <VideoParamsHRD *> (videoEncParams);
+
+            if (hrd->size != sizeof (VideoParamsHRD)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mHrdParam.bufferSize = hrd->bufferSize;
+            mHrdParam.initBufferFullness = hrd->initBufferFullness;
+            mRenderHrd = true;
+
+            break;
+        }
+
+        case VideoParamsTypeStoreMetaDataInBuffers: {
+            VideoParamsStoreMetaDataInBuffers *metadata =
+                    reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
+
+            if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mStoreMetaDataInBuffers.isEnabled = metadata->isEnabled;
+
+            break;
+        }
+
+        case VideoParamsTypeTemporalLayer:{
+            VideoParamsTemporalLayer *temporallayer =
+                    reinterpret_cast <VideoParamsTemporalLayer *> (videoEncParams);
+
+            if (temporallayer->size != sizeof(VideoParamsTemporalLayer)) {
+                 return ENCODE_INVALID_PARAMS;
+            }
+
+            mComParams.numberOfLayer = temporallayer->numberOfLayer;
+            mComParams.nPeriodicity = temporallayer->nPeriodicity;
+            for(uint32_t i=0;i<temporallayer->nPeriodicity;i++)
+                mComParams.nLayerID[i] = temporallayer->nLayerID[i];
+            mRenderMultiTemporal = true;
+            break;
+        }
+
+        case VideoParamsTypeAVC:
+        case VideoParamsTypeH263:
+        case VideoParamsTypeMP4:
+        case VideoParamsTypeVC1:
+        case VideoParamsTypeVP8: {
+            ret = derivedSetParams(videoEncParams);
+            break;
+        }
+
+        default: {
+            LOG_E ("Wrong ParamType here\n");
+            return ENCODE_INVALID_PARAMS;
+        }
+    }
+    return ret;
+}
+
+Encode_Status VideoEncoderBase::getParameters(
+        VideoParamConfigSet *videoEncParams) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+    LOG_I("Config type = %d\n", (int)videoEncParams->type);
+
+    switch (videoEncParams->type) {
+        case VideoParamsTypeCommon: {
+
+            VideoParamsCommon *paramsCommon =
+                    reinterpret_cast <VideoParamsCommon *> (videoEncParams);
+
+            if (paramsCommon->size != sizeof (VideoParamsCommon)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            *paramsCommon = mComParams;
+            break;
+        }
+
+        case VideoParamsTypeUpSteamBuffer: {
+
+            // Get upstream buffer could happen
+            // but not meaningful a lot
+            break;
+        }
+
+        case VideoParamsTypeUsrptrBuffer: {
+            VideoParamsUsrptrBuffer *usrptrBuffer =
+                    reinterpret_cast <VideoParamsUsrptrBuffer *> (videoEncParams);
+
+            if (usrptrBuffer->size != sizeof (VideoParamsUsrptrBuffer)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            ret = getNewUsrptrFromSurface(
+                    usrptrBuffer->width, usrptrBuffer->height, usrptrBuffer->format,
+                    usrptrBuffer->expectedSize, &(usrptrBuffer->actualSize),
+                    &(usrptrBuffer->stride), &(usrptrBuffer->usrPtr));
+
+            break;
+        }
+
+        case VideoParamsTypeHRD: {
+            VideoParamsHRD *hrd =
+                    reinterpret_cast <VideoParamsHRD *> (videoEncParams);
+
+            if (hrd->size != sizeof (VideoParamsHRD)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            hrd->bufferSize = mHrdParam.bufferSize;
+            hrd->initBufferFullness = mHrdParam.initBufferFullness;
+
+            break;
+        }
+
+        case VideoParamsTypeStoreMetaDataInBuffers: {
+            VideoParamsStoreMetaDataInBuffers *metadata =
+                    reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
+
+            if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            metadata->isEnabled = mStoreMetaDataInBuffers.isEnabled;
+
+            break;
+        }
+
+        case VideoParamsTypeProfileLevel: {
+            VideoParamsProfileLevel *profilelevel =
+                reinterpret_cast <VideoParamsProfileLevel *> (videoEncParams);
+
+            if (profilelevel->size != sizeof (VideoParamsProfileLevel)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            profilelevel->level = 0;
+            if(queryProfileLevelConfig(mVADisplay, profilelevel->profile) == ENCODE_SUCCESS){
+                profilelevel->isSupported = true;
+                if(profilelevel->profile == VAProfileH264High)
+                    profilelevel->level = 42;
+                else if(profilelevel->profile == VAProfileH264Main)
+                     profilelevel->level = 42;
+                else if(profilelevel->profile == VAProfileH264Baseline)
+                     profilelevel->level = 41;
+                else{
+                    profilelevel->level = 0;
+                    profilelevel->isSupported = false;
+                }
+            }
+        }
+
+        case VideoParamsTypeTemporalLayer:{
+            VideoParamsTemporalLayer *temporallayer =
+                reinterpret_cast <VideoParamsTemporalLayer *> (videoEncParams);
+
+            if(temporallayer->size != sizeof(VideoParamsTemporalLayer)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            temporallayer->numberOfLayer = mComParams.numberOfLayer;
+
+            break;
+        }
+
+        case VideoParamsTypeAVC:
+        case VideoParamsTypeH263:
+        case VideoParamsTypeMP4:
+        case VideoParamsTypeVC1:
+        case VideoParamsTypeVP8: {
+            derivedGetParams(videoEncParams);
+            break;
+        }
+
+        default: {
+            LOG_E ("Wrong ParamType here\n");
+            break;
+        }
+
+    }
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::setConfig(VideoParamConfigSet *videoEncConfig) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
+    LOG_I("Config type = %d\n", (int)videoEncConfig->type);
+
+   // workaround
+#if 0
+    if (!mStarted) {
+        LOG_E("Encoder has not initialized yet, can't call setConfig\n");
+        return ENCODE_NOT_INIT;
+    }
+#endif
+
+    switch (videoEncConfig->type) {
+        case VideoConfigTypeFrameRate: {
+            VideoConfigFrameRate *configFrameRate =
+                    reinterpret_cast <VideoConfigFrameRate *> (videoEncConfig);
+
+            if (configFrameRate->size != sizeof (VideoConfigFrameRate)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            mComParams.frameRate = configFrameRate->frameRate;
+            mRenderFrameRate = true;
+            break;
+        }
+
+        case VideoConfigTypeBitRate: {
+            VideoConfigBitRate *configBitRate =
+                    reinterpret_cast <VideoConfigBitRate *> (videoEncConfig);
+
+            if (configBitRate->size != sizeof (VideoConfigBitRate)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            if(mComParams.numberOfLayer == 1)
+            {
+                mComParams.rcParams = configBitRate->rcParams;
+                mRenderBitRate = true;
+            }
+            else
+            {
+                mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].nLayerID = configBitRate->rcParams.temporalID;
+                mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].bitRate = configBitRate->rcParams.bitRate;
+                mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].frameRate = configBitRate->rcParams.temporalFrameRate;
+            }
+            break;
+        }
+
+        case VideoConfigTypeResolution: {
+
+            // Not Implemented
+            break;
+        }
+        case VideoConfigTypeIntraRefreshType: {
+
+            VideoConfigIntraRefreshType *configIntraRefreshType =
+                    reinterpret_cast <VideoConfigIntraRefreshType *> (videoEncConfig);
+
+            if (configIntraRefreshType->size != sizeof (VideoConfigIntraRefreshType)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            mComParams.refreshType = configIntraRefreshType->refreshType;
+            break;
+        }
+
+        case VideoConfigTypeCyclicFrameInterval: {
+            VideoConfigCyclicFrameInterval *configCyclicFrameInterval =
+                    reinterpret_cast <VideoConfigCyclicFrameInterval *> (videoEncConfig);
+            if (configCyclicFrameInterval->size != sizeof (VideoConfigCyclicFrameInterval)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mComParams.cyclicFrameInterval = configCyclicFrameInterval->cyclicFrameInterval;
+            break;
+        }
+
+        case VideoConfigTypeAIR: {
+
+            VideoConfigAIR *configAIR = reinterpret_cast <VideoConfigAIR *> (videoEncConfig);
+
+            if (configAIR->size != sizeof (VideoConfigAIR)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mComParams.airParams = configAIR->airParams;
+            mRenderAIR = true;
+            break;
+        }
+        case VideoConfigTypeCIR: {
+
+            VideoConfigCIR *configCIR = reinterpret_cast <VideoConfigCIR *> (videoEncConfig);
+
+            if (configCIR->size != sizeof (VideoConfigCIR)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            mComParams.cirParams = configCIR->cirParams;
+            mRenderCIR = true;
+            break;
+        }
+        case VideoConfigTypeAVCIntraPeriod:
+        case VideoConfigTypeNALSize:
+        case VideoConfigTypeIDRRequest:
+        case VideoConfigTypeSliceNum:
+        case VideoConfigTypeVP8:
+        case VideoConfigTypeVP8ReferenceFrame:
+        case VideoConfigTypeVP8MaxFrameSizeRatio:{
+            ret = derivedSetConfig(videoEncConfig);
+            break;
+        }
+        default: {
+            LOG_E ("Wrong Config Type here\n");
+            break;
+        }
+    }
+    return ret;
+}
+
+Encode_Status VideoEncoderBase::getConfig(VideoParamConfigSet *videoEncConfig) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
+    LOG_I("Config type = %d\n", (int)videoEncConfig->type);
+
+    switch (videoEncConfig->type) {
+        case VideoConfigTypeFrameRate: {
+            VideoConfigFrameRate *configFrameRate =
+                    reinterpret_cast <VideoConfigFrameRate *> (videoEncConfig);
+
+            if (configFrameRate->size != sizeof (VideoConfigFrameRate)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configFrameRate->frameRate = mComParams.frameRate;
+            break;
+        }
+
+        case VideoConfigTypeBitRate: {
+            VideoConfigBitRate *configBitRate =
+                    reinterpret_cast <VideoConfigBitRate *> (videoEncConfig);
+
+            if (configBitRate->size != sizeof (VideoConfigBitRate)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            configBitRate->rcParams = mComParams.rcParams;
+
+
+            break;
+        }
+        case VideoConfigTypeResolution: {
+            // Not Implemented
+            break;
+        }
+        case VideoConfigTypeIntraRefreshType: {
+
+            VideoConfigIntraRefreshType *configIntraRefreshType =
+                    reinterpret_cast <VideoConfigIntraRefreshType *> (videoEncConfig);
+
+            if (configIntraRefreshType->size != sizeof (VideoConfigIntraRefreshType)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+            configIntraRefreshType->refreshType = mComParams.refreshType;
+            break;
+        }
+
+        case VideoConfigTypeCyclicFrameInterval: {
+            VideoConfigCyclicFrameInterval *configCyclicFrameInterval =
+                    reinterpret_cast <VideoConfigCyclicFrameInterval *> (videoEncConfig);
+            if (configCyclicFrameInterval->size != sizeof (VideoConfigCyclicFrameInterval)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configCyclicFrameInterval->cyclicFrameInterval = mComParams.cyclicFrameInterval;
+            break;
+        }
+
+        case VideoConfigTypeAIR: {
+
+            VideoConfigAIR *configAIR = reinterpret_cast <VideoConfigAIR *> (videoEncConfig);
+
+            if (configAIR->size != sizeof (VideoConfigAIR)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configAIR->airParams = mComParams.airParams;
+            break;
+        }
+        case VideoConfigTypeCIR: {
+
+            VideoConfigCIR *configCIR = reinterpret_cast <VideoConfigCIR *> (videoEncConfig);
+
+            if (configCIR->size != sizeof (VideoConfigCIR)) {
+                return ENCODE_INVALID_PARAMS;
+            }
+
+            configCIR->cirParams = mComParams.cirParams;
+            break;
+        }
+        case VideoConfigTypeAVCIntraPeriod:
+        case VideoConfigTypeNALSize:
+        case VideoConfigTypeIDRRequest:
+        case VideoConfigTypeSliceNum:
+        case VideoConfigTypeVP8: {
+
+            ret = derivedGetConfig(videoEncConfig);
+            break;
+        }
+        default: {
+            LOG_E ("Wrong ParamType here\n");
+            break;
+        }
+    }
+    return ret;
+}
+
+void VideoEncoderBase:: PrepareFrameInfo (EncodeTask* task) {
+    if (mNewHeader) mFrameNum = 0;
+    LOG_I( "mFrameNum = %d   ", mFrameNum);
+
+    updateFrameInfo(task) ;
+}
+
+Encode_Status VideoEncoderBase:: updateFrameInfo (EncodeTask* task) {
+
+    task->type = FTYPE_P;
+
+    // determine the picture type
+    if (mFrameNum == 0)
+        task->type = FTYPE_I;
+    if (mComParams.intraPeriod != 0 && ((mFrameNum % mComParams.intraPeriod) == 0))
+        task->type = FTYPE_I;
+
+    if (task->type == FTYPE_I)
+        task->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status  VideoEncoderBase::getMaxOutSize (uint32_t *maxSize) {
+
+    uint32_t size = mComParams.resolution.width * mComParams.resolution.height;
+
+    if (maxSize == NULL) {
+        LOG_E("maxSize == NULL\n");
+        return ENCODE_NULL_PTR;
+    }
+
+    LOG_V( "Begin\n");
+
+    if (mCodedBufSize > 0) {
+        *maxSize = mCodedBufSize;
+        LOG_V ("Already calculate the max encoded size, get the value directly");
+        return ENCODE_SUCCESS;
+    }
+
+    // here, VP8 is different from AVC/H263
+    if(mComParams.profile == VAProfileVP8Version0_3) // for VP8 encode
+    {
+        // According to VIED suggestions, in CBR mode, coded buffer should be the size of 3 bytes per luma pixel
+        // in CBR_HRD mode, coded buffer size should be  5 * rc_buf_sz * rc_target_bitrate;
+        // now we just hardcode mCodedBufSize as 2M to walk round coded buffer size issue;
+        /*
+        if(mComParams.rcMode == VA_RC_CBR) // CBR_HRD mode
+            mCodedBufSize = 5 * mComParams.rcParams.bitRate * 6000;
+        else // CBR mode
+            mCodedBufSize = 3 * mComParams.resolution.width * mComParams.resolution.height;
+        */
+        mCodedBufSize = (2 * 1024 * 1024 + 31) & (~31);
+    }
+    else // for AVC/H263/MPEG4 encode
+    {
+        // base on the rate control mode to calculate the defaule encoded buffer size
+        if (mComParams.rcMode == VA_RC_NONE) {
+             mCodedBufSize = (size * 400) / (16 * 16);
+             // set to value according to QP
+        } else {
+             mCodedBufSize = mComParams.rcParams.bitRate / 4;
+        }
+
+        mCodedBufSize = max (mCodedBufSize , (size * 400) / (16 * 16));
+
+        // in case got a very large user input bit rate value
+        mCodedBufSize = min(mCodedBufSize, (size * 1.5 * 8));
+        mCodedBufSize =  (mCodedBufSize + 15) &(~15);
+    }
+
+    *maxSize = mCodedBufSize;
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::getNewUsrptrFromSurface(
+    uint32_t width, uint32_t height, uint32_t format,
+    uint32_t expectedSize, uint32_t *outsize, uint32_t *stride, uint8_t **usrptr) {
+
+    Encode_Status ret = ENCODE_FAIL;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    VASurfaceID surface = VA_INVALID_SURFACE;
+    VAImage image;
+    uint32_t index = 0;
+
+    LOG_V( "Begin\n");
+    // If encode session has been configured, we can not request surface creation anymore
+    if (mStarted) {
+        LOG_E( "Already Initialized, can not request VA surface anymore\n");
+        return ENCODE_WRONG_STATE;
+    }
+    if (width<=0 || height<=0 ||outsize == NULL ||stride == NULL || usrptr == NULL) {
+        LOG_E("width<=0 || height<=0 || outsize == NULL || stride == NULL ||usrptr == NULL\n");
+        return ENCODE_NULL_PTR;
+    }
+
+    // Current only NV12 is supported in VA API
+    // Through format we can get known the number of planes
+    if (format != STRING_TO_FOURCC("NV12")) {
+        LOG_W ("Format is not supported\n");
+        return ENCODE_NOT_SUPPORTED;
+    }
+
+    surface = CreateNewVASurface(mVADisplay, width, height);
+    if (surface == VA_INVALID_SURFACE)
+        return ENCODE_DRIVER_FAIL;
+
+    vaStatus = vaDeriveImage(mVADisplay, surface, &image);
+    CHECK_VA_STATUS_RETURN("vaDeriveImage");
+    LOG_V( "vaDeriveImage Done\n");
+    vaStatus = vaMapBuffer(mVADisplay, image.buf, (void **) usrptr);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    // make sure the physical page been allocated
+    for (index = 0; index < image.data_size; index = index + 4096) {
+        unsigned char tmp =  *(*usrptr + index);
+        if (tmp == 0)
+            *(*usrptr + index) = 0;
+    }
+
+    *outsize = image.data_size;
+    *stride = image.pitches[0];
+
+    LOG_I( "surface = 0x%08x\n",(uint32_t)surface);
+    LOG_I("image->pitches[0] = %d\n", image.pitches[0]);
+    LOG_I("image->pitches[1] = %d\n", image.pitches[1]);
+    LOG_I("image->offsets[0] = %d\n", image.offsets[0]);
+    LOG_I("image->offsets[1] = %d\n", image.offsets[1]);
+    LOG_I("image->num_planes = %d\n", image.num_planes);
+    LOG_I("image->width = %d\n", image.width);
+    LOG_I("image->height = %d\n", image.height);
+    LOG_I ("data_size = %d\n", image.data_size);
+    LOG_I ("usrptr = 0x%p\n", *usrptr);
+
+    vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+    vaStatus = vaDestroyImage(mVADisplay, image.image_id);
+    CHECK_VA_STATUS_RETURN("vaDestroyImage");
+
+    if (*outsize < expectedSize) {
+        LOG_E ("Allocated buffer size is small than the expected size, destroy the surface");
+        LOG_I ("Allocated size is %d, expected size is %d\n", *outsize, expectedSize);
+        vaStatus = vaDestroySurfaces(mVADisplay, &surface, 1);
+        CHECK_VA_STATUS_RETURN("vaDestroySurfaces");
+        return ENCODE_FAIL;
+    }
+
+    VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
+    if (map == NULL) {
+        LOG_E( "new VASurfaceMap failed\n");
+        return ENCODE_NO_MEMORY;
+    }
+
+    map->setVASurface(surface);  //special case, vasuface is set, so nothing do in doMapping
+//    map->setType(MetadataBufferTypeEncoder);
+    map->setValue((intptr_t)*usrptr);
+    ValueInfo vinfo;
+    memset(&vinfo, 0, sizeof(ValueInfo));
+    vinfo.mode = (MemMode)MEM_MODE_USRPTR;
+    vinfo.handle = 0;
+    vinfo.size = 0;
+    vinfo.width = width;
+    vinfo.height = height;
+    vinfo.lumaStride = width;
+    vinfo.chromStride = width;
+    vinfo.format = VA_FOURCC_NV12;
+    vinfo.s3dformat = 0xffffffff;
+    map->setValueInfo(vinfo);
+    map->doMapping();
+
+    mSrcSurfaceMapList.push_back(map);
+
+    ret = ENCODE_SUCCESS;
+
+    return ret;
+}
+
+Encode_Status VideoEncoderBase::setUpstreamBuffer(VideoParamsUpstreamBuffer *upStreamBuffer) {
+
+    Encode_Status status = ENCODE_SUCCESS;
+
+    CHECK_NULL_RETURN_IFFAIL(upStreamBuffer);
+    if (upStreamBuffer->bufCnt == 0) {
+        LOG_E("bufCnt == 0\n");
+        return ENCODE_FAIL;
+    }
+
+    for(unsigned int i=0; i < upStreamBuffer->bufCnt; i++) {
+        if (findSurfaceMapByValue(upStreamBuffer->bufList[i]) != NULL)  //already mapped
+            continue;
+
+        //wrap upstream buffer into vaSurface
+        VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
+
+//        map->setType(MetadataBufferTypeUser);
+        map->setValue(upStreamBuffer->bufList[i]);
+        ValueInfo vinfo;
+        memset(&vinfo, 0, sizeof(ValueInfo));
+        vinfo.mode = (MemMode)upStreamBuffer->bufferMode;
+        vinfo.handle = (intptr_t)upStreamBuffer->display;
+        vinfo.size = 0;
+        if (upStreamBuffer->bufAttrib) {
+            vinfo.width = upStreamBuffer->bufAttrib->realWidth;
+            vinfo.height = upStreamBuffer->bufAttrib->realHeight;
+            vinfo.lumaStride = upStreamBuffer->bufAttrib->lumaStride;
+            vinfo.chromStride = upStreamBuffer->bufAttrib->chromStride;
+            vinfo.format = upStreamBuffer->bufAttrib->format;
+        }
+        vinfo.s3dformat = 0xFFFFFFFF;
+        map->setValueInfo(vinfo);
+        status = map->doMapping();
+
+        if (status == ENCODE_SUCCESS)
+            mSrcSurfaceMapList.push_back(map);
+        else
+           delete map;
+    }
+
+    return status;
+}
+
+Encode_Status VideoEncoderBase::manageSrcSurface(VideoEncRawBuffer *inBuffer, VASurfaceID *sid) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    IntelMetadataBufferType type;
+    intptr_t value;
+    ValueInfo vinfo;
+    ValueInfo *pvinfo = &vinfo;
+    intptr_t *extravalues = NULL;
+    unsigned int extravalues_count = 0;
+
+    IntelMetadataBuffer imb;
+    VASurfaceMap *map = NULL;
+
+    memset(&vinfo, 0, sizeof(ValueInfo));
+    if (mStoreMetaDataInBuffers.isEnabled) {
+        //metadatabuffer mode
+        LOG_I("in metadata mode, data=%p, size=%d\n", inBuffer->data, inBuffer->size);
+        if (imb.UnSerialize(inBuffer->data, inBuffer->size) != IMB_SUCCESS) {
+            //fail to parse buffer
+            return ENCODE_NO_REQUEST_DATA;
+        }
+
+        imb.GetType(type);
+        imb.GetValue(value);
+    } else {
+        //raw mode
+        LOG_I("in raw mode, data=%p, size=%d\n", inBuffer->data, inBuffer->size);
+        if (! inBuffer->data || inBuffer->size == 0) {
+            return ENCODE_NULL_PTR;
+        }
+
+        type = IntelMetadataBufferTypeUser;
+        value = (intptr_t)inBuffer->data;
+    }
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    uint32_t sflag = mSessionFlag;
+    imb.GetSessionFlag(mSessionFlag);
+    if (mSessionFlag != sflag) {
+        //new sharing session, flush buffer sharing cache
+        IntelMetadataBuffer::ClearContext(sflag, false);
+        //flush surfacemap cache
+        LOG_V( "Flush Src Surface Map\n");
+        while(! mSrcSurfaceMapList.empty())
+        {
+            delete (*mSrcSurfaceMapList.begin());
+            mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
+        }
+    }
+#endif
+
+    //find if mapped
+    map = (VASurfaceMap*) findSurfaceMapByValue(value);
+
+    if (map) {
+        //has mapped, get surfaceID directly and do all necessary actions
+        LOG_I("direct find surface %d from value %i\n", map->getVASurface(), value);
+        *sid = map->getVASurface();
+        map->doMapping();
+        return ret;
+    }
+
+    //if no found from list, then try to map value with parameters
+    LOG_I("not find surface from cache with value %i, start mapping if enough information\n", value);
+
+    if (mStoreMetaDataInBuffers.isEnabled) {
+
+        //if type is IntelMetadataBufferTypeGrallocSource, use default parameters since no ValueInfo
+        if (type == IntelMetadataBufferTypeGrallocSource) {
+            vinfo.mode = MEM_MODE_GFXHANDLE;
+            vinfo.handle = 0;
+            vinfo.size = 0;
+            vinfo.width = mComParams.resolution.width;
+            vinfo.height = mComParams.resolution.height;
+            vinfo.lumaStride = mComParams.resolution.width;
+            vinfo.chromStride = mComParams.resolution.width;
+            vinfo.format = VA_FOURCC_NV12;
+            vinfo.s3dformat = 0xFFFFFFFF;
+        } else {
+            //get all info mapping needs
+            imb.GetValueInfo(pvinfo);
+            imb.GetExtraValues(extravalues, extravalues_count);
+        }
+
+    } else {
+
+        //raw mode
+        vinfo.mode = MEM_MODE_MALLOC;
+        vinfo.handle = 0;
+        vinfo.size = inBuffer->size;
+        vinfo.width = mComParams.resolution.width;
+        vinfo.height = mComParams.resolution.height;
+        vinfo.lumaStride = mComParams.resolution.width;
+        vinfo.chromStride = mComParams.resolution.width;
+        vinfo.format = VA_FOURCC_NV12;
+        vinfo.s3dformat = 0xFFFFFFFF;
+    }
+
+    /*  Start mapping, if pvinfo is not NULL, then have enough info to map;
+     *   if extravalues is not NULL, then need to do more times mapping
+     */
+    if (pvinfo){
+        //map according info, and add to surfacemap list
+        map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
+        map->setValue(value);
+        map->setValueInfo(*pvinfo);
+        map->setAction(mVASurfaceMappingAction);
+
+        ret = map->doMapping();
+        if (ret == ENCODE_SUCCESS) {
+            LOG_I("surface mapping success, map value %i into surface %d\n", value, map->getVASurface());
+            mSrcSurfaceMapList.push_back(map);
+        } else {
+            delete map;
+            LOG_E("surface mapping failed, wrong info or meet serious error\n");
+            return ret;
+        }
+
+        *sid = map->getVASurface();
+
+    } else {
+        //can't map due to no info
+        LOG_E("surface mapping failed, missing information\n");
+        return ENCODE_NO_REQUEST_DATA;
+    }
+
+    if (extravalues) {
+        //map more using same ValueInfo
+        for(unsigned int i=0; i<extravalues_count; i++) {
+            map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
+            map->setValue(extravalues[i]);
+            map->setValueInfo(vinfo);
+
+            ret = map->doMapping();
+            if (ret == ENCODE_SUCCESS) {
+                LOG_I("surface mapping extravalue success, map value %i into surface %d\n", extravalues[i], map->getVASurface());
+                mSrcSurfaceMapList.push_back(map);
+            } else {
+                delete map;
+                map = NULL;
+                LOG_E( "surface mapping extravalue failed, extravalue is %i\n", extravalues[i]);
+            }
+        }
+    }
+
+    return ret;
+}
+
+Encode_Status VideoEncoderBase::renderDynamicBitrate(EncodeTask* task) {
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    LOG_V( "Begin\n\n");
+    // disable bits stuffing and skip frame apply to all rate control mode
+
+    VAEncMiscParameterBuffer   *miscEncParamBuf;
+    VAEncMiscParameterRateControl *bitrateControlParam;
+    VABufferID miscParamBufferID;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterRateControl),
+            1, NULL,
+            &miscParamBufferID);
+
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    miscEncParamBuf->type = VAEncMiscParameterTypeRateControl;
+    bitrateControlParam = (VAEncMiscParameterRateControl *)miscEncParamBuf->data;
+
+    bitrateControlParam->bits_per_second = mComParams.rcParams.bitRate;
+    bitrateControlParam->initial_qp = mComParams.rcParams.initQP;
+    if(mComParams.rcParams.enableIntraFrameQPControl && (task->type == FTYPE_IDR || task->type == FTYPE_I)) {
+        bitrateControlParam->min_qp = mComParams.rcParams.I_minQP;
+        bitrateControlParam->max_qp = mComParams.rcParams.I_maxQP;
+        mRenderBitRate = true;
+        LOG_I("apply I min/max qp for IDR or I frame\n");
+    } else {
+        bitrateControlParam->min_qp = mComParams.rcParams.minQP;
+        bitrateControlParam->max_qp = mComParams.rcParams.maxQP;
+        mRenderBitRate = false;
+        LOG_I("revert to original min/max qp after IDR or I frame\n");
+    }
+    bitrateControlParam->target_percentage = mComParams.rcParams.targetPercentage;
+    bitrateControlParam->window_size = mComParams.rcParams.windowSize;
+    bitrateControlParam->rc_flags.bits.disable_frame_skip = mComParams.rcParams.disableFrameSkip;
+    bitrateControlParam->rc_flags.bits.disable_bit_stuffing = mComParams.rcParams.disableBitsStuffing;
+    bitrateControlParam->basic_unit_size = 0;
+
+    LOG_I("bits_per_second = %d\n", bitrateControlParam->bits_per_second);
+    LOG_I("initial_qp = %d\n", bitrateControlParam->initial_qp);
+    LOG_I("min_qp = %d\n", bitrateControlParam->min_qp);
+    LOG_I("max_qp = %d\n", bitrateControlParam->max_qp);
+    LOG_I("target_percentage = %d\n", bitrateControlParam->target_percentage);
+    LOG_I("window_size = %d\n", bitrateControlParam->window_size);
+    LOG_I("disable_frame_skip = %d\n", bitrateControlParam->rc_flags.bits.disable_frame_skip);
+    LOG_I("disable_bit_stuffing = %d\n", bitrateControlParam->rc_flags.bits.disable_bit_stuffing);
+
+    vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext,
+            &miscParamBufferID, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    return ENCODE_SUCCESS;
+}
+
+
+Encode_Status VideoEncoderBase::renderDynamicFrameRate() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    if (mComParams.rcMode != RATE_CONTROL_VCM) {
+
+        LOG_W("Not in VCM mode, but call SendDynamicFramerate\n");
+        return ENCODE_SUCCESS;
+    }
+
+    VAEncMiscParameterBuffer   *miscEncParamBuf;
+    VAEncMiscParameterFrameRate *frameRateParam;
+    VABufferID miscParamBufferID;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterFrameRate),
+            1, NULL, &miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    miscEncParamBuf->type = VAEncMiscParameterTypeFrameRate;
+    frameRateParam = (VAEncMiscParameterFrameRate *)miscEncParamBuf->data;
+    frameRateParam->framerate =
+            (unsigned int) (mComParams.frameRate.frameRateNum + mComParams.frameRate.frameRateDenom/2)
+            / mComParams.frameRate.frameRateDenom;
+
+    vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_I( "frame rate = %d\n", frameRateParam->framerate);
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderBase::renderHrd() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    VAEncMiscParameterBuffer *miscEncParamBuf;
+    VAEncMiscParameterHRD *hrdParam;
+    VABufferID miscParamBufferID;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+            VAEncMiscParameterBufferType,
+            sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterHRD),
+            1, NULL, &miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    miscEncParamBuf->type = VAEncMiscParameterTypeHRD;
+    hrdParam = (VAEncMiscParameterHRD *)miscEncParamBuf->data;
+
+    hrdParam->buffer_size = mHrdParam.bufferSize;
+    hrdParam->initial_buffer_fullness = mHrdParam.initBufferFullness;
+
+    vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    return ENCODE_SUCCESS;
+}
+
+VASurfaceMap *VideoEncoderBase::findSurfaceMapByValue(intptr_t value) {
+    android::List<VASurfaceMap *>::iterator node;
+
+    for(node = mSrcSurfaceMapList.begin(); node !=  mSrcSurfaceMapList.end(); node++)
+    {
+        if ((*node)->getValue() == value)
+            return *node;
+        else
+            continue;
+    }
+
+    return NULL;
+}
diff --git a/videoencoder/VideoEncoderBase.h b/videoencoder/VideoEncoderBase.h
new file mode 100644
index 0000000..bf1eecf
--- /dev/null
+++ b/videoencoder/VideoEncoderBase.h
@@ -0,0 +1,186 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_BASE_H__
+#define __VIDEO_ENCODER_BASE_H__
+
+#include <va/va.h>
+#include <va/va_tpi.h>
+#include "VideoEncoderDef.h"
+#include "VideoEncoderInterface.h"
+#include "IntelMetadataBuffer.h"
+#include <utils/List.h>
+#include <utils/threads.h>
+#include "VideoEncoderUtils.h"
+
+struct SurfaceMap {
+    VASurfaceID surface;
+    VASurfaceID surface_backup;
+    IntelMetadataBufferType type;
+    int32_t value;
+    ValueInfo vinfo;
+    bool added;
+};
+
+struct EncodeTask {
+    VASurfaceID enc_surface;
+    VASurfaceID ref_surface;
+    VASurfaceID rec_surface;
+    VABufferID coded_buffer;
+
+    FrameType type;
+    int flag;
+    int64_t timestamp;  //corresponding input frame timestamp
+    void *priv;  //input buffer data
+
+    bool completed;   //if encode task is done complet by HW
+};
+
+class VideoEncoderBase : IVideoEncoder {
+
+public:
+    VideoEncoderBase();
+    virtual ~VideoEncoderBase();
+
+    virtual Encode_Status start(void);
+    virtual void flush(void);
+    virtual Encode_Status stop(void);
+    virtual Encode_Status encode(VideoEncRawBuffer *inBuffer, uint32_t timeout);
+
+    /*
+    * getOutput can be called several time for a frame (such as first time  codec data, and second time others)
+    * encoder will provide encoded data according to the format (whole frame, codec_data, sigle NAL etc)
+    * If the buffer passed to encoded is not big enough, this API call will return ENCODE_BUFFER_TOO_SMALL
+    * and caller should provide a big enough buffer and call again
+    */
+    virtual Encode_Status getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout);
+
+    virtual Encode_Status getParameters(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status setParameters(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status setConfig(VideoParamConfigSet *videoEncConfig);
+    virtual Encode_Status getConfig(VideoParamConfigSet *videoEncConfig);
+    virtual Encode_Status getMaxOutSize(uint32_t *maxSize);
+
+protected:
+    virtual Encode_Status sendEncodeCommand(EncodeTask* task) = 0;
+    virtual Encode_Status derivedSetParams(VideoParamConfigSet *videoEncParams) = 0;
+    virtual Encode_Status derivedGetParams(VideoParamConfigSet *videoEncParams) = 0;
+    virtual Encode_Status derivedGetConfig(VideoParamConfigSet *videoEncConfig) = 0;
+    virtual Encode_Status derivedSetConfig(VideoParamConfigSet *videoEncConfig) = 0;
+    virtual Encode_Status getExtFormatOutput(VideoEncOutputBuffer *outBuffer) = 0;
+    virtual Encode_Status updateFrameInfo(EncodeTask* task) ;
+
+    Encode_Status renderDynamicFrameRate();
+    Encode_Status renderDynamicBitrate(EncodeTask* task);
+    Encode_Status renderHrd();
+    Encode_Status queryProfileLevelConfig(VADisplay dpy, VAProfile profile);
+
+private:
+    void setDefaultParams(void);
+    Encode_Status setUpstreamBuffer(VideoParamsUpstreamBuffer *upStreamBuffer);
+    Encode_Status getNewUsrptrFromSurface(uint32_t width, uint32_t height, uint32_t format,
+            uint32_t expectedSize, uint32_t *outsize, uint32_t *stride, uint8_t **usrptr);
+    VASurfaceMap* findSurfaceMapByValue(intptr_t value);
+    Encode_Status manageSrcSurface(VideoEncRawBuffer *inBuffer, VASurfaceID *sid);
+    void PrepareFrameInfo(EncodeTask* task);
+
+    Encode_Status prepareForOutput(VideoEncOutputBuffer *outBuffer, bool *useLocalBuffer);
+    Encode_Status cleanupForOutput();
+    Encode_Status outputAllData(VideoEncOutputBuffer *outBuffer);
+    Encode_Status queryAutoReferenceConfig(VAProfile profile);
+    Encode_Status querySupportedSurfaceMemTypes();
+    Encode_Status copySurfaces(VASurfaceID srcId, VASurfaceID destId);
+    VASurfaceID CreateSurfaceFromExternalBuf(int32_t value, ValueInfo& vinfo);
+
+protected:
+
+    bool mInitialized;
+    bool mStarted;
+    VADisplay mVADisplay;
+    VAContextID mVAContext;
+    VAConfigID mVAConfig;
+    VAEntrypoint mVAEntrypoint;
+
+
+    VideoParamsCommon mComParams;
+    VideoParamsHRD mHrdParam;
+    VideoParamsStoreMetaDataInBuffers mStoreMetaDataInBuffers;
+
+    bool mNewHeader;
+
+    bool mRenderMaxSliceSize; //Max Slice Size
+    bool mRenderQP;
+    bool mRenderAIR;
+    bool mRenderCIR;
+    bool mRenderFrameRate;
+    bool mRenderBitRate;
+    bool mRenderHrd;
+    bool mRenderMaxFrameSize;
+    bool mRenderMultiTemporal;
+    bool mForceKFrame;
+
+    VABufferID mSeqParamBuf;
+    VABufferID mRcParamBuf;
+    VABufferID mFrameRateParamBuf;
+    VABufferID mPicParamBuf;
+    VABufferID mSliceParamBuf;
+    VASurfaceID* mAutoRefSurfaces;
+
+    android::List <VASurfaceMap *> mSrcSurfaceMapList;  //all mapped surface info list from input buffer
+    android::List <EncodeTask *> mEncodeTaskList;  //all encode tasks list
+    android::List <VABufferID> mVACodedBufferList;  //all available codedbuffer list
+
+    VASurfaceID mRefSurface;        //reference surface, only used in base
+    VASurfaceID mRecSurface;        //reconstructed surface, only used in base
+    uint32_t mFrameNum;
+    uint32_t mCodedBufSize;
+    bool mAutoReference;
+    uint32_t mAutoReferenceSurfaceNum;
+    uint32_t mEncPackedHeaders;
+    uint32_t mEncMaxRefFrames;
+
+    bool mSliceSizeOverflow;
+
+    //Current Outputting task
+    EncodeTask *mCurOutputTask;
+
+    //Current outputting CodedBuffer status
+    VABufferID mOutCodedBuffer;
+    bool mCodedBufferMapped;
+    uint8_t *mOutCodedBufferPtr;
+    VACodedBufferSegment *mCurSegment;
+    uint32_t mOffsetInSeg;
+    uint32_t mTotalSize;
+    uint32_t mTotalSizeCopied;
+    android::Mutex               mCodedBuffer_Lock, mEncodeTask_Lock;
+    android::Condition           mCodedBuffer_Cond, mEncodeTask_Cond;
+
+    bool mFrameSkipped;
+
+    //supported surface memory types
+    int mSupportedSurfaceMemType;
+
+    //VASurface mapping extra action
+    int mVASurfaceMappingAction;
+
+    // For Temporal Layer Bitrate FrameRate settings
+    VideoConfigTemperalLayerBitrateFramerate mTemporalLayerBitrateFramerate[3];
+
+#ifdef INTEL_VIDEO_XPROC_SHARING
+    uint32_t mSessionFlag;
+#endif
+};
+#endif /* __VIDEO_ENCODER_BASE_H__ */
diff --git a/videoencoder/VideoEncoderDef.h b/videoencoder/VideoEncoderDef.h
new file mode 100644
index 0000000..d89d93a
--- /dev/null
+++ b/videoencoder/VideoEncoderDef.h
@@ -0,0 +1,731 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_DEF_H__
+#define __VIDEO_ENCODER_DEF_H__
+
+#include <stdint.h>
+
+#define STRING_TO_FOURCC(format) ((uint32_t)(((format)[0])|((format)[1]<<8)|((format)[2]<<16)|((format)[3]<<24)))
+#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
+#define max(X,Y) (((X) > (Y)) ? (X) : (Y))
+
+typedef int32_t Encode_Status;
+
+// Video encode error code
+enum {
+    ENCODE_INVALID_SURFACE = -11,
+    ENCODE_NO_REQUEST_DATA = -10,
+    ENCODE_WRONG_STATE = -9,
+    ENCODE_NOTIMPL = -8,
+    ENCODE_NO_MEMORY = -7,
+    ENCODE_NOT_INIT = -6,
+    ENCODE_DRIVER_FAIL = -5,
+    ENCODE_INVALID_PARAMS = -4,
+    ENCODE_NOT_SUPPORTED = -3,
+    ENCODE_NULL_PTR = -2,
+    ENCODE_FAIL = -1,
+    ENCODE_SUCCESS = 0,
+    ENCODE_ALREADY_INIT = 1,
+    ENCODE_SLICESIZE_OVERFLOW = 2,
+    ENCODE_BUFFER_TOO_SMALL = 3, // The buffer passed to encode is too small to contain encoded data
+    ENCODE_DEVICE_BUSY = 4,
+    ENCODE_DATA_NOT_READY = 5,
+};
+
+typedef enum {
+    OUTPUT_EVERYTHING = 0,  //Output whatever driver generates
+    OUTPUT_CODEC_DATA = 1,
+    OUTPUT_FRAME_DATA = 2, //Equal to OUTPUT_EVERYTHING when no header along with the frame data
+    OUTPUT_ONE_NAL = 4,
+    OUTPUT_ONE_NAL_WITHOUT_STARTCODE = 8,
+    OUTPUT_LENGTH_PREFIXED = 16,
+    OUTPUT_CODEDBUFFER = 32,
+    OUTPUT_NALULENGTHS_PREFIXED = 64,
+    OUTPUT_BUFFER_LAST
+} VideoOutputFormat;
+
+typedef enum {
+    RAW_FORMAT_NONE = 0,
+    RAW_FORMAT_YUV420 = 1,
+    RAW_FORMAT_YUV422 = 2,
+    RAW_FORMAT_YUV444 = 4,
+    RAW_FORMAT_NV12 = 8,
+    RAW_FORMAT_RGBA = 16,
+    RAW_FORMAT_OPAQUE = 32,
+    RAW_FORMAT_PROTECTED = 0x80000000,
+    RAW_FORMAT_LAST
+} VideoRawFormat;
+
+typedef enum {
+    RATE_CONTROL_NONE = 1,
+    RATE_CONTROL_CBR = 2,
+    RATE_CONTROL_VBR = 4,
+    RATE_CONTROL_VCM = 8,
+    RATE_CONTROL_LAST
+} VideoRateControl;
+
+typedef enum {
+    PROFILE_MPEG2SIMPLE = 0,
+    PROFILE_MPEG2MAIN,
+    PROFILE_MPEG4SIMPLE,
+    PROFILE_MPEG4ADVANCEDSIMPLE,
+    PROFILE_MPEG4MAIN,
+    PROFILE_H264BASELINE,
+    PROFILE_H264MAIN,
+    PROFILE_H264HIGH,
+    PROFILE_VC1SIMPLE,
+    PROFILE_VC1MAIN,
+    PROFILE_VC1ADVANCED,
+    PROFILE_H263BASELINE
+} VideoProfile;
+
+typedef enum {
+    AVC_DELIMITER_LENGTHPREFIX = 0,
+    AVC_DELIMITER_ANNEXB
+} AVCDelimiterType;
+
+typedef enum {
+    VIDEO_ENC_NONIR,       // Non intra refresh
+    VIDEO_ENC_CIR, 		// Cyclic intra refresh
+    VIDEO_ENC_AIR, 		// Adaptive intra refresh
+    VIDEO_ENC_BOTH,
+    VIDEO_ENC_LAST
+} VideoIntraRefreshType;
+
+enum VideoBufferSharingMode {
+    BUFFER_SHARING_NONE = 1, //Means non shared buffer mode
+    BUFFER_SHARING_CI = 2,
+    BUFFER_SHARING_V4L2 = 4,
+    BUFFER_SHARING_SURFACE = 8,
+    BUFFER_SHARING_USRPTR = 16,
+    BUFFER_SHARING_GFXHANDLE = 32,
+    BUFFER_SHARING_KBUFHANDLE = 64,
+    BUFFER_LAST
+};
+
+typedef enum {
+    FTYPE_UNKNOWN = 0, // Unknown
+    FTYPE_I = 1, // General I-frame type
+    FTYPE_P = 2, // General P-frame type
+    FTYPE_B = 3, // General B-frame type
+    FTYPE_SI = 4, // H.263 SI-frame type
+    FTYPE_SP = 5, // H.263 SP-frame type
+    FTYPE_EI = 6, // H.264 EI-frame type
+    FTYPE_EP = 7, // H.264 EP-frame type
+    FTYPE_S = 8, // MPEG-4 S-frame type
+    FTYPE_IDR = 9, // IDR-frame type
+}FrameType;
+
+//function call mode
+#define FUNC_BLOCK        0xFFFFFFFF
+#define FUNC_NONBLOCK        0
+
+// Output buffer flag
+#define ENCODE_BUFFERFLAG_ENDOFFRAME       0x00000001
+#define ENCODE_BUFFERFLAG_PARTIALFRAME     0x00000002
+#define ENCODE_BUFFERFLAG_SYNCFRAME        0x00000004
+#define ENCODE_BUFFERFLAG_CODECCONFIG      0x00000008
+#define ENCODE_BUFFERFLAG_DATACORRUPT      0x00000010
+#define ENCODE_BUFFERFLAG_DATAINVALID      0x00000020
+#define ENCODE_BUFFERFLAG_SLICEOVERFOLOW   0x00000040
+#define ENCODE_BUFFERFLAG_ENDOFSTREAM     0x00000080
+#define ENCODE_BUFFERFLAG_NSTOPFRAME        0x00000100
+
+typedef struct {
+    uint8_t *data;
+    uint32_t bufferSize; //buffer size
+    uint32_t dataSize; //actual size
+    uint32_t offset; //buffer offset
+    uint32_t remainingSize;
+    int flag; //Key frame, Codec Data etc
+    VideoOutputFormat format; //output format
+    int64_t timeStamp; //reserved
+    FrameType type;
+    void *priv; //indicate corresponding input data
+} VideoEncOutputBuffer;
+
+typedef struct {
+    uint8_t *data;
+    uint32_t size;
+    bool bufAvailable; //To indicate whether this buffer can be reused
+    int64_t timeStamp; //reserved
+    FrameType type; //frame type expected to be encoded
+    int flag; // flag to indicate buffer property
+    void *priv; //indicate corresponding input data
+} VideoEncRawBuffer;
+
+struct VideoEncSurfaceBuffer {
+    VASurfaceID surface;
+    uint8_t *usrptr;
+    uint32_t index;
+    bool bufAvailable;
+    VideoEncSurfaceBuffer *next;
+};
+
+struct CirParams {
+    uint32_t cir_num_mbs;
+
+    CirParams &operator=(const CirParams &other) {
+        if (this == &other) return *this;
+
+        this->cir_num_mbs = other.cir_num_mbs;
+        return *this;
+    }
+};
+
+struct AirParams {
+    uint32_t airMBs;
+    uint32_t airThreshold;
+    uint32_t airAuto;
+
+    AirParams &operator=(const AirParams &other) {
+        if (this == &other) return *this;
+
+        this->airMBs= other.airMBs;
+        this->airThreshold= other.airThreshold;
+        this->airAuto = other.airAuto;
+        return *this;
+    }
+};
+
+struct VideoFrameRate {
+    uint32_t frameRateNum;
+    uint32_t frameRateDenom;
+
+    VideoFrameRate &operator=(const VideoFrameRate &other) {
+        if (this == &other) return *this;
+
+        this->frameRateNum = other.frameRateNum;
+        this->frameRateDenom = other.frameRateDenom;
+        return *this;
+    }
+};
+
+struct VideoResolution {
+    uint32_t width;
+    uint32_t height;
+
+    VideoResolution &operator=(const VideoResolution &other) {
+        if (this == &other) return *this;
+
+        this->width = other.width;
+        this->height = other.height;
+        return *this;
+    }
+};
+
+struct VideoRateControlParams {
+    uint32_t bitRate;
+    uint32_t initQP;
+    uint32_t minQP;
+    uint32_t maxQP;
+    uint32_t I_minQP;
+    uint32_t I_maxQP;
+    uint32_t windowSize;
+    uint32_t targetPercentage;
+    uint32_t disableFrameSkip;
+    uint32_t disableBitsStuffing;
+    uint32_t enableIntraFrameQPControl;
+    uint32_t temporalFrameRate;
+    uint32_t temporalID;
+
+    VideoRateControlParams &operator=(const VideoRateControlParams &other) {
+        if (this == &other) return *this;
+
+        this->bitRate = other.bitRate;
+        this->initQP = other.initQP;
+        this->minQP = other.minQP;
+        this->maxQP = other.maxQP;
+        this->I_minQP = other.I_minQP;
+        this->I_maxQP = other.I_maxQP;
+        this->windowSize = other.windowSize;
+        this->targetPercentage = other.targetPercentage;
+        this->disableFrameSkip = other.disableFrameSkip;
+        this->disableBitsStuffing = other.disableBitsStuffing;
+        this->enableIntraFrameQPControl = other.enableIntraFrameQPControl;
+        this->temporalFrameRate = other.temporalFrameRate;
+        this->temporalID = other.temporalID;
+
+        return *this;
+    }
+};
+
+struct SliceNum {
+    uint32_t iSliceNum;
+    uint32_t pSliceNum;
+
+    SliceNum &operator=(const SliceNum &other) {
+        if (this == &other) return *this;
+
+        this->iSliceNum = other.iSliceNum;
+        this->pSliceNum= other.pSliceNum;
+        return *this;
+    }
+};
+
+typedef struct {
+    uint32_t realWidth;
+    uint32_t realHeight;
+    uint32_t lumaStride;
+    uint32_t chromStride;
+    uint32_t format;
+} ExternalBufferAttrib;
+
+struct Cropping {
+    uint32_t LeftOffset;
+    uint32_t RightOffset;
+    uint32_t TopOffset;
+    uint32_t BottomOffset;
+
+    Cropping &operator=(const Cropping &other) {
+        if (this == &other) return *this;
+
+        this->LeftOffset = other.LeftOffset;
+        this->RightOffset = other.RightOffset;
+        this->TopOffset = other.TopOffset;
+        this->BottomOffset = other.BottomOffset;
+        return *this;
+    }
+};
+
+struct SamplingAspectRatio {
+    uint16_t SarWidth;
+    uint16_t SarHeight;
+
+    SamplingAspectRatio &operator=(const SamplingAspectRatio &other) {
+        if (this == &other) return *this;
+
+        this->SarWidth = other.SarWidth;
+        this->SarHeight = other.SarHeight;
+        return *this;
+    }
+};
+
+enum VideoParamConfigType {
+    VideoParamsTypeStartUnused = 0x01000000,
+    VideoParamsTypeCommon,
+    VideoParamsTypeAVC,
+    VideoParamsTypeH263,
+    VideoParamsTypeMP4,
+    VideoParamsTypeVC1,
+    VideoParamsTypeUpSteamBuffer,
+    VideoParamsTypeUsrptrBuffer,
+    VideoParamsTypeHRD,
+    VideoParamsTypeStoreMetaDataInBuffers,
+    VideoParamsTypeProfileLevel,
+    VideoParamsTypeVP8,
+    VideoParamsTypeTemporalLayer,
+
+    VideoConfigTypeFrameRate,
+    VideoConfigTypeBitRate,
+    VideoConfigTypeResolution,
+    VideoConfigTypeIntraRefreshType,
+    VideoConfigTypeAIR,
+    VideoConfigTypeCyclicFrameInterval,
+    VideoConfigTypeAVCIntraPeriod,
+    VideoConfigTypeNALSize,
+    VideoConfigTypeIDRRequest,
+    VideoConfigTypeSliceNum,
+    VideoConfigTypeVP8,
+    VideoConfigTypeVP8ReferenceFrame,
+    VideoConfigTypeCIR,
+    VideoConfigTypeVP8MaxFrameSizeRatio,
+    VideoConfigTypeTemperalLayerBitrateFramerate,
+
+    VideoParamsConfigExtension
+};
+
+struct VideoParamConfigSet {
+    VideoParamConfigType type;
+    uint32_t size;
+
+    VideoParamConfigSet &operator=(const VideoParamConfigSet &other) {
+        if (this == &other) return *this;
+        this->type = other.type;
+        this->size = other.size;
+        return *this;
+    }
+};
+
+struct VideoParamsCommon : VideoParamConfigSet {
+
+    VAProfile profile;
+    uint8_t level;
+    VideoRawFormat rawFormat;
+    VideoResolution resolution;
+    VideoFrameRate frameRate;
+    int32_t intraPeriod;
+    VideoRateControl rcMode;
+    VideoRateControlParams rcParams;
+    VideoIntraRefreshType refreshType;
+    int32_t cyclicFrameInterval;
+    AirParams airParams;
+    CirParams cirParams;
+    uint32_t disableDeblocking;
+    bool syncEncMode;
+    //CodedBuffer properties
+    uint32_t codedBufNum;
+    uint32_t numberOfLayer;
+    uint32_t nPeriodicity;
+    uint32_t nLayerID[32];
+
+    VideoParamsCommon() {
+        type = VideoParamsTypeCommon;
+        size = sizeof(VideoParamsCommon);
+    }
+
+    VideoParamsCommon &operator=(const VideoParamsCommon &other) {
+        if (this == &other) return *this;
+
+        VideoParamConfigSet::operator=(other);
+        this->profile = other.profile;
+        this->level = other.level;
+        this->rawFormat = other.rawFormat;
+        this->resolution = other.resolution;
+        this->frameRate = other.frameRate;
+        this->intraPeriod = other.intraPeriod;
+        this->rcMode = other.rcMode;
+        this->rcParams = other.rcParams;
+        this->refreshType = other.refreshType;
+        this->cyclicFrameInterval = other.cyclicFrameInterval;
+        this->airParams = other.airParams;
+        this->disableDeblocking = other.disableDeblocking;
+        this->syncEncMode = other.syncEncMode;
+        this->codedBufNum = other.codedBufNum;
+        this->numberOfLayer = other.numberOfLayer;
+        return *this;
+    }
+};
+
+struct VideoParamsAVC : VideoParamConfigSet {
+    uint32_t basicUnitSize;  //for rate control
+    uint8_t VUIFlag;
+    int32_t maxSliceSize;
+    uint32_t idrInterval;
+    uint32_t ipPeriod;
+    uint32_t refFrames;
+    SliceNum sliceNum;
+    AVCDelimiterType delimiterType;
+    Cropping crop;
+    SamplingAspectRatio SAR;
+    uint32_t refIdx10ActiveMinus1;
+    uint32_t refIdx11ActiveMinus1;
+    bool bFrameMBsOnly;
+    bool bMBAFF;
+    bool bEntropyCodingCABAC;
+    bool bWeightedPPrediction;
+    uint32_t weightedBipredicitonMode;
+    bool bConstIpred ;
+    bool bDirect8x8Inference;
+    bool bDirectSpatialTemporal;
+    uint32_t cabacInitIdc;
+
+    VideoParamsAVC() {
+        type = VideoParamsTypeAVC;
+        size = sizeof(VideoParamsAVC);
+    }
+
+    VideoParamsAVC &operator=(const VideoParamsAVC &other) {
+        if (this == &other) return *this;
+
+        VideoParamConfigSet::operator=(other);
+        this->basicUnitSize = other.basicUnitSize;
+        this->VUIFlag = other.VUIFlag;
+        this->maxSliceSize = other.maxSliceSize;
+        this->idrInterval = other.idrInterval;
+        this->ipPeriod = other.ipPeriod;
+        this->refFrames = other.refFrames;
+        this->sliceNum = other.sliceNum;
+        this->delimiterType = other.delimiterType;
+        this->crop.LeftOffset = other.crop.LeftOffset;
+        this->crop.RightOffset = other.crop.RightOffset;
+        this->crop.TopOffset = other.crop.TopOffset;
+        this->crop.BottomOffset = other.crop.BottomOffset;
+        this->SAR.SarWidth = other.SAR.SarWidth;
+        this->SAR.SarHeight = other.SAR.SarHeight;
+
+        this->refIdx10ActiveMinus1 = other.refIdx10ActiveMinus1;
+        this->refIdx11ActiveMinus1 = other.refIdx11ActiveMinus1;
+        this->bFrameMBsOnly = other.bFrameMBsOnly;
+        this->bMBAFF = other.bMBAFF;
+        this->bEntropyCodingCABAC = other.bEntropyCodingCABAC;
+        this->bWeightedPPrediction = other.bWeightedPPrediction;
+        this->weightedBipredicitonMode = other.weightedBipredicitonMode;
+        this->bConstIpred = other.bConstIpred;
+        this->bDirect8x8Inference = other.bDirect8x8Inference;
+        this->bDirectSpatialTemporal = other.bDirectSpatialTemporal;
+        this->cabacInitIdc = other.cabacInitIdc;
+        return *this;
+    }
+};
+
+struct VideoParamsUpstreamBuffer : VideoParamConfigSet {
+
+    VideoParamsUpstreamBuffer() {
+        type = VideoParamsTypeUpSteamBuffer;
+        size = sizeof(VideoParamsUpstreamBuffer);
+    }
+
+    VideoBufferSharingMode bufferMode;
+    intptr_t *bufList;
+    uint32_t bufCnt;
+    ExternalBufferAttrib *bufAttrib;
+    void *display;
+};
+
+struct VideoParamsUsrptrBuffer : VideoParamConfigSet {
+
+    VideoParamsUsrptrBuffer() {
+        type = VideoParamsTypeUsrptrBuffer;
+        size = sizeof(VideoParamsUsrptrBuffer);
+    }
+
+    //input
+    uint32_t width;
+    uint32_t height;
+    uint32_t format;
+    uint32_t expectedSize;
+
+    //output
+    uint32_t actualSize;
+    uint32_t stride;
+    uint8_t *usrPtr;
+};
+
+struct VideoParamsHRD : VideoParamConfigSet {
+
+    VideoParamsHRD() {
+        type = VideoParamsTypeHRD;
+        size = sizeof(VideoParamsHRD);
+    }
+
+    uint32_t bufferSize;
+    uint32_t initBufferFullness;
+};
+
+struct VideoParamsStoreMetaDataInBuffers : VideoParamConfigSet {
+
+    VideoParamsStoreMetaDataInBuffers() {
+        type = VideoParamsTypeStoreMetaDataInBuffers;
+        size = sizeof(VideoParamsStoreMetaDataInBuffers);
+    }
+
+    bool isEnabled;
+};
+
+struct VideoParamsProfileLevel : VideoParamConfigSet {
+
+    VideoParamsProfileLevel() {
+        type = VideoParamsTypeProfileLevel;
+        size = sizeof(VideoParamsProfileLevel);
+    }
+
+    VAProfile profile;
+    uint32_t level;
+    bool isSupported;
+};
+
+struct VideoParamsTemporalLayer : VideoParamConfigSet {
+
+    VideoParamsTemporalLayer() {
+        type = VideoParamsTypeTemporalLayer;
+        size = sizeof(VideoParamsTemporalLayer);
+    }
+
+    uint32_t numberOfLayer;
+    uint32_t nPeriodicity;
+    uint32_t nLayerID[32];
+};
+
+
+struct VideoConfigFrameRate : VideoParamConfigSet {
+
+    VideoConfigFrameRate() {
+        type = VideoConfigTypeFrameRate;
+        size = sizeof(VideoConfigFrameRate);
+    }
+
+    VideoFrameRate frameRate;
+};
+
+struct VideoConfigBitRate : VideoParamConfigSet {
+
+    VideoConfigBitRate() {
+        type = VideoConfigTypeBitRate;
+        size = sizeof(VideoConfigBitRate);
+    }
+
+    VideoRateControlParams rcParams;
+};
+
+struct VideoConfigAVCIntraPeriod : VideoParamConfigSet {
+
+    VideoConfigAVCIntraPeriod() {
+        type = VideoConfigTypeAVCIntraPeriod;
+        size = sizeof(VideoConfigAVCIntraPeriod);
+    }
+
+    uint32_t idrInterval;  //How many Intra frame will have a IDR frame
+    uint32_t intraPeriod;
+    uint32_t ipPeriod;
+};
+
+struct VideoConfigNALSize : VideoParamConfigSet {
+
+    VideoConfigNALSize() {
+        type = VideoConfigTypeNALSize;
+        size = sizeof(VideoConfigNALSize);
+    }
+
+    uint32_t maxSliceSize;
+};
+
+struct VideoConfigResolution : VideoParamConfigSet {
+
+    VideoConfigResolution() {
+        type = VideoConfigTypeResolution;
+        size = sizeof(VideoConfigResolution);
+    }
+
+    VideoResolution resolution;
+};
+
+struct VideoConfigIntraRefreshType : VideoParamConfigSet {
+
+    VideoConfigIntraRefreshType() {
+        type = VideoConfigTypeIntraRefreshType;
+        size = sizeof(VideoConfigIntraRefreshType);
+    }
+
+    VideoIntraRefreshType refreshType;
+};
+
+struct VideoConfigCyclicFrameInterval : VideoParamConfigSet {
+
+    VideoConfigCyclicFrameInterval() {
+        type = VideoConfigTypeCyclicFrameInterval;
+        size = sizeof(VideoConfigCyclicFrameInterval);
+    }
+
+    int32_t cyclicFrameInterval;
+};
+
+struct VideoConfigCIR : VideoParamConfigSet {
+
+    VideoConfigCIR() {
+        type = VideoConfigTypeCIR;
+        size = sizeof(VideoConfigCIR);
+    }
+
+    CirParams cirParams;
+};
+
+struct VideoConfigAIR : VideoParamConfigSet {
+
+    VideoConfigAIR() {
+        type = VideoConfigTypeAIR;
+        size = sizeof(VideoConfigAIR);
+    }
+
+    AirParams airParams;
+};
+
+struct VideoConfigSliceNum : VideoParamConfigSet {
+
+    VideoConfigSliceNum() {
+        type = VideoConfigTypeSliceNum;
+        size = sizeof(VideoConfigSliceNum);
+    }
+
+    SliceNum sliceNum;
+};
+
+struct VideoParamsVP8 : VideoParamConfigSet {
+
+        uint32_t profile;
+        uint32_t error_resilient;
+        uint32_t num_token_partitions;
+        uint32_t kf_auto;
+        uint32_t kf_min_dist;
+        uint32_t kf_max_dist;
+        uint32_t min_qp;
+        uint32_t max_qp;
+        uint32_t init_qp;
+        uint32_t rc_undershoot;
+        uint32_t rc_overshoot;
+        uint32_t hrd_buf_size;
+        uint32_t hrd_buf_initial_fullness;
+        uint32_t hrd_buf_optimal_fullness;
+        uint32_t max_frame_size_ratio;
+
+        VideoParamsVP8() {
+                type = VideoParamsTypeVP8;
+                size = sizeof(VideoParamsVP8);
+        }
+};
+
+struct VideoConfigVP8 : VideoParamConfigSet {
+
+        uint32_t force_kf;
+        uint32_t refresh_entropy_probs;
+        uint32_t value;
+        unsigned char sharpness_level;
+
+        VideoConfigVP8 () {
+                type = VideoConfigTypeVP8;
+                size = sizeof(VideoConfigVP8);
+        }
+};
+
+struct VideoConfigVP8ReferenceFrame : VideoParamConfigSet {
+
+        uint32_t no_ref_last;
+        uint32_t no_ref_gf;
+        uint32_t no_ref_arf;
+        uint32_t refresh_last;
+        uint32_t refresh_golden_frame;
+        uint32_t refresh_alternate_frame;
+
+        VideoConfigVP8ReferenceFrame () {
+                type = VideoConfigTypeVP8ReferenceFrame;
+                size = sizeof(VideoConfigVP8ReferenceFrame);
+        }
+};
+
+struct VideoConfigVP8MaxFrameSizeRatio : VideoParamConfigSet {
+
+    VideoConfigVP8MaxFrameSizeRatio() {
+        type = VideoConfigTypeVP8MaxFrameSizeRatio;
+        size = sizeof(VideoConfigVP8MaxFrameSizeRatio);
+    }
+
+    uint32_t max_frame_size_ratio;
+};
+
+struct VideoConfigTemperalLayerBitrateFramerate : VideoParamConfigSet {
+
+       VideoConfigTemperalLayerBitrateFramerate() {
+                type = VideoConfigTypeTemperalLayerBitrateFramerate;
+                size = sizeof(VideoConfigTemperalLayerBitrateFramerate);
+        }
+
+        uint32_t nLayerID;
+        uint32_t bitRate;
+        uint32_t frameRate;
+};
+
+#endif /*  __VIDEO_ENCODER_DEF_H__ */
diff --git a/videoencoder/VideoEncoderH263.cpp b/videoencoder/VideoEncoderH263.cpp
new file mode 100644
index 0000000..b9f3a9c
--- /dev/null
+++ b/videoencoder/VideoEncoderH263.cpp
@@ -0,0 +1,178 @@
+/*
+* Copyright (c) 2009-2011 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 <string.h>
+#include <stdlib.h>
+#include "VideoEncoderLog.h"
+#include "VideoEncoderH263.h"
+#include <va/va_tpi.h>
+
+VideoEncoderH263::VideoEncoderH263() {
+    mComParams.profile = (VAProfile)PROFILE_H263BASELINE;
+    mAutoReferenceSurfaceNum = 2;
+}
+
+Encode_Status VideoEncoderH263::sendEncodeCommand(EncodeTask *task) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    LOG_V( "Begin\n");
+
+    if (mFrameNum == 0) {
+        ret = renderSequenceParams(task);
+        CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
+    }
+
+    ret = renderPictureParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
+
+    ret = renderSliceParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderSliceParams");
+
+    LOG_V( "End\n");
+    return ENCODE_SUCCESS;
+}
+
+
+Encode_Status VideoEncoderH263::renderSequenceParams(EncodeTask *) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncSequenceParameterBufferH263 h263SequenceParam = VAEncSequenceParameterBufferH263();
+    uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
+    uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
+
+    LOG_V( "Begin\n\n");
+    //set up the sequence params for HW
+    h263SequenceParam.bits_per_second= mComParams.rcParams.bitRate;
+    h263SequenceParam.frame_rate = 
+            (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;   //hard-coded, driver need;
+    h263SequenceParam.initial_qp = mComParams.rcParams.initQP;
+    h263SequenceParam.min_qp = mComParams.rcParams.minQP;
+    h263SequenceParam.intra_period = mComParams.intraPeriod;
+
+    //h263_seq_param.fixed_vop_rate = 30;
+
+    LOG_V("===h263 sequence params===\n");
+    LOG_I( "bitrate = %d\n", h263SequenceParam.bits_per_second);
+    LOG_I( "frame_rate = %d\n", h263SequenceParam.frame_rate);
+    LOG_I( "initial_qp = %d\n", h263SequenceParam.initial_qp);
+    LOG_I( "min_qp = %d\n", h263SequenceParam.min_qp);
+    LOG_I( "intra_period = %d\n\n", h263SequenceParam.intra_period);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSequenceParameterBufferType,
+            sizeof(h263SequenceParam),
+            1, &h263SequenceParam,
+            &mSeqParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderH263::renderPictureParams(EncodeTask *task) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncPictureParameterBufferH263 h263PictureParams = VAEncPictureParameterBufferH263();
+
+    LOG_V( "Begin\n\n");
+
+    // set picture params for HW
+    if(mAutoReference == false){
+        h263PictureParams.reference_picture = task->ref_surface;
+        h263PictureParams.reconstructed_picture = task->rec_surface;
+    }else {
+        h263PictureParams.reference_picture = mAutoRefSurfaces[0];
+        h263PictureParams.reconstructed_picture = mAutoRefSurfaces[1];
+    }
+
+    h263PictureParams.coded_buf = task->coded_buffer;
+    h263PictureParams.picture_width = mComParams.resolution.width;
+    h263PictureParams.picture_height = mComParams.resolution.height;
+    h263PictureParams.picture_type = (task->type == FTYPE_I) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
+
+    LOG_V("======h263 picture params======\n");
+    LOG_I( "reference_picture = 0x%08x\n", h263PictureParams.reference_picture);
+    LOG_I( "reconstructed_picture = 0x%08x\n", h263PictureParams.reconstructed_picture);
+    LOG_I( "coded_buf = 0x%08x\n", h263PictureParams.coded_buf);
+//    LOG_I( "coded_buf_index = %d\n", mCodedBufIndex);
+    LOG_I( "picture_width = %d\n", h263PictureParams.picture_width);
+    LOG_I( "picture_height = %d\n",h263PictureParams.picture_height);
+    LOG_I( "picture_type = %d\n\n",h263PictureParams.picture_type);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncPictureParameterBufferType,
+            sizeof(h263PictureParams),
+            1,&h263PictureParams,
+            &mPicParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf , 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderH263::renderSliceParams(EncodeTask *task) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    uint32_t sliceHeight;
+    uint32_t sliceHeightInMB;
+
+    LOG_V("Begin\n\n");
+
+    sliceHeight = mComParams.resolution.height;
+    sliceHeight += 15;
+    sliceHeight &= (~15);
+    sliceHeightInMB = sliceHeight / 16;
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSliceParameterBufferType,
+            sizeof(VAEncSliceParameterBuffer),
+            1, NULL, &mSliceParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    VAEncSliceParameterBuffer *sliceParams;
+    vaStatus = vaMapBuffer(mVADisplay, mSliceParamBuf, (void **)&sliceParams);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    // starting MB row number for this slice
+    sliceParams->start_row_number = 0;
+    // slice height measured in MB
+    sliceParams->slice_height = sliceHeightInMB;
+    sliceParams->slice_flags.bits.is_intra = (task->type == FTYPE_I)?1:0;
+    sliceParams->slice_flags.bits.disable_deblocking_filter_idc = 0;
+
+    LOG_V("======h263 slice params======\n");
+    LOG_I("start_row_number = %d\n", (int) sliceParams->start_row_number);
+    LOG_I("slice_height_in_mb = %d\n", (int) sliceParams->slice_height);
+    LOG_I("slice.is_intra = %d\n", (int) sliceParams->slice_flags.bits.is_intra);
+
+    vaStatus = vaUnmapBuffer(mVADisplay, mSliceParamBuf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSliceParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V("end\n");
+    return ENCODE_SUCCESS;
+}
diff --git a/videoencoder/VideoEncoderH263.h b/videoencoder/VideoEncoderH263.h
new file mode 100644
index 0000000..4d0e7a2
--- /dev/null
+++ b/videoencoder/VideoEncoderH263.h
@@ -0,0 +1,57 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_H263_H__
+#define __VIDEO_ENCODER_H263_H__
+
+#include "VideoEncoderBase.h"
+
+/**
+  * H.263 Encoder class, derived from VideoEncoderBase
+  */
+class VideoEncoderH263: public VideoEncoderBase {
+public:
+    VideoEncoderH263();
+    virtual ~VideoEncoderH263() {};
+
+protected:
+    virtual Encode_Status sendEncodeCommand(EncodeTask *task);
+    virtual Encode_Status derivedSetParams(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status derivedGetParams(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status derivedGetConfig(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status derivedSetConfig(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status getExtFormatOutput(VideoEncOutputBuffer *) {
+        return ENCODE_NOT_SUPPORTED;
+    }
+    //virtual Encode_Status updateFrameInfo(EncodeTask* task);
+
+    // Local Methods
+private:
+    Encode_Status renderSequenceParams(EncodeTask *task);
+    Encode_Status renderPictureParams(EncodeTask *task);
+    Encode_Status renderSliceParams(EncodeTask *task);
+};
+
+#endif /* __VIDEO_ENCODER_H263_H__ */
+
diff --git a/videoencoder/VideoEncoderHost.cpp b/videoencoder/VideoEncoderHost.cpp
new file mode 100644
index 0000000..e4ea968
--- /dev/null
+++ b/videoencoder/VideoEncoderHost.cpp
@@ -0,0 +1,76 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoEncoderMP4.h"
+#include "VideoEncoderH263.h"
+#include "VideoEncoderAVC.h"
+#include "VideoEncoderVP8.h"
+#ifndef IMG_GFX
+#include "PVSoftMPEG4Encoder.h"
+#endif
+#include "VideoEncoderHost.h"
+#include <string.h>
+#include <cutils/properties.h>
+#include <wrs_omxil_core/log.h>
+
+int32_t gLogLevel = 0;
+
+IVideoEncoder *createVideoEncoder(const char *mimeType) {
+
+    char logLevelProp[PROPERTY_VALUE_MAX];
+
+    if (property_get("libmix.debug", logLevelProp, NULL)) {
+        gLogLevel = atoi(logLevelProp);
+        LOGD("Debug level is %d", gLogLevel);
+    }
+
+    if (mimeType == NULL) {
+        LOGE("NULL mime type");
+        return NULL;
+    }
+
+    if (strcasecmp(mimeType, "video/avc") == 0 ||
+            strcasecmp(mimeType, "video/h264") == 0) {
+        VideoEncoderAVC *p = new VideoEncoderAVC();
+        return (IVideoEncoder *)p;
+    } else if (strcasecmp(mimeType, "video/h263") == 0) {
+#ifdef IMG_GFX
+        VideoEncoderH263 *p = new VideoEncoderH263();
+#else
+        PVSoftMPEG4Encoder *p = new PVSoftMPEG4Encoder("OMX.google.h263.encoder");
+#endif
+        return (IVideoEncoder *)p;
+    } else if (strcasecmp(mimeType, "video/mpeg4") == 0 ||
+            strcasecmp(mimeType, "video/mp4v-es") == 0) {
+#ifdef IMG_GFX
+        VideoEncoderMP4 *p = new VideoEncoderMP4();
+#else
+        PVSoftMPEG4Encoder *p = new PVSoftMPEG4Encoder("OMX.google.mpeg4.encoder");
+#endif
+        return (IVideoEncoder *)p;
+    } else if (strcasecmp(mimeType, "video/x-vnd.on2.vp8") == 0) {
+        VideoEncoderVP8 *p = new VideoEncoderVP8();
+        return (IVideoEncoder *)p;
+    } else {
+        LOGE ("Unknown mime type: %s", mimeType);
+    }
+    return NULL;
+}
+
+void releaseVideoEncoder(IVideoEncoder *p) {
+    if (p) delete p;
+}
+
diff --git a/videoencoder/VideoEncoderHost.h b/videoencoder/VideoEncoderHost.h
new file mode 100644
index 0000000..ad5df6e
--- /dev/null
+++ b/videoencoder/VideoEncoderHost.h
@@ -0,0 +1,25 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_ENCODER_HOST_H_
+#define VIDEO_ENCODER_HOST_H_
+
+#include "VideoEncoderInterface.h"
+
+IVideoEncoder *createVideoEncoder(const char *mimeType);
+void releaseVideoEncoder(IVideoEncoder *p);
+
+#endif /* VIDEO_ENCODER_HOST_H_ */
\ No newline at end of file
diff --git a/videoencoder/VideoEncoderInterface.h b/videoencoder/VideoEncoderInterface.h
new file mode 100644
index 0000000..00604ce
--- /dev/null
+++ b/videoencoder/VideoEncoderInterface.h
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2009-2011 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 VIDEO_ENCODER_INTERFACE_H_
+#define VIDEO_ENCODER_INTERFACE_H_
+
+#include "VideoEncoderDef.h"
+
+class IVideoEncoder {
+public:
+    virtual ~IVideoEncoder() {};
+    virtual Encode_Status start(void) = 0;
+    virtual Encode_Status stop(void) = 0;
+    virtual void flush(void) = 0;
+    virtual Encode_Status encode(VideoEncRawBuffer *inBuffer, uint32_t timeout = FUNC_BLOCK) = 0;
+    virtual Encode_Status getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout = FUNC_BLOCK) = 0;
+    virtual Encode_Status getParameters(VideoParamConfigSet *videoEncParams) = 0;
+    virtual Encode_Status setParameters(VideoParamConfigSet *videoEncParams) = 0;
+    virtual Encode_Status getConfig(VideoParamConfigSet *videoEncConfig) = 0;
+    virtual Encode_Status setConfig(VideoParamConfigSet *videoEncConfig) = 0;
+    virtual Encode_Status getMaxOutSize(uint32_t *maxSize) = 0;
+};
+
+#endif /* VIDEO_ENCODER_INTERFACE_H_ */
diff --git a/videoencoder/VideoEncoderLog.h b/videoencoder/VideoEncoderLog.h
new file mode 100644
index 0000000..c38eb94
--- /dev/null
+++ b/videoencoder/VideoEncoderLog.h
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_LOG_H__
+#define __VIDEO_ENCODER_LOG_H__
+
+#define LOG_TAG "VideoEncoder"
+
+#include <wrs_omxil_core/log.h>
+
+#define LOG_V ALOGV
+#define LOG_D ALOGD
+#define LOG_I ALOGI
+#define LOG_W ALOGW
+#define LOG_E ALOGE
+
+extern int32_t gLogLevel;
+#define CHECK_VA_STATUS_RETURN(FUNC)\
+    if (vaStatus != VA_STATUS_SUCCESS) {\
+        LOG_E(FUNC" failed. vaStatus = %d\n", vaStatus);\
+        return ENCODE_DRIVER_FAIL;\
+    }
+
+#define CHECK_VA_STATUS_GOTO_CLEANUP(FUNC)\
+    if (vaStatus != VA_STATUS_SUCCESS) {\
+        LOG_E(FUNC" failed. vaStatus = %d\n", vaStatus);\
+        ret = ENCODE_DRIVER_FAIL; \
+        goto CLEAN_UP;\
+    }
+
+#define CHECK_ENCODE_STATUS_RETURN(FUNC)\
+    if (ret != ENCODE_SUCCESS) { \
+        LOG_E(FUNC"Failed. ret = 0x%08x\n", ret); \
+        return ret; \
+    }
+
+#define CHECK_ENCODE_STATUS_CLEANUP(FUNC)\
+    if (ret != ENCODE_SUCCESS) { \
+        LOG_E(FUNC"Failed, ret = 0x%08x\n", ret); \
+        goto CLEAN_UP;\
+    }
+
+#define CHECK_NULL_RETURN_IFFAIL(POINTER)\
+    if (POINTER == NULL) { \
+        LOG_E("Invalid pointer\n"); \
+        return ENCODE_NULL_PTR;\
+    }
+#endif /*  __VIDEO_ENCODER_LOG_H__ */
diff --git a/videoencoder/VideoEncoderMP4.cpp b/videoencoder/VideoEncoderMP4.cpp
new file mode 100644
index 0000000..b414c1d
--- /dev/null
+++ b/videoencoder/VideoEncoderMP4.cpp
@@ -0,0 +1,281 @@
+/*
+* Copyright (c) 2009-2011 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 <string.h>
+#include <stdlib.h>
+
+#include "VideoEncoderLog.h"
+#include "VideoEncoderMP4.h"
+#include <va/va_tpi.h>
+
+VideoEncoderMP4::VideoEncoderMP4()
+    :mProfileLevelIndication(3)
+    ,mFixedVOPTimeIncrement(0) {
+    mComParams.profile = (VAProfile)PROFILE_MPEG4SIMPLE;
+    mAutoReferenceSurfaceNum = 2;
+}
+
+Encode_Status VideoEncoderMP4::getHeaderPos(
+        uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize) {
+
+    uint32_t bytesLeft = bufSize;
+
+    *headerSize = 0;
+    CHECK_NULL_RETURN_IFFAIL(inBuffer);
+
+    if (bufSize < 4) {
+        //bufSize shoule not < 4
+        LOG_E("Buffer size too small\n");
+        return ENCODE_FAIL;
+    }
+
+    while (bytesLeft > 4  &&
+            (memcmp("\x00\x00\x01\xB6", &inBuffer[bufSize - bytesLeft], 4) &&
+             memcmp("\x00\x00\x01\xB3", &inBuffer[bufSize - bytesLeft], 4))) {
+        --bytesLeft;
+    }
+
+    if (bytesLeft <= 4) {
+        LOG_E("NO header found\n");
+        *headerSize = 0; //
+    } else {
+        *headerSize = bufSize - bytesLeft;
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderMP4::outputConfigData(
+        VideoEncOutputBuffer *outBuffer) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    uint32_t headerSize = 0;
+
+    ret = getHeaderPos((uint8_t *)mCurSegment->buf + mOffsetInSeg,
+            mCurSegment->size - mOffsetInSeg, &headerSize);
+    CHECK_ENCODE_STATUS_RETURN("getHeaderPos");
+    if (headerSize == 0) {
+        outBuffer->dataSize = 0;
+        mCurSegment = NULL;
+        return ENCODE_NO_REQUEST_DATA;
+    }
+
+    if (headerSize <= outBuffer->bufferSize) {
+        memcpy(outBuffer->data, (uint8_t *)mCurSegment->buf + mOffsetInSeg, headerSize);
+        mTotalSizeCopied += headerSize;
+        mOffsetInSeg += headerSize;
+        outBuffer->dataSize = headerSize;
+        outBuffer->remainingSize = 0;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_CODECCONFIG;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
+    } else {
+        // we need a big enough buffer, otherwise we won't output anything
+        outBuffer->dataSize = 0;
+        outBuffer->remainingSize = headerSize;
+        outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
+        LOG_E("Buffer size too small\n");
+        return ENCODE_BUFFER_TOO_SMALL;
+    }
+
+    return ret;
+}
+
+Encode_Status VideoEncoderMP4::getExtFormatOutput(VideoEncOutputBuffer *outBuffer) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    LOG_V("Begin\n");
+    CHECK_NULL_RETURN_IFFAIL(outBuffer);
+
+    switch (outBuffer->format) {
+        case OUTPUT_CODEC_DATA: {
+            // Output the codec config data
+            ret = outputConfigData(outBuffer);
+            CHECK_ENCODE_STATUS_CLEANUP("outputCodecData");
+            break;
+        }
+        default:
+            LOG_E("Invalid buffer mode for MPEG-4:2\n");
+            ret = ENCODE_FAIL;
+            break;
+    }
+
+    LOG_I("out size is = %d\n", outBuffer->dataSize);
+
+
+CLEAN_UP:
+
+    LOG_V("End\n");
+    return ret;
+}
+
+Encode_Status VideoEncoderMP4::renderSequenceParams(EncodeTask *) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncSequenceParameterBufferMPEG4 mp4SequenceParams = VAEncSequenceParameterBufferMPEG4();
+
+    uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
+    uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
+
+    LOG_V( "Begin\n\n");
+    // set up the sequence params for HW
+    mp4SequenceParams.profile_and_level_indication = mProfileLevelIndication;
+    mp4SequenceParams.video_object_layer_width= mComParams.resolution.width;
+    mp4SequenceParams.video_object_layer_height= mComParams.resolution.height;
+    mp4SequenceParams.vop_time_increment_resolution =
+            (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;
+    mp4SequenceParams.fixed_vop_time_increment= mFixedVOPTimeIncrement;
+    mp4SequenceParams.bits_per_second= mComParams.rcParams.bitRate;
+    mp4SequenceParams.frame_rate =
+            (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;
+    mp4SequenceParams.initial_qp = mComParams.rcParams.initQP;
+    mp4SequenceParams.min_qp = mComParams.rcParams.minQP;
+    mp4SequenceParams.intra_period = mComParams.intraPeriod;
+    //mpeg4_seq_param.fixed_vop_rate = 30;
+
+    LOG_V("===mpeg4 sequence params===\n");
+    LOG_I("profile_and_level_indication = %d\n", (uint32_t)mp4SequenceParams.profile_and_level_indication);
+    LOG_I("intra_period = %d\n", mp4SequenceParams.intra_period);
+    LOG_I("video_object_layer_width = %d\n", mp4SequenceParams.video_object_layer_width);
+    LOG_I("video_object_layer_height = %d\n", mp4SequenceParams.video_object_layer_height);
+    LOG_I("vop_time_increment_resolution = %d\n", mp4SequenceParams.vop_time_increment_resolution);
+    LOG_I("fixed_vop_rate = %d\n", mp4SequenceParams.fixed_vop_rate);
+    LOG_I("fixed_vop_time_increment = %d\n", mp4SequenceParams.fixed_vop_time_increment);
+    LOG_I("bitrate = %d\n", mp4SequenceParams.bits_per_second);
+    LOG_I("frame_rate = %d\n", mp4SequenceParams.frame_rate);
+    LOG_I("initial_qp = %d\n", mp4SequenceParams.initial_qp);
+    LOG_I("min_qp = %d\n", mp4SequenceParams.min_qp);
+    LOG_I("intra_period = %d\n\n", mp4SequenceParams.intra_period);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSequenceParameterBufferType,
+            sizeof(mp4SequenceParams),
+            1, &mp4SequenceParams,
+            &mSeqParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderMP4::renderPictureParams(EncodeTask *task) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncPictureParameterBufferMPEG4 mpeg4_pic_param = VAEncPictureParameterBufferMPEG4();
+    LOG_V( "Begin\n\n");
+    // set picture params for HW
+    if(mAutoReference == false){
+        mpeg4_pic_param.reference_picture = task->ref_surface;
+        mpeg4_pic_param.reconstructed_picture = task->rec_surface;
+    }else {
+        mpeg4_pic_param.reference_picture = mAutoRefSurfaces[0];
+        mpeg4_pic_param.reconstructed_picture = mAutoRefSurfaces[1];
+    }
+
+    mpeg4_pic_param.coded_buf = task->coded_buffer;
+    mpeg4_pic_param.picture_width = mComParams.resolution.width;
+    mpeg4_pic_param.picture_height = mComParams.resolution.height;
+    mpeg4_pic_param.vop_time_increment= mFrameNum;
+    mpeg4_pic_param.picture_type = (task->type == FTYPE_I) ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
+
+    LOG_V("======mpeg4 picture params======\n");
+    LOG_I("reference_picture = 0x%08x\n", mpeg4_pic_param.reference_picture);
+    LOG_I("reconstructed_picture = 0x%08x\n", mpeg4_pic_param.reconstructed_picture);
+    LOG_I("coded_buf = 0x%08x\n", mpeg4_pic_param.coded_buf);
+//    LOG_I("coded_buf_index = %d\n", mCodedBufIndex);
+    LOG_I("picture_width = %d\n", mpeg4_pic_param.picture_width);
+    LOG_I("picture_height = %d\n", mpeg4_pic_param.picture_height);
+    LOG_I("vop_time_increment = %d\n", mpeg4_pic_param.vop_time_increment);
+    LOG_I("picture_type = %d\n\n", mpeg4_pic_param.picture_type);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncPictureParameterBufferType,
+            sizeof(mpeg4_pic_param),
+            1,&mpeg4_pic_param,
+            &mPicParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    return ENCODE_SUCCESS;
+}
+
+
+Encode_Status VideoEncoderMP4::renderSliceParams(EncodeTask *task) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    uint32_t sliceHeight;
+    uint32_t sliceHeightInMB;
+
+    VAEncSliceParameterBuffer sliceParams;
+
+    LOG_V( "Begin\n\n");
+
+    sliceHeight = mComParams.resolution.height;
+    sliceHeight += 15;
+    sliceHeight &= (~15);
+    sliceHeightInMB = sliceHeight / 16;
+
+    sliceParams.start_row_number = 0;
+    sliceParams.slice_height = sliceHeightInMB;
+    sliceParams.slice_flags.bits.is_intra = (task->type == FTYPE_I)?1:0;
+    sliceParams.slice_flags.bits.disable_deblocking_filter_idc = 0;
+
+    LOG_V("======mpeg4 slice params======\n");
+    LOG_I( "start_row_number = %d\n", (int) sliceParams.start_row_number);
+    LOG_I( "sliceHeightInMB = %d\n", (int) sliceParams.slice_height);
+    LOG_I( "is_intra = %d\n", (int) sliceParams.slice_flags.bits.is_intra);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSliceParameterBufferType,
+            sizeof(VAEncSliceParameterBuffer),
+            1, &sliceParams,
+            &mSliceParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSliceParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "end\n");
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderMP4::sendEncodeCommand(EncodeTask *task) {
+    Encode_Status ret = ENCODE_SUCCESS;
+    LOG_V( "Begin\n");
+
+    if (mFrameNum == 0) {
+        ret = renderSequenceParams(task);
+        CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
+    }
+
+    ret = renderPictureParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
+
+    ret = renderSliceParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
+
+    LOG_V( "End\n");
+    return ENCODE_SUCCESS;
+}
diff --git a/videoencoder/VideoEncoderMP4.h b/videoencoder/VideoEncoderMP4.h
new file mode 100644
index 0000000..2691aab
--- /dev/null
+++ b/videoencoder/VideoEncoderMP4.h
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER__MPEG4_H__
+#define __VIDEO_ENCODER__MPEG4_H__
+
+#include "VideoEncoderBase.h"
+
+/**
+  * MPEG-4:2 Encoder class, derived from VideoEncoderBase
+  */
+class VideoEncoderMP4: public VideoEncoderBase {
+public:
+    VideoEncoderMP4();
+    virtual ~VideoEncoderMP4() {};
+
+//    Encode_Status getOutput(VideoEncOutputBuffer *outBuffer);
+
+protected:
+    virtual Encode_Status sendEncodeCommand(EncodeTask *task);
+    virtual Encode_Status derivedSetParams(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status derivedGetParams(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status derivedGetConfig(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status derivedSetConfig(VideoParamConfigSet *) {
+        return ENCODE_SUCCESS;
+    }
+    virtual Encode_Status getExtFormatOutput(VideoEncOutputBuffer *outBuffer);
+    //virtual Encode_Status updateFrameInfo(EncodeTask* task);
+
+    // Local Methods
+private:
+    Encode_Status getHeaderPos(uint8_t *inBuffer, uint32_t bufSize, uint32_t *headerSize);
+    Encode_Status outputConfigData(VideoEncOutputBuffer *outBuffer);
+    Encode_Status renderSequenceParams(EncodeTask *task);
+    Encode_Status renderPictureParams(EncodeTask *task);
+    Encode_Status renderSliceParams(EncodeTask *task);
+
+    unsigned char mProfileLevelIndication;
+    uint32_t mFixedVOPTimeIncrement;
+};
+
+#endif /* __VIDEO_ENCODER__MPEG4_H__ */
diff --git a/videoencoder/VideoEncoderUtils.cpp b/videoencoder/VideoEncoderUtils.cpp
new file mode 100644
index 0000000..8b55bb0
--- /dev/null
+++ b/videoencoder/VideoEncoderUtils.cpp
@@ -0,0 +1,808 @@
+/*
+* Copyright (c) 2009-2011 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 "VideoEncoderLog.h"
+#include "VideoEncoderUtils.h"
+#include <va/va_android.h>
+#include <va/va_drmcommon.h>
+
+#ifdef IMG_GFX
+#include <hal/hal_public.h>
+#include <hardware/gralloc.h>
+
+//#define GFX_DUMP
+
+#define OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar 0x7FA00E00
+
+static hw_module_t const *gModule = NULL;
+static gralloc_module_t *gAllocMod = NULL; /* get by force hw_module_t */
+static alloc_device_t  *gAllocDev = NULL;
+
+static int gfx_init(void) {
+
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &gModule);
+    if (err) {
+        LOG_E("FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+        return -1;
+    } else
+        LOG_V("hw_get_module returned\n");
+    gAllocMod = (gralloc_module_t *)gModule;
+
+    return 0;
+}
+
+static int gfx_alloc(uint32_t w, uint32_t h, int format,
+          int usage, buffer_handle_t* handle, int32_t* stride) {
+
+    int err;
+
+    if (!gAllocDev) {
+        if (!gModule) {
+            if (gfx_init()) {
+                LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+                return -1;
+            }
+        }
+
+        err = gralloc_open(gModule, &gAllocDev);
+        if (err) {
+            LOG_E("FATAL: gralloc open failed\n");
+            return -1;
+        }
+    }
+
+    err = gAllocDev->alloc(gAllocDev, w, h, format, usage, handle, stride);
+    if (err) {
+        LOG_E("alloc(%u, %u, %d, %08x, ...) failed %d (%s)\n",
+               w, h, format, usage, err, strerror(-err));
+    }
+
+    return err;
+}
+
+static int gfx_free(buffer_handle_t handle) {
+
+    int err;
+
+    if (!gAllocDev) {
+        if (!gModule) {
+            if (gfx_init()) {
+                LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+                return -1;
+            }
+        }
+
+        err = gralloc_open(gModule, &gAllocDev);
+        if (err) {
+            LOG_E("FATAL: gralloc open failed\n");
+            return -1;
+        }
+    }
+
+    err = gAllocDev->free(gAllocDev, handle);
+    if (err) {
+        LOG_E("free(...) failed %d (%s)\n", err, strerror(-err));
+    }
+
+    return err;
+}
+
+static int gfx_lock(buffer_handle_t handle, int usage,
+                      int left, int top, int width, int height, void** vaddr) {
+
+    int err;
+
+    if (!gAllocMod) {
+        if (gfx_init()) {
+            LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+            return -1;
+        }
+    }
+
+    err = gAllocMod->lock(gAllocMod, handle, usage,
+                          left, top, width, height, vaddr);
+    LOG_V("gfx_lock: handle is %x, usage is %x, vaddr is %x.\n", (unsigned int)handle, usage, (unsigned int)*vaddr);
+
+    if (err){
+        LOG_E("lock(...) failed %d (%s).\n", err, strerror(-err));
+        return -1;
+    } else
+        LOG_V("lock returned with address %p\n", *vaddr);
+
+    return err;
+}
+
+static int gfx_unlock(buffer_handle_t handle) {
+
+    int err;
+
+    if (!gAllocMod) {
+        if (gfx_init()) {
+            LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+            return -1;
+        }
+    }
+
+    err = gAllocMod->unlock(gAllocMod, handle);
+    if (err) {
+        LOG_E("unlock(...) failed %d (%s)", err, strerror(-err));
+        return -1;
+    } else
+        LOG_V("unlock returned\n");
+
+    return err;
+}
+
+static int gfx_Blit(buffer_handle_t src, buffer_handle_t dest,
+                      int w, int h, int , int )
+{
+    int err;
+
+    if (!gAllocMod) {
+        if (gfx_init()) {
+            LOG_E("can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+            return -1;
+        }
+    }
+
+    IMG_gralloc_module_public_t* GrallocMod = (IMG_gralloc_module_public_t*)gModule;
+
+#ifdef MRFLD_GFX
+    err = GrallocMod->Blit(GrallocMod, src, dest, w, h, 0, 0, 0, 0);
+#else
+    err = GrallocMod->Blit2(GrallocMod, src, dest, w, h, 0, 0);
+#endif
+
+    if (err) {
+        LOG_E("Blit(...) failed %d (%s)", err, strerror(-err));
+        return -1;
+    } else
+        LOG_V("Blit returned\n");
+
+    return err;
+}
+
+Encode_Status GetGfxBufferInfo(intptr_t handle, ValueInfo& vinfo){
+
+    /* only support OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
+                                HAL_PIXEL_FORMAT_NV12
+                                HAL_PIXEL_FORMAT_BGRA_8888
+                                HAL_PIXEL_FORMAT_RGBA_8888
+                                HAL_PIXEL_FORMAT_RGBX_8888
+                                HAL_PIXEL_FORMAT_BGRX_8888 */
+    IMG_native_handle_t* h = (IMG_native_handle_t*) handle;
+
+    vinfo.width = h->iWidth;
+    vinfo.height = h->iHeight;
+    vinfo.lumaStride = h->iWidth;
+
+    LOG_I("GetGfxBufferInfo: gfx iWidth=%d, iHeight=%d, iFormat=%x in handle structure\n", h->iWidth, h->iHeight, h->iFormat);
+
+    if (h->iFormat == HAL_PIXEL_FORMAT_NV12) {
+    #ifdef MRFLD_GFX
+        if((h->usage & GRALLOC_USAGE_HW_CAMERA_READ) || (h->usage & GRALLOC_USAGE_HW_CAMERA_WRITE) )
+            vinfo.lumaStride = (h->iWidth + 63) & ~63; //64 aligned
+        else
+            vinfo.lumaStride = (h->iWidth + 31) & ~31; //32 aligned
+    #else //on CTP
+        if (h->iWidth > 512)
+            vinfo.lumaStride = (h->iWidth + 63) & ~63;  //64 aligned
+        else
+            vinfo.lumaStride = 512;
+    #endif
+    } else if ((h->iFormat == HAL_PIXEL_FORMAT_BGRA_8888)||
+                  (h->iFormat == HAL_PIXEL_FORMAT_RGBA_8888)||
+                  (h->iFormat == HAL_PIXEL_FORMAT_RGBX_8888)||
+                  (h->iFormat == HAL_PIXEL_FORMAT_BGRX_8888)) {
+        vinfo.lumaStride = (h->iWidth + 31) & ~31;
+    } else if (h->iFormat == OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar) {
+        //nothing to do
+    } else
+        return ENCODE_NOT_SUPPORTED;
+
+    vinfo.format = h->iFormat;
+
+    LOG_I("			Actual Width=%d, Height=%d, Stride=%d\n\n", vinfo.width, vinfo.height, vinfo.lumaStride);
+    return ENCODE_SUCCESS;
+}
+
+#ifdef GFX_DUMP
+void DumpGfx(intptr_t handle, char* filename) {
+    ValueInfo vinfo;
+    void* vaddr[3];
+    FILE* fp;
+    int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN;
+
+    GetGfxBufferInfo(handle, vinfo);
+    if (gfx_lock((buffer_handle_t)handle, usage, 0, 0, vinfo.width, vinfo.height, &vaddr[0]) != 0)
+        return ENCODE_DRIVER_FAIL;
+    fp = fopen(filename, "wb");
+    fwrite(vaddr[0], 1, vinfo.lumaStride * vinfo.height * 4, fp);
+    fclose(fp);
+    LOG_I("dump %d bytes data to %s\n", vinfo.lumaStride * vinfo.height * 4, filename);
+    gfx_unlock((buffer_handle_t)handle);
+
+    return;
+}
+#endif
+
+#endif
+
+extern "C" {
+VAStatus vaLockSurface(VADisplay dpy,
+    VASurfaceID surface,
+    unsigned int *fourcc,
+    unsigned int *luma_stride,
+    unsigned int *chroma_u_stride,
+    unsigned int *chroma_v_stride,
+    unsigned int *luma_offset,
+    unsigned int *chroma_u_offset,
+    unsigned int *chroma_v_offset,
+    unsigned int *buffer_name,
+    void **buffer
+);
+
+VAStatus vaUnlockSurface(VADisplay dpy,
+    VASurfaceID surface
+);
+}
+
+VASurfaceMap::VASurfaceMap(VADisplay display, int hwcap) {
+
+    mVADisplay = display;
+    mSupportedSurfaceMemType = hwcap;
+    mValue = 0;
+    mVASurface = VA_INVALID_SURFACE;
+    mTracked = false;
+    mAction = 0;
+    memset(&mVinfo, 0, sizeof(ValueInfo));
+#ifdef IMG_GFX
+    mGfxHandle = NULL;
+#endif
+}
+
+VASurfaceMap::~VASurfaceMap() {
+
+    if (!mTracked && (mVASurface != VA_INVALID_SURFACE))
+        vaDestroySurfaces(mVADisplay, &mVASurface, 1);
+
+#ifdef IMG_GFX
+    if (mGfxHandle)
+        gfx_free(mGfxHandle);
+#endif
+}
+
+Encode_Status VASurfaceMap::doMapping() {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    if (mVASurface == VA_INVALID_SURFACE) {
+
+        int width = mVASurfaceWidth = mVinfo.width;
+        int height = mVASurfaceHeight = mVinfo.height;
+        int stride = mVASurfaceStride = mVinfo.lumaStride;
+
+        if (mAction & MAP_ACTION_COLORCONVERT) {
+
+            //only support gfx buffer
+            if (mVinfo.mode != MEM_MODE_GFXHANDLE)
+                return ENCODE_NOT_SUPPORTED;
+
+        #ifdef IMG_GFX //only enable on IMG chip
+
+            //do not trust valueinfo for gfx case, directly get from structure
+            ValueInfo tmp;
+
+            ret = GetGfxBufferInfo(mValue, tmp);
+            CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo");
+            width = tmp.width;
+            height = tmp.height;
+            stride = tmp.lumaStride;
+
+            if (HAL_PIXEL_FORMAT_NV12 == tmp.format || OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar == tmp.format)
+                mAction &= ~MAP_ACTION_COLORCONVERT;
+            else {
+                //allocate new gfx buffer if format is not NV12
+                int usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+
+                //use same size with original and HAL_PIXEL_FORMAT_NV12 format
+                if (gfx_alloc(width, height, HAL_PIXEL_FORMAT_NV12, usage, &mGfxHandle, &stride) != 0)
+                    return ENCODE_DRIVER_FAIL;
+
+                LOG_I("Create an new gfx buffer handle 0x%p for color convert, width=%d, height=%d, stride=%d\n",
+                           mGfxHandle, width, height, stride);
+            }
+
+        #else
+            return ENCODE_NOT_SUPPORTED;
+        #endif
+        }
+
+        if (mAction & MAP_ACTION_ALIGN64 && stride % 64 != 0) {
+            //check if stride is not 64 aligned, must allocate new 64 aligned vasurface
+            stride = (stride + 63 ) & ~63;
+            mAction |= MAP_ACTION_COPY;
+        }
+
+        if(mAction & MAP_ACTION_ALIGN64 && width <= 320 && height <= 240) {
+            mAction |= MAP_ACTION_COPY;
+        }
+
+        if (mAction & MAP_ACTION_COPY) { //must allocate new vasurface(EXternalMemoryNULL, uncached)
+            //allocate new vasurface
+            mVASurface = CreateNewVASurface(mVADisplay, stride, height);
+            if (mVASurface == VA_INVALID_SURFACE)
+                return ENCODE_DRIVER_FAIL;
+            mVASurfaceWidth = mVASurfaceStride = stride;
+            mVASurfaceHeight = height;
+            LOGI("create new vaSurface for MAP_ACTION_COPY\n");
+        } else {
+        #ifdef IMG_GFX
+            if (mGfxHandle != NULL) {
+                //map new gfx handle to vasurface
+                ret = MappingGfxHandle((intptr_t)mGfxHandle);
+                CHECK_ENCODE_STATUS_RETURN("MappingGfxHandle");
+                LOGI("map new allocated gfx handle to vaSurface\n");
+            } else
+        #endif
+            {
+                //map original value to vasurface
+                ret = MappingToVASurface();
+                CHECK_ENCODE_STATUS_RETURN("MappingToVASurface");
+            }
+        }
+    }
+
+    if (mAction & MAP_ACTION_COLORCONVERT) {
+        ret = doActionColConv();
+        CHECK_ENCODE_STATUS_RETURN("doActionColConv");
+    }
+
+    if (mAction & MAP_ACTION_COPY) {
+        //keep src color format is NV12, then do copy
+        ret = doActionCopy();
+        CHECK_ENCODE_STATUS_RETURN("doActionCopy");
+    }
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingToVASurface() {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    if (mVASurface != VA_INVALID_SURFACE) {
+        LOG_I("VASurface is already set before, nothing to do here\n");
+        return ENCODE_SUCCESS;
+    }
+    LOG_I("MappingToVASurface mode=%d, value=%p\n", mVinfo.mode, (void*)mValue);
+
+    const char *mode = NULL;
+    switch (mVinfo.mode) {
+        case MEM_MODE_SURFACE:
+            mode = "SURFACE";
+            ret = MappingSurfaceID(mValue);
+            break;
+        case MEM_MODE_GFXHANDLE:
+            mode = "GFXHANDLE";
+            ret = MappingGfxHandle(mValue);
+            break;
+        case MEM_MODE_KBUFHANDLE:
+            mode = "KBUFHANDLE";
+            ret = MappingKbufHandle(mValue);
+            break;
+        case MEM_MODE_MALLOC:
+        case MEM_MODE_NONECACHE_USRPTR:
+            mode = "MALLOC or NONCACHE_USRPTR";
+            ret = MappingMallocPTR(mValue);
+            break;
+        case MEM_MODE_ION:
+        case MEM_MODE_V4L2:
+        case MEM_MODE_USRPTR:
+        case MEM_MODE_CI:
+        default:
+            LOG_I("UnSupported memory mode 0x%08x", mVinfo.mode);
+            return ENCODE_NOT_SUPPORTED;
+    }
+
+    LOG_I("%s: Format=%x, lumaStride=%d, width=%d, height=%d\n", mode, mVinfo.format, mVinfo.lumaStride, mVinfo.width, mVinfo.height);
+    LOG_I("vaSurface 0x%08x is created for value = 0x%p\n", mVASurface, (void*)mValue);
+
+    return ret;
+}
+
+Encode_Status VASurfaceMap::MappingSurfaceID(intptr_t value) {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VASurfaceID surface;
+
+    //try to get kbufhandle from SurfaceID
+    uint32_t fourCC = 0;
+    uint32_t lumaStride = 0;
+    uint32_t chromaUStride = 0;
+    uint32_t chromaVStride = 0;
+    uint32_t lumaOffset = 0;
+    uint32_t chromaUOffset = 0;
+    uint32_t chromaVOffset = 0;
+    uint32_t kBufHandle = 0;
+
+    vaStatus = vaLockSurface(
+            (VADisplay)mVinfo.handle, (VASurfaceID)value,
+            &fourCC, &lumaStride, &chromaUStride, &chromaVStride,
+            &lumaOffset, &chromaUOffset, &chromaVOffset, &kBufHandle, NULL);
+
+    CHECK_VA_STATUS_RETURN("vaLockSurface");
+    LOG_I("Surface incoming = 0x%p\n", (void*)value);
+    LOG_I("lumaStride = %d, chromaUStride = %d, chromaVStride=%d\n", lumaStride, chromaUStride, chromaVStride);
+    LOG_I("lumaOffset = %d, chromaUOffset = %d, chromaVOffset = %d\n", lumaOffset, chromaUOffset, chromaVOffset);
+    LOG_I("kBufHandle = 0x%08x, fourCC = %d\n", kBufHandle, fourCC);
+
+    vaStatus = vaUnlockSurface((VADisplay)mVinfo.handle, (VASurfaceID)value);
+    CHECK_VA_STATUS_RETURN("vaUnlockSurface");
+
+    mVinfo.mode = MEM_MODE_KBUFHANDLE;
+    mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5;
+
+    mVASurface = CreateSurfaceFromExternalBuf(kBufHandle, mVinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_INVALID_SURFACE;
+
+    mVASurfaceWidth = mVinfo.width;
+    mVASurfaceHeight = mVinfo.height;
+    mVASurfaceStride = mVinfo.lumaStride;
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingGfxHandle(intptr_t value) {
+
+    LOG_I("MappingGfxHandle %p......\n", (void*)value);
+    LOG_I("format = 0x%08x, lumaStride = %d in ValueInfo\n", mVinfo.format, mVinfo.lumaStride);
+
+    //default value for all HW platforms, maybe not accurate
+    mVASurfaceWidth = mVinfo.width;
+    mVASurfaceHeight = mVinfo.height;
+    mVASurfaceStride = mVinfo.lumaStride;
+
+#ifdef IMG_GFX
+    Encode_Status ret;
+    ValueInfo tmp;
+
+    ret = GetGfxBufferInfo(value, tmp);
+    CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo");
+    mVASurfaceWidth = tmp.width;
+    mVASurfaceHeight = tmp.height;
+    mVASurfaceStride = tmp.lumaStride;
+#endif
+
+    LOG_I("Mapping vasurface Width=%d, Height=%d, Stride=%d\n", mVASurfaceWidth, mVASurfaceHeight, mVASurfaceStride);
+
+    ValueInfo vinfo;
+    memset(&vinfo, 0, sizeof(ValueInfo));
+    vinfo.mode = MEM_MODE_GFXHANDLE;
+    vinfo.width = mVASurfaceWidth;
+    vinfo.height = mVASurfaceHeight;
+    vinfo.lumaStride = mVASurfaceStride;
+    mVASurface = CreateSurfaceFromExternalBuf(value, vinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_INVALID_SURFACE;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingKbufHandle(intptr_t value) {
+
+    LOG_I("MappingKbufHandle value=%p\n", (void*)value);
+
+    mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5;
+    mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_INVALID_SURFACE;
+
+    mVASurfaceWidth = mVinfo.width;
+    mVASurfaceHeight = mVinfo.height;
+    mVASurfaceStride = mVinfo.lumaStride;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingMallocPTR(intptr_t value) {
+
+    mVASurface = CreateSurfaceFromExternalBuf(value, mVinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_INVALID_SURFACE;
+
+    mVASurfaceWidth = mVinfo.width;
+    mVASurfaceHeight = mVinfo.height;
+    mVASurfaceStride = mVinfo.lumaStride;
+
+    return ENCODE_SUCCESS;
+}
+
+//always copy with same color format NV12
+Encode_Status VASurfaceMap::doActionCopy() {
+
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+
+    uint32_t width = 0, height = 0, stride = 0;
+    uint8_t *pSrcBuffer, *pDestBuffer;
+    intptr_t handle = 0;
+
+    LOG_I("Copying Src Buffer data to VASurface\n");
+
+    if (mVinfo.mode != MEM_MODE_MALLOC && mVinfo.mode != MEM_MODE_GFXHANDLE) {
+        LOG_E("Not support copy in mode %d", mVinfo.mode);
+        return ENCODE_NOT_SUPPORTED;
+    }
+
+    LOG_I("Src Buffer information\n");
+    LOG_I("Mode = %d, width = %d, stride = %d, height = %d\n",
+           mVinfo.mode, mVinfo.width, mVinfo.lumaStride, mVinfo.height);
+
+    uint32_t srcY_offset, srcUV_offset;
+    uint32_t srcY_pitch, srcUV_pitch;
+
+    if (mVinfo.mode == MEM_MODE_MALLOC) {
+        width = mVinfo.width;
+        height = mVinfo.height;
+        stride = mVinfo.lumaStride;
+        pSrcBuffer = (uint8_t*) mValue;
+        srcY_offset = 0;
+        srcUV_offset = stride * height;
+        srcY_pitch = stride;
+        srcUV_pitch = stride;
+    } else {
+
+    #ifdef IMG_GFX  //only enable on IMG chips
+        int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN;
+
+        //do not trust valueinfo, directly get from structure
+        Encode_Status ret;
+        ValueInfo tmp;
+
+        if (mGfxHandle)
+            handle = (intptr_t) mGfxHandle;
+        else
+            handle = mValue;
+
+        ret = GetGfxBufferInfo(handle, tmp);
+        CHECK_ENCODE_STATUS_RETURN("GetGfxBufferInfo");
+        width = tmp.width;
+        height = tmp.height;
+        stride = tmp.lumaStride;
+
+        //only support HAL_PIXEL_FORMAT_NV12 & OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
+        if (HAL_PIXEL_FORMAT_NV12 != tmp.format && OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar != tmp.format) {
+            LOG_E("Not support gfx buffer format %x", tmp.format);
+            return ENCODE_NOT_SUPPORTED;
+        }
+
+        srcY_offset = 0;
+        srcUV_offset = stride * height;
+        srcY_pitch = stride;
+        srcUV_pitch = stride;
+
+        //lock gfx handle with buffer real size
+        void* vaddr[3];
+        if (gfx_lock((buffer_handle_t) handle, usage, 0, 0, width, height, &vaddr[0]) != 0)
+            return ENCODE_DRIVER_FAIL;
+        pSrcBuffer = (uint8_t*)vaddr[0];
+    #else
+
+        return ENCODE_NOT_SUPPORTED;
+    #endif
+    }
+
+
+    VAImage destImage;
+    vaStatus = vaDeriveImage(mVADisplay, mVASurface, &destImage);
+    CHECK_VA_STATUS_RETURN("vaDeriveImage");
+    vaStatus = vaMapBuffer(mVADisplay, destImage.buf, (void **)&pDestBuffer);
+    CHECK_VA_STATUS_RETURN("vaMapBuffer");
+
+    LOG_I("\nDest VASurface information\n");
+    LOG_I("pitches[0] = %d\n", destImage.pitches[0]);
+    LOG_I("pitches[1] = %d\n", destImage.pitches[1]);
+    LOG_I("offsets[0] = %d\n", destImage.offsets[0]);
+    LOG_I("offsets[1] = %d\n", destImage.offsets[1]);
+    LOG_I("num_planes = %d\n", destImage.num_planes);
+    LOG_I("width = %d\n", destImage.width);
+    LOG_I("height = %d\n", destImage.height);
+
+    if (width > destImage.width || height > destImage.height) {
+        LOG_E("src buffer is bigger than destination buffer\n");
+        return ENCODE_INVALID_PARAMS;
+    }
+
+    uint8_t *srcY, *dstY;
+    uint8_t *srcU, *srcV;
+    uint8_t *srcUV, *dstUV;
+
+    srcY = pSrcBuffer + srcY_offset;
+    dstY = pDestBuffer + destImage.offsets[0];
+    srcUV = pSrcBuffer + srcUV_offset;
+    dstUV = pDestBuffer + destImage.offsets[1];
+
+    for (uint32_t i = 0; i < height; i++) {
+        memcpy(dstY, srcY, width);
+        srcY += srcY_pitch;
+        dstY += destImage.pitches[0];
+    }
+
+    for (uint32_t i = 0; i < height / 2; i++) {
+        memcpy(dstUV, srcUV, width);
+        srcUV += srcUV_pitch;
+        dstUV += destImage.pitches[1];
+    }
+
+    vaStatus = vaUnmapBuffer(mVADisplay, destImage.buf);
+    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
+    vaStatus = vaDestroyImage(mVADisplay, destImage.image_id);
+    CHECK_VA_STATUS_RETURN("vaDestroyImage");
+
+#ifdef IMG_GFX
+    if (mVinfo.mode == MEM_MODE_GFXHANDLE) {
+        //unlock gfx handle
+        gfx_unlock((buffer_handle_t) handle);
+    }
+#endif
+    LOG_I("Copying Src Buffer data to VASurface Complete\n");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::doActionColConv() {
+
+#ifdef IMG_GFX
+    if (mGfxHandle == NULL) {
+        LOG_E("something wrong, why new gfxhandle is not allocated? \n");
+        return ENCODE_FAIL;
+    }
+
+    LOG_I("doActionColConv gfx_Blit width=%d, height=%d\n", mVinfo.width, mVinfo.height);
+    if (gfx_Blit((buffer_handle_t)mValue, mGfxHandle,
+            mVinfo.width, mVinfo.height, 0, 0) != 0)
+        return ENCODE_DRIVER_FAIL;
+
+  #ifdef GFX_DUMP
+    LOG_I("dumpping gfx data.....\n");
+    DumpGfx(mValue, "/data/dump.rgb");
+    DumpGfx((intptr_t)mGfxHandle, "/data/dump.yuv");
+  #endif
+    return ENCODE_SUCCESS;
+
+#else
+    return ENCODE_NOT_SUPPORTED;
+#endif
+}
+
+VASurfaceID VASurfaceMap::CreateSurfaceFromExternalBuf(intptr_t value, ValueInfo& vinfo) {
+
+    VAStatus vaStatus;
+    VASurfaceAttribExternalBuffers extbuf;
+    VASurfaceAttrib attribs[2];
+    VASurfaceID surface = VA_INVALID_SURFACE;
+    int type;
+    unsigned long data = value;
+
+    extbuf.pixel_format = VA_FOURCC_NV12;
+    extbuf.width = vinfo.width;
+    extbuf.height = vinfo.height;
+    extbuf.data_size = vinfo.size;
+    if (extbuf.data_size == 0)
+        extbuf.data_size = vinfo.lumaStride * vinfo.height * 1.5;
+    extbuf.num_buffers = 1;
+    extbuf.num_planes = 3;
+    extbuf.pitches[0] = vinfo.lumaStride;
+    extbuf.pitches[1] = vinfo.lumaStride;
+    extbuf.pitches[2] = vinfo.lumaStride;
+    extbuf.pitches[3] = 0;
+    extbuf.offsets[0] = 0;
+    extbuf.offsets[1] = vinfo.lumaStride * vinfo.height;
+    extbuf.offsets[2] = extbuf.offsets[1];
+    extbuf.offsets[3] = 0;
+    extbuf.buffers = &data;
+    extbuf.flags = 0;
+    extbuf.private_data = NULL;
+
+    switch(vinfo.mode) {
+        case MEM_MODE_GFXHANDLE:
+            type = VA_SURFACE_ATTRIB_MEM_TYPE_ANDROID_GRALLOC;
+            break;
+        case MEM_MODE_KBUFHANDLE:
+            type = VA_SURFACE_ATTRIB_MEM_TYPE_KERNEL_DRM;
+            break;
+        case MEM_MODE_MALLOC:
+            type = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
+            break;
+        case MEM_MODE_NONECACHE_USRPTR:
+            type = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
+            extbuf.flags |= VA_SURFACE_EXTBUF_DESC_UNCACHED;
+            break;
+        case MEM_MODE_SURFACE:
+        case MEM_MODE_ION:
+        case MEM_MODE_V4L2:
+        case MEM_MODE_USRPTR:
+        case MEM_MODE_CI:
+        default:
+            //not support
+            return VA_INVALID_SURFACE;
+    }
+
+    if (!(mSupportedSurfaceMemType & type))
+        return VA_INVALID_SURFACE;
+
+    attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType;
+    attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attribs[0].value.type = VAGenericValueTypeInteger;
+    attribs[0].value.value.i = type;
+
+    attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
+    attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attribs[1].value.type = VAGenericValueTypePointer;
+    attribs[1].value.value.p = (void *)&extbuf;
+
+    vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420, vinfo.width,
+                                 vinfo.height, &surface, 1, attribs, 2);
+    if (vaStatus != VA_STATUS_SUCCESS){
+        LOG_E("vaCreateSurfaces failed. vaStatus = %d\n", vaStatus);
+        surface = VA_INVALID_SURFACE;
+    }
+    return surface;
+}
+
+VASurfaceID CreateNewVASurface(VADisplay display, int32_t width, int32_t height) {
+
+    VAStatus vaStatus;
+    VASurfaceID surface = VA_INVALID_SURFACE;
+    VASurfaceAttrib attribs[2];
+    VASurfaceAttribExternalBuffers extbuf;
+    unsigned long data;
+
+    extbuf.pixel_format = VA_FOURCC_NV12;
+    extbuf.width = width;
+    extbuf.height = height;
+    extbuf.data_size = width * height * 3 / 2;
+    extbuf.num_buffers = 1;
+    extbuf.num_planes = 3;
+    extbuf.pitches[0] = width;
+    extbuf.pitches[1] = width;
+    extbuf.pitches[2] = width;
+    extbuf.pitches[3] = 0;
+    extbuf.offsets[0] = 0;
+    extbuf.offsets[1] = width * height;
+    extbuf.offsets[2] = extbuf.offsets[1];
+    extbuf.offsets[3] = 0;
+    extbuf.buffers = &data;
+    extbuf.flags = 0;
+    extbuf.private_data = NULL;
+
+    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_VA;
+
+    attribs[1].type = (VASurfaceAttribType)VASurfaceAttribExternalBufferDescriptor;
+    attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+    attribs[1].value.type = VAGenericValueTypePointer;
+    attribs[1].value.value.p = (void *)&extbuf;
+
+    vaStatus = vaCreateSurfaces(display, VA_RT_FORMAT_YUV420, width,
+                                 height, &surface, 1, attribs, 2);
+    if (vaStatus != VA_STATUS_SUCCESS)
+        LOG_E("vaCreateSurfaces failed. vaStatus = %d\n", vaStatus);
+
+    return surface;
+}
diff --git a/videoencoder/VideoEncoderUtils.h b/videoencoder/VideoEncoderUtils.h
new file mode 100644
index 0000000..05911cd
--- /dev/null
+++ b/videoencoder/VideoEncoderUtils.h
@@ -0,0 +1,85 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_UTILS_H__
+#define __VIDEO_ENCODER_UTILS_H__
+#include <va/va.h>
+#include <va/va_tpi.h>
+#include "VideoEncoderDef.h"
+#include "IntelMetadataBuffer.h"
+#ifdef IMG_GFX
+#include <hardware/gralloc.h>
+#endif
+
+#define MAP_ACTION_COPY         0x00000001  //mem copy
+#define MAP_ACTION_ALIGN64      0x00000002  //align 64
+#define MAP_ACTION_COLORCONVERT 0x00000004  //color convert
+#define MAP_ACTION_RESIZE       0x00000008  //resize
+
+class VASurfaceMap {
+public:
+    VASurfaceMap(VADisplay display, int hwcap);
+    ~VASurfaceMap();
+
+    Encode_Status doMapping();
+    VASurfaceID getVASurface() {return mVASurface;}
+    intptr_t getValue() {return mValue;}
+    ValueInfo* getValueInfo() {return &mVinfo;}
+
+    void setVASurface(VASurfaceID surface) {mVASurface = surface;}
+    void setValue(intptr_t value) {mValue = value;}
+    void setValueInfo(ValueInfo& vinfo) {memcpy(&mVinfo, &vinfo, sizeof(ValueInfo));}
+    void setTracked() {mTracked = true;}
+    void setAction(int32_t action) {mAction = action;}
+
+private:
+    Encode_Status doActionCopy();
+    Encode_Status doActionColConv();
+    Encode_Status MappingToVASurface();
+    Encode_Status MappingSurfaceID(intptr_t value);
+    Encode_Status MappingGfxHandle(intptr_t value);
+    Encode_Status MappingKbufHandle(intptr_t value);
+    Encode_Status MappingMallocPTR(intptr_t value);
+    VASurfaceID CreateSurfaceFromExternalBuf(intptr_t value, ValueInfo& vinfo);
+
+    VADisplay mVADisplay;
+
+    intptr_t mValue;
+
+    VASurfaceID mVASurface;
+    int32_t mVASurfaceWidth;
+    int32_t mVASurfaceHeight;
+    int32_t mVASurfaceStride;
+
+//    MetadataBufferType mType;
+
+    ValueInfo mVinfo;
+    bool mTracked;
+
+    int32_t mAction;
+
+    int32_t mSupportedSurfaceMemType;
+
+#ifdef IMG_GFX
+    //special for gfx color format converter
+    buffer_handle_t mGfxHandle;
+#endif
+};
+
+VASurfaceID CreateNewVASurface(VADisplay display, int32_t width, int32_t height);
+
+#endif
+
diff --git a/videoencoder/VideoEncoderVP8.cpp b/videoencoder/VideoEncoderVP8.cpp
new file mode 100644
index 0000000..d65b385
--- /dev/null
+++ b/videoencoder/VideoEncoderVP8.cpp
@@ -0,0 +1,521 @@
+/*
+* Copyright (c) 2009-2011 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 <string.h>
+#include <stdlib.h>
+#include "VideoEncoderLog.h"
+#include "VideoEncoderVP8.h"
+#include <va/va_tpi.h>
+#include <va/va_enc_vp8.h>
+
+VideoEncoderVP8::VideoEncoderVP8()
+    :VideoEncoderBase() {
+
+        mVideoParamsVP8.profile = 0;
+        mVideoParamsVP8.error_resilient = 0;
+        mVideoParamsVP8.num_token_partitions = 4;
+        mVideoParamsVP8.kf_auto = 0;
+        mVideoParamsVP8.kf_min_dist = 128;
+        mVideoParamsVP8.kf_max_dist = 128;
+        mVideoParamsVP8.min_qp = 0;
+        mVideoParamsVP8.max_qp = 63;
+        mVideoParamsVP8.init_qp = 26;
+        mVideoParamsVP8.rc_undershoot = 100;
+        mVideoParamsVP8.rc_overshoot = 100;
+        mVideoParamsVP8.hrd_buf_size = 1000;
+        mVideoParamsVP8.hrd_buf_initial_fullness = 500;
+        mVideoParamsVP8.hrd_buf_optimal_fullness = 600;
+        mVideoParamsVP8.max_frame_size_ratio = 0;
+
+        mVideoConfigVP8.force_kf = 0;
+        mVideoConfigVP8.refresh_entropy_probs = 0;
+        mVideoConfigVP8.value = 0;
+        mVideoConfigVP8.sharpness_level = 2;
+
+        mVideoConfigVP8ReferenceFrame.no_ref_last = 0;
+        mVideoConfigVP8ReferenceFrame.no_ref_gf = 0;
+        mVideoConfigVP8ReferenceFrame.no_ref_arf = 0;
+        mVideoConfigVP8ReferenceFrame.refresh_last = 1;
+        mVideoConfigVP8ReferenceFrame.refresh_golden_frame = 1;
+        mVideoConfigVP8ReferenceFrame.refresh_alternate_frame = 1;
+
+        mComParams.profile = VAProfileVP8Version0_3;
+}
+
+VideoEncoderVP8::~VideoEncoderVP8() {
+}
+
+Encode_Status VideoEncoderVP8::start() {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    LOG_V( "Begin\n");
+
+    ret = VideoEncoderBase::start ();
+    CHECK_ENCODE_STATUS_RETURN("VideoEncoderBase::start");
+
+    if (mComParams.rcMode == VA_RC_VCM) {
+        mRenderBitRate = false;
+    }
+
+    LOG_V( "end\n");
+    return ret;
+}
+
+
+Encode_Status VideoEncoderVP8::renderSequenceParams() {
+    Encode_Status ret = ENCODE_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncSequenceParameterBufferVP8 vp8SeqParam = VAEncSequenceParameterBufferVP8();
+
+    LOG_V( "Begin\n");
+
+    vp8SeqParam.frame_width = mComParams.resolution.width;
+    vp8SeqParam.frame_height = mComParams.resolution.height;
+    vp8SeqParam.error_resilient = mVideoParamsVP8.error_resilient;
+    vp8SeqParam.kf_auto = mVideoParamsVP8.kf_auto;
+    vp8SeqParam.kf_min_dist = mVideoParamsVP8.kf_min_dist;
+    vp8SeqParam.kf_max_dist = mVideoParamsVP8.kf_max_dist;
+    vp8SeqParam.bits_per_second = mComParams.rcParams.bitRate;
+    memcpy(vp8SeqParam.reference_frames, mAutoRefSurfaces, sizeof(mAutoRefSurfaces) * mAutoReferenceSurfaceNum);
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncSequenceParameterBufferType,
+            sizeof(vp8SeqParam),
+            1, &vp8SeqParam,
+            &mSeqParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mSeqParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "End\n");
+	return ret;
+}
+
+Encode_Status VideoEncoderVP8::renderPictureParams(EncodeTask *task) {
+    Encode_Status ret = ENCODE_SUCCESS;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncPictureParameterBufferVP8 vp8PicParam = VAEncPictureParameterBufferVP8();
+    LOG_V( "Begin\n");
+
+    vp8PicParam.coded_buf = task->coded_buffer;
+    vp8PicParam.pic_flags.value = 0;
+    vp8PicParam.ref_flags.bits.force_kf = mVideoConfigVP8.force_kf; //0;
+    if(!vp8PicParam.ref_flags.bits.force_kf) {
+        vp8PicParam.ref_flags.bits.no_ref_last = mVideoConfigVP8ReferenceFrame.no_ref_last;
+        vp8PicParam.ref_flags.bits.no_ref_arf = mVideoConfigVP8ReferenceFrame.no_ref_arf;
+        vp8PicParam.ref_flags.bits.no_ref_gf = mVideoConfigVP8ReferenceFrame.no_ref_gf;
+    }
+    vp8PicParam.pic_flags.bits.refresh_entropy_probs = 0;
+    vp8PicParam.sharpness_level = 2;
+    vp8PicParam.pic_flags.bits.num_token_partitions = 2;
+    vp8PicParam.pic_flags.bits.refresh_last = mVideoConfigVP8ReferenceFrame.refresh_last;
+    vp8PicParam.pic_flags.bits.refresh_golden_frame = mVideoConfigVP8ReferenceFrame.refresh_golden_frame;
+    vp8PicParam.pic_flags.bits.refresh_alternate_frame = mVideoConfigVP8ReferenceFrame.refresh_alternate_frame;
+
+    vaStatus = vaCreateBuffer(
+            mVADisplay, mVAContext,
+            VAEncPictureParameterBufferType,
+            sizeof(vp8PicParam),
+            1, &vp8PicParam,
+            &mPicParamBuf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &mPicParamBuf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");
+
+    LOG_V( "End\n");
+    return ret;
+}
+
+Encode_Status VideoEncoderVP8::renderRCParams(uint32_t layer_id, bool total_bitrate)
+{
+    VABufferID rc_param_buf;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncMiscParameterBuffer *misc_param;
+    VAEncMiscParameterRateControl *misc_rate_ctrl;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                              VAEncMiscParameterBufferType,
+                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
+                              1,NULL,&rc_param_buf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaMapBuffer(mVADisplay, rc_param_buf,(void **)&misc_param);
+
+    misc_param->type = VAEncMiscParameterTypeRateControl;
+    misc_rate_ctrl = (VAEncMiscParameterRateControl *)misc_param->data;
+    memset(misc_rate_ctrl, 0, sizeof(*misc_rate_ctrl));
+
+    if(total_bitrate)
+        misc_rate_ctrl->bits_per_second = mComParams.rcParams.bitRate;
+    else
+    {
+        misc_rate_ctrl->rc_flags.bits.temporal_id = layer_id;
+        if(mTemporalLayerBitrateFramerate[layer_id].bitRate != 0)
+             misc_rate_ctrl->bits_per_second = mTemporalLayerBitrateFramerate[layer_id].bitRate;
+    }
+
+    misc_rate_ctrl->target_percentage = 100;
+    misc_rate_ctrl->window_size = 1000;
+    misc_rate_ctrl->initial_qp = mVideoParamsVP8.init_qp;
+    misc_rate_ctrl->min_qp = mVideoParamsVP8.min_qp;
+    misc_rate_ctrl->basic_unit_size = 0;
+    misc_rate_ctrl->max_qp = mVideoParamsVP8.max_qp;
+
+    vaUnmapBuffer(mVADisplay, rc_param_buf);
+
+    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &rc_param_buf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
+    return 0;
+}
+
+Encode_Status VideoEncoderVP8::renderFrameRateParams(uint32_t layer_id, bool total_framerate)
+{
+    VABufferID framerate_param_buf;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncMiscParameterBuffer *misc_param;
+    VAEncMiscParameterFrameRate * misc_framerate;
+    uint32_t frameRateNum = mComParams.frameRate.frameRateNum;
+    uint32_t frameRateDenom = mComParams.frameRate.frameRateDenom;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                              VAEncMiscParameterBufferType,
+                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterFrameRate),
+                              1,NULL,&framerate_param_buf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaMapBuffer(mVADisplay, framerate_param_buf,(void **)&misc_param);
+    misc_param->type = VAEncMiscParameterTypeFrameRate;
+    misc_framerate = (VAEncMiscParameterFrameRate *)misc_param->data;
+    memset(misc_framerate, 0, sizeof(*misc_framerate));
+
+    if(total_framerate)
+        misc_framerate->framerate = (unsigned int) (frameRateNum + frameRateDenom /2) / frameRateDenom;
+    else
+    {
+        misc_framerate->framerate_flags.bits.temporal_id = layer_id;
+        if(mTemporalLayerBitrateFramerate[layer_id].frameRate != 0)
+            misc_framerate->framerate = mTemporalLayerBitrateFramerate[layer_id].frameRate;
+    }
+
+    vaUnmapBuffer(mVADisplay, framerate_param_buf);
+
+    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &framerate_param_buf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
+
+    return 0;
+}
+
+Encode_Status VideoEncoderVP8::renderHRDParams(void)
+{
+    VABufferID hrd_param_buf;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncMiscParameterBuffer *misc_param;
+    VAEncMiscParameterHRD * misc_hrd;
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                              VAEncMiscParameterBufferType,
+                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterHRD),
+                              1,NULL,&hrd_param_buf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaMapBuffer(mVADisplay, hrd_param_buf,(void **)&misc_param);
+    misc_param->type = VAEncMiscParameterTypeHRD;
+    misc_hrd = (VAEncMiscParameterHRD *)misc_param->data;
+    memset(misc_hrd, 0, sizeof(*misc_hrd));
+    misc_hrd->buffer_size = 1000;
+    misc_hrd->initial_buffer_fullness = 500;
+    misc_hrd->optimal_buffer_fullness = 600;
+    vaUnmapBuffer(mVADisplay, hrd_param_buf);
+
+    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &hrd_param_buf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
+
+    return 0;
+}
+
+Encode_Status VideoEncoderVP8::renderMaxFrameSizeParams(void)
+{
+    VABufferID max_frame_size_param_buf;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncMiscParameterBuffer *misc_param;
+    VAEncMiscParameterBufferMaxFrameSize * misc_maxframesize;
+    unsigned int frameRateNum = mComParams.frameRate.frameRateNum;
+    unsigned int frameRateDenom = mComParams.frameRate.frameRateDenom;
+    unsigned int frameRate = (unsigned int)(frameRateNum + frameRateDenom /2);
+    unsigned int bitRate = mComParams.rcParams.bitRate;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+                              VAEncMiscParameterBufferType,
+                              sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterHRD),
+                              1,NULL,&max_frame_size_param_buf);
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+
+    vaMapBuffer(mVADisplay, max_frame_size_param_buf,(void **)&misc_param);
+    misc_param->type = VAEncMiscParameterTypeMaxFrameSize;
+    misc_maxframesize = (VAEncMiscParameterBufferMaxFrameSize *)misc_param->data;
+    memset(misc_maxframesize, 0, sizeof(*misc_maxframesize));
+    misc_maxframesize->max_frame_size = (unsigned int)((bitRate/frameRate) * mVideoParamsVP8.max_frame_size_ratio);
+    vaUnmapBuffer(mVADisplay, max_frame_size_param_buf);
+
+    vaStatus = vaRenderPicture(mVADisplay,mVAContext, &max_frame_size_param_buf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
+
+    return 0;
+}
+
+Encode_Status VideoEncoderVP8::renderLayerStructureParam(void)
+{
+    VABufferID layer_struc_buf;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    VAEncMiscParameterBuffer *misc_param;
+    VAEncMiscParameterTemporalLayerStructure *misc_layer_struc;
+    uint32_t i;
+
+    vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
+		               VAEncMiscParameterBufferType,
+			       sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterTemporalLayerStructure),
+			       1, NULL, &layer_struc_buf);
+
+    CHECK_VA_STATUS_RETURN("vaCreateBuffer");
+    vaMapBuffer(mVADisplay, layer_struc_buf, (void **)&misc_param);
+    misc_param->type = VAEncMiscParameterTypeTemporalLayerStructure;
+    misc_layer_struc = (VAEncMiscParameterTemporalLayerStructure *)misc_param->data;
+    memset(misc_layer_struc, 0, sizeof(*misc_layer_struc));
+
+    misc_layer_struc->number_of_layers = mComParams.numberOfLayer;
+    misc_layer_struc->periodicity = mComParams.nPeriodicity;
+    LOGE("renderLayerStructureParam misc_layer_struc->number_of_layers is %d",misc_layer_struc->number_of_layers);
+
+    for(i=0;i<mComParams.nPeriodicity;i++)
+    {
+        misc_layer_struc->layer_id[i] = mComParams.nLayerID[i];
+    }
+
+    vaUnmapBuffer(mVADisplay, layer_struc_buf);
+
+    vaStatus = vaRenderPicture(mVADisplay, mVAContext, &layer_struc_buf, 1);
+    CHECK_VA_STATUS_RETURN("vaRenderPicture");;
+
+    return 0;
+}
+
+
+Encode_Status VideoEncoderVP8::sendEncodeCommand(EncodeTask *task) {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+    uint32_t i;
+
+    if (mFrameNum == 0) {
+        ret = renderSequenceParams();
+        ret = renderFrameRateParams(0,true);
+        ret = renderRCParams(0,true);
+        ret = renderHRDParams();
+        ret = renderMaxFrameSizeParams();
+        if(mRenderMultiTemporal)
+        {
+            ret = renderLayerStructureParam();
+            mRenderMultiTemporal = false;
+
+        }
+
+        if(mComParams.numberOfLayer > 1)
+            for(i=0;i<mComParams.numberOfLayer;i++)
+            {
+                ret = renderFrameRateParams(i, false);
+                ret = renderRCParams(i, false);
+            }
+
+        CHECK_ENCODE_STATUS_RETURN("renderSequenceParams");
+    }
+
+    if (mRenderBitRate){
+        ret = renderRCParams(0,true);
+        CHECK_ENCODE_STATUS_RETURN("renderRCParams");
+
+        mRenderBitRate = false;
+    }
+
+    if (mRenderFrameRate) {
+        ret = renderFrameRateParams(0,true);
+        CHECK_ENCODE_STATUS_RETURN("renderFrameRateParams");
+
+        mRenderFrameRate = false;
+    }
+
+    if (mRenderMaxFrameSize) {
+        ret = renderMaxFrameSizeParams();
+        CHECK_ENCODE_STATUS_RETURN("renderMaxFrameSizeParams");
+
+        mRenderMaxFrameSize = false;
+    }
+
+    ret = renderPictureParams(task);
+    CHECK_ENCODE_STATUS_RETURN("renderPictureParams");
+
+    if(mForceKFrame) {
+        mVideoConfigVP8.force_kf = 0;//rest it as default value
+        mForceKFrame = false;
+    }
+
+    LOG_V( "End\n");
+    return ret;
+}
+
+
+Encode_Status VideoEncoderVP8::derivedSetParams(VideoParamConfigSet *videoEncParams) {
+
+	CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+	VideoParamsVP8 *encParamsVP8 = reinterpret_cast <VideoParamsVP8*> (videoEncParams);
+
+	if (encParamsVP8->size != sizeof(VideoParamsVP8)) {
+		return ENCODE_INVALID_PARAMS;
+	}
+
+	mVideoParamsVP8 = *encParamsVP8;
+	return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderVP8::derivedGetParams(VideoParamConfigSet *videoEncParams) {
+
+	CHECK_NULL_RETURN_IFFAIL(videoEncParams);
+	VideoParamsVP8 *encParamsVP8 = reinterpret_cast <VideoParamsVP8*> (videoEncParams);
+
+	if (encParamsVP8->size != sizeof(VideoParamsVP8)) {
+	       return ENCODE_INVALID_PARAMS;
+        }
+
+        *encParamsVP8 = mVideoParamsVP8;
+        return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderVP8::derivedGetConfig(VideoParamConfigSet *videoEncConfig) {
+
+		int layer_id;
+        CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
+
+        switch (videoEncConfig->type)
+        {
+                case VideoConfigTypeVP8:{
+                        VideoConfigVP8 *encConfigVP8 =
+                                reinterpret_cast<VideoConfigVP8*> (videoEncConfig);
+
+                        if (encConfigVP8->size != sizeof(VideoConfigVP8)) {
+                                return ENCODE_INVALID_PARAMS;
+                        }
+
+                        *encConfigVP8 = mVideoConfigVP8;
+                }
+                break;
+
+                case VideoConfigTypeVP8ReferenceFrame:{
+
+                        VideoConfigVP8ReferenceFrame *encConfigVP8ReferenceFrame =
+                                reinterpret_cast<VideoConfigVP8ReferenceFrame*> (videoEncConfig);
+
+                        if (encConfigVP8ReferenceFrame->size != sizeof(VideoConfigVP8ReferenceFrame)) {
+                                return ENCODE_INVALID_PARAMS;
+                        }
+
+                        *encConfigVP8ReferenceFrame = mVideoConfigVP8ReferenceFrame;
+
+                }
+                break;
+
+                case VideoConfigTypeVP8MaxFrameSizeRatio :{
+
+                        VideoConfigVP8MaxFrameSizeRatio *encConfigVP8MaxFrameSizeRatio =
+                                reinterpret_cast<VideoConfigVP8MaxFrameSizeRatio*> (videoEncConfig);
+
+                        if (encConfigVP8MaxFrameSizeRatio->size != sizeof(VideoConfigVP8MaxFrameSizeRatio)) {
+                                return ENCODE_INVALID_PARAMS;
+                        }
+
+                        encConfigVP8MaxFrameSizeRatio->max_frame_size_ratio = mVideoParamsVP8.max_frame_size_ratio;
+                }
+                break;
+
+                default: {
+                   LOG_E ("Invalid Config Type");
+                   break;
+                }
+       }
+
+       return ENCODE_SUCCESS;
+}
+
+Encode_Status VideoEncoderVP8::derivedSetConfig(VideoParamConfigSet *videoEncConfig) {
+
+        int layer_id;
+        CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
+
+        switch (videoEncConfig->type)
+        {
+                case VideoConfigTypeVP8:{
+                        VideoConfigVP8 *encConfigVP8 =
+                                reinterpret_cast<VideoConfigVP8*> (videoEncConfig);
+
+                        if (encConfigVP8->size != sizeof(VideoConfigVP8)) {
+                                return ENCODE_INVALID_PARAMS;
+                        }
+
+                        mVideoConfigVP8 = *encConfigVP8;
+                }
+                break;
+
+                case VideoConfigTypeVP8ReferenceFrame:{
+                        VideoConfigVP8ReferenceFrame *encConfigVP8ReferenceFrame =
+                                reinterpret_cast<VideoConfigVP8ReferenceFrame*> (videoEncConfig);
+
+                        if (encConfigVP8ReferenceFrame->size != sizeof(VideoConfigVP8ReferenceFrame)) {
+                                return ENCODE_INVALID_PARAMS;
+                        }
+
+                        mVideoConfigVP8ReferenceFrame = *encConfigVP8ReferenceFrame;
+
+                }
+                break;
+
+                case VideoConfigTypeVP8MaxFrameSizeRatio:{
+                        VideoConfigVP8MaxFrameSizeRatio *encConfigVP8MaxFrameSizeRatio =
+                                reinterpret_cast<VideoConfigVP8MaxFrameSizeRatio*> (videoEncConfig);
+
+                        if (encConfigVP8MaxFrameSizeRatio->size != sizeof(VideoConfigVP8MaxFrameSizeRatio)) {
+                                return ENCODE_INVALID_PARAMS;
+                        }
+
+                        mVideoParamsVP8.max_frame_size_ratio = encConfigVP8MaxFrameSizeRatio->max_frame_size_ratio;
+                        mRenderMaxFrameSize = true;
+		}
+                break;
+
+                case VideoConfigTypeIDRRequest:{
+                        VideoParamConfigSet *encConfigVP8KFrameRequest =
+                                reinterpret_cast<VideoParamConfigSet*> (videoEncConfig);
+
+                        mVideoConfigVP8.force_kf = 1;
+                        mForceKFrame = true;
+                 }
+                 break;
+
+                default: {
+            LOG_E ("Invalid Config Type");
+            break;
+                }
+        }
+        return ENCODE_SUCCESS;
+}
diff --git a/videoencoder/VideoEncoderVP8.h b/videoencoder/VideoEncoderVP8.h
new file mode 100644
index 0000000..1a4360b
--- /dev/null
+++ b/videoencoder/VideoEncoderVP8.h
@@ -0,0 +1,58 @@
+/*
+* Copyright (c) 2009-2011 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 __VIDEO_ENCODER_VP8_H__
+#define __VIDEO_ENCODER_VP8_H__
+
+#include "VideoEncoderBase.h"
+
+/**
+  * VP8 Encoder class, derived from VideoEncoderBase
+  */
+class VideoEncoderVP8: public VideoEncoderBase {
+public:
+    VideoEncoderVP8();
+    virtual ~VideoEncoderVP8();
+    virtual Encode_Status start();
+
+
+
+protected:
+    virtual Encode_Status sendEncodeCommand(EncodeTask *task);
+    virtual Encode_Status derivedSetParams(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status derivedGetParams(VideoParamConfigSet *videoEncParams);
+    virtual Encode_Status derivedGetConfig(VideoParamConfigSet *videoEncConfig);
+    virtual Encode_Status derivedSetConfig(VideoParamConfigSet *videoEncConfig);
+    virtual Encode_Status getExtFormatOutput(VideoEncOutputBuffer *) {
+        return ENCODE_NOT_SUPPORTED;
+    }
+
+    // Local Methods
+private:
+        Encode_Status renderSequenceParams();
+        Encode_Status renderPictureParams(EncodeTask *task);
+        Encode_Status renderRCParams(uint32_t layer_id, bool total_bitrate);
+        Encode_Status renderHRDParams(void);
+        Encode_Status renderFrameRateParams(uint32_t layer_id, bool total_framerate);
+        Encode_Status renderMaxFrameSizeParams(void);
+        Encode_Status renderLayerStructureParam(void);
+
+        VideoConfigVP8 mVideoConfigVP8;
+        VideoParamsVP8 mVideoParamsVP8;
+        VideoConfigVP8ReferenceFrame mVideoConfigVP8ReferenceFrame;
+};
+
+#endif /* __VIDEO_ENCODER_VP8_H__ */
diff --git a/videoencoder/bitstream.h b/videoencoder/bitstream.h
new file mode 100644
index 0000000..c7f919e
--- /dev/null
+++ b/videoencoder/bitstream.h
@@ -0,0 +1,403 @@
+/*
+* Copyright (c) 2009-2011 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 __BITSTREAM_H__
+#define __BITSTREAM_H__
+
+#include <VideoEncoderBase.h>
+#include <assert.h>
+
+struct bitstream {
+    unsigned int *buffer;
+    int bit_offset;
+    int max_size_in_dword;
+};
+
+#define BITSTREAM_ALLOCATE_STEPPING     4096
+
+static unsigned int va_swap32(unsigned int val)
+{
+    unsigned char *pval = (unsigned char *)&val;
+
+    return ((pval[0] << 24)     |
+            (pval[1] << 16)     |
+            (pval[2] << 8)      |
+            (pval[3] << 0));
+}
+
+static void bitstream_start(bitstream *bs)
+{
+    bs->max_size_in_dword = BITSTREAM_ALLOCATE_STEPPING;
+    bs->buffer = (unsigned int*)calloc(bs->max_size_in_dword * sizeof(int), 1);
+    bs->bit_offset = 0;
+}
+
+static void bitstream_end(bitstream *bs)
+{
+    int pos = (bs->bit_offset >> 5);
+    int bit_offset = (bs->bit_offset & 0x1f);
+    int bit_left = 32 - bit_offset;
+
+    if (bit_offset) {
+        bs->buffer[pos] = va_swap32((bs->buffer[pos] << bit_left));
+    }
+}
+
+static void bitstream_put_ui(bitstream *bs, unsigned int val, int size_in_bits)
+{
+    int pos = (bs->bit_offset >> 5);
+    int bit_offset = (bs->bit_offset & 0x1f);
+    int bit_left = 32 - bit_offset;
+
+    if (!size_in_bits)
+        return;
+
+    bs->bit_offset += size_in_bits;
+
+    if (bit_left > size_in_bits) {
+        bs->buffer[pos] = (bs->buffer[pos] << size_in_bits | val);
+    } else {
+        size_in_bits -= bit_left;
+        bs->buffer[pos] = (bs->buffer[pos] << bit_left) | (val >> size_in_bits);
+        bs->buffer[pos] = va_swap32(bs->buffer[pos]);
+
+        if (pos + 1 == bs->max_size_in_dword) {
+            bs->max_size_in_dword += BITSTREAM_ALLOCATE_STEPPING;
+            bs->buffer = (unsigned int*)realloc(bs->buffer, bs->max_size_in_dword * sizeof(unsigned int));
+            if (bs->buffer == NULL)
+                abort();
+        }
+
+        bs->buffer[pos + 1] = val;
+    }
+}
+
+static void bitstream_put_ue(bitstream *bs, unsigned int val)
+{
+    int size_in_bits = 0;
+    int tmp_val = ++val;
+
+    while (tmp_val) {
+        tmp_val >>= 1;
+        size_in_bits++;
+    }
+
+    bitstream_put_ui(bs, 0, size_in_bits - 1); // leading zero
+    bitstream_put_ui(bs, val, size_in_bits);
+}
+
+static void bitstream_put_se(bitstream *bs, int val)
+{
+    unsigned int new_val;
+
+    if (val <= 0)
+        new_val = -2 * val;
+    else
+        new_val = 2 * val - 1;
+
+    bitstream_put_ue(bs, new_val);
+}
+
+static void bitstream_byte_aligning(bitstream *bs, int bit)
+{
+    int bit_offset = (bs->bit_offset & 0x7);
+    int bit_left = 8 - bit_offset;
+    int new_val;
+
+    if (!bit_offset)
+        return;
+
+    assert(bit == 0 || bit == 1);
+
+    if (bit)
+        new_val = (1 << bit_left) - 1;
+    else
+        new_val = 0;
+
+    bitstream_put_ui(bs, new_val, bit_left);
+}
+
+static void rbsp_trailing_bits(bitstream *bs)
+{
+    bitstream_put_ui(bs, 1, 1);
+    bitstream_byte_aligning(bs, 0);
+}
+
+static void nal_start_code_prefix(bitstream *bs)
+{
+    bitstream_put_ui(bs, 0x00000001, 32);
+}
+
+static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
+{
+    bitstream_put_ui(bs, 0, 1);                /* forbidden_zero_bit: 0 */
+    bitstream_put_ui(bs, nal_ref_idc, 2);
+    bitstream_put_ui(bs, nal_unit_type, 5);
+}
+
+#define NAL_REF_IDC_NONE        0
+#define NAL_REF_IDC_LOW         1
+#define NAL_REF_IDC_MEDIUM      2
+#define NAL_REF_IDC_HIGH        3
+
+#define NAL_NON_IDR             1
+#define NAL_IDR                 5
+#define NAL_SPS                 7
+#define NAL_PPS                 8
+#define NAL_SEI			6
+
+#define SLICE_TYPE_P            0
+#define SLICE_TYPE_B            1
+#define SLICE_TYPE_I            2
+
+#define ENTROPY_MODE_CAVLC      0
+#define ENTROPY_MODE_CABAC      1
+
+#define PROFILE_IDC_BASELINE    66
+#define PROFILE_IDC_MAIN        77
+#define PROFILE_IDC_HIGH        100
+
+static void sps_rbsp(bitstream *bs, VAProfile profile, int frame_bit_rate, VAEncSequenceParameterBufferH264 *seq_param)
+{
+    int profile_idc = 0;
+    int constraint_set_flag = 0;
+
+    if (profile == VAProfileH264High) {
+        profile_idc = PROFILE_IDC_HIGH;
+        constraint_set_flag |= (1 << 3); /* Annex A.2.4 */
+    }
+    else if (profile == VAProfileH264Main) {
+        profile_idc = PROFILE_IDC_MAIN;
+        constraint_set_flag |= (1 << 1); /* Annex A.2.2 */
+    } else {
+        profile_idc = PROFILE_IDC_BASELINE;
+        constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
+    }
+
+    bitstream_put_ui(bs, profile_idc, 8);               /* profile_idc */
+    bitstream_put_ui(bs, !!(constraint_set_flag & 1), 1);                         /* constraint_set0_flag */
+    bitstream_put_ui(bs, !!(constraint_set_flag & 2), 1);                         /* constraint_set1_flag */
+    bitstream_put_ui(bs, !!(constraint_set_flag & 4), 1);                         /* constraint_set2_flag */
+    bitstream_put_ui(bs, !!(constraint_set_flag & 8), 1);                         /* constraint_set3_flag */
+    bitstream_put_ui(bs, 0, 4);                         /* reserved_zero_4bits */
+    bitstream_put_ui(bs, seq_param->level_idc, 8);      /* level_idc */
+    bitstream_put_ue(bs, seq_param->seq_parameter_set_id);      /* seq_parameter_set_id */
+
+    if ( profile_idc == PROFILE_IDC_HIGH) {
+        bitstream_put_ue(bs, 1);        /* chroma_format_idc = 1, 4:2:0 */
+        bitstream_put_ue(bs, 0);        /* bit_depth_luma_minus8 */
+        bitstream_put_ue(bs, 0);        /* bit_depth_chroma_minus8 */
+        bitstream_put_ui(bs, 0, 1);     /* qpprime_y_zero_transform_bypass_flag */
+        bitstream_put_ui(bs, 0, 1);     /* seq_scaling_matrix_present_flag */
+    }
+
+    bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_frame_num_minus4); /* log2_max_frame_num_minus4 */
+    bitstream_put_ue(bs, seq_param->seq_fields.bits.pic_order_cnt_type);        /* pic_order_cnt_type */
+
+    if (seq_param->seq_fields.bits.pic_order_cnt_type == 0)
+        bitstream_put_ue(bs, seq_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4);     /* log2_max_pic_order_cnt_lsb_minus4 */
+    else {
+        assert(0);
+    }
+
+    bitstream_put_ue(bs, seq_param->max_num_ref_frames);        /* num_ref_frames */
+    bitstream_put_ui(bs, 0, 1);                                 /* gaps_in_frame_num_value_allowed_flag */
+
+    bitstream_put_ue(bs, seq_param->picture_width_in_mbs - 1);  /* pic_width_in_mbs_minus1 */
+    bitstream_put_ue(bs, seq_param->picture_height_in_mbs - 1); /* pic_height_in_map_units_minus1 */
+    bitstream_put_ui(bs, seq_param->seq_fields.bits.frame_mbs_only_flag, 1);    /* frame_mbs_only_flag */
+
+    if (!seq_param->seq_fields.bits.frame_mbs_only_flag) {
+        assert(0);
+    }
+
+    bitstream_put_ui(bs, seq_param->seq_fields.bits.direct_8x8_inference_flag, 1);      /* direct_8x8_inference_flag */
+    bitstream_put_ui(bs, seq_param->frame_cropping_flag, 1);            /* frame_cropping_flag */
+
+    if (seq_param->frame_cropping_flag) {
+        bitstream_put_ue(bs, seq_param->frame_crop_left_offset);        /* frame_crop_left_offset */
+        bitstream_put_ue(bs, seq_param->frame_crop_right_offset);       /* frame_crop_right_offset */
+        bitstream_put_ue(bs, seq_param->frame_crop_top_offset);         /* frame_crop_top_offset */
+        bitstream_put_ue(bs, seq_param->frame_crop_bottom_offset);      /* frame_crop_bottom_offset */
+    }
+
+    if ( frame_bit_rate < 0 ) {
+        bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
+    } else {
+        bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
+        bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
+        bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
+        bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
+        bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
+        bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
+        {
+            bitstream_put_ui(bs, 15, 32);
+            bitstream_put_ui(bs, 900, 32);
+            bitstream_put_ui(bs, 1, 1);
+        }
+        bitstream_put_ui(bs, 1, 1); /* nal_hrd_parameters_present_flag */
+        {
+            // hrd_parameters
+            bitstream_put_ue(bs, 0);    /* cpb_cnt_minus1 */
+            bitstream_put_ui(bs, 4, 4); /* bit_rate_scale */
+            bitstream_put_ui(bs, 6, 4); /* cpb_size_scale */
+
+            bitstream_put_ue(bs, frame_bit_rate - 1); /* bit_rate_value_minus1[0] */
+            bitstream_put_ue(bs, frame_bit_rate*8 - 1); /* cpb_size_value_minus1[0] */
+            bitstream_put_ui(bs, 1, 1);  /* cbr_flag[0] */
+
+            bitstream_put_ui(bs, 23, 5);   /* initial_cpb_removal_delay_length_minus1 */
+            bitstream_put_ui(bs, 23, 5);   /* cpb_removal_delay_length_minus1 */
+            bitstream_put_ui(bs, 23, 5);   /* dpb_output_delay_length_minus1 */
+            bitstream_put_ui(bs, 23, 5);   /* time_offset_length  */
+        }
+        bitstream_put_ui(bs, 0, 1);   /* vcl_hrd_parameters_present_flag */
+        bitstream_put_ui(bs, 0, 1);   /* low_delay_hrd_flag */
+
+        bitstream_put_ui(bs, 0, 1); /* pic_struct_present_flag */
+        bitstream_put_ui(bs, 0, 1); /* bitstream_restriction_flag */
+    }
+
+    rbsp_trailing_bits(bs);     /* rbsp_trailing_bits */
+}
+
+static void pps_rbsp(bitstream *bs, VAEncPictureParameterBufferH264 *pic_param)
+{
+
+    bitstream_put_ue(bs, pic_param->pic_parameter_set_id);      /* pic_parameter_set_id */
+    bitstream_put_ue(bs, pic_param->seq_parameter_set_id);      /* seq_parameter_set_id */
+
+    bitstream_put_ui(bs, pic_param->pic_fields.bits.entropy_coding_mode_flag, 1);  /* entropy_coding_mode_flag */
+
+    bitstream_put_ui(bs, 0, 1);                         /* pic_order_present_flag: 0 */
+
+    bitstream_put_ue(bs, 0);                            /* num_slice_groups_minus1 */
+
+    bitstream_put_ue(bs, pic_param->num_ref_idx_l0_active_minus1);      /* num_ref_idx_l0_active_minus1 */
+    bitstream_put_ue(bs, pic_param->num_ref_idx_l1_active_minus1);      /* num_ref_idx_l1_active_minus1 1 */
+
+    bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);     /* weighted_pred_flag: 0 */
+    bitstream_put_ui(bs, pic_param->pic_fields.bits.weighted_bipred_idc, 2);	/* weighted_bipred_idc: 0 */
+
+    bitstream_put_se(bs, pic_param->pic_init_qp - 26);  /* pic_init_qp_minus26 */
+    bitstream_put_se(bs, 0);                            /* pic_init_qs_minus26 */
+    bitstream_put_se(bs, 0);                            /* chroma_qp_index_offset */
+
+    bitstream_put_ui(bs, pic_param->pic_fields.bits.deblocking_filter_control_present_flag, 1); /* deblocking_filter_control_present_flag */
+    bitstream_put_ui(bs, 0, 1);                         /* constrained_intra_pred_flag */
+    bitstream_put_ui(bs, 0, 1);                         /* redundant_pic_cnt_present_flag */
+
+    /* more_rbsp_data */
+    bitstream_put_ui(bs, pic_param->pic_fields.bits.transform_8x8_mode_flag, 1);    /*transform_8x8_mode_flag */
+    bitstream_put_ui(bs, 0, 1);                         /* pic_scaling_matrix_present_flag */
+    bitstream_put_se(bs, pic_param->second_chroma_qp_index_offset );    /*second_chroma_qp_index_offset */
+
+    rbsp_trailing_bits(bs);
+}
+
+int build_packed_seq_buffer(unsigned char **header_buffer, VAProfile profile, VAEncSequenceParameterBufferH264 *seq_param)
+{
+    bitstream bs;
+
+    bitstream_start(&bs);
+    nal_start_code_prefix(&bs);
+    nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
+    sps_rbsp(&bs, profile, seq_param->bits_per_second, seq_param);
+    bitstream_end(&bs);
+
+    *header_buffer = (unsigned char *)bs.buffer;
+    return bs.bit_offset;
+}
+
+int build_packed_pic_buffer(unsigned char **header_buffer, VAEncPictureParameterBufferH264 *pic_param)
+{
+    bitstream bs;
+
+    bitstream_start(&bs);
+    nal_start_code_prefix(&bs);
+    nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
+    pps_rbsp(&bs, pic_param);
+    bitstream_end(&bs);
+
+    *header_buffer = (unsigned char *)bs.buffer;
+    return bs.bit_offset;
+}
+
+int build_packed_sei_buffer_timing(unsigned int init_cpb_removal_delay,
+				unsigned int init_cpb_removal_delay_offset,
+				unsigned int cpb_removal_length,
+				unsigned int cpb_removal_delay,
+				unsigned int dpb_output_length,
+				unsigned int dpb_output_delay,
+				unsigned char **sei_buffer)
+{
+    unsigned char *byte_buf;
+    int bp_byte_size, i, pic_byte_size;
+
+    bitstream nal_bs;
+    bitstream sei_bp_bs, sei_pic_bs;
+
+    bitstream_start(&sei_bp_bs);
+    bitstream_put_ue(&sei_bp_bs, 0);       /*seq_parameter_set_id*/
+    bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay, cpb_removal_length);
+    bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay_offset, cpb_removal_length);
+    if ( sei_bp_bs.bit_offset & 0x7) {
+        bitstream_put_ui(&sei_bp_bs, 1, 1);
+    }
+    bitstream_end(&sei_bp_bs);
+    bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8;
+
+    bitstream_start(&sei_pic_bs);
+    bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
+    bitstream_put_ui(&sei_pic_bs, dpb_output_delay, dpb_output_length);
+    if ( sei_pic_bs.bit_offset & 0x7) {
+        bitstream_put_ui(&sei_pic_bs, 1, 1);
+    }
+    bitstream_end(&sei_pic_bs);
+    pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
+
+    bitstream_start(&nal_bs);
+    nal_start_code_prefix(&nal_bs);
+    nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
+
+    /* Write the SEI buffer period data */
+    bitstream_put_ui(&nal_bs, 0, 8);
+    bitstream_put_ui(&nal_bs, bp_byte_size, 8);
+
+    byte_buf = (unsigned char *)sei_bp_bs.buffer;
+    for(i = 0; i < bp_byte_size; i++) {
+        bitstream_put_ui(&nal_bs, byte_buf[i], 8);
+    }
+    free(byte_buf);
+	/* write the SEI timing data */
+    bitstream_put_ui(&nal_bs, 0x01, 8);
+    bitstream_put_ui(&nal_bs, pic_byte_size, 8);
+
+    byte_buf = (unsigned char *)sei_pic_bs.buffer;
+    for(i = 0; i < pic_byte_size; i++) {
+        bitstream_put_ui(&nal_bs, byte_buf[i], 8);
+    }
+    free(byte_buf);
+
+    rbsp_trailing_bits(&nal_bs);
+    bitstream_end(&nal_bs);
+
+    *sei_buffer = (unsigned char *)nal_bs.buffer;
+
+    return nal_bs.bit_offset;
+}
+
+#endif