Home | History | Annotate | Download | only in videoprocess
      1 /*
      2  * Copyright (c) 2014 Intel Corporation. All Rights Reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sub license, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial portions
     14  * of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     19  * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR
     20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 /*
     25  * Video process test case based on LibVA.
     26  * This test covers deinterlace, denoise, color balance, sharpening,
     27  * blending, scaling and several surface format conversion.
     28  * Usage: videoprocess process.cfg
     29  */
     30 
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <stdint.h>
     35 #include <sys/time.h>
     36 #include <assert.h>
     37 #include <va/va.h>
     38 #include <va/va_vpp.h>
     39 #include "va_display.h"
     40 
     41 #ifndef VA_FOURCC_I420
     42 #define VA_FOURCC_I420 0x30323449
     43 #endif
     44 
     45 #define MAX_LEN   1024
     46 
     47 #define CHECK_VASTATUS(va_status,func)                                      \
     48   if (va_status != VA_STATUS_SUCCESS) {                                     \
     49       fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
     50       exit(1);                                                              \
     51   }
     52 
     53 static VADisplay va_dpy = NULL;
     54 static VAContextID context_id = 0;
     55 static VAConfigID  config_id = 0;
     56 static VAProcFilterType g_filter_type = VAProcFilterNone;
     57 static VASurfaceID g_in_surface_id = VA_INVALID_ID;
     58 static VASurfaceID g_out_surface_id = VA_INVALID_ID;
     59 
     60 static FILE* g_config_file_fd = NULL;
     61 static FILE* g_src_file_fd = NULL;
     62 static FILE* g_dst_file_fd = NULL;
     63 
     64 static char g_config_file_name[MAX_LEN];
     65 static char g_src_file_name[MAX_LEN];
     66 static char g_dst_file_name[MAX_LEN];
     67 static char g_filter_type_name[MAX_LEN];
     68 
     69 static uint32_t g_in_pic_width = 352;
     70 static uint32_t g_in_pic_height = 288;
     71 static uint32_t g_out_pic_width = 352;
     72 static uint32_t g_out_pic_height = 288;
     73 
     74 static uint32_t g_in_fourcc  = VA_FOURCC('N', 'V', '1', '2');
     75 static uint32_t g_in_format  = VA_RT_FORMAT_YUV420;
     76 static uint32_t g_out_fourcc = VA_FOURCC('N', 'V', '1', '2');
     77 static uint32_t g_out_format = VA_RT_FORMAT_YUV420;
     78 
     79 static uint8_t g_blending_enabled = 0;
     80 static uint8_t g_blending_min_luma = 1;
     81 static uint8_t g_blending_max_luma = 254;
     82 
     83 static uint32_t g_frame_count = 0;
     84 
     85 static int8_t
     86 read_value_string(FILE *fp, const char* field_name, char* value)
     87 {
     88     char strLine[MAX_LEN];
     89     char* field;
     90     char* str;
     91     uint16_t i;
     92 
     93     if (!fp || !field_name || !value)  {
     94         printf("Invalid fuction parameters\n");
     95         return -1;
     96     }
     97 
     98     rewind(fp);
     99 
    100     while (!feof(fp)) {
    101         if (!fgets(strLine, MAX_LEN, fp))
    102             continue;
    103 
    104         for (i = 0; strLine[i] && i < MAX_LEN; i++)
    105             if (strLine[i] != ' ') break;
    106 
    107         if (strLine[i] == '#' || strLine[i] == '\n' || i == 1024)
    108             continue;
    109 
    110         field = strtok(&strLine[i], ":");
    111         if (strncmp(field, field_name, strlen(field_name)))
    112             continue;
    113 
    114         if (!(str = strtok(NULL, ":")))
    115             continue;
    116 
    117         /* skip blank space in string */
    118         while (*str == ' ')
    119             str++;
    120 
    121         *(str + strlen(str)-1) = '\0';
    122         strcpy(value, str);
    123 
    124         return 0;
    125     }
    126 
    127     return -1;
    128 }
    129 
    130 static int8_t
    131 read_value_uint8(FILE* fp, const char* field_name, uint8_t* value)
    132 {
    133     char str[MAX_LEN];
    134 
    135     if (read_value_string(fp, field_name, str)) {
    136         printf("Failed to find integer field: %s", field_name);
    137         return -1;
    138     }
    139 
    140     *value = (uint8_t)atoi(str);
    141     return 0;
    142 }
    143 
    144 static int8_t
    145 read_value_uint32(FILE* fp, const char* field_name, uint32_t* value)
    146 {
    147     char str[MAX_LEN];
    148 
    149     if (read_value_string(fp, field_name, str)) {
    150        printf("Failed to find integer field: %s", field_name);
    151        return -1;
    152     }
    153 
    154     *value = (uint32_t)atoi(str);
    155     return 0;
    156 }
    157 
    158 static int8_t
    159 read_value_float(FILE *fp, const char* field_name, float* value)
    160 {
    161     char str[MAX_LEN];
    162     if (read_value_string(fp, field_name, str)) {
    163        printf("Failed to find float field: %s \n",field_name);
    164        return -1;
    165     }
    166 
    167     *value = atof(str);
    168     return 0;
    169 }
    170 
    171 static float
    172 adjust_to_range(VAProcFilterValueRange *range, float value)
    173 {
    174     if (value < range->min_value || value > range->max_value){
    175         printf("Value: %f exceed range: (%f ~ %f), force to use default: %f \n",
    176                 value, range->min_value, range->max_value, range->default_value);
    177         return range->default_value;
    178     }
    179 
    180     return value;
    181 }
    182 
    183 static VAStatus
    184 create_surface(VASurfaceID * p_surface_id,
    185                uint32_t width, uint32_t height,
    186                uint32_t fourCC, uint32_t format)
    187 {
    188     VAStatus va_status;
    189     VASurfaceAttrib    surface_attrib;
    190     surface_attrib.type =  VASurfaceAttribPixelFormat;
    191     surface_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
    192     surface_attrib.value.type = VAGenericValueTypeInteger;
    193     surface_attrib.value.value.i = fourCC;
    194 
    195     va_status = vaCreateSurfaces(va_dpy,
    196                                  format,
    197                                  width ,
    198                                  height,
    199                                  p_surface_id,
    200                                  1,
    201                                  &surface_attrib,
    202                                  1);
    203    return va_status;
    204 }
    205 
    206 static VAStatus
    207 construct_nv12_mask_surface(VASurfaceID surface_id,
    208                             uint8_t min_luma,
    209                             uint8_t max_luma)
    210 {
    211     VAStatus va_status;
    212     VAImage surface_image;
    213     void *surface_p = NULL;
    214     unsigned char *y_dst, *u_dst, *v_dst;
    215     uint32_t row, col;
    216 
    217     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
    218     CHECK_VASTATUS(va_status, "vaDeriveImage");
    219 
    220     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
    221     CHECK_VASTATUS(va_status, "vaMapBuffer");
    222 
    223     y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
    224     u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    225     v_dst = u_dst;
    226 
    227     /* fill Y plane, the luma values of some pixels is in the range of min_luma~max_luma,
    228      * and others are out side of it, in luma key blending case, the pixels with Y value
    229      * exceeding the range will be hided*/
    230     for (row = 0; row < surface_image.height; row++) {
    231         if (row < surface_image.height / 4 || row > surface_image.height * 3 / 4)
    232             memset(y_dst, max_luma + 1, surface_image.pitches[0]);
    233         else
    234             memset(y_dst, (min_luma + max_luma) / 2, surface_image.pitches[0]);
    235 
    236         y_dst += surface_image.pitches[0];
    237      }
    238 
    239      /* fill UV plane */
    240      for (row = 0; row < surface_image.height / 2; row++) {
    241          for (col = 0; col < surface_image.width / 2; col++) {
    242              u_dst[col * 2] = 128;
    243              u_dst[col * 2 + 1] = 128;
    244         }
    245         u_dst += surface_image.pitches[1];
    246      }
    247 
    248     vaUnmapBuffer(va_dpy, surface_image.buf);
    249     vaDestroyImage(va_dpy, surface_image.image_id);
    250 
    251     return VA_STATUS_SUCCESS;
    252 }
    253 
    254 /* Load yv12 frame to NV12/YV12/I420 surface*/
    255 static VAStatus
    256 upload_yv12_frame_to_yuv_surface(FILE *fp,
    257                                  VASurfaceID surface_id)
    258 {
    259     VAStatus va_status;
    260     VAImage surface_image;
    261     unsigned char *y_src, *u_src, *v_src;
    262     unsigned char *y_dst, *u_dst, *v_dst;
    263     void *surface_p = NULL;
    264     uint32_t frame_size, i, row, col;
    265     size_t n_items;
    266     unsigned char * newImageBuffer = NULL;
    267 
    268     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
    269     CHECK_VASTATUS(va_status, "vaDeriveImage");
    270 
    271     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
    272     CHECK_VASTATUS(va_status, "vaMapBuffer");
    273 
    274     if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
    275         surface_image.format.fourcc == VA_FOURCC_I420 ||
    276         surface_image.format.fourcc == VA_FOURCC_NV12){
    277 
    278         frame_size = surface_image.width * surface_image.height * 3 / 2;
    279         newImageBuffer = (unsigned char*)malloc(frame_size);
    280         do {
    281             n_items = fread(newImageBuffer, frame_size, 1, fp);
    282         } while (n_items != 1);
    283 
    284         y_src = newImageBuffer;
    285         v_src = newImageBuffer + surface_image.width * surface_image.height;
    286         u_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4;
    287 
    288         y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
    289 
    290         if(surface_image.format.fourcc == VA_FOURCC_YV12){
    291             v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    292             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
    293         }else if(surface_image.format.fourcc == VA_FOURCC_I420){
    294             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    295             v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
    296         }else {
    297             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    298             v_dst = u_dst;
    299         }
    300 
    301         /* Y plane, directly copy */
    302         for (row = 0; row < surface_image.height; row++) {
    303             memcpy(y_dst, y_src, surface_image.width);
    304             y_dst += surface_image.pitches[0];
    305             y_src += surface_image.width;
    306         }
    307 
    308         /* UV plane */
    309         if (surface_image.format.fourcc == VA_FOURCC_YV12||
    310             surface_image.format.fourcc == VA_FOURCC_I420){
    311             /* UV plane */
    312             for (row = 0; row < surface_image.height /2; row ++){
    313                 memcpy(v_dst, v_src, surface_image.width/2);
    314                 memcpy(u_dst, u_src, surface_image.width/2);
    315 
    316                 v_src += surface_image.width/2;
    317                 u_src += surface_image.width/2;
    318 
    319                 if (surface_image.format.fourcc == VA_FOURCC_YV12){
    320                     v_dst += surface_image.pitches[1];
    321                     u_dst += surface_image.pitches[2];
    322                 } else {
    323                     v_dst += surface_image.pitches[2];
    324                     u_dst += surface_image.pitches[1];
    325                 }
    326             }
    327         } else if (surface_image.format.fourcc == VA_FOURCC_NV12){
    328             for (row = 0; row < surface_image.height / 2; row++) {
    329                 for (col = 0; col < surface_image.width / 2; col++) {
    330                     u_dst[col * 2] = u_src[col];
    331                     u_dst[col * 2 + 1] = v_src[col];
    332                 }
    333 
    334                 u_dst += surface_image.pitches[1];
    335                 u_src += (surface_image.width / 2);
    336                 v_src += (surface_image.width / 2);
    337             }
    338         }
    339      } else {
    340          printf("Not supported YUV surface fourcc !!! \n");
    341          return VA_STATUS_ERROR_INVALID_SURFACE;
    342      }
    343 
    344      if (newImageBuffer){
    345          free(newImageBuffer);
    346          newImageBuffer = NULL;
    347      }
    348 
    349      vaUnmapBuffer(va_dpy, surface_image.buf);
    350      vaDestroyImage(va_dpy, surface_image.image_id);
    351 
    352      return VA_STATUS_SUCCESS;
    353 }
    354 
    355 /* Store NV12/YV12/I420 surface to yv12 frame*/
    356 static VAStatus
    357 store_yuv_surface_to_yv12_frame(FILE *fp,
    358                             VASurfaceID surface_id)
    359 {
    360     VAStatus va_status;
    361     VAImageFormat image_format;
    362     VAImage surface_image;
    363     void *surface_p = NULL;
    364     unsigned char *y_src, *u_src, *v_src;
    365     unsigned char *y_dst, *u_dst, *v_dst;
    366     uint32_t frame_size, row, col;
    367     int32_t  ret, n_items;
    368     unsigned char * newImageBuffer = NULL;
    369 
    370     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
    371     CHECK_VASTATUS(va_status, "vaDeriveImage");
    372 
    373     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
    374     CHECK_VASTATUS(va_status, "vaMapBuffer");
    375 
    376     /* store the surface to one YV12 file or one bmp file*/
    377     if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
    378         surface_image.format.fourcc == VA_FOURCC_I420 ||
    379         surface_image.format.fourcc == VA_FOURCC_NV12){
    380 
    381         uint32_t y_size = surface_image.width * surface_image.height;
    382         uint32_t u_size = y_size/4;
    383 
    384         newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
    385 
    386         /* stored as YV12 format */
    387         y_dst = newImageBuffer;
    388         v_dst = newImageBuffer + y_size;
    389         u_dst = newImageBuffer + y_size + u_size;
    390 
    391         y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
    392         if (surface_image.format.fourcc == VA_FOURCC_YV12){
    393             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    394             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
    395         } else if(surface_image.format.fourcc == VA_FOURCC_I420){
    396             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    397             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
    398         } else if(surface_image.format.fourcc == VA_FOURCC_NV12){
    399             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
    400             v_src = u_src;
    401         }
    402 
    403         /* Y plane copy */
    404         for (row = 0; row < surface_image.height; row++) {
    405             memcpy(y_dst, y_src, surface_image.width);
    406             y_src += surface_image.pitches[0];
    407             y_dst += surface_image.width;
    408         }
    409 
    410         /* UV plane copy */
    411         if (surface_image.format.fourcc == VA_FOURCC_YV12||
    412             surface_image.format.fourcc == VA_FOURCC_I420){
    413             for (row = 0; row < surface_image.height /2; row ++){
    414                 memcpy(v_dst, v_src, surface_image.width/2);
    415                 memcpy(u_dst, u_src, surface_image.width/2);
    416 
    417                 v_dst += surface_image.width/2;
    418                 u_dst += surface_image.width/2;
    419 
    420                 if (surface_image.format.fourcc == VA_FOURCC_YV12){
    421                     v_src += surface_image.pitches[1];
    422                     u_src += surface_image.pitches[2];
    423                  } else {
    424                     v_src += surface_image.pitches[2];
    425                     u_src += surface_image.pitches[1];
    426                  }
    427              }
    428          } else if (surface_image.format.fourcc == VA_FOURCC_NV12){
    429              for (row = 0; row < surface_image.height / 2; row++) {
    430                  for (col = 0; col < surface_image.width /2; col++) {
    431                      u_dst[col] = u_src[col * 2];
    432                      v_dst[col] = u_src[col * 2 + 1];
    433                   }
    434 
    435                   u_src += surface_image.pitches[1];
    436                   u_dst += (surface_image.width / 2);
    437                   v_dst += (surface_image.width / 2);
    438              }
    439          }
    440 
    441          /* write frame to file */
    442          do {
    443              n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
    444          } while (n_items != 1);
    445 
    446      } else {
    447          printf("Not supported YUV surface fourcc !!! \n");
    448          return VA_STATUS_ERROR_INVALID_SURFACE;
    449      }
    450 
    451      if (newImageBuffer){
    452          free(newImageBuffer);
    453          newImageBuffer = NULL;
    454      }
    455 
    456      vaUnmapBuffer(va_dpy, surface_image.buf);
    457      vaDestroyImage(va_dpy, surface_image.image_id);
    458 
    459      return VA_STATUS_SUCCESS;
    460 }
    461 
    462 static VAStatus
    463 denoise_filter_init(VABufferID *filter_param_buf_id)
    464 {
    465     VAStatus va_status = VA_STATUS_SUCCESS;
    466     VAProcFilterParameterBuffer denoise_param;
    467     VABufferID denoise_param_buf_id;
    468     float intensity;
    469 
    470     VAProcFilterCap denoise_caps;
    471     uint32_t num_denoise_caps = 1;
    472     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
    473                                            VAProcFilterNoiseReduction,
    474                                            &denoise_caps, &num_denoise_caps);
    475     CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps");
    476 
    477     if (read_value_float(g_config_file_fd, "DENOISE_INTENSITY", &intensity)) {
    478         printf("Read denoise intensity failed, use default value");
    479         intensity = denoise_caps.range.default_value;
    480     }
    481     intensity = adjust_to_range(&denoise_caps.range, intensity);
    482 
    483     denoise_param.type  = VAProcFilterNoiseReduction;
    484     denoise_param.value = intensity;
    485 
    486     printf("Denoise intensity: %f\n", intensity);
    487 
    488     va_status = vaCreateBuffer(va_dpy, context_id,
    489                                VAProcFilterParameterBufferType, sizeof(denoise_param), 1,
    490                                &denoise_param, &denoise_param_buf_id);
    491     CHECK_VASTATUS(va_status,"vaCreateBuffer");
    492 
    493     *filter_param_buf_id = denoise_param_buf_id;
    494 
    495     return va_status;
    496 }
    497 
    498 static VAStatus
    499 deinterlace_filter_init(VABufferID *filter_param_buf_id)
    500 {
    501     VAStatus va_status = VA_STATUS_SUCCESS;
    502     VAProcFilterParameterBufferDeinterlacing deinterlacing_param;
    503     VABufferID deinterlacing_param_buf_id;
    504     char algorithm_str[MAX_LEN], flags_str[MAX_LEN];
    505     uint32_t i;
    506 
    507     /* read and check whether configured deinterlace algorithm is supported */
    508     deinterlacing_param.algorithm  = VAProcDeinterlacingBob;
    509     if (!read_value_string(g_config_file_fd, "DEINTERLACING_ALGORITHM", algorithm_str)) {
    510         printf("Deinterlacing algorithm in config: %s \n", algorithm_str);
    511         if (!strcmp(algorithm_str, "VAProcDeinterlacingBob"))
    512             deinterlacing_param.algorithm  = VAProcDeinterlacingBob;
    513         else if (!strcmp(algorithm_str, "VAProcDeinterlacingWeave"))
    514             deinterlacing_param.algorithm  = VAProcDeinterlacingWeave;
    515         else if (!strcmp(algorithm_str, "VAProcDeinterlacingMotionAdaptive"))
    516             deinterlacing_param.algorithm  = VAProcDeinterlacingMotionAdaptive;
    517         else if (!strcmp(algorithm_str, "VAProcDeinterlacingMotionCompensated"))
    518             deinterlacing_param.algorithm  = VAProcDeinterlacingMotionCompensated;
    519     } else {
    520         printf("Read deinterlace algorithm failed, use default algorithm");
    521         deinterlacing_param.algorithm  = VAProcDeinterlacingBob;
    522     }
    523 
    524     VAProcFilterCapDeinterlacing deinterlacing_caps[VAProcDeinterlacingCount];
    525     uint32_t num_deinterlacing_caps = VAProcDeinterlacingCount;
    526     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
    527                                            VAProcFilterDeinterlacing,
    528                                            &deinterlacing_caps, &num_deinterlacing_caps);
    529     CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps");
    530 
    531     for (i = 0; i < VAProcDeinterlacingCount; i ++)
    532        if (deinterlacing_caps[i].type == deinterlacing_param.algorithm)
    533          break;
    534 
    535     if (i == VAProcDeinterlacingCount) {
    536         printf("Deinterlacing algorithm: %d is not supported by driver, \
    537                 use defautl algorithm :%d \n",
    538                 deinterlacing_param.algorithm,
    539                 VAProcDeinterlacingBob);
    540         deinterlacing_param.algorithm = VAProcDeinterlacingBob;
    541     }
    542 
    543     /* read and check the deinterlace flags */
    544     deinterlacing_param.flags = 0;
    545     if (!read_value_string(g_config_file_fd, "DEINTERLACING_FLAG", flags_str)) {
    546         if (strstr(flags_str, "VA_DEINTERLACING_BOTTOM_FIELD_FIRST"))
    547             deinterlacing_param.flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST;
    548         if (strstr(flags_str, "VA_DEINTERLACING_BOTTOM_FIELD"))
    549             deinterlacing_param.flags |= VA_DEINTERLACING_BOTTOM_FIELD;
    550         if (strstr(flags_str, "VA_DEINTERLACING_ONE_FIELD"))
    551             deinterlacing_param.flags |= VA_DEINTERLACING_ONE_FIELD;
    552     }
    553 
    554     deinterlacing_param.type  = VAProcFilterDeinterlacing;
    555 
    556     /* create deinterlace fitler buffer */
    557     va_status = vaCreateBuffer(va_dpy, context_id,
    558                                VAProcFilterParameterBufferType, sizeof(deinterlacing_param), 1,
    559                                &deinterlacing_param, &deinterlacing_param_buf_id);
    560     CHECK_VASTATUS(va_status, "vaCreateBuffer");
    561 
    562     *filter_param_buf_id = deinterlacing_param_buf_id;
    563 
    564     return va_status;
    565 }
    566 
    567 static VAStatus
    568 sharpening_filter_init(VABufferID *filter_param_buf_id)
    569 {
    570     VAStatus va_status;
    571     VAProcFilterParameterBuffer sharpening_param;
    572     VABufferID sharpening_param_buf_id;
    573     float intensity;
    574 
    575     VAProcFilterCap sharpening_caps;
    576     uint32_t num_sharpening_caps = 1;
    577     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
    578                 VAProcFilterSharpening,
    579                 &sharpening_caps, &num_sharpening_caps);
    580     CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps");
    581 
    582     if(read_value_float(g_config_file_fd, "SHARPENING_INTENSITY", &intensity)) {
    583         printf("Read sharpening intensity failed, use default value.");
    584         intensity = sharpening_caps.range.default_value;
    585     }
    586 
    587     intensity = adjust_to_range(&sharpening_caps.range, intensity);
    588     printf("Sharpening intensity: %f\n", intensity);
    589     sharpening_param.value = intensity;
    590 
    591     sharpening_param.type  = VAProcFilterSharpening;
    592 
    593     /* create sharpening fitler buffer */
    594     va_status = vaCreateBuffer(va_dpy, context_id,
    595                                VAProcFilterParameterBufferType, sizeof(sharpening_param), 1,
    596                                &sharpening_param, &sharpening_param_buf_id);
    597 
    598     *filter_param_buf_id = sharpening_param_buf_id;
    599 
    600     return va_status;
    601 }
    602 
    603 static VAStatus
    604 color_balance_filter_init(VABufferID *filter_param_buf_id)
    605 {
    606     VAStatus va_status;
    607     VAProcFilterParameterBufferColorBalance color_balance_param[4];
    608     VABufferID color_balance_param_buf_id;
    609     float value;
    610     uint32_t i, count;
    611     int8_t status;
    612 
    613     VAProcFilterCapColorBalance color_balance_caps[VAProcColorBalanceCount];
    614     unsigned int num_color_balance_caps = VAProcColorBalanceCount;
    615     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
    616                                            VAProcFilterColorBalance,
    617                                            &color_balance_caps, &num_color_balance_caps);
    618     CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps");
    619 
    620     count = 0;
    621     printf("Color balance params: ");
    622     for (i = 0; i < num_color_balance_caps; i++) {
    623         if (color_balance_caps[i].type == VAProcColorBalanceHue) {
    624             color_balance_param[count].attrib  = VAProcColorBalanceHue;
    625             status = read_value_float(g_config_file_fd, "COLOR_BALANCE_HUE", &value);
    626             printf("Hue: ");
    627         } else if (color_balance_caps[i].type == VAProcColorBalanceSaturation) {
    628             color_balance_param[count].attrib  = VAProcColorBalanceSaturation;
    629             status = read_value_float(g_config_file_fd, "COLOR_BALANCE_SATURATION", &value);
    630             printf("Saturation: ");
    631         } else if (color_balance_caps[i].type == VAProcColorBalanceBrightness) {
    632             color_balance_param[count].attrib  = VAProcColorBalanceBrightness;
    633             status = read_value_float(g_config_file_fd, "COLOR_BALANCE_BRIGHTNESS", &value);
    634             printf("Brightness: ");
    635         } else if (color_balance_caps[i].type == VAProcColorBalanceContrast) {
    636             color_balance_param[count].attrib  = VAProcColorBalanceContrast;
    637             status = read_value_float(g_config_file_fd, "COLOR_BALANCE_CONTRAST", &value);
    638             printf("Contrast: ");
    639         } else {
    640             continue;
    641         }
    642 
    643         if (status)
    644             value = color_balance_caps[i].range.default_value;
    645         else
    646             value = adjust_to_range(&color_balance_caps[i].range, value);
    647 
    648         color_balance_param[count].value = value;
    649         color_balance_param[count].type  = VAProcFilterColorBalance;
    650         count++;
    651 
    652         printf("%4f,  ", value);
    653     }
    654     printf("\n");
    655 
    656     va_status = vaCreateBuffer(va_dpy, context_id,
    657                                VAProcFilterParameterBufferType, sizeof(color_balance_param), 4,
    658                                color_balance_param, &color_balance_param_buf_id);
    659 
    660     *filter_param_buf_id = color_balance_param_buf_id;
    661 
    662     return va_status;
    663 }
    664 
    665 static VAStatus
    666 blending_state_init(VABlendState *state)
    667 {
    668     VAStatus va_status = VA_STATUS_SUCCESS;
    669     char blending_flags_str[MAX_LEN];
    670     float global_alpha;
    671     uint32_t min_luma, max_luma;
    672 
    673     /* read and check blend state */
    674     state->flags = 0;
    675     if (!read_value_string(g_config_file_fd, "BLENDING_FLAGS", blending_flags_str)){
    676         if (strstr(blending_flags_str, "VA_BLEND_GLOBAL_ALPHA")) {
    677            if (read_value_float(g_config_file_fd, "BLENDING_GLOBAL_ALPHA", &global_alpha)) {
    678                global_alpha = 1.0  ;
    679                printf("Use default global alpha : %4f \n", global_alpha);
    680            }
    681            state->flags |= VA_BLEND_GLOBAL_ALPHA;
    682            state->global_alpha = global_alpha;
    683         }
    684         if (strstr(blending_flags_str, "VA_BLEND_LUMA_KEY")) {
    685             if (read_value_uint8(g_config_file_fd, "BLENDING_MIN_LUMA", &g_blending_min_luma)) {
    686                 g_blending_min_luma = 1;
    687                 printf("Use default min luma : %3d \n", g_blending_min_luma);
    688             }
    689             if (read_value_uint8(g_config_file_fd, "BLENDING_MAX_LUMA", &g_blending_max_luma)) {
    690                 g_blending_max_luma = 254;
    691                 printf("Use default max luma : %3d \n", g_blending_max_luma);
    692             }
    693             state->flags |= VA_BLEND_LUMA_KEY;
    694             state->min_luma = g_blending_min_luma * 1.0 / 256;
    695             state->max_luma = g_blending_max_luma * 1.0 / 256;
    696         }
    697 
    698         printf("Blending type = %s, alpha = %f, min_luma = %3d, max_luma = %3d \n",
    699               blending_flags_str, global_alpha, min_luma, max_luma);
    700     }
    701 
    702     VAProcPipelineCaps pipeline_caps;
    703     va_status = vaQueryVideoProcPipelineCaps(va_dpy, context_id,
    704                 NULL, 0, &pipeline_caps);
    705     CHECK_VASTATUS(va_status,"vaQueryVideoProcPipelineCaps");
    706 
    707     if (!pipeline_caps.blend_flags){
    708         printf("Blending is not supported in driver! \n");
    709         return VA_STATUS_ERROR_UNIMPLEMENTED;
    710     }
    711 
    712     if (! (pipeline_caps.blend_flags & state->flags)) {
    713         printf("Driver do not support current blending flags: %d", state->flags);
    714         return VA_STATUS_ERROR_UNIMPLEMENTED;
    715     }
    716 
    717     return va_status;
    718 }
    719 
    720 static VAStatus
    721 video_frame_process(VAProcFilterType filter_type,
    722                     uint32_t frame_idx,
    723                     VASurfaceID in_surface_id,
    724                     VASurfaceID out_surface_id)
    725 {
    726     VAStatus va_status;
    727     VAProcPipelineParameterBuffer pipeline_param;
    728     VARectangle surface_region, output_region;
    729     VABufferID pipeline_param_buf_id = VA_INVALID_ID;
    730     VABufferID filter_param_buf_id = VA_INVALID_ID;
    731     VABlendState state ;
    732     uint32_t filter_count = 1;
    733 
    734     /* create denoise_filter buffer id */
    735     switch(filter_type){
    736       case VAProcFilterNoiseReduction:
    737            denoise_filter_init(&filter_param_buf_id);
    738            break;
    739       case VAProcFilterDeinterlacing:
    740            deinterlace_filter_init(&filter_param_buf_id);
    741            break;
    742       case VAProcFilterSharpening:
    743            sharpening_filter_init(&filter_param_buf_id);
    744            break;
    745       case VAProcFilterColorBalance:
    746            color_balance_filter_init(&filter_param_buf_id);
    747            break;
    748       default :
    749            filter_count = 0;
    750          break;
    751     }
    752 
    753     /* Fill pipeline buffer */
    754     surface_region.x = 0;
    755     surface_region.y = 0;
    756     surface_region.width = g_in_pic_width;
    757     surface_region.height = g_in_pic_height;
    758     output_region.x = 0;
    759     output_region.y = 0;
    760     output_region.width = g_out_pic_width;
    761     output_region.height = g_out_pic_height;
    762 
    763     memset(&pipeline_param, 0, sizeof(pipeline_param));
    764     pipeline_param.surface = in_surface_id;
    765     pipeline_param.surface_region = &surface_region;
    766     pipeline_param.output_region = &output_region;
    767 
    768     pipeline_param.filter_flags = 0;
    769     pipeline_param.filters      = &filter_param_buf_id;
    770     pipeline_param.num_filters  = filter_count;
    771 
    772     /* Blending related state */
    773     if (g_blending_enabled){
    774         blending_state_init(&state);
    775         pipeline_param.blend_state = &state;
    776     }
    777 
    778     va_status = vaCreateBuffer(va_dpy,
    779                                context_id,
    780                                VAProcPipelineParameterBufferType,
    781                                sizeof(pipeline_param),
    782                                1,
    783                                &pipeline_param,
    784                                &pipeline_param_buf_id);
    785     CHECK_VASTATUS(va_status, "vaCreateBuffer");
    786 
    787     va_status = vaBeginPicture(va_dpy,
    788                                context_id,
    789                                out_surface_id);
    790     CHECK_VASTATUS(va_status, "vaBeginPicture");
    791 
    792     va_status = vaRenderPicture(va_dpy,
    793                                 context_id,
    794                                 &pipeline_param_buf_id,
    795                                 1);
    796     CHECK_VASTATUS(va_status, "vaRenderPicture");
    797 
    798     va_status = vaEndPicture(va_dpy, context_id);
    799     CHECK_VASTATUS(va_status, "vaEndPicture");
    800 
    801     if (filter_param_buf_id != VA_INVALID_ID)
    802         vaDestroyBuffer(va_dpy,filter_param_buf_id);
    803 
    804     if (pipeline_param_buf_id != VA_INVALID_ID)
    805         vaDestroyBuffer(va_dpy,pipeline_param_buf_id);
    806 
    807     return va_status;
    808 }
    809 
    810 static VAStatus
    811 vpp_context_create()
    812 {
    813     VAStatus va_status = VA_STATUS_SUCCESS;
    814     uint32_t i;
    815 
    816     /* VA driver initialization */
    817     va_dpy = va_open_display();
    818     int32_t major_ver, minor_ver;
    819     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
    820     assert(va_status == VA_STATUS_SUCCESS);
    821 
    822     /* Check whether VPP is supported by driver */
    823     VAEntrypoint entrypoints[5];
    824     int32_t num_entrypoints;
    825     num_entrypoints = vaMaxNumEntrypoints(va_dpy);
    826     va_status = vaQueryConfigEntrypoints(va_dpy,
    827                                          VAProfileNone,
    828                                          entrypoints,
    829                                          &num_entrypoints);
    830     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
    831 
    832     for	(i = 0; i < num_entrypoints; i++) {
    833         if (entrypoints[i] == VAEntrypointVideoProc)
    834             break;
    835     }
    836 
    837     if (i == num_entrypoints) {
    838         printf("VPP is not supported by driver\n");
    839         assert(0);
    840     }
    841 
    842     /* Render target surface format check */
    843     VAConfigAttrib attrib;
    844     attrib.type = VAConfigAttribRTFormat;
    845     va_status = vaGetConfigAttributes(va_dpy,
    846                                       VAProfileNone,
    847                                       VAEntrypointVideoProc,
    848                                       &attrib,
    849                                      1);
    850     CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
    851     if ((attrib.value != g_out_format)) {
    852         printf("RT format %d is not supported by VPP !\n",g_out_format);
    853         assert(0);
    854     }
    855 
    856     /* Create surface/config/context for VPP pipeline */
    857     va_status = create_surface(&g_in_surface_id, g_in_pic_width, g_in_pic_height,
    858                                 g_in_fourcc, g_in_format);
    859     CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
    860 
    861     va_status = create_surface(&g_out_surface_id, g_out_pic_width, g_out_pic_height,
    862                                 g_out_fourcc, g_out_format);
    863     CHECK_VASTATUS(va_status, "vaCreateSurfaces for output");
    864 
    865     va_status = vaCreateConfig(va_dpy,
    866                                VAProfileNone,
    867                                VAEntrypointVideoProc,
    868                                &attrib,
    869                                1,
    870                                &config_id);
    871     CHECK_VASTATUS(va_status, "vaCreateConfig");
    872 
    873     /* Source surface format check */
    874     uint32_t num_surf_attribs = VASurfaceAttribCount;
    875     VASurfaceAttrib * surf_attribs = (VASurfaceAttrib*)
    876               malloc(sizeof(VASurfaceAttrib) * num_surf_attribs);
    877     if (!surf_attribs)
    878        assert(0);
    879 
    880     va_status = vaQuerySurfaceAttributes(va_dpy,
    881                                         config_id,
    882                                         surf_attribs,
    883                                         &num_surf_attribs);
    884 
    885     if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) {
    886         surf_attribs = (VASurfaceAttrib*)realloc(surf_attribs,
    887                         sizeof(VASurfaceAttrib) * num_surf_attribs);
    888          if (!surf_attribs)
    889              assert(0);
    890          va_status = vaQuerySurfaceAttributes(va_dpy,
    891                                               config_id,
    892                                               surf_attribs,
    893                                               &num_surf_attribs);
    894     }
    895     CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes");
    896 
    897     for (i = 0; i < num_surf_attribs; i++) {
    898         if (surf_attribs[i].type == VASurfaceAttribPixelFormat &&
    899             surf_attribs[i].value.value.i == g_in_fourcc)
    900             break;
    901     }
    902     free(surf_attribs);
    903 
    904     if (i == num_surf_attribs) {
    905         printf("Input fourCC %d  is not supported by VPP !\n", g_in_fourcc);
    906         assert(0);
    907     }
    908 
    909     va_status = vaCreateContext(va_dpy,
    910                                 config_id,
    911                                 g_out_pic_width,
    912                                 g_out_pic_height,
    913                                 VA_PROGRESSIVE,
    914                                 &g_out_surface_id,
    915                                 1,
    916                                 &context_id);
    917     CHECK_VASTATUS(va_status, "vaCreateContext");
    918 
    919 
    920     /* Validate  whether currect filter is supported */
    921     if (g_filter_type != VAProcFilterNone) {
    922         uint32_t supported_filter_num = VAProcFilterCount;
    923         VAProcFilterType supported_filter_types[VAProcFilterCount];
    924 
    925         va_status = vaQueryVideoProcFilters(va_dpy,
    926                                             context_id,
    927                                             supported_filter_types,
    928                                             &supported_filter_num);
    929 
    930         CHECK_VASTATUS(va_status, "vaQueryVideoProcFilters");
    931 
    932         for (i = 0; i < supported_filter_num; i++){
    933             if (supported_filter_types[i] == g_filter_type)
    934                 break;
    935         }
    936 
    937         if (i == supported_filter_num) {
    938             printf("VPP filter type %s is not supported by driver !\n", g_filter_type_name);
    939             assert(0);
    940         }
    941     }
    942 
    943     return va_status;
    944 }
    945 
    946 static void
    947 vpp_context_destroy()
    948 {
    949     /* Release resource */
    950     vaDestroySurfaces(va_dpy, &g_in_surface_id, 1);
    951     vaDestroySurfaces(va_dpy, &g_out_surface_id, 1);
    952     vaDestroyContext(va_dpy, context_id);
    953     vaDestroyConfig(va_dpy, config_id);
    954 
    955     vaTerminate(va_dpy);
    956     va_close_display(va_dpy);
    957 }
    958 
    959 static int8_t
    960 parse_fourcc_and_format(char *str, uint32_t *fourcc, uint32_t *format)
    961 {
    962     if (!strcmp(str, "YV12")){
    963         *fourcc = VA_FOURCC('Y', 'V', '1', '2');
    964         *format = VA_RT_FORMAT_YUV420;
    965     } else if(!strcmp(str, "I420")){
    966         *fourcc = VA_FOURCC('I', '4', '2', '0');
    967         *format = VA_RT_FORMAT_YUV420;
    968     } else if(!strcmp(str, "NV12")){
    969         *fourcc = VA_FOURCC('N', 'V', '1', '2');
    970         *format = VA_RT_FORMAT_YUV420;
    971     } else{
    972         printf("Not supported format: %s! Currently only support following format: %s\n",
    973          str, "YV12, I420, NV12");
    974         assert(0);
    975     }
    976     return 0;
    977 }
    978 
    979 static int8_t
    980 parse_basic_parameters()
    981 {
    982     char str[MAX_LEN];
    983 
    984     /* Read src frame file information */
    985     read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src_file_name);
    986     read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_in_pic_width);
    987     read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_in_pic_height);
    988     read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str);
    989     parse_fourcc_and_format(str, &g_in_fourcc, &g_in_format);
    990 
    991     /* Read dst frame file information */
    992     read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst_file_name);
    993     read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_out_pic_width);
    994     read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT",&g_out_pic_height);
    995     read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str);
    996     parse_fourcc_and_format(str, &g_out_fourcc, &g_out_format);
    997 
    998     read_value_uint32(g_config_file_fd, "FRAME_SUM", &g_frame_count);
    999 
   1000     /* Read filter type */
   1001     if (read_value_string(g_config_file_fd, "FILTER_TYPE", g_filter_type_name)){
   1002         printf("Read filter type error !\n");
   1003         assert(0);
   1004     }
   1005 
   1006     if (!strcmp(g_filter_type_name, "VAProcFilterNoiseReduction"))
   1007         g_filter_type = VAProcFilterNoiseReduction;
   1008     else if (!strcmp(g_filter_type_name, "VAProcFilterDeinterlacing"))
   1009         g_filter_type = VAProcFilterDeinterlacing;
   1010     else if (!strcmp(g_filter_type_name, "VAProcFilterSharpening"))
   1011         g_filter_type = VAProcFilterSharpening;
   1012     else if (!strcmp(g_filter_type_name, "VAProcFilterColorBalance"))
   1013         g_filter_type = VAProcFilterColorBalance;
   1014     else if (!strcmp(g_filter_type_name, "VAProcFilterNone"))
   1015         g_filter_type = VAProcFilterNone;
   1016     else {
   1017         printf("Unsupported filter type :%s \n", g_filter_type_name);
   1018         return -1;
   1019     }
   1020 
   1021     /* Check whether blending is enabled */
   1022     if (read_value_uint8(g_config_file_fd, "BLENDING_ENABLED", &g_blending_enabled))
   1023         g_blending_enabled = 0;
   1024 
   1025     if (g_blending_enabled)
   1026         printf("Blending will be done \n");
   1027 
   1028     if (g_in_pic_width != g_out_pic_width ||
   1029         g_in_pic_height != g_out_pic_height)
   1030         printf("Scaling will be done : from %4d x %4d to %4d x %4d \n",
   1031                 g_in_pic_width, g_in_pic_height,
   1032                 g_out_pic_width, g_out_pic_height);
   1033 
   1034     if (g_in_fourcc != g_out_fourcc)
   1035         printf("Format conversion will be done: from %d to %d \n",
   1036                g_in_fourcc, g_out_fourcc);
   1037 
   1038     return 0;
   1039 }
   1040 
   1041 int32_t main(int32_t argc, char *argv[])
   1042 {
   1043     VAStatus va_status;
   1044     uint32_t i;
   1045 
   1046     if (argc != 2){
   1047         printf("Input error! please specify the configure file \n");
   1048         return -1;
   1049     }
   1050 
   1051     /* Parse the configure file for video process*/
   1052     strcpy(g_config_file_name, argv[1]);
   1053     if (NULL == (g_config_file_fd = fopen(g_config_file_name, "r"))){
   1054         printf("Open configure file %s failed!\n",g_config_file_name);
   1055         assert(0);
   1056     }
   1057 
   1058     /* Parse basic parameters */
   1059     if (parse_basic_parameters()){
   1060         printf("Parse parameters in configure file error\n");
   1061         assert(0);
   1062     }
   1063 
   1064     va_status = vpp_context_create();
   1065     if (va_status != VA_STATUS_SUCCESS) {
   1066         printf("vpp context create failed \n");
   1067         assert(0);
   1068     }
   1069 
   1070     /* Video frame fetch, process and store */
   1071     if (NULL == (g_src_file_fd = fopen(g_src_file_name, "r"))){
   1072         printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n",
   1073                 g_src_file_name, g_config_file_name);
   1074         assert(0);
   1075     }
   1076 
   1077     if (NULL == (g_dst_file_fd = fopen(g_dst_file_name, "w"))){
   1078         printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n",
   1079                g_dst_file_name, g_config_file_name);
   1080         assert(0);
   1081     }
   1082 
   1083     printf("\nStart to process, processing type is %s ...\n", g_filter_type_name);
   1084     struct timeval start_time, end_time;
   1085     gettimeofday(&start_time, NULL);
   1086 
   1087     for (i = 0; i < g_frame_count; i ++){
   1088         if (g_blending_enabled) {
   1089             construct_nv12_mask_surface(g_in_surface_id, g_blending_min_luma, g_blending_max_luma);
   1090             upload_yv12_frame_to_yuv_surface(g_src_file_fd, g_out_surface_id);
   1091         } else {
   1092             upload_yv12_frame_to_yuv_surface(g_src_file_fd, g_in_surface_id);
   1093         }
   1094 
   1095         video_frame_process(g_filter_type, i, g_in_surface_id, g_out_surface_id);
   1096         store_yuv_surface_to_yv12_frame(g_dst_file_fd, g_out_surface_id);
   1097     }
   1098 
   1099     gettimeofday(&end_time, NULL);
   1100     float duration = (end_time.tv_sec - start_time.tv_sec) +
   1101                      (end_time.tv_usec - start_time.tv_usec)/1000000.0;
   1102     printf("Finish processing, performance: \n" );
   1103     printf("%d frames processed in: %f s, ave time = %.6fs \n",g_frame_count, duration, duration/g_frame_count);
   1104 
   1105     if (g_src_file_fd)
   1106        fclose(g_src_file_fd);
   1107 
   1108     if (g_dst_file_fd)
   1109        fclose(g_dst_file_fd);
   1110 
   1111     if (g_config_file_fd)
   1112        fclose(g_config_file_fd);
   1113 
   1114     vpp_context_destroy();
   1115 
   1116     return 0;
   1117 }
   1118 
   1119