C++程序  |  809行  |  24.82 KB

/*
* 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_V("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_V("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_V("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");
                LOGV("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_V("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_V("%s: Format=%x, lumaStride=%d, width=%d, height=%d\n", mode, mVinfo.format, mVinfo.lumaStride, mVinfo.width, mVinfo.height);
    LOG_V("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_V("Surface incoming = 0x%p\n", (void*)value);
    LOG_V("lumaStride = %d, chromaUStride = %d, chromaVStride=%d\n", lumaStride, chromaUStride, chromaVStride);
    LOG_V("lumaOffset = %d, chromaUOffset = %d, chromaVOffset = %d\n", lumaOffset, chromaUOffset, chromaVOffset);
    LOG_V("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_V("MappingGfxHandle %p......\n", (void*)value);
    LOG_V("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_V("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_V("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_V("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_V("Src Buffer information\n");
    LOG_V("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_V("\nDest VASurface information\n");
    LOG_V("pitches[0] = %d\n", destImage.pitches[0]);
    LOG_V("pitches[1] = %d\n", destImage.pitches[1]);
    LOG_V("offsets[0] = %d\n", destImage.offsets[0]);
    LOG_V("offsets[1] = %d\n", destImage.offsets[1]);
    LOG_V("num_planes = %d\n", destImage.num_planes);
    LOG_V("width = %d\n", destImage.width);
    LOG_V("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_V("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_V("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;
}