blob: acafa00b8eb1146dc1873da56ceb1b86c548ad14 [file] [log] [blame]
/*
* test-gles-handler.cpp - test gles handler
*
* Copyright (c) 2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Yinhang Liu <[email protected]>
*/
#include "test_common.h"
#include "test_stream.h"
#include <gles/gl_video_buffer.h>
#include <gles/egl/egl_base.h>
#include <gles/gl_copy_handler.h>
#include <gles/gl_geomap_handler.h>
#include <interface/blender.h>
using namespace XCam;
enum GLType {
GLTypeNone = 0,
GLTypeCopy,
GLTypeRemap,
GLTypeBlender
};
class GLStream
: public Stream
{
public:
explicit GLStream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0);
virtual ~GLStream () {}
virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count);
};
typedef std::vector<SmartPtr<GLStream>> GLStreams;
GLStream::GLStream (const char *file_name, uint32_t width, uint32_t height)
: Stream (file_name, width, height)
{
}
XCamReturn
GLStream::create_buf_pool (const VideoBufferInfo &info, uint32_t count)
{
SmartPtr<GLVideoBufferPool> pool = new GLVideoBufferPool (info);
XCAM_ASSERT (pool.ptr ());
if (!pool->reserve (count)) {
XCAM_LOG_ERROR ("create buffer pool failed");
return XCAM_RETURN_ERROR_MEM;
}
set_buf_pool (pool);
return XCAM_RETURN_NO_ERROR;
}
static void
calc_hor_flip_table (uint32_t width, uint32_t height, PointFloat2 *&map_table)
{
XCAM_ASSERT (map_table);
float lut_size[2] = {8, 8};
for (uint32_t i = 0; i < height; ++i) {
PointFloat2 *line = &map_table[i * width];
for (uint32_t j = 0; j < width; j++) {
line[j].x = (width - j) * lut_size[0];
line[j].y = i * lut_size[1];
}
}
}
static void usage (const char *arg0)
{
printf ("Usage:\n"
"%s --type TYPE --input0 input.nv12 --input1 input1.nv12 --output output.nv12 ...\n"
"\t--type processing type, selected from: copy, remap, blend\n"
"\t--input0 input image(NV12)\n"
"\t--input1 input image(NV12)\n"
"\t--output output image(NV12/MP4)\n"
"\t--in-w optional, input width, default: 1280\n"
"\t--in-h optional, input height, default: 800\n"
"\t--out-w optional, output width, default: 1280\n"
"\t--out-h optional, output height, default: 800\n"
"\t--save optional, save file or not, select from [true/false], default: true\n"
"\t--loop optional, how many loops need to run, default: 1\n"
"\t--help usage\n",
arg0);
}
int main (int argc, char **argv)
{
uint32_t input_width = 1280;
uint32_t input_height = 800;
uint32_t output_width = 1280;
uint32_t output_height = 800;
GLStreams ins;
GLStreams outs;
GLType type = GLTypeNone;
int loop = 1;
bool save_output = true;
const struct option long_opts[] = {
{"type", required_argument, NULL, 't'},
{"input0", required_argument, NULL, 'i'},
{"input1", required_argument, NULL, 'j'},
{"output", required_argument, NULL, 'o'},
{"in-w", required_argument, NULL, 'w'},
{"in-h", required_argument, NULL, 'h'},
{"out-w", required_argument, NULL, 'W'},
{"out-h", required_argument, NULL, 'H'},
{"save", required_argument, NULL, 's'},
{"loop", required_argument, NULL, 'l'},
{"help", no_argument, NULL, 'e'},
{NULL, 0, NULL, 0},
};
int opt = -1;
while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
switch (opt) {
case 't':
XCAM_ASSERT (optarg);
if (!strcasecmp (optarg, "copy"))
type = GLTypeCopy;
else if (!strcasecmp (optarg, "remap"))
type = GLTypeRemap;
else if (!strcasecmp (optarg, "blend"))
type = GLTypeBlender;
else {
XCAM_LOG_ERROR ("unknown type:%s", optarg);
usage (argv[0]);
return -1;
}
break;
case 'i':
XCAM_ASSERT (optarg);
PUSH_STREAM (GLStream, ins, optarg);
break;
case 'j':
XCAM_ASSERT (optarg);
PUSH_STREAM (GLStream, ins, optarg);
break;
case 'o':
XCAM_ASSERT (optarg);
PUSH_STREAM (GLStream, outs, optarg);
break;
case 'w':
input_width = atoi(optarg);
break;
case 'h':
input_height = atoi(optarg);
break;
case 'W':
output_width = atoi(optarg);
break;
case 'H':
output_height = atoi(optarg);
break;
case 's':
save_output = (strcasecmp (optarg, "false") == 0 ? false : true);
break;
case 'l':
loop = atoi(optarg);
break;
case 'e':
usage (argv[0]);
return 0;
default:
XCAM_LOG_ERROR ("getopt_long return unknown value:%c", opt);
usage (argv[0]);
return -1;
}
}
if (optind < argc || argc < 2) {
XCAM_LOG_ERROR ("unknown option %s", argv[optind]);
usage (argv[0]);
return -1;
}
if (ins.empty () || outs.empty ()) {
XCAM_LOG_ERROR ("input or output stream is empty");
usage (argv[0]);
return -1;
}
for (uint32_t i = 0; i < ins.size (); ++i) {
printf ("input%d file:\t\t%s\n", i, ins[i]->get_file_name ());
}
printf ("output file:\t\t%s\n", outs[0]->get_file_name ());
printf ("input width:\t\t%d\n", input_width);
printf ("input height:\t\t%d\n", input_height);
printf ("output width:\t\t%d\n", output_width);
printf ("output height:\t\t%d\n", output_height);
printf ("save output:\t\t%s\n", save_output ? "true" : "false");
printf ("loop count:\t\t%d\n", loop);
SmartPtr<EGLBase> egl = new EGLBase ();
XCAM_FAIL_RETURN (ERROR, egl->init (), -1, "init EGL failed");
VideoBufferInfo in_info;
in_info.init (V4L2_PIX_FMT_NV12, input_width, input_height);
for (uint32_t i = 0; i < ins.size (); ++i) {
ins[i]->set_buf_size (input_width, input_height);
CHECK (ins[i]->create_buf_pool (in_info, XCAM_GL_RESERVED_BUF_COUNT), "create buffer pool failed");
CHECK (ins[i]->open_reader ("rb"), "open input file(%s) failed", ins[i]->get_file_name ());
}
VideoBufferInfo out_info;
out_info.init (V4L2_PIX_FMT_NV12, output_width, output_height);
outs[0]->set_buf_size (output_width, output_height);
if (save_output) {
CHECK (outs[0]->estimate_file_format (), "%s: estimate file format failed", outs[0]->get_file_name ());
CHECK (outs[0]->open_writer ("wb"), "open output file(%s) failed", outs[0]->get_file_name ());
}
switch (type) {
case GLTypeCopy: {
SmartPtr<GLCopyHandler> copyer = new GLCopyHandler ();
XCAM_ASSERT (copyer.ptr ());
Rect in_area = Rect (0, 0, output_width, output_height);
Rect out_area = in_area;
copyer->set_copy_area (0, in_area, out_area);
copyer->set_out_video_info (out_info);
CHECK (ins[0]->read_buf(), "read buffer from file(%s) failed.", ins[0]->get_file_name ());
for (int i = 0; i < loop; ++i) {
CHECK (copyer->copy (ins[0]->get_buf (), outs[0]->get_buf ()), "copy buffer failed");
if (save_output)
outs[0]->write_buf ();
FPS_CALCULATION (gl-copy, XCAM_OBJ_DUR_FRAME_NUM);
}
break;
}
case GLTypeRemap: {
SmartPtr<GLGeoMapHandler> mapper = new GLGeoMapHandler ();
XCAM_ASSERT (mapper.ptr ());
mapper->set_output_size (output_width, output_height);
uint32_t lut_width = XCAM_ALIGN_UP (output_width, 8) / 8;
uint32_t lut_height = XCAM_ALIGN_UP (output_height, 8) / 8;
PointFloat2 *map_table = new PointFloat2[lut_width * lut_height];
calc_hor_flip_table (lut_width, lut_height, map_table);
mapper->set_lookup_table (map_table, lut_width, lut_height);
delete [] map_table;
CHECK (ins[0]->read_buf(), "read buffer from file(%s) failed.", ins[0]->get_file_name ());
for (int i = 0; i < loop; ++i) {
CHECK (mapper->remap (ins[0]->get_buf (), outs[0]->get_buf ()), "remap buffer failed");
if (save_output)
outs[0]->write_buf ();
FPS_CALCULATION (gl-remap, XCAM_OBJ_DUR_FRAME_NUM);
}
break;
}
case GLTypeBlender: {
CHECK_EXP (ins.size () == 2, "Error: blender needs 2 input files.");
SmartPtr<Blender> blender = Blender::create_gl_blender ();
XCAM_ASSERT (blender.ptr ());
blender->set_output_size (output_width, output_height);
Rect area;
area.pos_x = 0;
area.pos_y = 0;
area.width = output_width;
area.height = output_height;
blender->set_merge_window (area);
area.pos_x = 0;
area.pos_y = 0;
area.width = input_width;
area.height = input_height;
blender->set_input_merge_area (area, 0);
area.pos_x = 0;
area.pos_y = 0;
area.width = input_width;
area.height = input_height;
blender->set_input_merge_area (area, 1);
CHECK (ins[0]->read_buf(), "read buffer from file(%s) failed.", ins[0]->get_file_name ());
CHECK (ins[1]->read_buf(), "read buffer from file(%s) failed.", ins[1]->get_file_name ());
for (int i = 0; i < loop; ++i) {
CHECK (blender->blend (ins[0]->get_buf (), ins[1]->get_buf (), outs[0]->get_buf ()), "blend buffer failed");
if (save_output)
outs[0]->write_buf ();
FPS_CALCULATION (gl-blend, XCAM_OBJ_DUR_FRAME_NUM);
}
break;
}
default: {
XCAM_LOG_ERROR ("unsupported type:%d", type);
usage (argv[0]);
return -1;
}
}
return 0;
}