mirror of https://github.com/intel/libva-utils.git
1788 lines
64 KiB
C++
1788 lines
64 KiB
C++
/*
|
|
* 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; strLine[i] && i < MAX_LEN; i++)
|
|
if (strLine[i] != ' ') break;
|
|
|
|
if (strLine[i] == '#' || strLine[i] == '\n' || i == 1024)
|
|
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, *v_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]);
|
|
v_dst = u_dst;
|
|
|
|
/* 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, i, 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);
|
|
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");
|
|
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)) {
|
|
frame_size = surface_image.width * surface_image.height * 2;
|
|
newImageBuffer = (unsigned char*)malloc(frame_size);
|
|
|
|
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];
|
|
}
|
|
} 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);
|
|
|
|
do {
|
|
n_items = fread(newImageBuffer, frame_size, 1, fp);
|
|
} while (n_items != 1);
|
|
|
|
y_src = newImageBuffer;
|
|
|
|
if (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;
|
|
} else if (g_src_file_fourcc == VA_FOURCC_P010) {
|
|
u_src = newImageBuffer + surface_image.width * surface_image.height * 2;
|
|
v_src = u_src;
|
|
}
|
|
|
|
y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
|
|
|
|
if (surface_image.format.fourcc == VA_FOURCC_I010) {
|
|
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 if (surface_image.format.fourcc == VA_FOURCC_P010) {
|
|
u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
|
|
v_dst = u_dst;
|
|
}
|
|
|
|
/* 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);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
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;
|
|
VAImageFormat image_format;
|
|
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 frame_size, row, col;
|
|
int32_t ret, 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);
|
|
|
|
/* 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;
|
|
VAImageFormat image_format;
|
|
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 frame_size, row, col;
|
|
int32_t ret, 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);
|
|
|
|
/* 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;
|
|
VAImageFormat image_format;
|
|
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 frame_size, row, col;
|
|
int32_t ret, 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;
|
|
uint32_t u_size = y_size/4;
|
|
|
|
newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
|
|
|
|
/* 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;
|
|
VAImageFormat image_format;
|
|
VAImage surface_image;
|
|
void *surface_p = NULL;
|
|
unsigned char *y_src;
|
|
unsigned char *y_dst;
|
|
uint32_t frame_size, row, col;
|
|
int32_t ret, 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) {
|
|
uint32_t frame_size = surface_image.width * surface_image.height * 2;
|
|
|
|
newImageBuffer = (unsigned char*)malloc(frame_size);
|
|
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 * 2);
|
|
y_src += surface_image.pitches[0];
|
|
y_dst += surface_image.width * 2;
|
|
}
|
|
|
|
/* 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;
|
|
VAImageFormat image_format;
|
|
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 frame_size, row, col;
|
|
int32_t ret, 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);
|
|
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");
|
|
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;
|
|
VAImageFormat image_format;
|
|
VAImage surface_image;
|
|
void *surface_p = NULL;
|
|
unsigned char *y_src;
|
|
unsigned char *y_dst;
|
|
uint32_t frame_size, row, col;
|
|
int32_t ret, 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);
|
|
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)) {
|
|
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_RGBA &&
|
|
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;
|
|
|
|
/* 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 (i = 0; i < num_entrypoints; i++) {
|
|
if (entrypoints[i] == VAEntrypointVideoProc)
|
|
break;
|
|
}
|
|
|
|
if (i == 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 == 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{
|
|
printf("Not supported format: %s! Currently only support following format: %s\n",
|
|
str, "YV12, I420, NV12, YUY2(YUYV), UYVY, P010, I010, RGBA, RGBX, BGRA or BGRX");
|
|
assert(0);
|
|
}
|
|
|
|
if (fourcc)
|
|
*fourcc = tfourcc;
|
|
|
|
if (format)
|
|
*format = tformat;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int8_t
|
|
parse_basic_parameters()
|
|
{
|
|
char str[MAX_LEN];
|
|
|
|
/* 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*/
|
|
strcpy(g_config_file_name, argv[1]);
|
|
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;
|
|
}
|