| /* |
| * Copyright (c) 2014 Intel Corporation. All Rights Reserved. |
| * |
| * 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, sub license, 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 (including the |
| * next paragraph) 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 NON-INFRINGEMENT. |
| * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS 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 deinterlace, denoise, color balance, sharpening, |
| * blending, scaling and several surface format conversion. |
| * Usage: vavpp process.cfg |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <sys/time.h> |
| #include <assert.h> |
| #include <va/va.h> |
| #include <va/va_vpp.h> |
| #include "va_display.h" |
| |
| #define BLEND_ON 0 |
| |
| #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); \ |
| } |
| |
| static VADisplay va_dpy = NULL; |
| static VAContextID context_id = 0; |
| static VAConfigID config_id = 0; |
| static VAProcFilterType g_filter_type = VAProcFilterNone; |
| static VASurfaceID g_in_surface_id = VA_INVALID_ID; |
| static VASurfaceID g_out_surface_id = VA_INVALID_ID; |
| |
| static FILE* g_config_file_fd = NULL; |
| static FILE* g_src_file_fd = NULL; |
| static FILE* g_dst_file_fd = NULL; |
| |
| static char g_config_file_name[MAX_LEN]; |
| static char g_src_file_name[MAX_LEN]; |
| static char g_dst_file_name[MAX_LEN]; |
| static char g_filter_type_name[MAX_LEN]; |
| |
| static uint32_t g_in_pic_width = 352; |
| static uint32_t g_in_pic_height = 288; |
| static uint32_t g_out_pic_width = 352; |
| static uint32_t g_out_pic_height = 288; |
| |
| static uint32_t g_in_fourcc = VA_FOURCC('N', 'V', '1', '2'); |
| static uint32_t g_in_format = VA_RT_FORMAT_YUV420; |
| static uint32_t g_out_fourcc = VA_FOURCC('N', 'V', '1', '2'); |
| static uint32_t g_out_format = VA_RT_FORMAT_YUV420; |
| 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'); |
| |
| static uint8_t g_blending_enabled = 0; |
| static uint8_t g_blending_min_luma = 1; |
| static uint8_t g_blending_max_luma = 254; |
| |
| static uint32_t g_frame_count = 0; |
| |
| static int8_t |
| read_value_string(FILE *fp, const char* field_name, char* value) |
| { |
| char strLine[MAX_LEN]; |
| char* field; |
| char* str; |
| 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_uint8(FILE* fp, const char* field_name, uint8_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 = (uint8_t)atoi(str); |
| return 0; |
| } |
| |
| 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 int8_t |
| read_value_float(FILE *fp, const char* field_name, float* value) |
| { |
| char str[MAX_LEN]; |
| if (read_value_string(fp, field_name, str)) { |
| printf("Failed to find float field: %s \n",field_name); |
| return -1; |
| } |
| |
| *value = atof(str); |
| return 0; |
| } |
| |
| static float |
| adjust_to_range(VAProcFilterValueRange *range, float value) |
| { |
| if (value < range->min_value || value > range->max_value){ |
| printf("Value: %f exceed range: (%f ~ %f), force to use default: %f \n", |
| value, range->min_value, range->max_value, range->default_value); |
| return range->default_value; |
| } |
| |
| return value; |
| } |
| |
| static VAStatus |
| create_surface(VASurfaceID * p_surface_id, |
| uint32_t width, uint32_t height, |
| uint32_t fourCC, uint32_t format) |
| { |
| VAStatus va_status; |
| VASurfaceAttrib surface_attrib; |
| surface_attrib.type = VASurfaceAttribPixelFormat; |
| surface_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE; |
| surface_attrib.value.type = VAGenericValueTypeInteger; |
| surface_attrib.value.value.i = fourCC; |
| |
| va_status = vaCreateSurfaces(va_dpy, |
| format, |
| width , |
| height, |
| p_surface_id, |
| 1, |
| &surface_attrib, |
| 1); |
| return va_status; |
| } |
| |
| static VAStatus |
| construct_nv12_mask_surface(VASurfaceID surface_id, |
| uint8_t min_luma, |
| uint8_t max_luma) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_dst, *u_dst; |
| uint32_t row, col; |
| |
| 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"); |
| |
| y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| |
| /* fill Y plane, the luma values of some pixels is in the range of min_luma~max_luma, |
| * and others are out side of it, in luma key blending case, the pixels with Y value |
| * exceeding the range will be hided*/ |
| for (row = 0; row < surface_image.height; row++) { |
| if (row < surface_image.height / 4 || row > surface_image.height * 3 / 4) |
| memset(y_dst, max_luma + 1, surface_image.pitches[0]); |
| else |
| memset(y_dst, (min_luma + max_luma) / 2, surface_image.pitches[0]); |
| |
| y_dst += surface_image.pitches[0]; |
| } |
| |
| /* fill UV plane */ |
| for (row = 0; row < surface_image.height / 2; row++) { |
| for (col = 0; col < surface_image.width / 2; col++) { |
| u_dst[col * 2] = 128; |
| u_dst[col * 2 + 1] = 128; |
| } |
| u_dst += surface_image.pitches[1]; |
| } |
| |
| vaUnmapBuffer(va_dpy, surface_image.buf); |
| vaDestroyImage(va_dpy, surface_image.image_id); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| /* Load yuv frame to NV12/YV12/I420 surface*/ |
| static VAStatus |
| upload_yuv_frame_to_yuv_surface(FILE *fp, |
| VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| unsigned char *y_src, *u_src, *v_src; |
| unsigned char *y_dst, *u_dst, *v_dst; |
| void *surface_p = NULL; |
| uint32_t frame_size, row, col; |
| size_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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 (surface_image.format.fourcc == VA_FOURCC_YV12 || |
| surface_image.format.fourcc == VA_FOURCC_I420 || |
| 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; |
| if (g_src_file_fourcc == VA_FOURCC_I420) { |
| u_src = newImageBuffer + surface_image.width * surface_image.height; |
| v_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4; |
| } else if (g_src_file_fourcc == VA_FOURCC_YV12) { |
| v_src = newImageBuffer + surface_image.width * surface_image.height; |
| u_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4; |
| } else if (g_src_file_fourcc == VA_FOURCC_NV12) { |
| u_src = newImageBuffer + surface_image.width * surface_image.height; |
| v_src = u_src; |
| } else { |
| printf("Not supported YUV fourcc for input file !!!\n"); |
| free(newImageBuffer); |
| return VA_STATUS_ERROR_INVALID_SURFACE; |
| } |
| |
| y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| if(surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]); |
| }else if(surface_image.format.fourcc == VA_FOURCC_I420){ |
| u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]); |
| }else { |
| 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 */ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12|| |
| surface_image.format.fourcc == VA_FOURCC_I420){ |
| for (row = 0; row < surface_image.height /2; row ++){ |
| if (g_src_file_fourcc == VA_FOURCC_I420 || |
| g_src_file_fourcc == VA_FOURCC_YV12) { |
| memcpy(v_dst, v_src, surface_image.width/2); |
| memcpy(u_dst, u_src, surface_image.width/2); |
| |
| v_src += surface_image.width/2; |
| u_src += surface_image.width/2; |
| } else { |
| for (col = 0; col < surface_image.width / 2; col++) { |
| u_dst[col] = u_src[col * 2]; |
| v_dst[col] = u_src[col * 2 + 1]; |
| } |
| |
| u_src += surface_image.width; |
| v_src = u_src; |
| } |
| |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_dst += surface_image.pitches[1]; |
| u_dst += surface_image.pitches[2]; |
| } else { |
| v_dst += surface_image.pitches[2]; |
| u_dst += surface_image.pitches[1]; |
| } |
| } |
| } else if (surface_image.format.fourcc == VA_FOURCC_NV12){ |
| for (row = 0; row < surface_image.height / 2; row++) { |
| if (g_src_file_fourcc == VA_FOURCC_I420 || |
| g_src_file_fourcc == VA_FOURCC_YV12) { |
| for (col = 0; col < surface_image.width / 2; col++) { |
| u_dst[col * 2] = u_src[col]; |
| u_dst[col * 2 + 1] = v_src[col]; |
| } |
| |
| u_src += (surface_image.width / 2); |
| v_src += (surface_image.width / 2); |
| } else { |
| memcpy(u_dst, u_src, surface_image.width); |
| u_src += surface_image.width; |
| v_src = u_src; |
| } |
| |
| u_dst += surface_image.pitches[1]; |
| } |
| } |
| } else if ((surface_image.format.fourcc == VA_FOURCC_YUY2 && |
| g_src_file_fourcc == VA_FOURCC_YUY2) || |
| (surface_image.format.fourcc == VA_FOURCC_UYVY && |
| g_src_file_fourcc == VA_FOURCC_UYVY) || |
| (surface_image.format.fourcc == VA_FOURCC_AYUV && |
| g_src_file_fourcc == VA_FOURCC_AYUV)) { |
| uint32_t byte_per_pixel = (g_src_file_fourcc == VA_FOURCC_AYUV) ? 4 : 2; |
| |
| frame_size = surface_image.width * surface_image.height * byte_per_pixel; |
| newImageBuffer = (unsigned char*)malloc(frame_size); |
| assert(newImageBuffer); |
| |
| do { |
| n_items = fread(newImageBuffer, frame_size, 1, fp); |
| } while (n_items != 1); |
| |
| y_src = newImageBuffer; |
| y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| /* plane 0, directly copy */ |
| for (row = 0; row < surface_image.height; row++) { |
| memcpy(y_dst, y_src, surface_image.width * byte_per_pixel); |
| y_src += surface_image.width * byte_per_pixel; |
| y_dst += surface_image.pitches[0]; |
| } |
| } else if ((surface_image.format.fourcc == VA_FOURCC_P010 && |
| g_src_file_fourcc == VA_FOURCC_P010) || |
| (surface_image.format.fourcc == VA_FOURCC_I010 && |
| g_src_file_fourcc == VA_FOURCC_I010)) { |
| 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; |
| y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| /* plane 0, directly copy */ |
| for (row = 0; row < surface_image.height; row++) { |
| memcpy(y_dst, y_src, surface_image.width * 2); |
| y_src += surface_image.width * 2; |
| y_dst += surface_image.pitches[0]; |
| } |
| |
| /* UV plane */ |
| if (surface_image.format.fourcc == VA_FOURCC_I010) { |
| assert(g_src_file_fourcc == VA_FOURCC_I010); |
| |
| u_src = newImageBuffer + surface_image.width * surface_image.height * 2; |
| v_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 2; |
| |
| 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 / 2; row++) { |
| memcpy(u_dst, u_src, surface_image.width); |
| memcpy(v_dst, v_src, surface_image.width); |
| |
| u_src += surface_image.width; |
| v_src += surface_image.width; |
| |
| u_dst += surface_image.pitches[1]; |
| v_dst += surface_image.pitches[2]; |
| } |
| } else if (surface_image.format.fourcc == VA_FOURCC_P010){ |
| assert(g_src_file_fourcc == VA_FOURCC_P010); |
| |
| u_src = newImageBuffer + surface_image.width * surface_image.height * 2; |
| v_src = u_src; |
| |
| u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| v_dst = u_dst; |
| |
| for (row = 0; row < surface_image.height / 2; row++) { |
| memcpy(u_dst, u_src, surface_image.width * 2); |
| |
| u_src += surface_image.width * 2; |
| v_src = u_src; |
| |
| u_dst += surface_image.pitches[1]; |
| v_dst = u_dst; |
| } |
| } |
| } else if ((surface_image.format.fourcc == VA_FOURCC_RGBA && |
| g_src_file_fourcc == VA_FOURCC_RGBA) || |
| (surface_image.format.fourcc == VA_FOURCC_RGBX && |
| g_src_file_fourcc == VA_FOURCC_RGBX) || |
| (surface_image.format.fourcc == VA_FOURCC_BGRA && |
| g_src_file_fourcc == VA_FOURCC_BGRA) || |
| (surface_image.format.fourcc == VA_FOURCC_BGRX && |
| g_src_file_fourcc == VA_FOURCC_BGRX)) { |
| frame_size = surface_image.width * surface_image.height * 4; |
| newImageBuffer = (unsigned char*)malloc(frame_size); |
| assert(newImageBuffer); |
| |
| do { |
| n_items = fread(newImageBuffer, frame_size, 1, fp); |
| } while (n_items != 1); |
| |
| y_src = newImageBuffer; |
| y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| /* plane 0, directly copy */ |
| for (row = 0; row < surface_image.height; row++) { |
| memcpy(y_dst, y_src, surface_image.width * 4); |
| y_src += surface_image.width * 4; |
| y_dst += surface_image.pitches[0]; |
| } |
| } else { |
| printf("Not supported YUV 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; |
| } |
| |
| /* Store NV12/YV12/I420 surface to yv12 file */ |
| static VAStatus |
| store_yuv_surface_to_yv12_file(FILE *fp, |
| VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_src, *u_src, *v_src; |
| unsigned char *y_dst, *u_dst, *v_dst; |
| uint32_t row, col; |
| int32_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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"); |
| |
| /* store the surface to one YV12 file or one bmp file*/ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12 || |
| surface_image.format.fourcc == VA_FOURCC_I420 || |
| surface_image.format.fourcc == VA_FOURCC_NV12){ |
| |
| uint32_t y_size = surface_image.width * surface_image.height; |
| uint32_t u_size = y_size/4; |
| |
| newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2); |
| assert(newImageBuffer); |
| |
| /* stored as YV12 format */ |
| y_dst = newImageBuffer; |
| v_dst = newImageBuffer + y_size; |
| u_dst = newImageBuffer + y_size + u_size; |
| |
| y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]); |
| } else if(surface_image.format.fourcc == VA_FOURCC_I420){ |
| 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; |
| } |
| |
| /* 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 copy */ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12|| |
| surface_image.format.fourcc == VA_FOURCC_I420){ |
| for (row = 0; row < surface_image.height /2; row ++){ |
| memcpy(v_dst, v_src, surface_image.width/2); |
| memcpy(u_dst, u_src, surface_image.width/2); |
| |
| v_dst += surface_image.width/2; |
| u_dst += surface_image.width/2; |
| |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_src += surface_image.pitches[1]; |
| u_src += surface_image.pitches[2]; |
| } else { |
| v_src += surface_image.pitches[2]; |
| u_src += surface_image.pitches[1]; |
| } |
| } |
| } else if (surface_image.format.fourcc == VA_FOURCC_NV12){ |
| for (row = 0; row < surface_image.height / 2; row++) { |
| for (col = 0; col < surface_image.width /2; col++) { |
| u_dst[col] = u_src[col * 2]; |
| v_dst[col] = u_src[col * 2 + 1]; |
| } |
| |
| u_src += surface_image.pitches[1]; |
| u_dst += (surface_image.width / 2); |
| v_dst += (surface_image.width / 2); |
| } |
| } |
| |
| /* write frame to file */ |
| do { |
| n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp); |
| } while (n_items != 1); |
| |
| } else { |
| printf("Not supported YUV 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 |
| store_yuv_surface_to_i420_file(FILE *fp, |
| VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_src, *u_src, *v_src; |
| unsigned char *y_dst, *u_dst, *v_dst; |
| uint32_t row, col; |
| int32_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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"); |
| |
| /* store the surface to one i420 file */ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12 || |
| surface_image.format.fourcc == VA_FOURCC_I420 || |
| surface_image.format.fourcc == VA_FOURCC_NV12){ |
| |
| uint32_t y_size = surface_image.width * surface_image.height; |
| uint32_t u_size = y_size/4; |
| |
| newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2); |
| assert(newImageBuffer); |
| |
| /* stored as YV12 format */ |
| y_dst = newImageBuffer; |
| u_dst = newImageBuffer + y_size; |
| v_dst = newImageBuffer + y_size + u_size; |
| |
| y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]); |
| } else if(surface_image.format.fourcc == VA_FOURCC_I420){ |
| 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; |
| } |
| |
| /* 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 copy */ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12|| |
| surface_image.format.fourcc == VA_FOURCC_I420){ |
| for (row = 0; row < surface_image.height /2; row ++){ |
| memcpy(v_dst, v_src, surface_image.width/2); |
| memcpy(u_dst, u_src, surface_image.width/2); |
| |
| v_dst += surface_image.width/2; |
| u_dst += surface_image.width/2; |
| |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_src += surface_image.pitches[1]; |
| u_src += surface_image.pitches[2]; |
| } else { |
| v_src += surface_image.pitches[2]; |
| u_src += surface_image.pitches[1]; |
| } |
| } |
| } else if (surface_image.format.fourcc == VA_FOURCC_NV12){ |
| for (row = 0; row < surface_image.height / 2; row++) { |
| for (col = 0; col < surface_image.width /2; col++) { |
| u_dst[col] = u_src[col * 2]; |
| v_dst[col] = u_src[col * 2 + 1]; |
| } |
| |
| u_src += surface_image.pitches[1]; |
| u_dst += (surface_image.width / 2); |
| v_dst += (surface_image.width / 2); |
| } |
| } |
| |
| /* write frame to file */ |
| do { |
| n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp); |
| } while (n_items != 1); |
| |
| } else { |
| printf("Not supported YUV 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 |
| store_yuv_surface_to_nv12_file(FILE *fp, |
| VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_src, *u_src, *v_src; |
| unsigned char *y_dst, *u_dst, *v_dst; |
| uint32_t row, col; |
| int32_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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"); |
| |
| /* store the surface to one nv12 file */ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12 || |
| surface_image.format.fourcc == VA_FOURCC_I420 || |
| 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); |
| |
| /* stored as YV12 format */ |
| y_dst = newImageBuffer; |
| u_dst = v_dst = newImageBuffer + y_size; |
| |
| y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]); |
| } else if(surface_image.format.fourcc == VA_FOURCC_I420){ |
| 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; |
| } |
| |
| /* 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 copy */ |
| if (surface_image.format.fourcc == VA_FOURCC_YV12|| |
| surface_image.format.fourcc == VA_FOURCC_I420){ |
| for (row = 0; row < surface_image.height / 2; row ++){ |
| for (col = 0; col < surface_image.width / 2; col++) { |
| u_dst[col * 2] = u_src[col]; |
| u_dst[col * 2 + 1] = v_src[col]; |
| } |
| |
| u_dst += surface_image.width; |
| |
| if (surface_image.format.fourcc == VA_FOURCC_YV12){ |
| v_src += surface_image.pitches[1]; |
| u_src += surface_image.pitches[2]; |
| } else { |
| v_src += surface_image.pitches[2]; |
| u_src += surface_image.pitches[1]; |
| } |
| } |
| } else if (surface_image.format.fourcc == VA_FOURCC_NV12){ |
| 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 { |
| printf("Not supported YUV 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 |
| store_packed_yuv_surface_to_packed_file(FILE *fp, |
| VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_src; |
| unsigned char *y_dst; |
| uint32_t row; |
| int32_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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"); |
| |
| /* store the surface to one YUY2 or UYVY file */ |
| if (surface_image.format.fourcc == VA_FOURCC_YUY2 || |
| surface_image.format.fourcc == VA_FOURCC_UYVY || |
| surface_image.format.fourcc == VA_FOURCC_AYUV) { |
| uint32_t byte_per_pixel = (surface_image.format.fourcc == VA_FOURCC_AYUV ? 4 : 2); |
| uint32_t frame_size = surface_image.width * surface_image.height * byte_per_pixel; |
| |
| newImageBuffer = (unsigned char*)malloc(frame_size); |
| assert(newImageBuffer); |
| memset(newImageBuffer, 0, frame_size); |
| |
| /* stored as YUY2 or UYVY format */ |
| y_dst = newImageBuffer; |
| |
| y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| /* Plane 0 copy */ |
| for (row = 0; row < surface_image.height; row++) { |
| memcpy(y_dst, y_src, surface_image.width * byte_per_pixel); |
| y_src += surface_image.pitches[0]; |
| y_dst += surface_image.width * byte_per_pixel; |
| } |
| |
| /* write frame to file */ |
| do { |
| n_items = fwrite(newImageBuffer, frame_size, 1, fp); |
| } while (n_items != 1); |
| |
| } else { |
| printf("Not supported YUV 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 |
| store_yuv_surface_to_10bit_file(FILE *fp, VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_src, *u_src, *v_src; |
| unsigned char *y_dst, *u_dst, *v_dst; |
| uint32_t row; |
| int32_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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"); |
| |
| /* store the surface to one 10bit file */ |
| uint32_t y_size = surface_image.width * surface_image.height * 2; |
| uint32_t u_size = y_size / 4; |
| |
| newImageBuffer = (unsigned char*)malloc(y_size * 3); |
| assert(newImageBuffer); |
| y_dst = newImageBuffer; |
| |
| y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| /* Y plane copy */ |
| for (row = 0; row < surface_image.height; row++) { |
| memcpy(y_dst, y_src, surface_image.width * 2); |
| y_src += surface_image.pitches[0]; |
| y_dst += surface_image.width * 2; |
| } |
| |
| if (surface_image.format.fourcc == VA_FOURCC_I010) { |
| u_dst = newImageBuffer + y_size; |
| v_dst = newImageBuffer + y_size + u_size; |
| |
| u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]); |
| |
| for (row = 0; row < surface_image.height / 2; row++){ |
| memcpy(u_dst, u_src, surface_image.width); |
| memcpy(v_dst, v_src, surface_image.width); |
| |
| u_dst += surface_image.width; |
| v_dst += surface_image.width; |
| |
| u_src += surface_image.pitches[1]; |
| v_src += surface_image.pitches[2]; |
| } |
| } else if (surface_image.format.fourcc == VA_FOURCC_P010) { |
| u_dst = newImageBuffer + y_size; |
| v_dst = u_dst; |
| |
| u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]); |
| v_src = u_src; |
| |
| for (row = 0; row < surface_image.height / 2; row++) { |
| memcpy(u_dst, u_src, surface_image.width * 2); |
| u_dst += surface_image.width * 2; |
| u_src += surface_image.pitches[1]; |
| } |
| } else { |
| printf("Not supported YUV surface fourcc !!! \n"); |
| free(newImageBuffer); |
| return VA_STATUS_ERROR_INVALID_SURFACE; |
| } |
| |
| /* write frame to file */ |
| do { |
| n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp); |
| } while (n_items != 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_rgb_surface_to_rgb_file(FILE *fp, VASurfaceID surface_id) |
| { |
| VAStatus va_status; |
| VAImage surface_image; |
| void *surface_p = NULL; |
| unsigned char *y_src; |
| unsigned char *y_dst; |
| uint32_t frame_size, row; |
| int32_t n_items; |
| unsigned char * newImageBuffer = NULL; |
| |
| 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"); |
| |
| frame_size = surface_image.width * surface_image.height * 4; |
| newImageBuffer = (unsigned char*)malloc(frame_size); |
| assert(newImageBuffer); |
| y_dst = newImageBuffer; |
| |
| y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]); |
| |
| for (row = 0; row < surface_image.height; row++) { |
| memcpy(y_dst, y_src, surface_image.width * 4); |
| y_src += surface_image.pitches[0]; |
| y_dst += surface_image.width * 4; |
| } |
| |
| /* write frame to file */ |
| do { |
| n_items = fwrite(newImageBuffer, frame_size, 1, fp); |
| } while (n_items != 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_yuv_surface_to_file(FILE *fp, |
| VASurfaceID surface_id) |
| { |
| if (g_out_fourcc == VA_FOURCC_YV12 || |
| g_out_fourcc == VA_FOURCC_I420 || |
| g_out_fourcc == VA_FOURCC_NV12) { |
| if (g_dst_file_fourcc == VA_FOURCC_YV12) |
| return store_yuv_surface_to_yv12_file(fp, surface_id); |
| else if (g_dst_file_fourcc == VA_FOURCC_I420) |
| return store_yuv_surface_to_i420_file(fp, surface_id); |
| else if (g_dst_file_fourcc == VA_FOURCC_NV12) |
| return store_yuv_surface_to_nv12_file(fp, surface_id); |
| else { |
| printf("Not supported YUV fourcc for output !!!\n"); |
| return VA_STATUS_ERROR_INVALID_SURFACE; |
| } |
| } else if ((g_out_fourcc == VA_FOURCC_YUY2 && |
| g_dst_file_fourcc == VA_FOURCC_YUY2) || |
| (g_out_fourcc == VA_FOURCC_UYVY && |
| g_dst_file_fourcc == VA_FOURCC_UYVY) || |
| (g_out_fourcc == VA_FOURCC_AYUV && |
| g_dst_file_fourcc == VA_FOURCC_AYUV)) { |
| return store_packed_yuv_surface_to_packed_file(fp, surface_id); |
| } else if ((g_out_fourcc == VA_FOURCC_I010 && |
| g_dst_file_fourcc == VA_FOURCC_I010) || |
| (g_out_fourcc == VA_FOURCC_P010 && |
| g_dst_file_fourcc == VA_FOURCC_P010)) { |
| return store_yuv_surface_to_10bit_file(fp, surface_id); |
| } else if ((g_out_fourcc == VA_FOURCC_RGBA && |
| g_dst_file_fourcc == VA_FOURCC_RGBA) || |
| (g_out_fourcc == VA_FOURCC_RGBX && |
| g_dst_file_fourcc == VA_FOURCC_RGBX) || |
| (g_out_fourcc == VA_FOURCC_BGRA && |
| g_dst_file_fourcc == VA_FOURCC_BGRA) || |
| (g_out_fourcc == VA_FOURCC_BGRX && |
| g_dst_file_fourcc == VA_FOURCC_BGRX)) { |
| return store_rgb_surface_to_rgb_file(fp, surface_id); |
| } else { |
| printf("Not supported YUV fourcc for output !!!\n"); |
| return VA_STATUS_ERROR_INVALID_SURFACE; |
| } |
| } |
| |
| static VAStatus |
| denoise_filter_init(VABufferID *filter_param_buf_id) |
| { |
| VAStatus va_status = VA_STATUS_SUCCESS; |
| VAProcFilterParameterBuffer denoise_param; |
| VABufferID denoise_param_buf_id; |
| float intensity; |
| |
| VAProcFilterCap denoise_caps; |
| uint32_t num_denoise_caps = 1; |
| va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id, |
| VAProcFilterNoiseReduction, |
| &denoise_caps, &num_denoise_caps); |
| CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps"); |
| |
| if (read_value_float(g_config_file_fd, "DENOISE_INTENSITY", &intensity)) { |
| printf("Read denoise intensity failed, use default value"); |
| intensity = denoise_caps.range.default_value; |
| } |
| intensity = adjust_to_range(&denoise_caps.range, intensity); |
| |
| denoise_param.type = VAProcFilterNoiseReduction; |
| denoise_param.value = intensity; |
| |
| printf("Denoise intensity: %f\n", intensity); |
| |
| va_status = vaCreateBuffer(va_dpy, context_id, |
| VAProcFilterParameterBufferType, sizeof(denoise_param), 1, |
| &denoise_param, &denoise_param_buf_id); |
| CHECK_VASTATUS(va_status,"vaCreateBuffer"); |
| |
| *filter_param_buf_id = denoise_param_buf_id; |
| |
| return va_status; |
| } |
| |
| /* |
| * This is a method to initialize STDE filter. |
| * If this filter is called, it is enabled by default. |
| */ |
| static VAStatus |
| skintone_filter_init(VABufferID *filter_param_buf_id) |
| { |
| VAStatus va_status = VA_STATUS_SUCCESS; |
| VAProcFilterParameterBuffer stde_param; |
| VABufferID stde_param_buf_id; |
| uint8_t stde_factor = 0; |
| |
| if (read_value_uint8(g_config_file_fd, "STDE_FACTOR", &stde_factor)) { |
| printf("Read STDE Factor failed, use default value"); |
| stde_factor = 0; |
| } |
| |
| printf("Applying STDE factor: %d\n", stde_factor); |
| |
| stde_param.type = VAProcFilterSkinToneEnhancement; |
| stde_param.value = stde_factor; |
| |
| va_status = vaCreateBuffer(va_dpy, context_id, |
| VAProcFilterParameterBufferType, sizeof(stde_param), 1, |
| &stde_param, &stde_param_buf_id); |
| CHECK_VASTATUS(va_status,"vaCreateBuffer"); |
| |
| *filter_param_buf_id = stde_param_buf_id; |
| |
| return va_status; |
| } |
| |
| static VAStatus |
| deinterlace_filter_init(VABufferID *filter_param_buf_id) |
| { |
| VAStatus va_status = VA_STATUS_SUCCESS; |
| VAProcFilterParameterBufferDeinterlacing deinterlacing_param; |
| VABufferID deinterlacing_param_buf_id; |
| char algorithm_str[MAX_LEN], flags_str[MAX_LEN]; |
| uint32_t i; |
| |
| /* read and check whether configured deinterlace algorithm is supported */ |
| deinterlacing_param.algorithm = VAProcDeinterlacingBob; |
| if (!read_value_string(g_config_file_fd, "DEINTERLACING_ALGORITHM", algorithm_str)) { |
| printf("Deinterlacing algorithm in config: %s \n", algorithm_str); |
| if (!strcmp(algorithm_str, "VAProcDeinterlacingBob")) |
| deinterlacing_param.algorithm = VAProcDeinterlacingBob; |
| else if (!strcmp(algorithm_str, "VAProcDeinterlacingWeave")) |
| deinterlacing_param.algorithm = VAProcDeinterlacingWeave; |
| else if (!strcmp(algorithm_str, "VAProcDeinterlacingMotionAdaptive")) |
| deinterlacing_param.algorithm = VAProcDeinterlacingMotionAdaptive; |
| else if (!strcmp(algorithm_str, "VAProcDeinterlacingMotionCompensated")) |
| deinterlacing_param.algorithm = VAProcDeinterlacingMotionCompensated; |
| } else { |
| printf("Read deinterlace algorithm failed, use default algorithm"); |
| deinterlacing_param.algorithm = VAProcDeinterlacingBob; |
| } |
| |
| VAProcFilterCapDeinterlacing deinterlacing_caps[VAProcDeinterlacingCount]; |
| uint32_t num_deinterlacing_caps = VAProcDeinterlacingCount; |
| va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id, |
| VAProcFilterDeinterlacing, |
| &deinterlacing_caps, &num_deinterlacing_caps); |
| CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps"); |
| |
| for (i = 0; i < VAProcDeinterlacingCount; i ++) |
| if (deinterlacing_caps[i].type == deinterlacing_param.algorithm) |
| break; |
| |
| if (i == VAProcDeinterlacingCount) { |
| printf("Deinterlacing algorithm: %d is not supported by driver, \ |
| use defautl algorithm :%d \n", |
| deinterlacing_param.algorithm, |
| VAProcDeinterlacingBob); |
| deinterlacing_param.algorithm = VAProcDeinterlacingBob; |
| } |
| |
| /* read and check the deinterlace flags */ |
| deinterlacing_param.flags = 0; |
| if (!read_value_string(g_config_file_fd, "DEINTERLACING_FLAG", flags_str)) { |
| if (strstr(flags_str, "VA_DEINTERLACING_BOTTOM_FIELD_FIRST")) |
| deinterlacing_param.flags |= VA_DEINTERLACING_BOTTOM_FIELD_FIRST; |
| if (strstr(flags_str, "VA_DEINTERLACING_BOTTOM_FIELD")) |
| deinterlacing_param.flags |= VA_DEINTERLACING_BOTTOM_FIELD; |
| if (strstr(flags_str, "VA_DEINTERLACING_ONE_FIELD")) |
| deinterlacing_param.flags |= VA_DEINTERLACING_ONE_FIELD; |
| } |
| |
| deinterlacing_param.type = VAProcFilterDeinterlacing; |
| |
| /* create deinterlace fitler buffer */ |
| va_status = vaCreateBuffer(va_dpy, context_id, |
| VAProcFilterParameterBufferType, sizeof(deinterlacing_param), 1, |
| &deinterlacing_param, &deinterlacing_param_buf_id); |
| CHECK_VASTATUS(va_status, "vaCreateBuffer"); |
| |
| *filter_param_buf_id = deinterlacing_param_buf_id; |
| |
| return va_status; |
| } |
| |
| static VAStatus |
| sharpening_filter_init(VABufferID *filter_param_buf_id) |
| { |
| VAStatus va_status; |
| VAProcFilterParameterBuffer sharpening_param; |
| VABufferID sharpening_param_buf_id; |
| float intensity; |
| |
| VAProcFilterCap sharpening_caps; |
| uint32_t num_sharpening_caps = 1; |
| va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id, |
| VAProcFilterSharpening, |
| &sharpening_caps, &num_sharpening_caps); |
| CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps"); |
| |
| if(read_value_float(g_config_file_fd, "SHARPENING_INTENSITY", &intensity)) { |
| printf("Read sharpening intensity failed, use default value."); |
| intensity = sharpening_caps.range.default_value; |
| } |
| |
| intensity = adjust_to_range(&sharpening_caps.range, intensity); |
| printf("Sharpening intensity: %f\n", intensity); |
| sharpening_param.value = intensity; |
| |
| sharpening_param.type = VAProcFilterSharpening; |
| |
| /* create sharpening fitler buffer */ |
| va_status = vaCreateBuffer(va_dpy, context_id, |
| VAProcFilterParameterBufferType, sizeof(sharpening_param), 1, |
| &sharpening_param, &sharpening_param_buf_id); |
| |
| *filter_param_buf_id = sharpening_param_buf_id; |
| |
| return va_status; |
| } |
| |
| static VAStatus |
| color_balance_filter_init(VABufferID *filter_param_buf_id) |
| { |
| VAStatus va_status; |
| VAProcFilterParameterBufferColorBalance color_balance_param[4]; |
| VABufferID color_balance_param_buf_id; |
| float value; |
| uint32_t i, count; |
| int8_t status; |
| |
| VAProcFilterCapColorBalance color_balance_caps[VAProcColorBalanceCount]; |
| unsigned int num_color_balance_caps = VAProcColorBalanceCount; |
| va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id, |
| VAProcFilterColorBalance, |
| &color_balance_caps, &num_color_balance_caps); |
| CHECK_VASTATUS(va_status,"vaQueryVideoProcFilterCaps"); |
| |
| count = 0; |
| printf("Color balance params: "); |
| for (i = 0; i < num_color_balance_caps; i++) { |
| if (color_balance_caps[i].type == VAProcColorBalanceHue) { |
| color_balance_param[count].attrib = VAProcColorBalanceHue; |
| status = read_value_float(g_config_file_fd, "COLOR_BALANCE_HUE", &value); |
| printf("Hue: "); |
| } else if (color_balance_caps[i].type == VAProcColorBalanceSaturation) { |
| color_balance_param[count].attrib = VAProcColorBalanceSaturation; |
| status = read_value_float(g_config_file_fd, "COLOR_BALANCE_SATURATION", &value); |
| printf("Saturation: "); |
| } else if (color_balance_caps[i].type == VAProcColorBalanceBrightness) { |
| color_balance_param[count].attrib = VAProcColorBalanceBrightness; |
| status = read_value_float(g_config_file_fd, "COLOR_BALANCE_BRIGHTNESS", &value); |
| printf("Brightness: "); |
| } else if (color_balance_caps[i].type == VAProcColorBalanceContrast) { |
| color_balance_param[count].attrib = VAProcColorBalanceContrast; |
| status = read_value_float(g_config_file_fd, "COLOR_BALANCE_CONTRAST", &value); |
| printf("Contrast: "); |
| } else { |
| continue; |
| } |
| |
| if (status) |
| value = color_balance_caps[i].range.default_value; |
| else |
| value = adjust_to_range(&color_balance_caps[i].range, value); |
| |
| color_balance_param[count].value = value; |
| color_balance_param[count].type = VAProcFilterColorBalance; |
| count++; |
| |
| printf("%4f, ", value); |
| } |
| printf("\n"); |
| |
| va_status = vaCreateBuffer(va_dpy, context_id, |
| VAProcFilterParameterBufferType, sizeof(color_balance_param), 4, |
| color_balance_param, &color_balance_param_buf_id); |
| |
| *filter_param_buf_id = color_balance_param_buf_id; |
| |
| return va_status; |
| } |
| |
| #if BLEND_ON |
| |
| static VAStatus |
| blending_state_init(VABlendState *state) |
| { |
| VAStatus va_status = VA_STATUS_SUCCESS; |
| char blending_flags_str[MAX_LEN]; |
| float global_alpha; |
| uint32_t min_luma, max_luma; |
| |
| /* read and check blend state */ |
| state->flags = 0; |
| if (!read_value_string(g_config_file_fd, "BLENDING_FLAGS", blending_flags_str)){ |
| if (strstr(blending_flags_str, "VA_BLEND_GLOBAL_ALPHA")) { |
| if (read_value_float(g_config_file_fd, "BLENDING_GLOBAL_ALPHA", &global_alpha)) { |
| global_alpha = 1.0 ; |
| printf("Use default global alpha : %4f \n", global_alpha); |
| } |
| state->flags |= VA_BLEND_GLOBAL_ALPHA; |
| state->global_alpha = global_alpha; |
| } |
| if (strstr(blending_flags_str, "VA_BLEND_LUMA_KEY")) { |
| if (read_value_uint8(g_config_file_fd, "BLENDING_MIN_LUMA", &g_blending_min_luma)) { |
| g_blending_min_luma = 1; |
| printf("Use default min luma : %3d \n", g_blending_min_luma); |
| } |
| if (read_value_uint8(g_config_file_fd, "BLENDING_MAX_LUMA", &g_blending_max_luma)) { |
| g_blending_max_luma = 254; |
| printf("Use default max luma : %3d \n", g_blending_max_luma); |
| } |
| state->flags |= VA_BLEND_LUMA_KEY; |
| state->min_luma = g_blending_min_luma * 1.0 / 256; |
| state->max_luma = g_blending_max_luma * 1.0 / 256; |
| } |
| |
| printf("Blending type = %s, alpha = %f, min_luma = %3d, max_luma = %3d \n", |
| blending_flags_str, global_alpha, min_luma, max_luma); |
| } |
| |
| VAProcPipelineCaps pipeline_caps; |
| va_status = vaQueryVideoProcPipelineCaps(va_dpy, context_id, |
| NULL, 0, &pipeline_caps); |
| CHECK_VASTATUS(va_status,"vaQueryVideoProcPipelineCaps"); |
| |
| if (!pipeline_caps.blend_flags){ |
| printf("Blending is not supported in driver! \n"); |
| return VA_STATUS_ERROR_UNIMPLEMENTED; |
| } |
| |
| if (! (pipeline_caps.blend_flags & state->flags)) { |
| printf("Driver do not support current blending flags: %d", state->flags); |
| return VA_STATUS_ERROR_UNIMPLEMENTED; |
| } |
| |
| return va_status; |
| } |
| |
| #endif |
| |
| static VAStatus |
| video_frame_process(VAProcFilterType filter_type, |
| uint32_t frame_idx, |
| VASurfaceID in_surface_id, |
| VASurfaceID out_surface_id) |
| { |
| VAStatus va_status; |
| VAProcPipelineParameterBuffer pipeline_param; |
| VARectangle surface_region, output_region; |
| VABufferID pipeline_param_buf_id = VA_INVALID_ID; |
| VABufferID filter_param_buf_id = VA_INVALID_ID; |
| #if BLEND_ON |
| VABlendState state ; |
| #endif |
| uint32_t filter_count = 1; |
| |
| /* create denoise_filter buffer id */ |
| switch(filter_type){ |
| case VAProcFilterNoiseReduction: |
| denoise_filter_init(&filter_param_buf_id); |
| break; |
| case VAProcFilterDeinterlacing: |
| deinterlace_filter_init(&filter_param_buf_id); |
| break; |
| case VAProcFilterSharpening: |
| sharpening_filter_init(&filter_param_buf_id); |
| break; |
| case VAProcFilterColorBalance: |
| color_balance_filter_init(&filter_param_buf_id); |
| break; |
| case VAProcFilterSkinToneEnhancement: |
| skintone_filter_init(&filter_param_buf_id); |
| break; |
| default : |
| filter_count = 0; |
| break; |
| } |
| |
| /* Fill pipeline buffer */ |
| surface_region.x = 0; |
| surface_region.y = 0; |
| surface_region.width = g_in_pic_width; |
| surface_region.height = g_in_pic_height; |
| output_region.x = 0; |
| output_region.y = 0; |
| output_region.width = g_out_pic_width; |
| output_region.height = g_out_pic_height; |
| |
| memset(&pipeline_param, 0, sizeof(pipeline_param)); |
| pipeline_param.surface = in_surface_id; |
| pipeline_param.surface_region = &surface_region; |
| pipeline_param.output_region = &output_region; |
| |
| pipeline_param.filter_flags = 0; |
| pipeline_param.filters = &filter_param_buf_id; |
| pipeline_param.num_filters = filter_count; |
| |
| #if BLEND_ON |
| /* Blending related state */ |
| if (g_blending_enabled){ |
| blending_state_init(&state); |
| pipeline_param.blend_state = &state; |
| } |
| #endif |
| |
| va_status = vaCreateBuffer(va_dpy, |
| context_id, |
| VAProcPipelineParameterBufferType, |
| sizeof(pipeline_param), |
| 1, |
| &pipeline_param, |
| &pipeline_param_buf_id); |
| CHECK_VASTATUS(va_status, "vaCreateBuffer"); |
| |
| va_status = vaBeginPicture(va_dpy, |
| context_id, |
| out_surface_id); |
| CHECK_VASTATUS(va_status, "vaBeginPicture"); |
| |
| va_status = vaRenderPicture(va_dpy, |
| context_id, |
| &pipeline_param_buf_id, |
| 1); |
| CHECK_VASTATUS(va_status, "vaRenderPicture"); |
| |
| va_status = vaEndPicture(va_dpy, context_id); |
| CHECK_VASTATUS(va_status, "vaEndPicture"); |
| |
| if (filter_param_buf_id != VA_INVALID_ID) |
| vaDestroyBuffer(va_dpy,filter_param_buf_id); |
| |
| if (pipeline_param_buf_id != VA_INVALID_ID) |
| vaDestroyBuffer(va_dpy,pipeline_param_buf_id); |
| |
| return va_status; |
| } |
| |
| static VAStatus |
| vpp_context_create() |
| { |
| VAStatus va_status = VA_STATUS_SUCCESS; |
| uint32_t i; |
| 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_out_format)) { |
| printf("RT format %d is not supported by VPP !\n",g_out_format); |
| assert(0); |
| } |
| |
| /* Create surface/config/context for VPP pipeline */ |
| va_status = create_surface(&g_in_surface_id, g_in_pic_width, g_in_pic_height, |
| g_in_fourcc, g_in_format); |
| CHECK_VASTATUS(va_status, "vaCreateSurfaces for input"); |
| |
| va_status = create_surface(&g_out_surface_id, g_out_pic_width, g_out_pic_height, |
| g_out_fourcc, g_out_format); |
| CHECK_VASTATUS(va_status, "vaCreateSurfaces for output"); |
| |
| va_status = vaCreateConfig(va_dpy, |
| VAProfileNone, |
| VAEntrypointVideoProc, |
| &attrib, |
| 1, |
| &config_id); |
| CHECK_VASTATUS(va_status, "vaCreateConfig"); |
| |
| /* Source surface format check */ |
| uint32_t num_surf_attribs = VASurfaceAttribCount; |
| VASurfaceAttrib * surf_attribs = (VASurfaceAttrib*) |
| malloc(sizeof(VASurfaceAttrib) * num_surf_attribs); |
| if (!surf_attribs) |
| assert(0); |
| |
| va_status = vaQuerySurfaceAttributes(va_dpy, |
| config_id, |
| surf_attribs, |
| &num_surf_attribs); |
| |
| if (va_status == VA_STATUS_ERROR_MAX_NUM_EXCEEDED) { |
| surf_attribs = (VASurfaceAttrib*)realloc(surf_attribs, |
| sizeof(VASurfaceAttrib) * num_surf_attribs); |
| if (!surf_attribs) |
| assert(0); |
| va_status = vaQuerySurfaceAttributes(va_dpy, |
| config_id, |
| surf_attribs, |
| &num_surf_attribs); |
| } |
| CHECK_VASTATUS(va_status, "vaQuerySurfaceAttributes"); |
| |
| for (i = 0; i < num_surf_attribs; i++) { |
| if (surf_attribs[i].type == VASurfaceAttribPixelFormat && |
| surf_attribs[i].value.value.i == (int)g_in_fourcc) |
| break; |
| } |
| free(surf_attribs); |
| |
| if (i == num_surf_attribs) { |
| printf("Input fourCC %d is not supported by VPP !\n", g_in_fourcc); |
| assert(0); |
| } |
| |
| va_status = vaCreateContext(va_dpy, |
| config_id, |
| g_out_pic_width, |
| g_out_pic_height, |
| VA_PROGRESSIVE, |
| &g_out_surface_id, |
| 1, |
| &context_id); |
| CHECK_VASTATUS(va_status, "vaCreateContext"); |
| |
| |
| /* Validate whether currect filter is supported */ |
| if (g_filter_type != VAProcFilterNone) { |
| uint32_t supported_filter_num = VAProcFilterCount; |
| VAProcFilterType supported_filter_types[VAProcFilterCount]; |
| |
| va_status = vaQueryVideoProcFilters(va_dpy, |
| context_id, |
| supported_filter_types, |
| &supported_filter_num); |
| |
| CHECK_VASTATUS(va_status, "vaQueryVideoProcFilters"); |
| |
| for (i = 0; i < supported_filter_num; i++){ |
| if (supported_filter_types[i] == g_filter_type) |
| break; |
| } |
| |
| if (i == supported_filter_num) { |
| printf("VPP filter type %s is not supported by driver !\n", g_filter_type_name); |
| assert(0); |
| } |
| } |
| |
| 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); |
| } |
| |
| 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'); |
| tformat = VA_RT_FORMAT_YUV420; |
| } else if(!strcmp(str, "I420")){ |
| tfourcc = VA_FOURCC('I', '4', '2', '0'); |
| tformat = VA_RT_FORMAT_YUV420; |
| } else if(!strcmp(str, "NV12")){ |
| tfourcc = VA_FOURCC('N', 'V', '1', '2'); |
| tformat = VA_RT_FORMAT_YUV420; |
| } else if(!strcmp(str, "YUY2") || !strcmp(str, "YUYV")) { |
| tfourcc = VA_FOURCC('Y', 'U', 'Y', '2'); |
| tformat = VA_RT_FORMAT_YUV422; |
| } else if(!strcmp(str, "UYVY")){ |
| tfourcc = VA_FOURCC('U', 'Y', 'V', 'Y'); |
| tformat = VA_RT_FORMAT_YUV422; |
| } else if (!strcmp(str, "P010")) { |
| tfourcc = VA_FOURCC('P', '0', '1', '0'); |
| tformat = VA_RT_FORMAT_YUV420_10BPP; |
| } else if (!strcmp(str, "I010")) { |
| tfourcc = VA_FOURCC('I', '0', '1', '0'); |
| tformat = VA_RT_FORMAT_YUV420_10BPP; |
| } else if (!strcmp(str, "RGBA")) { |
| tfourcc = VA_FOURCC_RGBA; |
| tformat = VA_RT_FORMAT_RGB32; |
| } else if (!strcmp(str, "RGBX")) { |
| tfourcc = VA_FOURCC_RGBX; |
| tformat = VA_RT_FORMAT_RGB32; |
| } else if (!strcmp(str, "BGRA")) { |
| tfourcc = VA_FOURCC_BGRA; |
| tformat = VA_RT_FORMAT_RGB32; |
| } else if (!strcmp(str, "BGRX")) { |
| tfourcc = VA_FOURCC_BGRX; |
| tformat = VA_RT_FORMAT_RGB32; |
| } else if (!strcmp(str, "AYUV")) { |
| tfourcc = VA_FOURCC_AYUV; |
| tformat = VA_RT_FORMAT_YUV444; |
| } else{ |
| printf("Not supported format: %s! Currently only support following format: %s\n", |
| str, "YV12, I420, NV12, YUY2(YUYV), UYVY, AYUV, 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]; |
| |
| /* Read src frame file information */ |
| read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src_file_name); |
| read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_in_pic_width); |
| read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_in_pic_height); |
| read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str); |
| parse_fourcc_and_format(str, &g_in_fourcc, &g_in_format); |
| |
| /* Read dst frame file information */ |
| read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst_file_name); |
| read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_out_pic_width); |
| read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT",&g_out_pic_height); |
| read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str); |
| parse_fourcc_and_format(str, &g_out_fourcc, &g_out_format); |
| |
| 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 filter type */ |
| if (read_value_string(g_config_file_fd, "FILTER_TYPE", g_filter_type_name)){ |
| printf("Read filter type error !\n"); |
| assert(0); |
| } |
| |
| if (!strcmp(g_filter_type_name, "VAProcFilterNoiseReduction")) |
| g_filter_type = VAProcFilterNoiseReduction; |
| else if (!strcmp(g_filter_type_name, "VAProcFilterDeinterlacing")) |
| g_filter_type = VAProcFilterDeinterlacing; |
| else if (!strcmp(g_filter_type_name, "VAProcFilterSharpening")) |
| g_filter_type = VAProcFilterSharpening; |
| else if (!strcmp(g_filter_type_name, "VAProcFilterColorBalance")) |
| g_filter_type = VAProcFilterColorBalance; |
| else if (!strcmp(g_filter_type_name, "VAProcFilterSkinToneEnhancement")) |
| g_filter_type = VAProcFilterSkinToneEnhancement; |
| else if (!strcmp(g_filter_type_name, "VAProcFilterNone")) |
| g_filter_type = VAProcFilterNone; |
| else { |
| printf("Unsupported filter type :%s \n", g_filter_type_name); |
| return -1; |
| } |
| |
| /* Check whether blending is enabled */ |
| if (read_value_uint8(g_config_file_fd, "BLENDING_ENABLED", &g_blending_enabled)) |
| g_blending_enabled = 0; |
| |
| if (g_blending_enabled) |
| printf("Blending will be done \n"); |
| |
| if (g_in_pic_width != g_out_pic_width || |
| g_in_pic_height != g_out_pic_height) |
| printf("Scaling will be done : from %4d x %4d to %4d x %4d \n", |
| g_in_pic_width, g_in_pic_height, |
| g_out_pic_width, g_out_pic_height); |
| |
| if (g_in_fourcc != g_out_fourcc) |
| printf("Format conversion will be done: from %d to %d \n", |
| g_in_fourcc, g_out_fourcc); |
| |
| return 0; |
| } |
| |
| int32_t main(int32_t argc, char *argv[]) |
| { |
| VAStatus va_status; |
| uint32_t i; |
| |
| if (argc != 2){ |
| printf("Input error! please specify the configure file \n"); |
| 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_file_fd = fopen(g_src_file_name, "r"))){ |
| printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n", |
| g_src_file_name, g_config_file_name); |
| assert(0); |
| } |
| |
| if (NULL == (g_dst_file_fd = fopen(g_dst_file_name, "w"))){ |
| printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n", |
| g_dst_file_name, g_config_file_name); |
| assert(0); |
| } |
| |
| printf("\nStart to process, processing type is %s ...\n", g_filter_type_name); |
| struct timeval start_time, end_time; |
| gettimeofday(&start_time, NULL); |
| |
| for (i = 0; i < g_frame_count; i ++){ |
| if (g_blending_enabled) { |
| construct_nv12_mask_surface(g_in_surface_id, g_blending_min_luma, g_blending_max_luma); |
| upload_yuv_frame_to_yuv_surface(g_src_file_fd, g_out_surface_id); |
| } else { |
| upload_yuv_frame_to_yuv_surface(g_src_file_fd, g_in_surface_id); |
| } |
| |
| video_frame_process(g_filter_type, i, g_in_surface_id, g_out_surface_id); |
| store_yuv_surface_to_file(g_dst_file_fd, g_out_surface_id); |
| } |
| |
| gettimeofday(&end_time, NULL); |
| float duration = (end_time.tv_sec - start_time.tv_sec) + |
| (end_time.tv_usec - start_time.tv_usec)/1000000.0; |
| printf("Finish processing, performance: \n" ); |
| printf("%d frames processed in: %f s, ave time = %.6fs \n",g_frame_count, duration, duration/g_frame_count); |
| |
| if (g_src_file_fd) |
| fclose(g_src_file_fd); |
| |
| if (g_dst_file_fd) |
| fclose(g_dst_file_fd); |
| |
| if (g_config_file_fd) |
| fclose(g_config_file_fd); |
| |
| vpp_context_destroy(); |
| |
| return 0; |
| } |