New Implementation for SurfaceMap

BZ: 151334

Refine code and Support new features:
a) Support copy for stride not 64 aligned gfx buffers, like 736x480
b) Refine code to support features in center, like 64 alignment, vp8 uncached memory, no buffer share on BYT.
   Separate codec modules use flag to make the extra features in itself.
c) Support more color formats for input gfx buffers, it means libmix will do color converting internally.

Change-Id: I7af44bc9d31b1a433768e28573c71ea7da722db9
Signed-off-by: Zhao Liang <leo.zhao@intel.com>
diff --git a/test/mix_encoder2.cpp b/test/mix_encoder2.cpp
index 0fa9096..f17311f 100755
--- a/test/mix_encoder2.cpp
+++ b/test/mix_encoder2.cpp
@@ -183,7 +183,7 @@
         gNumFramesOutput = 0;
         createResource ();
 
-#if 1
+#if 0
         {
             int size= mStride * mHeight * 1.5;
             void* tmp = malloc(size);
@@ -211,7 +211,14 @@
             //upload src data
             LOG("Fill src pictures width=%d, Height=%d\n", mStride, mHeight);
             for(int i=0; i<PRELOAD_FRAME_NUM; i++) {
-                YUV_generator_planar(mStride, mHeight, mUsrptr[i], mStride, mUsrptr[i] + mStride*mHeight, mStride, 0, 0, 1);
+                preSourceWriting(i);
+                if (mColorFormat == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    int color = 0xFF0000FF;
+                    for(int j=0; j<mStride*mHeight; j++)
+                        memcpy(mUsrptr[i]+ j*4, &color, 4);
+                }else
+                    YUV_generator_planar(mStride, mHeight, mUsrptr[i], mStride, mUsrptr[i] + mStride*mHeight, mStride, 0, 0, 1);
+                postSourceWriting(i);
             }
             LOG("Fill src pictures end\n");
         }else{
@@ -239,13 +246,23 @@
             return err;
         }
 
