add Mediacopy Sample code
diff --git a/videoprocess/Makefile.am b/videoprocess/Makefile.am
index 1a37269..7ee8c3b 100644
--- a/videoprocess/Makefile.am
+++ b/videoprocess/Makefile.am
@@ -20,7 +20,7 @@
 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-bin_PROGRAMS = vavpp vppscaling_csc vppdenoise vppsharpness vppchromasitting vppblending vppscaling_n_out_usrptr
+bin_PROGRAMS = vavpp vppscaling_csc vppdenoise vppsharpness vppchromasitting vppblending vppscaling_n_out_usrptr vacopy
 
 AM_CPPFLAGS = \
 	-Wall					\
@@ -57,6 +57,9 @@
 
 vppscaling_n_out_usrptr_SOURCES = vppscaling_n_out_usrptr.cpp
 vppscaling_n_out_usrptr_LDADD   = $(TEST_LIBS)
+
+vacopy_SOURCES = vacopy.cpp
+vacopy_LDADD = $(TEST_LIBS)
 valgrind:(bin_PROGRAMS)
 	for a in(bin_PROGRAMS); do \
 		valgrind --leak-check=full --show-reachable=yes .libs/$$a; \
diff --git a/videoprocess/process_va_copy.cfg.template b/videoprocess/process_va_copy.cfg.template
new file mode 100644
index 0000000..69ee03e
--- /dev/null
+++ b/videoprocess/process_va_copy.cfg.template
@@ -0,0 +1,43 @@
+# Configuration information for video process test case.
+#    This application will firstly load yuv frames to one type of surface(NV12/RBGP)
+#  you require. After GPU HW copy, the processed content (NV12/RGBP surface)
+#  will be stored to frames.
+#    Supported features include intput/ouput internal surface and external(usrptr surface) copy. 
+#  you can modify this configuration file to set the corresponding parameters.
+
+#1.Source YUV(RGB) file information
+SRC_FILE_NAME: ./src_480x320.nv12
+SRC_FRAME_WIDTH: 480
+SRC_FRAME_HEIGHT: 320
+SRC_FRAME_FORMAT: NV12
+
+#Note .nv12 files are in NV12 format
+SRC_FILE_FORMAT: NV12
+
+# source surface memory type
+# supported type: (CPU, VA), default: VA
+SRC_SURFACE_MEMORY_TYPE: VA
+
+#if use usrptr CPU memory type, can support customization align size
+SRC_SURFACE_CPU_ALIGN_SIZE: 1
+
+#2.Destination YUV(RGB) file information
+DST_FILE_NAME:    ./dst_480x320.nv12
+DST_FRAME_WIDTH:  480
+DST_FRAME_HEIGHT: 320
+DST_FRAME_FORMAT: NV12
+
+#Note .nv12 files are in NV12 format
+DST_FILE_FORMAT: NV12
+
+# destination surface memory type
+# supported type: (CPU, VA), default: VA
+DST_SURFACE_MEMORY_TYPE: VA
+
+#if use usrptr CPU memory type, can support customization align size
+DST_SURFACE_CPU_ALIGN_SIZE: 128
+
+FRAME_SUM: 1
+
+# hw engine select, 0:balance 1:perf, 2 powersaving
+COPY_METHOD: 1
diff --git a/videoprocess/vacopy.cpp b/videoprocess/vacopy.cpp
new file mode 100644
index 0000000..8bee4c6
--- /dev/null
+++ b/videoprocess/vacopy.cpp
@@ -0,0 +1,858 @@
+/*
+* Copyright (c) 2009-2018, Intel Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+/*
+ * Video process test case based on LibVA.
+ * This test covers different surface format copy.
+ * Usage: ./vacopy process_copy.cfg
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <iostream>
+#include <time.h>
+#include <assert.h>
+#include <va/va.h>
+#include <va/va_vpp.h>
+#include "va_display.h"
+
+#ifndef VA_FOURCC_I420
+#define VA_FOURCC_I420 0x30323449
+#endif
+
+#define MAX_LEN   1024
+
+#define CHECK_VASTATUS(va_status,func)                                      \
+  if (va_status != VA_STATUS_SUCCESS) {                                     \
+      fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
+      exit(1);                                                              \
+  }
+using namespace std;
+static VADisplay va_dpy = NULL;
+static VAContextID context_id = 0;
+
+typedef struct _SurfInfo
+{
+    FILE        *fd;
+    char        name[MAX_LEN];
+    uint32_t    width;
+    uint32_t    height;
+    uint32_t    fourCC;
+    uint32_t    format;
+    uint32_t    memtype;
+    uint32_t    alignsize;
+    void        *pBuf;
+    uint8_t     *pBufBase;
+    uintptr_t   ptrb;
+}SurfInfo;
+
+static SurfInfo g_src;
+static SurfInfo g_dst;
+
+static VAConfigID  config_id = 0;
+static FILE* g_config_file_fd = NULL;
+static char g_config_file_name[MAX_LEN];
+
+static VASurfaceID g_in_surface_id = VA_INVALID_ID;
+static VASurfaceID g_out_surface_id = VA_INVALID_ID;
+
+static uint32_t g_src_file_fourcc = VA_FOURCC('I', '4', '2', '0');
+static uint32_t g_dst_file_fourcc = VA_FOURCC('Y', 'V', '1', '2');
+
+#define _FREE(p)                       \
+    if(p != NULL){                      \
+        free(p);  p = NULL;                        \
+    }
+
+static uint32_t g_frame_count = 0;
+static uint32_t g_copy_method = 0; //0 blance, 1 perf. 2 power_saving
+
+static int8_t
+parse_memtype_format(char *str,uint32_t *dst_memtype)
+{
+    uint32_t tmemtype = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
+    
+    if (!strcmp(str, "VA")){
+        tmemtype = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
+    } else if(!strcmp(str, "CPU")){
+        tmemtype = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
+    }else{
+        printf("Not supported format: %s! Currently only support following format: %s\n",
+               str, "VA,CPU");
+        assert(0);
+    }
+    if(dst_memtype)
+        *dst_memtype = tmemtype;
+    return 0;
+}
+
+static int8_t
+read_value_string(FILE *fp, const char* field_name, char* value)
+{
+    char strLine[MAX_LEN];
+    char* field = NULL;
+    char* str = NULL;
+    uint16_t i;
+
+    if (!fp || !field_name || !value)  {
+        printf("Invalid fuction parameters\n");
+        return -1;
+    }
+
+    rewind(fp);
+
+    while (!feof(fp)) {
+        if (!fgets(strLine, MAX_LEN, fp))
+            continue;
+
+        for (i = 0; i < MAX_LEN && strLine[i]; i++)
+            if (strLine[i] != ' ') break;
+
+        if (i == MAX_LEN || strLine[i] == '#' || strLine[i] == '\n')
+            continue;
+
+        field = strtok(&strLine[i], ":");
+        if (strncmp(field, field_name, strlen(field_name)))
+            continue;
+
+        if (!(str = strtok(NULL, ":")))
+            continue;
+
+        /* skip blank space in string */
+        while (*str == ' ')
+            str++;
+
+        *(str + strlen(str)-1) = '\0';
+        strcpy(value, str);
+
+        return 0;
+    }
+
+    return -1;
+}
+
+static int8_t
+read_value_uint32(FILE* fp, const char* field_name, uint32_t* value)
+{
+    char str[MAX_LEN];
+
+    if (read_value_string(fp, field_name, str)) {
+       printf("Failed to find integer field: %s", field_name);
+       return -1;
+    }
+
+    *value = (uint32_t)atoi(str);
+    return 0;
+}
+
+static VAStatus
+create_surface(VASurfaceID * p_surface_id,SurfInfo &surf)
+{
+    VAStatus va_status = VA_STATUS_ERROR_INVALID_PARAMETER;
+    if (surf.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
+    {
+        VASurfaceAttrib    surface_attrib;
+        surface_attrib.type =  VASurfaceAttribPixelFormat;
+        surface_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
+        surface_attrib.value.type = VAGenericValueTypeInteger;
+        surface_attrib.value.value.i = surf.fourCC;
+    
+        va_status = vaCreateSurfaces(va_dpy,
+                                     surf.format,
+                                     surf.width ,
+                                     surf.height,
+                                     p_surface_id,
+                                     1,
+                                     &surface_attrib,
+                                     1);
+    }
+    else if (surf.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR)
+    {
+        VASurfaceAttrib surfaceAttrib[3];
+        VASurfaceAttribExternalBuffers extBuffer;
+        uint32_t base_addr_align = 0x1000;
+        uint32_t size = 0; 
+        surfaceAttrib[0].flags = VA_SURFACE_ATTRIB_SETTABLE;
+        surfaceAttrib[0].type = VASurfaceAttribPixelFormat;
+        surfaceAttrib[0].value.type = VAGenericValueTypeInteger;
+        surfaceAttrib[0].value.value.i = surf.fourCC;
+
+        surfaceAttrib[1].flags = VA_SURFACE_ATTRIB_SETTABLE;
+        surfaceAttrib[1].type = VASurfaceAttribMemoryType;
+        surfaceAttrib[1].value.type = VAGenericValueTypeInteger;
+        surfaceAttrib[1].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
+
+        surfaceAttrib[2].flags = VA_SURFACE_ATTRIB_SETTABLE;
+        surfaceAttrib[2].type = VASurfaceAttribExternalBufferDescriptor;
+        surfaceAttrib[2].value.type = VAGenericValueTypePointer;
+        surfaceAttrib[2].value.value.p = (void *)&extBuffer; 
+        memset(&extBuffer, 0, sizeof(extBuffer));
+
+        uint32_t pitch_align = surf.alignsize;
+        switch(surf.fourCC)
+        {
+            case VA_FOURCC_NV12:
+                extBuffer.pitches[0] = ((surf.width + pitch_align -1)/pitch_align) * pitch_align;
+                size = (extBuffer.pitches[0] * surf.height) * 3/2;// frame size align with pitch.
+                size = (size+base_addr_align-1)/base_addr_align*base_addr_align;// frame size align as 4K page.
+                extBuffer.offsets[0] = 0;// Y channel
+                extBuffer.offsets[1] = extBuffer.pitches[0] * surf.height; // UV channel.
+                extBuffer.pitches[1] = extBuffer.pitches[0];
+                extBuffer.num_planes =2;
+                break;
+            case VA_FOURCC_RGBP:
+                extBuffer.pitches[0] = ((surf.width + pitch_align -1)/pitch_align) * pitch_align;
+                size = (extBuffer.pitches[0] * surf.height) * 3;// frame size align with pitch.
+                size = (size+base_addr_align-1)/base_addr_align*base_addr_align;// frame size align as 4K page.
+                extBuffer.offsets[0] = 0;// Y channel
+                extBuffer.offsets[1] = extBuffer.pitches[0] * surf.height; // U channel.
+                extBuffer.pitches[1] = extBuffer.pitches[0];
+                extBuffer.offsets[2] = extBuffer.pitches[0] * surf.height * 2; // V channel.
+                extBuffer.pitches[2] = extBuffer.pitches[0];
+                extBuffer.num_planes = 3;
+                break;
+            default :
+                std::cout << surf.fourCC <<"format doesn't support!"<<endl;
+                return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
+        }
+        if (!surf.pBuf && !surf.pBufBase)
+        {
+            surf.pBuf = malloc(size+base_addr_align);
+            surf.pBufBase = (uint8_t*)((((uint64_t)(surf.pBuf) + base_addr_align-1)/base_addr_align)*base_addr_align);
+
+            extBuffer.pixel_format = surf.fourCC;
+            extBuffer.width = surf.width;
+            extBuffer.height = surf.height;
+            extBuffer.data_size = size;
+            extBuffer.num_buffers = 1;
+            extBuffer.buffers = &(surf.ptrb);
+            extBuffer.buffers[0] = (uintptr_t)(surf.pBufBase);
+            extBuffer.flags = VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR;
+
+            va_status = vaCreateSurfaces(va_dpy, surf.format, surf.width, surf.height,p_surface_id, 1, surfaceAttrib, 3);
+            CHECK_VASTATUS(va_status, "vaCreateSurfaces");
+        }
+        else
+        {
+            std::cout<<"previous frame buffer hasn't be released!"<<endl;
+        }
+    }
+
+   return va_status;
+}
+
+/* Load frame to surface*/
+static VAStatus
+upload_frame_to_surface(FILE *fp,
+                                 VASurfaceID surface_id)
+{
+    VAStatus va_status;
+    VAImage surface_image;
+    unsigned char *y_src = NULL;
+    unsigned char *u_src = NULL;
+    unsigned char *v_src = NULL;
+    unsigned char *y_dst = NULL;
+    unsigned char *u_dst = NULL;
+    unsigned char *v_dst = NULL;
+    void *surface_p = NULL;
+    uint32_t frame_size, row;
+    size_t n_items;
+    unsigned char * newImageBuffer = NULL;
+    va_status = vaSyncSurface (va_dpy,surface_id);
+    CHECK_VASTATUS(va_status, "vaSyncSurface");
+    
+    va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
+    CHECK_VASTATUS(va_status, "vaDeriveImage");
+
+    va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
+    CHECK_VASTATUS(va_status, "vaMapBuffer");
+
+    if (g_src.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
+    {
+        std::cout<<"2D src surface width = "<<g_src.width<<" pitch = "<<surface_image.pitches[0]<<endl;
+    }
+    else
+    {
+        std::cout<<"linear src surface width = "<<g_src.width<<" pitch = "<<surface_image.pitches[0]<<((g_src.width%surface_image.pitches[0])?" it is 2D linear":" it is 1D linear")<<endl;
+    }
+
+    if (surface_image.format.fourcc == VA_FOURCC_RGBP)
+    {
+        frame_size = surface_image.width * surface_image.height * 3;
+        newImageBuffer = (unsigned char*)malloc(frame_size);
+        assert(newImageBuffer);
+
+        do {
+            n_items = fread(newImageBuffer, frame_size, 1, fp);
+        } while (n_items != 1);
+
+        y_src = newImageBuffer;
+        u_src = newImageBuffer + surface_image.width * surface_image.height;
+        v_src = newImageBuffer + surface_image.width * surface_image.height * 2;
+
+        y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
+        u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
+        v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
+
+        for (row = 0; row < surface_image.height; row++) {
+            memcpy(y_dst, y_src, surface_image.width);
+            y_dst += surface_image.pitches[0];
+            y_src += surface_image.width;
+
+            memcpy(u_dst, u_src, surface_image.width);
+            u_dst += surface_image.pitches[0];
+            u_src += surface_image.width;
+
+            memcpy(v_dst, v_src, surface_image.width);
+            v_dst += surface_image.pitches[0];
+            v_src += surface_image.width;
+        }
+    }
+    else if (surface_image.format.fourcc == VA_FOURCC_NV12)
+    {
+        frame_size = surface_image.width * surface_image.height * 3 / 2;
+        newImageBuffer = (unsigned char*)malloc(frame_size);
+        assert(newImageBuffer);
+
+        do {
+            n_items = fread(newImageBuffer, frame_size, 1, fp);
+        } while (n_items != 1);
+
+        y_src = newImageBuffer;
+        u_src = newImageBuffer + surface_image.width * surface_image.height;
+        v_src = u_src;
+
+        y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
+        u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
+        v_dst = u_dst;
+
+        /* Y plane, directly copy */
+        for (row = 0; row < surface_image.height; row++) {
+            memcpy(y_dst, y_src, surface_image.width);
+            y_dst += surface_image.pitches[0];
+            y_src += surface_image.width;
+        }
+
+        /* UV plane */
+        for (row = 0; row < surface_image.height / 2; row++) 
+        {
+            memcpy(u_dst, u_src, surface_image.width);
+            u_src += surface_image.width;
+            v_src = u_src;
+            u_dst += surface_image.pitches[1];
+        }
+    }
+
+     if (newImageBuffer){
+         free(newImageBuffer);
+         newImageBuffer = NULL;
+     }
+
+     vaUnmapBuffer(va_dpy, surface_image.buf);
+     vaDestroyImage(va_dpy, surface_image.image_id);
+
+     return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+store_surface_to_file(FILE *fp,
+                               VASurfaceID surface_id)
+{
+    VAStatus va_status;
+    VAImage surface_image;
+    void *surface_p = NULL;
+    unsigned char *y_src = NULL;
+    unsigned char *u_src = NULL;
+    unsigned char *v_src = NULL;
+    unsigned char *y_dst = NULL;
+    unsigned char *u_dst = NULL;
+    unsigned char *v_dst = NULL;
+    uint32_t row;
+    int32_t n_items;
+    unsigned char * newImageBuffer = NULL;
+    va_status = vaSyncSurface (va_dpy,surface_id);
+    CHECK_VASTATUS(va_status, "vaSyncSurface");
+
+    va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
+    CHECK_VASTATUS(va_status, "vaDeriveImage");
+
+    va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
+    CHECK_VASTATUS(va_status, "vaMapBuffer");
+
+    if (g_dst.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
+    {
+        std::cout<<"2D dst surface width = "<<g_dst.width<<" pitch = "<<surface_image.pitches[0]<<endl;
+    }
+    else
+    {
+        std::cout<<"linear dst surface width = "<<g_dst.width<<" pitch = "<<surface_image.pitches[0]<<((g_dst.width%surface_image.pitches[0])?" it is 2D linear":" it is 1D linear")<<endl;
+    }
+
+    /* store the surface to one nv12 file */
+    if (surface_image.format.fourcc == VA_FOURCC_NV12 ||
+        surface_image.format.fourcc == VA_FOURCC_RGBP ){
+
+        y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
+
+        if (surface_image.format.fourcc == VA_FOURCC_RGBP){
+            u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
+            v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
+        } else if(surface_image.format.fourcc == VA_FOURCC_NV12){
+            u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
+            v_src = u_src;
+        }
+
+        if(g_dst.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
+        {
+            if (surface_image.format.fourcc == VA_FOURCC_NV12)
+            {
+                uint32_t y_size = surface_image.width * surface_image.height;
+                newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
+                assert(newImageBuffer);
+
+                y_dst = newImageBuffer;
+                u_dst = v_dst = newImageBuffer + y_size;
+
+                /* Y plane copy */
+                for (row = 0; row < surface_image.height; row++) {
+                    memcpy(y_dst, y_src, surface_image.width);
+                    y_src += surface_image.pitches[0];
+                    y_dst += surface_image.width;
+                }
+                // UV plane
+                for (row = 0; row < surface_image.height / 2; row++) {
+                    memcpy(u_dst, u_src, surface_image.width);
+                    u_dst += surface_image.width;
+                    u_src += surface_image.pitches[1];
+                }
+
+                /* write frame to file */
+                do {
+                    n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
+                } while (n_items != 1);
+            }
+            else if (surface_image.format.fourcc == VA_FOURCC_RGBP)
+            {
+                uint32_t y_size = surface_image.width * surface_image.height;
+                newImageBuffer = (unsigned char*)malloc(y_size * 3);
+                assert(newImageBuffer);
+
+                y_dst = newImageBuffer;
+                u_dst = newImageBuffer + y_size;
+                v_dst = newImageBuffer + y_size *2;
+
+                for (row = 0; row < surface_image.height; row++) {
+                    memcpy(y_dst, y_src, surface_image.width);
+                    y_src += surface_image.pitches[0];
+                    y_dst += surface_image.width;
+
+                    memcpy(u_dst, u_src, surface_image.width);
+                    u_dst += surface_image.width;
+                    u_src += surface_image.pitches[0];
+
+                    memcpy(v_dst, v_src, surface_image.width);
+                    v_dst += surface_image.width;
+                    v_src += surface_image.pitches[0];
+                }
+
+                do {
+                    n_items = fwrite(newImageBuffer, y_size * 3, 1, fp);
+                } while (n_items != 1);
+            }
+        }
+        else // usrptr surface.
+        {
+            if (surface_image.format.fourcc == VA_FOURCC_NV12)
+            {
+                // directly copy NV12 1D/2D surface. skip derive and map image.
+                uint32_t y_size = surface_image.height * surface_image.pitches[0];
+                newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
+                assert(newImageBuffer);
+                memcpy(newImageBuffer, g_dst.pBufBase, (y_size * 3 / 2));
+
+                do {
+                    n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
+                } while (n_items != 1);
+            }
+            else if (surface_image.format.fourcc == VA_FOURCC_RGBP)
+            {
+                uint32_t y_size = surface_image.height * surface_image.pitches[0];
+                newImageBuffer = (unsigned char*)malloc(y_size * 3);
+                assert(newImageBuffer);
+                memcpy(newImageBuffer, g_dst.pBufBase, (y_size * 3));
+
+                do {
+                    n_items = fwrite(newImageBuffer, y_size * 3, 1, fp);
+                } while (n_items != 1);
+            }
+        }
+    } 
+    else {
+        printf("Not supported surface fourcc !!! \n");
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+    }
+
+    if (newImageBuffer){
+        free(newImageBuffer);
+        newImageBuffer = NULL;
+    }
+
+    vaUnmapBuffer(va_dpy, surface_image.buf);
+    vaDestroyImage(va_dpy, surface_image.image_id);
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+video_frame_process(       VASurfaceID in_surface_id,
+                    VASurfaceID out_surface_id)
+{
+    VAStatus va_status;
+#if VA_CHECK_VERSION(1, 10, 0)
+    VACopyObject src_obj, dst_obj;
+    VACopyOption option;
+    memset(&src_obj, 0, sizeof(src_obj));
+    memset(&dst_obj, 0, sizeof(dst_obj));
+    memset(&option, 0, sizeof(option));
+
+    src_obj.obj_type = VACopyObjectSurface;
+    src_obj.object.surface_id = in_surface_id;
+    dst_obj.obj_type = VACopyObjectSurface;
+    dst_obj.object.surface_id = out_surface_id;
+    option.bits.va_copy_mode = g_copy_method; // VA_COPY_MODE_BALANCE;
+
+    va_status = vaCopy(va_dpy, &dst_obj, &src_obj, option);
+#else
+    printf("incorrect libva version!\n");
+    va_status = VA_STATUS_ERROR_OPERATION_FAILED;
+#endif
+    return va_status;
+}
+
+static VAStatus
+vpp_context_create()
+{
+    VAStatus va_status = VA_STATUS_SUCCESS;
+    int32_t j;
+
+    /* VA driver initialization */
+    va_dpy = va_open_display();
+    int32_t major_ver, minor_ver;
+    va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
+    assert(va_status == VA_STATUS_SUCCESS);
+
+    /* Check whether VPP is supported by driver */
+    VAEntrypoint entrypoints[5];
+    int32_t num_entrypoints;
+    num_entrypoints = vaMaxNumEntrypoints(va_dpy);
+    va_status = vaQueryConfigEntrypoints(va_dpy,
+                                         VAProfileNone,
+                                         entrypoints,
+                                         &num_entrypoints);
+    CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
+
+    for (j = 0; j < num_entrypoints; j++) {
+        if (entrypoints[j] == VAEntrypointVideoProc)
+            break;
+    }
+
+    if (j == num_entrypoints) {
+        printf("VPP is not supported by driver\n");
+        assert(0);
+    }
+
+    /* Render target surface format check */
+    VAConfigAttrib attrib;
+    attrib.type = VAConfigAttribRTFormat;
+    va_status = vaGetConfigAttributes(va_dpy,
+                                      VAProfileNone,
+                                      VAEntrypointVideoProc,
+                                      &attrib,
+                                     1);
+    CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
+    if (!(attrib.value & g_dst.format)) {
+        printf("RT format %d is not supported by VPP !\n",g_dst.format);
+        assert(0);
+    }
+
+    /* Create surface/config/context for VPP pipeline */
+    va_status = create_surface(&g_in_surface_id, g_src);
+    CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
+
+    va_status = create_surface(&g_out_surface_id, g_dst);
+    CHECK_VASTATUS(va_status, "vaCreateSurfaces for output");
+
+    va_status = vaCreateConfig(va_dpy,
+                               VAProfileNone,
+                               VAEntrypointVideoProc,
+                               &attrib,
+                               1,
+                               &config_id);
+    CHECK_VASTATUS(va_status, "vaCreateConfig");
+
+    va_status = vaCreateContext(va_dpy,
+                                config_id,
+                                g_dst.width,
+                                g_dst.height,
+                                VA_PROGRESSIVE,
+                                &g_out_surface_id,
+                                1,
+                                &context_id);
+    CHECK_VASTATUS(va_status, "vaCreateContext");
+    return va_status;
+}
+
+static void
+vpp_context_destroy()
+{
+    /* Release resource */
+    vaDestroySurfaces(va_dpy, &g_in_surface_id, 1);
+    vaDestroySurfaces(va_dpy, &g_out_surface_id, 1);
+    vaDestroyContext(va_dpy, context_id);
+    vaDestroyConfig(va_dpy, config_id);
+
+    vaTerminate(va_dpy);
+    va_close_display(va_dpy);
+
+    _FREE(g_src.pBuf);
+    _FREE(g_dst.pBuf);
+}
+
+static int8_t
+parse_fourcc_and_format(char *str, uint32_t *fourcc, uint32_t *format)
+{
+    uint32_t tfourcc = VA_FOURCC('N', 'V', '1', '2');
+    uint32_t tformat = VA_RT_FORMAT_YUV420;
+
+    if (!strcmp(str, "YV12")){
+        tfourcc = VA_FOURCC('Y', 'V', '1', '2');
+    } else if(!strcmp(str, "I420")){
+        tfourcc = VA_FOURCC('I', '4', '2', '0');
+    } else if(!strcmp(str, "NV12")){
+        tfourcc = VA_FOURCC('N', 'V', '1', '2');
+    } else if(!strcmp(str, "YUY2") || !strcmp(str, "YUYV")) {
+        tfourcc = VA_FOURCC('Y', 'U', 'Y', '2');
+    } else if(!strcmp(str, "UYVY")){
+        tfourcc = VA_FOURCC('U', 'Y', 'V', 'Y');
+    } else if (!strcmp(str, "P010")) {
+        tfourcc = VA_FOURCC('P', '0', '1', '0');
+    } else if (!strcmp(str, "I010")) {
+        tfourcc = VA_FOURCC('I', '0', '1', '0');
+    } else if (!strcmp(str, "RGBA")) {
+        tfourcc = VA_FOURCC_RGBA;
+    } else if (!strcmp(str, "RGBX")) {
+        tfourcc = VA_FOURCC_RGBX;
+    } else if (!strcmp(str, "BGRA")) {
+        tfourcc = VA_FOURCC_BGRA;
+    } else if (!strcmp(str, "BGRX")) {
+        tfourcc = VA_FOURCC_BGRX;
+    } else if (!strcmp(str, "RGBP")) {
+        tfourcc = VA_FOURCC_RGBP; 
+    } else if (!strcmp(str, "BGRP")) {
+        tfourcc = VA_FOURCC_BGRP; 
+    } else{
+        printf("Not supported format: %s! Currently only support following format: %s\n",
+               str, "YV12, I420, NV12, YUY2(YUYV), UYVY, P010, I010, RGBA, RGBX, BGRA or BGRX");
+        assert(0);
+    }
+
+    if (fourcc)
+        *fourcc = tfourcc;
+
+    if (format)
+        *format = tformat;
+
+    return 0;
+}
+
+static int8_t
+parse_basic_parameters()
+{
+    char str[MAX_LEN];
+    memset(&g_src, 0, sizeof(g_src));
+    memset(&g_dst, 0, sizeof(g_dst));
+
+    /* Read src frame file information */
+    read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src.name);
+    read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_src.width);
+    read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_src.height);
+    read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str);
+    parse_fourcc_and_format(str, &g_src.fourCC, &g_src.format);
+    read_value_string(g_config_file_fd, "SRC_SURFACE_MEMORY_TYPE", str);
+    parse_memtype_format(str,&g_src.memtype);
+    read_value_uint32(g_config_file_fd, "SRC_SURFACE_CPU_ALIGN_SIZE", &g_src.alignsize);
+
+    /* Read dst frame file information */
+    read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst.name);
+    read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_dst.width);
+    read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT",&g_dst.height);
+    read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str);
+    parse_fourcc_and_format(str, &g_dst.fourCC, &g_dst.format);
+    read_value_string(g_config_file_fd, "DST_SURFACE_MEMORY_TYPE", str);
+    parse_memtype_format(str,&g_dst.memtype);
+    read_value_uint32(g_config_file_fd, "DST_SURFACE_CPU_ALIGN_SIZE", &g_dst.alignsize);
+
+    read_value_string(g_config_file_fd, "SRC_FILE_FORMAT", str);
+    parse_fourcc_and_format(str, &g_src_file_fourcc, NULL);
+
+    read_value_string(g_config_file_fd, "DST_FILE_FORMAT", str);
+    parse_fourcc_and_format(str, &g_dst_file_fourcc, NULL);
+
+    read_value_uint32(g_config_file_fd, "FRAME_SUM", &g_frame_count);
+    read_value_uint32(g_config_file_fd, "COPY_METHOD", &g_copy_method);
+
+    if (g_src.width != g_dst.width ||
+        g_src.height != g_dst.height)
+    {
+        std::cout<<"va copy doesn't support resize!"<<endl;
+        return -1;
+    }
+
+    if (g_src.fourCC != g_dst.fourCC)
+    {
+        std::cout<<"va copy doesn't support CSC!" <<endl;
+        return -1;
+    }
+
+    std::cout<<"=========Media Copy========="<<endl;
+
+    if (g_src.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
+    {
+        std::cout<<"copy from 2D tile surface to ";
+    }
+    else
+    {
+        if (g_src.alignsize == 1 || !(g_src.width%g_src.alignsize))
+            std::cout<<"copy from 1D linear surface to ";
+        else
+            std::cout<<"copy from 2D linear surface with pitch_align "<<g_src.alignsize<<" to ";
+    }
+
+    if (g_dst.memtype == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
+    {
+        std::cout<<"2D tile surface."<<endl;
+    }
+    else
+    {
+        if (g_dst.alignsize == 1 || !(g_dst.width%g_dst.alignsize))
+            std::cout<<"1D linear surface."<<endl;
+        else
+            std::cout<<"2D linear surface with pitch_align "<<g_dst.alignsize<<endl;
+    }
+    std::cout << "prefer hw engine is "<<g_copy_method<<". notification, 0: blanance(vebox), 1: perf(EU), 2 powersaving(blt)"<<endl;
+
+    return 0;
+}
+
+static void
+print_help()
+{
+    printf("The app is used to test the scaling and csc feature.\n");
+    printf("Cmd Usage: ./vacopy process_copy.cfg\n");
+    printf("The configure file process_copy.cfg is used to configure the para.\n");
+    printf("You can refer process_copy.cfg.template for each para meaning and create the configure file.\n");
+}
+int32_t main(int32_t argc, char *argv[])
+{
+    VAStatus va_status;
+    uint32_t i;
+
+    if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
+        print_help();
+        return -1;
+    }
+
+    /* Parse the configure file for video process*/
+    strncpy(g_config_file_name, argv[1], MAX_LEN);
+    g_config_file_name[MAX_LEN - 1] = '\0';
+
+    if (NULL == (g_config_file_fd = fopen(g_config_file_name, "r"))){
+        printf("Open configure file %s failed!\n",g_config_file_name);
+        assert(0);
+    }
+
+    /* Parse basic parameters */
+    if (parse_basic_parameters()){
+        printf("Parse parameters in configure file error\n");
+        assert(0);
+    }
+
+    va_status = vpp_context_create();
+    if (va_status != VA_STATUS_SUCCESS) {
+        printf("vpp context create failed \n");
+        assert(0);
+    }
+
+    /* Video frame fetch, process and store */
+    if (NULL == (g_src.fd = fopen(g_src.name, "r"))){
+        printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n",
+                g_src.name, g_config_file_name);
+        assert(0);
+    }
+
+    if (NULL == (g_dst.fd = fopen(g_dst.name, "w"))){
+        printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n",
+               g_dst.name, g_config_file_name);
+        assert(0);
+    }
+
+    printf("\nStart to process, ...\n");
+    struct timespec Pre_time;
+    struct timespec Cur_time;
+    unsigned int duration = 0;
+    clock_gettime(CLOCK_MONOTONIC, &Pre_time);
+
+    for (i = 0; i < g_frame_count; i ++){
+        upload_frame_to_surface(g_src.fd, g_in_surface_id);
+        if (VA_STATUS_SUCCESS != video_frame_process(g_in_surface_id, g_out_surface_id))
+        {
+            std::cout<<"***vaCopy failed***"<<std::endl;
+        }
+        store_surface_to_file(g_dst.fd, g_out_surface_id);
+    }
+
+    clock_gettime(CLOCK_MONOTONIC, &Cur_time);
+    duration = (Cur_time.tv_sec - Pre_time.tv_sec) * 1000;
+    if (Cur_time.tv_nsec > Pre_time.tv_nsec) {
+        duration += (Cur_time.tv_nsec - Pre_time.tv_nsec) / 1000000;
+    } else {
+        duration += (Cur_time.tv_nsec + 1000000000 - Pre_time.tv_nsec) / 1000000 - 1000;
+    }
+
+    printf("Finish processing, performance: \n" );
+    printf("%d frames processed in: %d ms, ave time = %d ms\n",g_frame_count, duration, duration/g_frame_count);
+
+    if (g_src.fd)
+       fclose(g_src.fd);
+
+    if (g_dst.fd)
+       fclose(g_dst.fd);
+
+    if (g_config_file_fd)
+       fclose(g_config_file_fd);
+
+    vpp_context_destroy();
+
+    return 0;
+}
+