+        preSourceWriting(gNumFramesOutput % PRELOAD_FRAME_NUM);
+
         if (mYuvhandle) {
             //load from yuv file
-            size_t readsize = mStride*mHeight*3/2;
+            size_t readsize = 0;
+            if (mColorFormat == HAL_PIXEL_FORMAT_RGBA_8888)
+                readsize = mStride * mHeight * 4;
+            else
+                readsize = mStride * mHeight * 3 / 2;
+
             size_t ret = 0;
 
             while (readsize > 0) {
-                ret = fread(mUsrptr[gNumFramesOutput % PRELOAD_FRAME_NUM] + mStride*mHeight*3/2 - readsize,  1, readsize, mYuvhandle);
+                if (mColorFormat == HAL_PIXEL_FORMAT_RGBA_8888)
+                    ret = fread(mUsrptr[gNumFramesOutput % PRELOAD_FRAME_NUM] + mStride*mHeight*4 - readsize,  1, readsize, mYuvhandle);
+                else
+                    ret = fread(mUsrptr[gNumFramesOutput % PRELOAD_FRAME_NUM] + mStride*mHeight*3/2 - readsize,  1, readsize, mYuvhandle);
 
                 if (ret <= 0) {
                     (*buffer)->release();
@@ -283,6 +300,8 @@
         (*buffer)->meta_data()->setInt64(
                 kKeyTime, (gNumFramesOutput * 1000000) / mFrameRate);
 
+        postSourceWriting(gNumFramesOutput % PRELOAD_FRAME_NUM);
+
         ++gNumFramesOutput;
         if (gNumFramesOutput % 10 ==0)
             fprintf(stderr, ".");
@@ -293,6 +312,8 @@
         return OK;
     }
 
+    virtual void preSourceWriting(int i) {}
+    virtual void postSourceWriting(int i) {}
 protected:
     virtual ~DummySource() {
         for(int i = 0; i < PRELOAD_FRAME_NUM; i ++)
@@ -642,11 +663,6 @@
             }
             mGraphicBuffer[i] = graphicBuffer;
 
-            void* vaddr[3];
-            if (graphicBuffer->lock(usage, &vaddr[0]) != OK)
-                return UNKNOWN_ERROR;
-
-            mUsrptr[i] = (uint8_t*)vaddr[0];
             mIMB[i] = new IntelMetadataBuffer();
             mIMB[i]->SetType(MetadataBufferTypeCameraSource);
 #ifdef INTEL_VIDEO_XPROC_SHARING
@@ -656,10 +672,7 @@
             mIMB[i]->SetValue((int32_t)mGraphicBuffer[i]->handle);
 #endif
             mIMB[i]->SetValueInfo(&vinfo);
-            graphicBuffer->unlock();
 
-            mUsrptr[i] = (uint8_t*)vaddr[0];
-			
             IMG_native_handle_t* h = (IMG_native_handle_t*) mGraphicBuffer[i]->handle;
             mStride = h->iWidth;
             mHeight = h->iHeight;
@@ -670,6 +683,17 @@
         return OK;
     }
 
+    void preSourceWriting(int i) {
+        uint32_t usage = GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_OFTEN;// | GraphicBuffer::USAGE_HW_COMPOSER;
+        void* vaddr[3];
+        if (mGraphicBuffer[i]->lock(usage, &vaddr[0]) != OK)
+            printf("GfxSource lock failed\n");
+        mUsrptr[i] = (uint8_t*)vaddr[0];
+    }
+    void postSourceWriting(int i) {
+        mGraphicBuffer[i]->unlock();
+    }
+
 private:
     //for gfxhandle
     sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
@@ -699,13 +723,9 @@
         {
             if (gfx_alloc(mWidth, mHeight, mColorFormat, usage, &mHandle[i], (int32_t*)&mStride) != 0)
                 return UNKNOWN_ERROR;
-            void* vaddr[3];
 
-            if (gfx_lock(mHandle[i], usage, 0, 0, mWidth, mHeight, &vaddr[0]) != 0)
-                return UNKNOWN_ERROR;
             mIMB[i] = new IntelMetadataBuffer(MetadataBufferTypeGrallocSource, (int32_t)mHandle[i]);
-            gfx_unlock(mHandle[i]);
-            mUsrptr[i] = (uint8_t*)vaddr[0];
+
             IMG_native_handle_t* h = (IMG_native_handle_t*) mHandle[i];
             mStride = h->iWidth;
             mHeight = h->iHeight;
@@ -713,6 +733,17 @@
         return OK;
     }
 
+    void preSourceWriting(int i) {
+        int usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_WRITE_OFTEN;
+        void* vaddr[3];
+        if (gfx_lock(mHandle[i], usage, 0, 0, mWidth, mHeight, &vaddr[0]) != 0)
+            printf("GrallocSource lock failed\n");
+        mUsrptr[i] = (uint8_t*)vaddr[0];
+    }
+    void postSourceWriting(int i) {
+        gfx_unlock(mHandle[i]);
+    }
+
 private:
     void gfx_init()
     {
@@ -939,6 +970,9 @@
         success = meta->findInt32('sync', &mSyncMode);
         CHECK(success);
 
+        success = meta->findInt32('rawc', &mRawColor);
+        CHECK(success);
+
 //    const char *RCMODE[] = {"VBR", "CBR", "VCM", "NO_RC", NULL};
         VideoRateControl RC_MODES[] = {RATE_CONTROL_VBR,
         							RATE_CONTROL_CBR,
@@ -1154,6 +1188,10 @@
         mEncoderParams.frameRate.frameRateDenom = 1;
         mEncoderParams.frameRate.frameRateNum = mFPS;
         mEncoderParams.rcMode = mRCMode;
+        if (mRawColor == 2)
+            mEncoderParams.rawFormat = RAW_FORMAT_OPAQUE;
+        else
+            mEncoderParams.rawFormat = RAW_FORMAT_NV12;
 
         if (strcmp(mMixCodec, MPEG4_MIME_TYPE) == 0) {
             mEncoderParams.profile = (VAProfile)VAProfileMPEG4Simple;
@@ -1213,6 +1251,7 @@
     int mIdrInt;
     int mDisableFrameSkip;
     int mSyncMode;
+    int mRawColor;
 
     bool mFirstFrame;
     bool mSrcEOS;
@@ -1459,25 +1498,26 @@
 void usage() {
     printf("2nd generation Mix_encoder\n");
     printf("Usage: mix_encoder2 [options]\n\n");
-    printf(" -a/--initQP <qp>					set initQP, default 0\n");
+    printf(" -a/--initQP <qp>				set initQP, default 0\n");
     printf(" -b/--bitrate <Bitrate>				set bitrate bps, default 10M\n");
     printf(" -c/--codec <Codec>				select codec, like H264(default), MPEG4, H263, VP8\n");
     printf(" -d/--intraPeriod <period>			set IntraPeriod, default 30\n");
     printf(" -e/--encoder	 <encoder>			select encoder, like MIX(default), OMXCODEC\n");
     printf(" -f <output file>				set output file name\n");
     printf(" -i/--yuv <yuvfile>				select yuv generate method, AUTO(default) or from yuv file\n");
-    printf(" -j/--winSize						set window size, default 1000\n");
+    printf(" -j/--winSize					set window size, default 1000\n");
     printf(" -k/--encWidth <Width> -g/--encHeight <Hight>	set encoder width/height, default 1280*720\n");
-    printf(" -l/--idrInterval					set IdrInterval, default 1\n");
+    printf(" -l/--idrInterval				set IdrInterval, default 1\n");
     printf(" -m/--disableMetadata				disable Metadata Mode(default enabled)\n");
     printf(" -n/--count <number>				set source frame number, default 30\n");
     printf(" -o/--outputformat <format>			set output file format, like MP4(default), RAW, IVF(only for VP8)\n");
     printf(" -p/--fps <Bitrate>				set frame rate, default 30\n");
-    printf(" -q/--minQP <qp>					set minQP, default 0\n");
+    printf(" -q/--minQP <qp>				set minQP, default 0\n");
     printf(" -r/--rcMode <Mode>				set rc mode, like VBR(default), CBR, VCM, NO_RC\n");
     printf(" -s/--src <source>				select source, like MALLOC(default), VASURFACE, KBUFHANDLE, GFX, GRALLOC, MEMHEAP, SURFACEMEDIASOURCE (CAMERASOURCE, not support yet) \n");
-    printf(" -t/--sessionFlag	<sessionflag>	            set sessionflag, default is 0\n");
+    printf(" -t/--sessionFlag	<sessionflag>	       	set sessionflag, default is 0\n");
     printf(" -u/--disableFrameSkip				disable frame skip, default is false\n");
+    printf(" -v/--gfxColor					set gfx color, default is 0(HAL_PIXEL_FORMAT_NV12), 1(OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar), 2(HAL_PIXEL_FORMAT_RGBA_8888)\n");
     printf(" -w <Width> -h <Height>				set source width /height, default 1280*720\n");
 
     printf("\n");
@@ -1506,6 +1546,7 @@
     int IdrInt = 1;
     int IntraPeriod = 30;
     int DisableFrameSkip = 0;
+    int GfxColor = 0;
     int OutFormat = 0;
     int SyncMode = 0;
     char* OutFileName = "out.264";
@@ -1539,6 +1580,7 @@
 						{"idrInt", required_argument, NULL, 'l'},
 						{"disableFrameSkip", no_argument, NULL, 'u'},
 						{"sessionFlag", required_argument, NULL, 't'},
+						{"gfxColor", required_argument, NULL, 'v'},
 						{0, 0, 0, 0}
     };
 
@@ -1676,6 +1718,10 @@
                     DisableFrameSkip = 1;
                     break;
 
+                case 'v':
+                    GfxColor = atoi(optarg);
+                    break;
+
                 case 'w':
                     SrcWidth = atoi(optarg);
                     SrcStride = SrcWidth;
@@ -1689,6 +1735,10 @@
         }
     }
 
+    //RGB is only valid in gfx/gralloc source mode
+    if ( GfxColor > 2 && (SrcType != 3 || SrcType != 4) )
+        GfxColor = 0;
+
     //export encoding parameters summary
     printf("=========================================\n");
     printf("Source:\n");
@@ -1699,7 +1749,7 @@
     printf("Type: %s, Codec: %s, Width: %d, Height: %d\n", ENCTYPE[EncType], CODEC[EncCodec], EncWidth, EncHeight);
     printf("RC: %s, Bitrate: %d bps, initQP: %d, minQP: %d\n", RCMODE[EncRCMode], EncBitrate, InitQP, MinQP);
     printf("winSize: %d, IdrInterval: %d, IntraPeriod: %d, FPS: %d \n", WinSize, IdrInt, IntraPeriod, SrcFps);
-    printf("Frameskip: %d\n", !DisableFrameSkip);
+    printf("Frameskip: %d, GfxColor: %s\n", !DisableFrameSkip, GfxColor > 0 ? (GfxColor > 1? "HAL_PIXEL_FORMAT_RGBA_8888":"OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar"):"HAL_PIXEL_FORMAT_NV12");
 
     printf("\nOut:\n");
     printf("Type: %s, File: %s\n", OUTFORMAT[OutFormat], OutFileName);
@@ -1715,7 +1765,12 @@
     src_meta->setInt32(kKeyHeight, SrcHeight);
     src_meta->setInt32(kKeyStride, SrcStride);
     src_meta->setInt32(kKeyFrameRate, SrcFps);
-    src_meta->setInt32(kKeyColorFormat, OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar); //HAL_PIXEL_FORMAT_NV12     OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar =  0x7FA00E00,
+    if (GfxColor == 1)
+        src_meta->setInt32(kKeyColorFormat, 0x7FA00E00); //OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
+    else if (GfxColor == 2)
+        src_meta->setInt32(kKeyColorFormat, HAL_PIXEL_FORMAT_RGBA_8888);
+    else
+        src_meta->setInt32(kKeyColorFormat, HAL_PIXEL_FORMAT_NV12);
 
     src_meta->setCString('yuvf', Yuvfile);
     src_meta->setInt32('fnum', SrcFrameNum);
@@ -1777,9 +1832,10 @@
     enc_meta->setInt32('mnqp', MinQP);
     enc_meta->setInt32('iapd', IntraPeriod);
     enc_meta->setInt32('wsiz', WinSize);
-    enc_meta->setInt32('idri', WinSize);
+    enc_meta->setInt32('idri', IdrInt);
     enc_meta->setInt32('difs', DisableFrameSkip);
     enc_meta->setInt32('sync', SyncMode);
+    enc_meta->setInt32('rawc', GfxColor);
 
     uint32_t encoder_flags = 0;
     if (MetadataMode)
diff --git a/videoencoder/Android.mk b/videoencoder/Android.mk
index 3ec61de..480b5a1 100644
--- a/videoencoder/Android.mk
+++ b/videoencoder/Android.mk
@@ -17,6 +17,7 @@
     VideoEncoderH263.cpp        \
     VideoEncoderMP4.cpp         \
     VideoEncoderVP8.cpp         \
+    VideoEncoderUtils.cpp       \
     VideoEncoderHost.cpp
 
 ifeq ($(ENABLE_IMG_GRAPHICS),)
@@ -51,6 +52,7 @@
         libva-tpi		\
         libui \
         libutils \
+        libhardware \
 	libintelmetadatabuffer
 
 #LOCAL_CFLAGS += -DANDROID
@@ -76,6 +78,10 @@
 
 ifeq ($(ENABLE_IMG_GRAPHICS),true)
     LOCAL_CFLAGS += -DIMG_GFX
+
+    ifeq ($(ENABLE_MRFL_GRAPHICS),true)
+        LOCAL_CFLAGS += -DMRFLD_GFX
+    endif
 endif
 
 LOCAL_MODULE_TAGS := optional
diff --git a/videoencoder/PVSoftMPEG4Encoder.cpp b/videoencoder/PVSoftMPEG4Encoder.cpp
index 11ef971..47ddb12 100644
--- a/videoencoder/PVSoftMPEG4Encoder.cpp
+++ b/videoencoder/PVSoftMPEG4Encoder.cpp
@@ -132,6 +132,9 @@
     }
 
     setDefaultParams();
+#if NO_BUFFER_SHARE
+    mVASurfaceMappingAction |= MAPACT_COPY;
+#endif
 
     LOG_I("Construct PVSoftMPEG4Encoder");
 
diff --git a/videoencoder/VideoEncoderBase.cpp b/videoencoder/VideoEncoderBase.cpp
index 8e90e9f..f2ae139 100644
--- a/videoencoder/VideoEncoderBase.cpp
+++ b/videoencoder/VideoEncoderBase.cpp
@@ -11,30 +11,7 @@
 #include "IntelMetadataBuffer.h"
 #include <va/va_tpi.h>
 #include <va/va_android.h>
-#include <va/va_drmcommon.h>
-#ifdef IMG_GFX
-#include <hal/hal_public.h>
-#endif
 
-// API declaration
-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
-);
-}
 VideoEncoderBase::VideoEncoderBase()
     :mInitialized(true)
     ,mStarted(false)
@@ -69,6 +46,7 @@
     ,mTotalSizeCopied(0)
     ,mFrameSkipped(false)
     ,mSupportedSurfaceMemType(0)
+    ,mVASurfaceMappingAction(0)
 #ifdef INTEL_VIDEO_XPROC_SHARING
     ,mSessionFlag(0)
 #endif
@@ -131,6 +109,13 @@
         return ENCODE_ALREADY_INIT;
     }
 
+    if (mComParams.rawFormat != RAW_FORMAT_NV12)
+#ifdef IMG_GFX
+        mVASurfaceMappingAction |= MAP_ACTION_COLORCONVERT;
+#else
+        return ENCODE_NOT_SUPPORTED;
+#endif
+
     queryAutoReferenceConfig(mComParams.profile);
 
     VAConfigAttrib vaAttrib[5];
@@ -182,38 +167,32 @@
 
     uint32_t stride_aligned, height_aligned;
     if(mAutoReference == false){
-        stride_aligned = ((mComParams.resolution.width + 15) / 16 ) * 16;
-        height_aligned = ((mComParams.resolution.height + 15) / 16 ) * 16;
+        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;
-           }
-           else
-           {
-                stride_aligned = ((mComParams.resolution.width + 63) / 64 ) * 64;  //on Merr, stride must be 64 aligned.
-                height_aligned = ((mComParams.resolution.height + 31) / 32 ) * 32;
-           }
+        // 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;
+        }
     }
 
-    ValueInfo vinfo;
-    vinfo.mode = MEM_MODE_SURFACE;
-    vinfo.width = stride_aligned;
-    vinfo.height = height_aligned;
-    vinfo.lumaStride = stride_aligned;
-    vinfo.size = stride_aligned * height_aligned * 1.5;
-    vinfo.format = VA_FOURCC_NV12;
-
     if(mAutoReference == false){
-        mRefSurface = CreateSurfaceFromExternalBuf(0, vinfo);
-        mRecSurface = CreateSurfaceFromExternalBuf(0, vinfo);
+        mRefSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
+        mRecSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
 
     }else {
         mAutoRefSurfaces = new VASurfaceID [mAutoReferenceSurfaceNum];
         for(int i = 0; i < mAutoReferenceSurfaceNum; i ++)
-                mAutoRefSurfaces[i] = CreateSurfaceFromExternalBuf(0, vinfo);
+            mAutoRefSurfaces[i] = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
     }
     CHECK_VA_STATUS_RETURN("vaCreateSurfaces");
 
@@ -226,12 +205,12 @@
 
     VASurfaceID *contextSurfaces = new VASurfaceID[contextSurfaceCnt];
     int32_t index = -1;
-    android::List<SurfaceMap *>::iterator map_node;
+    android::List<VASurfaceMap *>::iterator map_node;
 
     for(map_node = mSrcSurfaceMapList.begin(); map_node !=  mSrcSurfaceMapList.end(); map_node++)
     {
-        contextSurfaces[++index] = (*map_node)->surface;
-        (*map_node)->added = true;
+        contextSurfaces[++index] = (*map_node)->getVASurface();
+        (*map_node)->setTracked();
     }
 
     if(mAutoReference == false){
@@ -604,12 +583,6 @@
     LOG_V( "Rlease Src Surface Map\n");
     while(! mSrcSurfaceMapList.empty())
     {
-        if (! (*mSrcSurfaceMapList.begin())->added) {
-            LOG_V( "Rlease the Src Surface Buffer not added into vaContext\n");
-            vaDestroySurfaces(mVADisplay, &((*mSrcSurfaceMapList.begin())->surface), 1);
-            if ((*mSrcSurfaceMapList.begin())->surface_backup != VA_INVALID_SURFACE)
-                vaDestroySurfaces(mVADisplay, &((*mSrcSurfaceMapList.begin())->surface_backup), 1);
-        }
         delete (*mSrcSurfaceMapList.begin());
         mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
     }
@@ -1393,8 +1366,6 @@
     VAImage image;
     uint32_t index = 0;
 
-    SurfaceMap *map = NULL;
-
     LOG_V( "Begin\n");
     // If encode session has been configured, we can not request surface creation anymore
     if (mStarted) {
@@ -1413,15 +1384,7 @@
         return ENCODE_NOT_SUPPORTED;
     }
 
-    ValueInfo vinfo;
-    vinfo.mode = MEM_MODE_SURFACE;
-    vinfo.width = width;
-    vinfo.height = height;
-    vinfo.lumaStride = width;
-    vinfo.size = expectedSize;
-    vinfo.format = format;
-
-    surface = CreateSurfaceFromExternalBuf(0, vinfo);
+    surface = CreateNewVASurface(mVADisplay, width, height);
     if (surface == VA_INVALID_SURFACE)
         return ENCODE_DRIVER_FAIL;
 
@@ -1441,29 +1404,6 @@
     *outsize = image.data_size;
     *stride = image.pitches[0];
 
-    map = new SurfaceMap;
-    if (map == NULL) {
-        LOG_E( "new SurfaceMap failed\n");
-        return ENCODE_NO_MEMORY;
-    }
-
-    map->surface = surface;
-    map->surface_backup = VA_INVALID_SURFACE;
-    map->type = MetadataBufferTypeEncoder;
-    map->value = (int32_t)*usrptr;
-    map->vinfo.mode = (MemMode)MEM_MODE_USRPTR;
-    map->vinfo.handle = 0;
-    map->vinfo.size = 0;
-    map->vinfo.width = width;
-    map->vinfo.height = height;
-    map->vinfo.lumaStride = width;
-    map->vinfo.chromStride = width;
-    map->vinfo.format = VA_FOURCC_NV12;
-    map->vinfo.s3dformat = 0xffffffff;
-    map->added = false;
-
-    mSrcSurfaceMapList.push_back(map);
-
     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]);
@@ -1474,7 +1414,6 @@
     LOG_I("image->height = %d\n", image.height);
     LOG_I ("data_size = %d\n", image.data_size);
     LOG_I ("usrptr = 0x%p\n", *usrptr);
-    LOG_I ("map->value = 0x%p\n ", (void *)map->value);
 
     vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
@@ -1489,12 +1428,36 @@
         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((int32_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;
@@ -1510,24 +1473,25 @@
             continue;
 
         //wrap upstream buffer into vaSurface
-        SurfaceMap *map = new SurfaceMap;
+        VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
 
-        map->surface_backup = VA_INVALID_SURFACE;
-        map->type = MetadataBufferTypeUser;
-        map->value = upStreamBuffer->bufList[i];
-        map->vinfo.mode = (MemMode)upStreamBuffer->bufferMode;
-        map->vinfo.handle = (uint32_t)upStreamBuffer->display;
-        map->vinfo.size = 0;
+//        map->setType(MetadataBufferTypeUser);
+        map->setValue(upStreamBuffer->bufList[i]);
+        ValueInfo vinfo;
+        memset(&vinfo, 0, sizeof(ValueInfo));
+        vinfo.mode = (MemMode)upStreamBuffer->bufferMode;
+        vinfo.handle = (uint32_t)upStreamBuffer->display;
+        vinfo.size = 0;
         if (upStreamBuffer->bufAttrib) {
-            map->vinfo.width = upStreamBuffer->bufAttrib->realWidth;
-            map->vinfo.height = upStreamBuffer->bufAttrib->realHeight;
-            map->vinfo.lumaStride = upStreamBuffer->bufAttrib->lumaStride;
-            map->vinfo.chromStride = upStreamBuffer->bufAttrib->chromStride;
-            map->vinfo.format = upStreamBuffer->bufAttrib->format;
+            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;
         }
-        map->vinfo.s3dformat = 0xFFFFFFFF;
-        map->added = false;
-        status = surfaceMapping(map);
+        vinfo.s3dformat = 0xFFFFFFFF;
+        map->setValueInfo(vinfo);
+        status = map->doMapping();
 
         if (status == ENCODE_SUCCESS)
             mSrcSurfaceMapList.push_back(map);
@@ -1538,248 +1502,6 @@
     return status;
 }
 
-Encode_Status VideoEncoderBase::surfaceMappingForSurface(SurfaceMap *map) {
-
-    if (!map)
-        return ENCODE_NULL_PTR;
-
-    VAStatus vaStatus = VA_STATUS_SUCCESS;
-    Encode_Status ret = ENCODE_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)map->vinfo.handle, (VASurfaceID)map->value,
-            &fourCC, &lumaStride, &chromaUStride, &chromaVStride,
-            &lumaOffset, &chromaUOffset, &chromaVOffset, &kBufHandle, NULL);
-
-    CHECK_VA_STATUS_RETURN("vaLockSurface");
-    LOG_I("Surface incoming = 0x%08x", map->value);
-    LOG_I("lumaStride = %d", lumaStride);
-    LOG_I("chromaUStride = %d", chromaUStride);
-    LOG_I("chromaVStride = %d", chromaVStride);
-    LOG_I("lumaOffset = %d", lumaOffset);
-    LOG_I("chromaUOffset = %d", chromaUOffset);
-    LOG_I("chromaVOffset = %d", chromaVOffset);
-    LOG_I("kBufHandle = 0x%08x", kBufHandle);
-    LOG_I("fourCC = %d", fourCC);
-
-    vaStatus = vaUnlockSurface((VADisplay)map->vinfo.handle, (VASurfaceID)map->value);
-    CHECK_VA_STATUS_RETURN("vaUnlockSurface");
-
-    ValueInfo vinfo;
-    memcpy(&vinfo, &(map->vinfo), sizeof(ValueInfo));
-    vinfo.mode = MEM_MODE_KBUFHANDLE;
-
-    surface = CreateSurfaceFromExternalBuf(kBufHandle, vinfo);
-    if (surface == VA_INVALID_SURFACE)
-        return ENCODE_DRIVER_FAIL;
-
-    LOG_I("Surface ID created from Kbuf = 0x%08x", surface);
-
-    map->surface = surface;
-
-    return ret;
-}
-
-Encode_Status VideoEncoderBase::surfaceMappingForGfxHandle(SurfaceMap *map) {
-
-    if (!map)
-        return ENCODE_NULL_PTR;
-
-    VAStatus vaStatus = VA_STATUS_SUCCESS;
-    Encode_Status ret = ENCODE_SUCCESS;
-    VASurfaceID surface;
-
-    LOG_I("surfaceMappingForGfxHandle ......\n");
-    LOG_I("lumaStride = %d\n", map->vinfo.lumaStride);
-    LOG_I("format = 0x%08x\n", map->vinfo.format);
-    LOG_I("width = %d\n", mComParams.resolution.width);
-    LOG_I("height = %d\n", mComParams.resolution.height);
-    LOG_I("gfxhandle = %d\n", map->value);
-
-    ValueInfo vinfo;
-    memcpy(&vinfo, &(map->vinfo), sizeof(ValueInfo));
-
-#ifdef IMG_GFX
-    // color fmrat may be OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar or HAL_PIXEL_FORMAT_NV12
-    IMG_native_handle_t* h = (IMG_native_handle_t*) map->value;
-    LOG_I("IMG_native_handle_t h->iWidth=%d, h->iHeight=%d, h->iFormat=%x\n", h->iWidth, h->iHeight, h->iFormat);
-    vinfo.lumaStride = h->iWidth;
-    vinfo.format = h->iFormat;
-    vinfo.width = h->iWidth;
-    vinfo.height = h->iHeight;
-#endif
-
-    surface = CreateSurfaceFromExternalBuf(map->value, vinfo);
-    if (surface == VA_INVALID_SURFACE)
-        return ENCODE_DRIVER_FAIL;
-
-    map->surface = surface;
-
-    LOG_V("surfaceMappingForGfxHandle: Done");
-    return ret;
-}
-
-Encode_Status VideoEncoderBase::surfaceMappingForKbufHandle(SurfaceMap *map) {
-
-    if (!map)
-        return ENCODE_NULL_PTR;
-
-    LOG_I("surfaceMappingForKbufHandle value=%d\n", map->value);
-    VAStatus vaStatus = VA_STATUS_SUCCESS;
-    Encode_Status ret = ENCODE_SUCCESS;
-    VASurfaceID surface;
-
-    map->vinfo.size = map->vinfo.lumaStride * map->vinfo.height * 1.5;
-    surface = CreateSurfaceFromExternalBuf(map->value, map->vinfo);
-    if (surface == VA_INVALID_SURFACE)
-        return ENCODE_DRIVER_FAIL;
-    LOG_I("Surface ID created from Kbuf = 0x%08x", map->value);
-
-    map->surface = surface;
-
-    return ret;
-}
-
-#if NO_BUFFER_SHARE
-static VAStatus upload_yuv_to_surface(VADisplay va_dpy,
-        SurfaceMap *map, VASurfaceID surface_id, int picture_width,
-        int picture_height)
-{
-    VAImage surface_image;
-    VAStatus vaStatus;
-    unsigned char *surface_p = NULL;
-    unsigned char *y_src, *uv_src;
-    unsigned char *y_dst, *uv_dst;
-    int y_size = map->vinfo.height * map->vinfo.lumaStride;
-    int row, col;
-
-    vaStatus = vaDeriveImage(va_dpy, surface_id, &surface_image);
-    CHECK_VA_STATUS_RETURN("vaDeriveImage");
-
-    vaStatus = vaMapBuffer(va_dpy, surface_image.buf, (void**)&surface_p);
-    CHECK_VA_STATUS_RETURN("vaMapBuffer");
-
-    y_src = (unsigned char*)map->value;
-    uv_src = (unsigned char*)map->value + y_size; /* UV offset for NV12 */
-
-    y_dst = surface_p + surface_image.offsets[0];
-    uv_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
-
-    /* Y plane */
-    for (row = 0; row < picture_height; row++) {
-        memcpy(y_dst, y_src, picture_width);
-        y_dst += surface_image.pitches[0];
-        y_src += map->vinfo.lumaStride;
-    }
-
-    for (row = 0; row < (picture_height / 2); row++) {
-        memcpy(uv_dst, uv_src, picture_width);
-        uv_dst += surface_image.pitches[1];
-        uv_src += map->vinfo.chromStride;
-    }
-
-    vaUnmapBuffer(va_dpy, surface_image.buf);
-    vaDestroyImage(va_dpy, surface_image.image_id);
-
-    return vaStatus;
-}
-#endif
-
-Encode_Status VideoEncoderBase::surfaceMappingForMalloc(SurfaceMap *map) {
-
-    if (!map)
-        return ENCODE_NULL_PTR;
-
-    VAStatus vaStatus = VA_STATUS_SUCCESS;
-    Encode_Status ret = ENCODE_SUCCESS;
-    VASurfaceID surface;
-#if NO_BUFFER_SHARE
-    vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420,
-            map->vinfo.width, map->vinfo.height, &surface, 1,
-            NULL, 0);
-    CHECK_VA_STATUS_RETURN("vaCreateSurfaces");
-    map->surface = surface;
-
-    vaStatus = upload_yuv_to_surface(mVADisplay, map, surface,
-            mComParams.resolution.width, mComParams.resolution.height);
-    CHECK_ENCODE_STATUS_RETURN("upload_yuv_to_surface");
-
-#else
-    surface = CreateSurfaceFromExternalBuf(map->value, map->vinfo);
-    if (surface == VA_INVALID_SURFACE)
-        return ENCODE_DRIVER_FAIL;
-
-    LOG_I("Surface ID created from Malloc = 0x%08x\n", map->value);
-
-    //Merrifield limitation, should use mAutoReference to check if on Merr
-    if ((mAutoReference == false) || (map->vinfo.lumaStride % 64 == 0))
-        map->surface = surface;
-    else {
-        map->surface_backup = surface;
-
-        //TODO: need optimization for both width/height not aligned case
-        VASurfaceID surfaceId;
-        unsigned int stride_aligned;
-        if(mComParams.profile == VAProfileVP8Version0_3)
-            stride_aligned = mComParams.resolution.width;
-        else
-            stride_aligned = ((mComParams.resolution.width + 63) / 64 ) * 64;
-        vaStatus = vaCreateSurfaces(mVADisplay, VA_RT_FORMAT_YUV420,
-                    stride_aligned, map->vinfo.height, &surfaceId, 1, NULL, 0);
-
-        map->surface = surfaceId;
-        LOG_E("Due to 64 alignment, an alternative Surface ID 0x%08x created\n", surfaceId);
-    }
-#endif
-
-    return ret;
-}
-
-Encode_Status VideoEncoderBase::surfaceMapping(SurfaceMap *map) {
-
-    if (!map)
-        return ENCODE_NULL_PTR;
-
-    Encode_Status status;
-
-    LOG_I("surfaceMapping mode=%d, format=%d, lumaStride=%d, width=%d, height=%d, value=%x\n", map->vinfo.mode, map->vinfo.format, map->vinfo.lumaStride, map->vinfo.width, map->vinfo.height, map->value);
-    switch (map->vinfo.mode) {
-        case MEM_MODE_SURFACE:
-            status = surfaceMappingForSurface(map);
-            break;
-        case MEM_MODE_GFXHANDLE:
-            status = surfaceMappingForGfxHandle(map);
-            break;
-        case MEM_MODE_KBUFHANDLE:
-            status = surfaceMappingForKbufHandle(map);
-            break;
-        case MEM_MODE_MALLOC:
-        case MEM_MODE_NONECACHE_USRPTR:
-            status = surfaceMappingForMalloc(map);
-            break;
-        case MEM_MODE_ION:
-        case MEM_MODE_V4L2:
-        case MEM_MODE_USRPTR:
-        case MEM_MODE_CI:
-        default:
-            status = ENCODE_NOT_SUPPORTED;
-            break;
-    }
-
-    return status;
-}
-
 Encode_Status VideoEncoderBase::manageSrcSurface(VideoEncRawBuffer *inBuffer, VASurfaceID *sid) {
 
     Encode_Status ret = ENCODE_SUCCESS;
@@ -1791,7 +1513,7 @@
     unsigned int extravalues_count = 0;
 
     IntelMetadataBuffer imb;
-    SurfaceMap *map = NULL;
+    VASurfaceMap *map = NULL;
 
     if (mStoreMetaDataInBuffers.isEnabled) {
         //metadatabuffer mode
@@ -1819,17 +1541,13 @@
 #endif
 
     //find if mapped
-    map = (SurfaceMap*) findSurfaceMapByValue(value);
+    map = (VASurfaceMap*) findSurfaceMapByValue(value);
 
     if (map) {
-        //has mapped, get surfaceID directly
-        LOG_I("direct find surface %d from value %x\n", map->surface, value);
-        *sid = map->surface;
-        if (map->surface_backup != VA_INVALID_SURFACE) {
-            //need to copy data
-            LOG_I("Need copy surfaces from %x to %x\n", map->surface_backup, *sid);
-            ret = copySurfaces(map->surface_backup, *sid);
-        }
+        //has mapped, get surfaceID directly and do all necessary actions
+        LOG_I("direct find surface %d from value %x\n", map->getVASurface(), value);
+        *sid = map->getVASurface();
+        map->doMapping();
         return ret;
     }
 
@@ -1838,7 +1556,7 @@
 
     if (mStoreMetaDataInBuffers.isEnabled) {
 
-        //if type is MetadataBufferTypeGrallocSource, use default parameters
+        //if type is MetadataBufferTypeGrallocSource, use default parameters since no ValueInfo
         if (type == MetadataBufferTypeGrallocSource) {
             vinfo.mode = MEM_MODE_GFXHANDLE;
             vinfo.handle = 0;
@@ -1853,7 +1571,7 @@
             //get all info mapping needs
             imb.GetValueInfo(pvinfo);
             imb.GetExtraValues(extravalues, extravalues_count);
-  	}
+        }
 
     } else {
 
@@ -1874,16 +1592,14 @@
      */
     if (pvinfo){
         //map according info, and add to surfacemap list
-        map = new SurfaceMap;
-        map->surface_backup = VA_INVALID_SURFACE;
-        map->type = type;
-        map->value = value;
-        memcpy(&(map->vinfo), pvinfo, sizeof(ValueInfo));
-        map->added = false;
+        map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
+        map->setValue(value);
+        map->setValueInfo(*pvinfo);
+        map->setAction(mVASurfaceMappingAction);
 
-        ret = surfaceMapping(map);
+        ret = map->doMapping();
         if (ret == ENCODE_SUCCESS) {
-            LOG_I("surface mapping success, map value %x into surface %d\n", value, map->surface);
+            LOG_I("surface mapping success, map value %x into surface %d\n", value, map->getVASurface());
             mSrcSurfaceMapList.push_back(map);
         } else {
             delete map;
@@ -1891,32 +1607,24 @@
             return ret;
         }
 
-        *sid = map->surface;
-        if (map->surface_backup != VA_INVALID_SURFACE) {
-            //need to copy data
-            LOG_I("Need copy surfaces from %x to %x\n", map->surface_backup, *sid);
-            ret = copySurfaces(map->surface_backup, *sid);
-        }
+        *sid = map->getVASurface();
 
     } else {
         //can't map due to no info
-        LOG_E("surface mapping failed,  missing information\n");
+        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 SurfaceMap;
-            map->surface_backup = VA_INVALID_SURFACE;
-            map->type = type;
-            map->value = extravalues[i];
-            memcpy(&(map->vinfo), pvinfo, sizeof(ValueInfo));
-            map->added = false;
+            map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
+            map->setValue(extravalues[i]);
+            map->setValueInfo(vinfo);
 
-            ret = surfaceMapping(map);
+            ret = map->doMapping();
             if (ret == ENCODE_SUCCESS) {
-                LOG_I("surface mapping extravalue success, map value %x into surface %d\n", extravalues[i], map->surface);
+                LOG_I("surface mapping extravalue success, map value %x into surface %d\n", extravalues[i], map->getVASurface());
                 mSrcSurfaceMapList.push_back(map);
             } else {
                 delete map;
@@ -1973,7 +1681,6 @@
     vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
     CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
 
-
     vaStatus = vaRenderPicture(mVADisplay, mVAContext,
             &miscParamBufferID, 1);
     CHECK_VA_STATUS_RETURN("vaRenderPicture");
@@ -2053,12 +1760,12 @@
     return ENCODE_SUCCESS;
 }
 
-SurfaceMap *VideoEncoderBase::findSurfaceMapByValue(int32_t value) {
-    android::List<SurfaceMap *>::iterator node;
+VASurfaceMap *VideoEncoderBase::findSurfaceMapByValue(int32_t value) {
+    android::List<VASurfaceMap *>::iterator node;
 
     for(node = mSrcSurfaceMapList.begin(); node !=  mSrcSurfaceMapList.end(); node++)
     {
-        if ((*node)->value == value)
+        if ((*node)->getValue() == value)
             return *node;
         else
             continue;
@@ -2066,184 +1773,3 @@
 
     return NULL;
 }
-
-Encode_Status VideoEncoderBase::copySurfaces(VASurfaceID srcId, VASurfaceID destId) {
-
-    VAStatus vaStatus = VA_STATUS_SUCCESS;
-
-    uint32_t width = mComParams.resolution.width;
-    uint32_t height = mComParams.resolution.height;
-
-    uint32_t i, j;
-
-    VAImage srcImage, destImage;
-    uint8_t *pSrcBuffer, *pDestBuffer;
-
-    uint8_t *srcY, *dstY;
-    uint8_t *srcU, *srcV;
-    uint8_t *srcUV, *dstUV;
-
-    LOG_I("src Surface ID = 0x%08x, dest Surface ID = 0x%08x\n", (uint32_t) srcId, (uint32_t) destId);
-
-    vaStatus = vaDeriveImage(mVADisplay, srcId, &srcImage);
-    CHECK_VA_STATUS_RETURN("vaDeriveImage");
-    vaStatus = vaMapBuffer(mVADisplay, srcImage.buf, (void **)&pSrcBuffer);
-    CHECK_VA_STATUS_RETURN("vaMapBuffer");
-
-    LOG_V("Src Image information\n");
-    LOG_I("srcImage.pitches[0] = %d\n", srcImage.pitches[0]);
-    LOG_I("srcImage.pitches[1] = %d\n", srcImage.pitches[1]);
-    LOG_I("srcImage.offsets[0] = %d\n", srcImage.offsets[0]);
-    LOG_I("srcImage.offsets[1] = %d\n", srcImage.offsets[1]);
-    LOG_I("srcImage.num_planes = %d\n", srcImage.num_planes);
-    LOG_I("srcImage.width = %d\n", srcImage.width);
-    LOG_I("srcImage.height = %d\n", srcImage.height);
-
-    vaStatus = vaDeriveImage(mVADisplay, destId, &destImage);
-    CHECK_VA_STATUS_RETURN("vaDeriveImage");
-    vaStatus = vaMapBuffer(mVADisplay, destImage.buf, (void **)&pDestBuffer);
-    CHECK_VA_STATUS_RETURN("vaMapBuffer");
-
-    LOG_V("Dest Image information\n");
-    LOG_I("destImage.pitches[0] = %d\n", destImage.pitches[0]);
-    LOG_I("destImage.pitches[1] = %d\n", destImage.pitches[1]);
-    LOG_I("destImage.offsets[0] = %d\n", destImage.offsets[0]);
-    LOG_I("destImage.offsets[1] = %d\n", destImage.offsets[1]);
-    LOG_I("destImage.num_planes = %d\n", destImage.num_planes);
-    LOG_I("destImage.width = %d\n", destImage.width);
-    LOG_I("destImage.height = %d\n", destImage.height);
-
-    if (mComParams.rawFormat == RAW_FORMAT_YUV420) {
-
-        srcY = pSrcBuffer +srcImage.offsets[0];
-        srcU = pSrcBuffer + srcImage.offsets[1];
-        srcV = pSrcBuffer + srcImage.offsets[2];
-        dstY = pDestBuffer + destImage.offsets[0];
-        dstUV = pDestBuffer + destImage.offsets[1];
-
-        for (i = 0; i < height; i ++) {
-            memcpy(dstY, srcY, width);
-            srcY += srcImage.pitches[0];
-            dstY += destImage.pitches[0];
-        }
-
-        for (i = 0; i < height / 2; i ++) {
-            for (j = 0; j < width; j+=2) {
-                dstUV [j] = srcU [j / 2];
-                dstUV [j + 1] = srcV [j / 2];
-            }
-            srcU += srcImage.pitches[1];
-            srcV += srcImage.pitches[2];
-            dstUV += destImage.pitches[1];
-        }
-    }else if (mComParams.rawFormat == RAW_FORMAT_NV12) {
-
-        srcY = pSrcBuffer + srcImage.offsets[0];
-        dstY = pDestBuffer + destImage.offsets[0];
-        srcUV = pSrcBuffer + srcImage.offsets[1];
-        dstUV = pDestBuffer + destImage.offsets[1];
-
-        for (i = 0; i < height; i++) {
-            memcpy(dstY, srcY, width);
-            srcY += srcImage.pitches[0];
-            dstY += destImage.pitches[0];
-        }
-
-        for (i = 0; i < height / 2; i++) {
-            memcpy(dstUV, srcUV, width);
-            srcUV += srcImage.pitches[1];
-            dstUV += destImage.pitches[1];
-        }
-    } else {
-        LOG_E("Raw format not supoort\n");
-        return ENCODE_FAIL;
-    }
-
-    vaStatus = vaUnmapBuffer(mVADisplay, srcImage.buf);
-    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
-    vaStatus = vaDestroyImage(mVADisplay, srcImage.image_id);
-    CHECK_VA_STATUS_RETURN("vaDestroyImage");
-
-    vaStatus = vaUnmapBuffer(mVADisplay, destImage.buf);
-    CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
-    vaStatus = vaDestroyImage(mVADisplay, destImage.image_id);
-    CHECK_VA_STATUS_RETURN("vaDestroyImage");
-
-    return ENCODE_SUCCESS;
-}
-
-VASurfaceID VideoEncoderBase::CreateSurfaceFromExternalBuf(int32_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;
-            extbuf.pixel_format = vinfo.format;
-            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:
-            type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
-            break;
-        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 == 0)
-        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);
-
-    return surface;
-}
diff --git a/videoencoder/VideoEncoderBase.h b/videoencoder/VideoEncoderBase.h
index 75c3874..ca71f27 100644
--- a/videoencoder/VideoEncoderBase.h
+++ b/videoencoder/VideoEncoderBase.h
@@ -16,15 +16,7 @@
 #include "IntelMetadataBuffer.h"
 #include <utils/List.h>
 #include <utils/threads.h>
-
-struct SurfaceMap {
-    VASurfaceID surface;
-    VASurfaceID surface_backup;
-    MetadataBufferType type;
-    int32_t value;
-    ValueInfo vinfo;
-    bool added;
-};
+#include "VideoEncoderUtils.h"
 
 struct EncodeTask {
     VASurfaceID enc_surface;
@@ -84,12 +76,7 @@
     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);
-    Encode_Status surfaceMappingForSurface(SurfaceMap *map);
-    Encode_Status surfaceMappingForGfxHandle(SurfaceMap *map);
-    Encode_Status surfaceMappingForKbufHandle(SurfaceMap *map);
-    Encode_Status surfaceMappingForMalloc(SurfaceMap *map);
-    Encode_Status surfaceMapping(SurfaceMap *map);
-    SurfaceMap *findSurfaceMapByValue(int32_t value);
+    VASurfaceMap* findSurfaceMapByValue(int32_t value);
     Encode_Status manageSrcSurface(VideoEncRawBuffer *inBuffer, VASurfaceID *sid);
     void PrepareFrameInfo(EncodeTask* task);
 
@@ -131,7 +118,7 @@
     VABufferID mSliceParamBuf;
     VASurfaceID* mAutoRefSurfaces;
 
-    android::List <SurfaceMap *> mSrcSurfaceMapList;  //all mapped surface info list from input buffer
+    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
 
@@ -164,6 +151,9 @@
     //supported surface memory types
     int mSupportedSurfaceMemType;
 
+    //VASurface mapping extra action
+    int mVASurfaceMappingAction;
+
 #ifdef INTEL_VIDEO_XPROC_SHARING
     uint32_t mSessionFlag;
 #endif
diff --git a/videoencoder/VideoEncoderDef.h b/videoencoder/VideoEncoderDef.h
index d91ed23..fa4c2a1 100644
--- a/videoencoder/VideoEncoderDef.h
+++ b/videoencoder/VideoEncoderDef.h
@@ -54,6 +54,8 @@
     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;
diff --git a/videoencoder/VideoEncoderLog.h b/videoencoder/VideoEncoderLog.h
index 8176489..74760fe 100644
--- a/videoencoder/VideoEncoderLog.h
+++ b/videoencoder/VideoEncoderLog.h
@@ -9,10 +9,11 @@
 #ifndef __VIDEO_ENCODER_LOG_H__
 #define __VIDEO_ENCODER_LOG_H__
 
+#define LOG_TAG "VideoEncoder"
+
 // Components
 #include <cutils/log.h>
 
-#define LOG_TAG "VideoEncoder"
 #if 1
 #define LOG_V(...) LOGV_IF(gLogLevel, __VA_ARGS__)
 #define LOG_I(...) LOGI_IF(gLogLevel, __VA_ARGS__)
diff --git a/videoencoder/VideoEncoderUtils.cpp b/videoencoder/VideoEncoderUtils.cpp
new file mode 100644
index 0000000..69d2518
--- /dev/null
+++ b/videoencoder/VideoEncoderUtils.cpp
@@ -0,0 +1,692 @@
+#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 <ui/PixelFormat.h>
+#include <hardware/gralloc.h>
+
+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_I("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_I("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_I("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_I("unlock returned\n");
+
+    return err;
+}
+
+static int gfx_Blit(buffer_handle_t src, buffer_handle_t dest,
+                      int w, int h, int x, int y)
+{
+    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);
+#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_I("Blit returned\n");
+
+    return err;
+}
+#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
+    mGfxHandleAllocated = false;
+#endif
+}
+
+VASurfaceMap::~VASurfaceMap() {
+
+    if (!mTracked && (mVASurface != VA_INVALID_SURFACE))
+        vaDestroySurfaces(mVADisplay, &mVASurface, 1);
+
+#ifdef IMG_GFX
+    if (mGfxHandleAllocated)
+        gfx_free(mGfxHandle);
+#endif
+}
+
+Encode_Status VASurfaceMap::doMapping() {
+
+    Encode_Status ret = ENCODE_SUCCESS;
+
+    if (mVASurface == VA_INVALID_SURFACE) {
+
+        bool AllocSurface = false;
+        mVASurfaceWidth = mVinfo.lumaStride;
+        mVASurfaceHeight = mVinfo.height;
+
+        if (mAction & MAP_ACTION_ALIGN64 && mVASurfaceWidth % 64 != 0) {
+            //check if source is not 64 aligned, must allocate new 64 aligned vasurface(EXternalMemoryNULL)
+            mVASurfaceWidth = (mVASurfaceWidth + 63 ) & ~63;
+            mAction |= MAP_ACTION_COPY;
+        }
+
+        if (mAction & MAP_ACTION_COPY) //must allocate new vasurface(EXternalMemoryNULL)
+            AllocSurface = true;
+
+        if (mAction & MAP_ACTION_COLORCONVERT) {
+
+        #ifdef IMG_GFX  //only enable on IMG chip
+            /*only support gfx buffer, need allocate new gfx buffer, then map new one to vasurface */
+            if (mVinfo.mode != MEM_MODE_GFXHANDLE)
+                return ENCODE_NOT_SUPPORTED;
+
+            //do not trust valueinfo, directly get from structure
+            IMG_native_handle_t* h = (IMG_native_handle_t*) mValue;
+            //only allocate new buffer if color format is not NV12
+            if (HAL_PIXEL_FORMAT_NV12 == h->iFormat || 0x7FA00E00 == h->iFormat) //OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
+                mAction &= ~MAP_ACTION_COLORCONVERT;
+            else
+                AllocSurface = true;
+            LOG_I("src gfx buffer iFormat=%x, iWidth=%d, iHeight=%d in handle structure", h->iFormat, h->iWidth, h->iHeight);
+        #else
+            return ENCODE_NOT_SUPPORTED;
+        #endif
+        }
+
+        if (AllocSurface) {
+            //allocate new buffer and map to vasurface
+            ret = doAllocation();
+            CHECK_ENCODE_STATUS_RETURN("doAllocation");
+        } else {
+            //direct map mem to vasurface
+            ret = MappingToVASurface();
+            CHECK_ENCODE_STATUS_RETURN("MappingToVASurface");
+        }
+    }
+
+    if (mAction & MAP_ACTION_COLORCONVERT) {
+        ret = doActionColConv();
+        CHECK_ENCODE_STATUS_RETURN("doActionColConv");
+    } else 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=%x\n", mVinfo.mode, mValue);
+
+    const char *mode = NULL;
+    switch (mVinfo.mode) {
+        case MEM_MODE_SURFACE:
+            mode = "SURFACE";
+            ret = MappingSurfaceID();
+            break;
+        case MEM_MODE_GFXHANDLE:
+            mode = "GFXHANDLE";
+            ret = MappingGfxHandle();
+            break;
+        case MEM_MODE_KBUFHANDLE:
+            mode = "KBUFHANDLE";
+            ret = MappingKbufHandle();
+            break;
+        case MEM_MODE_MALLOC:
+        case MEM_MODE_NONECACHE_USRPTR:
+            mode = "MALLOC or NONCACHE_USRPTR";
+            ret = MappingMallocPTR();
+            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%08x", mVASurface, mValue);
+
+    return ret;
+}
+
+Encode_Status VASurfaceMap::MappingSurfaceID() {
+
+    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)mValue,
+            &fourCC, &lumaStride, &chromaUStride, &chromaVStride,
+            &lumaOffset, &chromaUOffset, &chromaVOffset, &kBufHandle, NULL);
+
+    CHECK_VA_STATUS_RETURN("vaLockSurface");
+    LOG_I("Surface incoming = 0x%08x", mValue);
+    LOG_I("lumaStride = %d", lumaStride);
+    LOG_I("chromaUStride = %d", chromaUStride);
+    LOG_I("chromaVStride = %d", chromaVStride);
+    LOG_I("lumaOffset = %d", lumaOffset);
+    LOG_I("chromaUOffset = %d", chromaUOffset);
+    LOG_I("chromaVOffset = %d", chromaVOffset);
+    LOG_I("kBufHandle = 0x%08x", kBufHandle);
+    LOG_I("fourCC = %d", fourCC);
+
+    vaStatus = vaUnlockSurface((VADisplay)mVinfo.handle, (VASurfaceID)mValue);
+    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_DRIVER_FAIL;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingGfxHandle() {
+
+    LOG_I("MappingGfxHandle %x......\n", mValue);
+    LOG_I("format = 0x%08x, lumaStride = %d in ValueInfo\n", mVinfo.format, mVinfo.lumaStride);
+
+#ifdef IMG_GFX
+    // color format may be OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar or HAL_PIXEL_FORMAT_NV12
+    IMG_native_handle_t* h = (IMG_native_handle_t*) mValue;
+    mVinfo.lumaStride = h->iWidth;
+    mVinfo.format = h->iFormat;
+    mVinfo.width = h->iWidth;
+    mVinfo.height = h->iHeight;
+    LOG_I("Update ValueInfo with iWidth=%d, iHeight=%d, iFormat=%x in handle structure\n", h->iWidth, h->iHeight, h->iFormat);
+#endif
+
+    mVASurface = CreateSurfaceFromExternalBuf(mValue, mVinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_DRIVER_FAIL;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingKbufHandle() {
+
+    LOG_I("MappingKbufHandle value=%d\n", mValue);
+
+    mVinfo.size = mVinfo.lumaStride * mVinfo.height * 1.5;
+    mVASurface = CreateSurfaceFromExternalBuf(mValue, mVinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_DRIVER_FAIL;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::MappingMallocPTR() {
+
+    mVASurface = CreateSurfaceFromExternalBuf(mValue, mVinfo);
+    if (mVASurface == VA_INVALID_SURFACE)
+        return ENCODE_DRIVER_FAIL;
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::doAllocation() {
+
+    if (mAction & MAP_ACTION_COLORCONVERT) {
+    #ifdef IMG_GFX
+        //for gfx buffer color convert
+        int usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+
+        int32_t stride;
+        if (gfx_alloc(mVASurfaceWidth, mVASurfaceHeight, /*0x7FA00E00*/HAL_PIXEL_FORMAT_NV12, usage, &mGfxHandle, &stride) != 0)
+            return ENCODE_DRIVER_FAIL;
+
+        LOG_I("Create an new gfx buffer handle 0x%08x for color convert, width=%d, height=%d, stride=%d\n",
+                   (unsigned int)mGfxHandle, mVASurfaceWidth, mVASurfaceHeight, stride);
+
+        ValueInfo vinfo;
+        memset(&vinfo, 0, sizeof(ValueInfo));
+        vinfo.mode = MEM_MODE_GFXHANDLE;
+        vinfo.width = mVASurfaceWidth;
+        vinfo.height = mVASurfaceHeight;
+        vinfo.lumaStride = stride;
+        mVASurface = CreateSurfaceFromExternalBuf((int32_t)mGfxHandle, vinfo);
+        if (mVASurface == VA_INVALID_SURFACE)
+            return ENCODE_DRIVER_FAIL;
+        mGfxHandleAllocated = true;
+    #else
+        return ENCODE_NOT_SUPPORTED;
+    #endif
+
+    } else {
+        //for 64 align and uncached mem
+        LOG_I("Create an new vaSurface for Action 0x%08x\n", mAction);
+        mVASurface = CreateNewVASurface(mVADisplay, mVASurfaceWidth, mVASurfaceHeight);
+        if (mVASurface == VA_INVALID_SURFACE)
+            return ENCODE_DRIVER_FAIL;
+    }
+
+    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;
+
+    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
+        IMG_native_handle_t* h = (IMG_native_handle_t*) mValue;
+
+        //only copy expected to be encoded area
+        width = mVinfo.width;
+        height = mVinfo.height;
+        stride = h->iWidth;
+
+        //only support HAL_PIXEL_FORMAT_NV12 & OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar
+        if (HAL_PIXEL_FORMAT_NV12 != h->iFormat && 0x7FA00E00 != h->iFormat) {
+            LOG_E("Not support gfx buffer format %x", h->iFormat);
+            return ENCODE_NOT_SUPPORTED;
+        }
+
+        srcY_offset = 0;
+        srcUV_offset = stride * height;
+        srcY_pitch = stride;
+        srcUV_pitch = stride;
+
+        //lock gfx handle with buffer real size
+        LOG_I("Width=%d,Height=%d,Format=%x in raw gfx handle\n", h->iWidth, h->iHeight, h->iFormat);
+        void* vaddr[3];
+        if (gfx_lock((buffer_handle_t) mValue, usage, 0, 0, h->iWidth, h->iHeight, &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) mValue);
+    }
+#endif
+    LOG_I("Copying Src Buffer data to VASurface Complete\n");
+
+    return ENCODE_SUCCESS;
+}
+
+Encode_Status VASurfaceMap::doActionColConv() {
+
+#ifdef IMG_GFX
+LOG_I("gfx_Blit width=%d, height=%d\n", mVinfo.width, mVinfo.height);
+    if (gfx_Blit((buffer_handle_t)mValue, mGfxHandle,
+//            mVASurfaceWidth, mVASurfaceHeight, 0, 0) != 0)
+            mVinfo.width, mVinfo.height, 0, 0) != 0)
+        return ENCODE_DRIVER_FAIL;
+    return ENCODE_SUCCESS;
+#else
+    return ENCODE_NOT_SUPPORTED;
+#endif
+}
+
+VASurfaceID VASurfaceMap::CreateSurfaceFromExternalBuf(int32_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);
+
+    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..9f6b9cb
--- /dev/null
+++ b/videoencoder/VideoEncoderUtils.h
@@ -0,0 +1,70 @@
+#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;}
+    int32_t getValue() {return mValue;}
+    ValueInfo* getValueInfo() {return &mVinfo;}
+
+    void setVASurface(VASurfaceID surface) {mVASurface = surface;}
+    void setValue(int32_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 doAllocation();
+    Encode_Status doActionCopy();
+    Encode_Status doActionColConv();
+    Encode_Status MappingToVASurface();
+    Encode_Status MappingSurfaceID();
+    Encode_Status MappingGfxHandle();
+    Encode_Status MappingKbufHandle();
+    Encode_Status MappingMallocPTR();
+    VASurfaceID CreateSurfaceFromExternalBuf(int32_t value, ValueInfo& vinfo);
+
+    VADisplay mVADisplay;
+
+    int32_t mValue;
+
+    VASurfaceID mVASurface;
+    int32_t mVASurfaceWidth;
+    int32_t mVASurfaceHeight;
+
+//    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;
+    bool mGfxHandleAllocated;
+#endif
+};
+
+VASurfaceID CreateNewVASurface(VADisplay display, int32_t width, int32_t height);
+
+#endif
+