/*
|
* test-pipe-manager.cpp -test pipe manager
|
*
|
* Copyright (c) 2016 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 <yinhangx.liu@intel.com>
|
*/
|
|
#include <pipe_manager.h>
|
#include <smart_analyzer_loader.h>
|
#include <ocl/cl_post_image_processor.h>
|
#if HAVE_LIBDRM
|
#include <drm_display.h>
|
#endif
|
#include <getopt.h>
|
#include <test_common.h>
|
#include <signal.h>
|
#include <stdio.h>
|
|
#define DEFAULT_FPT_BUF_COUNT 32
|
|
using namespace XCam;
|
|
static bool is_stop = false;
|
|
struct FileFP {
|
FILE *fp;
|
FileFP ()
|
: fp (NULL)
|
{}
|
~FileFP ()
|
{
|
if (fp)
|
fclose (fp);
|
fp = NULL;
|
}
|
};
|
|
class MainPipeManager
|
: public PipeManager
|
{
|
public:
|
MainPipeManager ()
|
: _image_width (0)
|
, _image_height (0)
|
, _enable_display (false)
|
{
|
#if HAVE_LIBDRM
|
_display = DrmDisplay::instance ();
|
#endif
|
XCAM_OBJ_PROFILING_INIT;
|
}
|
|
void set_image_width (uint32_t image_width) {
|
_image_width = image_width;
|
}
|
|
void set_image_height (uint32_t image_height) {
|
_image_height = image_height;
|
}
|
|
void enable_display (bool value) {
|
_enable_display = value;
|
}
|
|
#if HAVE_LIBDRM
|
void set_display_mode (DrmDisplayMode mode) {
|
_display->set_display_mode (mode);
|
}
|
#endif
|
|
protected:
|
virtual void post_buffer (const SmartPtr<VideoBuffer> &buf);
|
int display_buf (const SmartPtr<VideoBuffer> &buf);
|
|
private:
|
uint32_t _image_width;
|
uint32_t _image_height;
|
bool _enable_display;
|
#if HAVE_LIBDRM
|
SmartPtr<DrmDisplay> _display;
|
#endif
|
XCAM_OBJ_PROFILING_DEFINES;
|
};
|
|
void
|
MainPipeManager::post_buffer (const SmartPtr<VideoBuffer> &buf)
|
{
|
FPS_CALCULATION (fps_buf, XCAM_OBJ_DUR_FRAME_NUM);
|
|
XCAM_OBJ_PROFILING_START;
|
|
if (_enable_display)
|
display_buf (buf);
|
|
XCAM_OBJ_PROFILING_END("main_pipe_manager_display", XCAM_OBJ_DUR_FRAME_NUM);
|
}
|
|
int
|
MainPipeManager::display_buf (const SmartPtr<VideoBuffer> &data)
|
{
|
#if HAVE_LIBDRM
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
SmartPtr<VideoBuffer> buf = data;
|
const VideoBufferInfo & frame_info = buf->get_video_info ();
|
struct v4l2_rect rect = { 0, 0, frame_info.width, frame_info.height};
|
|
if (!_display->is_render_inited ()) {
|
ret = _display->render_init (0, 0, this->_image_width, this->_image_height,
|
frame_info.format, &rect);
|
CHECK (ret, "display failed on render_init");
|
}
|
ret = _display->render_setup_frame_buffer (buf);
|
CHECK (ret, "display failed on framebuf set");
|
ret = _display->render_buffer (buf);
|
CHECK (ret, "display failed on rendering");
|
#else
|
XCAM_UNUSED (data);
|
#endif
|
|
return 0;
|
}
|
|
XCamReturn
|
read_buf (SmartPtr<VideoBuffer> &buf, FileFP &file)
|
{
|
const VideoBufferInfo info = buf->get_video_info ();
|
VideoBufferPlanarInfo planar;
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
uint8_t *memory = buf->map ();
|
for (uint32_t index = 0; index < info.components; index++) {
|
info.get_planar_info (planar, index);
|
uint32_t line_bytes = planar.width * planar.pixel_bytes;
|
|
for (uint32_t i = 0; i < planar.height; i++) {
|
if (fread (memory + info.offsets [index] + i * info.strides [index], 1, line_bytes, file.fp) != line_bytes) {
|
if (feof (file.fp)) {
|
fseek (file.fp, 0, SEEK_SET);
|
ret = XCAM_RETURN_BYPASS;
|
} else {
|
XCAM_LOG_ERROR ("read file failed, size doesn't match");
|
ret = XCAM_RETURN_ERROR_FILE;
|
}
|
goto done;
|
}
|
}
|
}
|
done:
|
buf->unmap ();
|
return ret;
|
}
|
|
void pipe_stop_handler(int sig)
|
{
|
XCAM_UNUSED (sig);
|
is_stop = true;
|
}
|
|
void print_help (const char *bin_name)
|
{
|
printf ("Usage: %s [--format=NV12] [--width=1920] ...\n"
|
"\t --format specify output pixel format, default is NV12\n"
|
"\t --width specify input image width, default is 1920\n"
|
"\t --height specify input image height, default is 1080\n"
|
"\t --fake-input specify the path of image as fake source\n"
|
"\t --defog-mode specify defog mode\n"
|
"\t select from [disabled, retinex, dcp], default is [disabled]\n"
|
"\t --wavelet-mode specify wavelet denoise mode, default is disable\n"
|
"\t select from [0:disable, 1:Hat Y, 2:Hat UV, 3:Haar Y, 4:Haar UV, 5:Haar YUV, 6:Haar Bayes Shrink]\n"
|
"\t --3d-denoise specify 3D Denoise mode\n"
|
"\t select from [disabled, yuv, uv], default is [disabled]\n"
|
"\t --enable-wireframe enable wire frame\n"
|
"\t --enable-warp enable image warp\n"
|
"\t --display-mode display mode\n"
|
"\t select from [primary, overlay], default is [primary]\n"
|
"\t -p enable local display, need root privilege\n"
|
"\t -h help\n"
|
, bin_name);
|
}
|
|
int main (int argc, char *argv[])
|
{
|
const char *bin_name = argv[0];
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
VideoBufferInfo buf_info;
|
SmartPtr<VideoBuffer> video_buf;
|
SmartPtr<SmartAnalyzer> smart_analyzer;
|
SmartPtr<CLPostImageProcessor> cl_post_processor;
|
SmartPtr<BufferPool> buf_pool;
|
|
uint32_t pixel_format = V4L2_PIX_FMT_NV12;
|
uint32_t image_width = 1920;
|
uint32_t image_height = 1080;
|
bool need_display = false;
|
#if HAVE_LIBDRM
|
DrmDisplayMode display_mode = DRM_DISPLAY_MODE_PRIMARY;
|
#endif
|
const char *input_path = NULL;
|
FileFP input_fp;
|
|
uint32_t defog_mode = 0;
|
CLWaveletBasis wavelet_mode = CL_WAVELET_DISABLED;
|
uint32_t wavelet_channel = CL_IMAGE_CHANNEL_UV;
|
bool wavelet_bayes_shrink = false;
|
uint32_t denoise_3d_mode = 0;
|
uint8_t denoise_3d_ref_count = 3;
|
bool enable_wireframe = false;
|
bool enable_image_warp = false;
|
|
int opt;
|
const char *short_opts = "ph";
|
const struct option long_opts [] = {
|
{"format", required_argument, NULL, 'F'},
|
{"width", required_argument, NULL, 'W'},
|
{"height", required_argument, NULL, 'H'},
|
{"fake-input", required_argument, NULL, 'A'},
|
{"defog-mode", required_argument, NULL, 'D'},
|
{"wavelet-mode", required_argument, NULL, 'V'},
|
{"3d-denoise", required_argument, NULL, 'N'},
|
{"enable-wireframe", no_argument, NULL, 'I'},
|
{"enable-warp", no_argument, NULL, 'S'},
|
{"display-mode", required_argument, NULL, 'P'},
|
{NULL, 0, NULL, 0}
|
};
|
|
while ((opt = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) {
|
switch (opt) {
|
case 'F': {
|
XCAM_ASSERT (optarg);
|
CHECK_EXP ((strlen (optarg) == 4), "invalid pixel format\n");
|
pixel_format = v4l2_fourcc ((unsigned) optarg[0],
|
(unsigned) optarg[1],
|
(unsigned) optarg[2],
|
(unsigned) optarg[3]);
|
break;
|
}
|
case 'W': {
|
XCAM_ASSERT (optarg);
|
image_width = atoi (optarg);
|
break;
|
}
|
case 'H': {
|
XCAM_ASSERT (optarg);
|
image_height = atoi (optarg);
|
break;
|
}
|
case 'A': {
|
XCAM_ASSERT (optarg);
|
XCAM_LOG_INFO ("use image %s as input source", optarg);
|
input_path = optarg;
|
break;
|
}
|
case 'D': {
|
XCAM_ASSERT (optarg);
|
if (!strcmp (optarg, "disabled"))
|
defog_mode = CLPostImageProcessor::DefogDisabled;
|
else if (!strcmp (optarg, "retinex"))
|
defog_mode = CLPostImageProcessor::DefogRetinex;
|
else if (!strcmp (optarg, "dcp"))
|
defog_mode = CLPostImageProcessor::DefogDarkChannelPrior;
|
else {
|
print_help (bin_name);
|
return -1;
|
}
|
break;
|
}
|
case 'V': {
|
XCAM_ASSERT (optarg);
|
if (atoi(optarg) < 0 || atoi(optarg) > 255) {
|
print_help (bin_name);
|
return -1;
|
}
|
if (atoi(optarg) == 1) {
|
wavelet_mode = CL_WAVELET_HAT;
|
wavelet_channel = CL_IMAGE_CHANNEL_Y;
|
} else if (atoi(optarg) == 2) {
|
wavelet_mode = CL_WAVELET_HAT;
|
wavelet_channel = CL_IMAGE_CHANNEL_UV;
|
} else if (atoi(optarg) == 3) {
|
wavelet_mode = CL_WAVELET_HAAR;
|
wavelet_channel = CL_IMAGE_CHANNEL_Y;
|
} else if (atoi(optarg) == 4) {
|
wavelet_mode = CL_WAVELET_HAAR;
|
wavelet_channel = CL_IMAGE_CHANNEL_UV;
|
} else if (atoi(optarg) == 5) {
|
wavelet_mode = CL_WAVELET_HAAR;
|
wavelet_channel = CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y;
|
} else if (atoi(optarg) == 6) {
|
wavelet_mode = CL_WAVELET_HAAR;
|
wavelet_channel = CL_IMAGE_CHANNEL_UV | CL_IMAGE_CHANNEL_Y;
|
wavelet_bayes_shrink = true;
|
} else {
|
wavelet_mode = CL_WAVELET_DISABLED;
|
}
|
break;
|
}
|
case 'N': {
|
XCAM_ASSERT (optarg);
|
if (!strcmp (optarg, "disabled"))
|
denoise_3d_mode = CLPostImageProcessor::Denoise3DDisabled;
|
else if (!strcmp (optarg, "yuv"))
|
denoise_3d_mode = CLPostImageProcessor::Denoise3DYuv;
|
else if (!strcmp (optarg, "uv"))
|
denoise_3d_mode = CLPostImageProcessor::Denoise3DUV;
|
else {
|
print_help (bin_name);
|
return -1;
|
}
|
break;
|
}
|
case 'I': {
|
enable_wireframe = true;
|
break;
|
}
|
case 'S': {
|
enable_image_warp = true;
|
break;
|
}
|
case 'P': {
|
#if HAVE_LIBDRM
|
XCAM_ASSERT (optarg);
|
if (!strcmp (optarg, "primary"))
|
display_mode = DRM_DISPLAY_MODE_PRIMARY;
|
else if (!strcmp (optarg, "overlay"))
|
display_mode = DRM_DISPLAY_MODE_OVERLAY;
|
else {
|
print_help (bin_name);
|
return -1;
|
}
|
#else
|
XCAM_LOG_WARNING ("preview is not supported");
|
#endif
|
break;
|
}
|
case 'p': {
|
#if HAVE_LIBDRM
|
need_display = true;
|
#else
|
XCAM_LOG_WARNING ("preview is not supported, disable preview now");
|
need_display = false;
|
#endif
|
break;
|
}
|
case 'h':
|
print_help (bin_name);
|
return 0;
|
default:
|
print_help (bin_name);
|
return -1;
|
}
|
}
|
|
signal (SIGINT, pipe_stop_handler);
|
|
if (!input_path) {
|
XCAM_LOG_ERROR ("path of image is NULL");
|
return -1;
|
}
|
input_fp.fp = fopen (input_path, "rb");
|
if (!input_fp.fp) {
|
XCAM_LOG_ERROR ("failed to open file: %s", XCAM_STR (input_path));
|
return -1;
|
}
|
|
SmartPtr<MainPipeManager> pipe_manager = new MainPipeManager ();
|
pipe_manager->set_image_width (image_width);
|
pipe_manager->set_image_height (image_height);
|
|
SmartHandlerList smart_handlers = SmartAnalyzerLoader::load_smart_handlers (DEFAULT_SMART_ANALYSIS_LIB_DIR);
|
if (!smart_handlers.empty () ) {
|
smart_analyzer = new SmartAnalyzer ();
|
if (smart_analyzer.ptr ()) {
|
SmartHandlerList::iterator i_handler = smart_handlers.begin ();
|
for (; i_handler != smart_handlers.end (); ++i_handler) {
|
XCAM_ASSERT ((*i_handler).ptr ());
|
smart_analyzer->add_handler (*i_handler);
|
}
|
} else {
|
XCAM_LOG_INFO ("load smart analyzer(%s) failed", DEFAULT_SMART_ANALYSIS_LIB_DIR);
|
}
|
}
|
if (smart_analyzer.ptr ()) {
|
if (smart_analyzer->prepare_handlers () != XCAM_RETURN_NO_ERROR) {
|
XCAM_LOG_WARNING ("analyzer(%s) prepare handlers failed", smart_analyzer->get_name ());
|
}
|
pipe_manager->set_smart_analyzer (smart_analyzer);
|
}
|
|
cl_post_processor = new CLPostImageProcessor ();
|
cl_post_processor->set_stats_callback (pipe_manager);
|
cl_post_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode) defog_mode);
|
cl_post_processor->set_wavelet (wavelet_mode, wavelet_channel, wavelet_bayes_shrink);
|
cl_post_processor->set_3ddenoise_mode ((CLPostImageProcessor::CL3DDenoiseMode) denoise_3d_mode, denoise_3d_ref_count);
|
|
cl_post_processor->set_wireframe (enable_wireframe);
|
cl_post_processor->set_image_warp (enable_image_warp);
|
if (smart_analyzer.ptr () && (enable_wireframe || enable_image_warp)) {
|
cl_post_processor->set_scaler (true);
|
cl_post_processor->set_scaler_factor (640.0 / image_width);
|
}
|
|
pipe_manager->add_image_processor (cl_post_processor);
|
|
buf_info.init (pixel_format, image_width, image_height);
|
buf_pool = new CLVideoBufferPool ();
|
XCAM_ASSERT (buf_pool.ptr ());
|
if (!buf_pool->set_video_info (buf_info) || !buf_pool->reserve (DEFAULT_FPT_BUF_COUNT)) {
|
XCAM_LOG_ERROR ("init buffer pool failed");
|
return -1;
|
}
|
|
if (need_display) {
|
need_display = false;
|
XCAM_LOG_WARNING ("CLVideoBuffer doesn't support local preview, disable local preview now");
|
}
|
|
if (need_display) {
|
#if HAVE_LIBDRM
|
if (DrmDisplay::set_preview (need_display)) {
|
pipe_manager->set_display_mode (display_mode);
|
cl_post_processor->set_output_format (V4L2_PIX_FMT_XBGR32);
|
} else {
|
need_display = false;
|
XCAM_LOG_WARNING ("set preview failed, disable local preview now");
|
}
|
#else
|
XCAM_LOG_WARNING ("preview is not supported, disable preview now");
|
need_display = false;
|
#endif
|
}
|
pipe_manager->enable_display (need_display);
|
|
ret = pipe_manager->start ();
|
CHECK (ret, "pipe manager start failed");
|
|
while (!is_stop) {
|
video_buf = buf_pool->get_buffer (buf_pool);
|
XCAM_ASSERT (video_buf.ptr ());
|
|
ret = read_buf (video_buf, input_fp);
|
if (ret == XCAM_RETURN_BYPASS) {
|
ret = read_buf (video_buf, input_fp);
|
}
|
|
if (ret == XCAM_RETURN_NO_ERROR)
|
pipe_manager->push_buffer (video_buf);
|
}
|
|
ret = pipe_manager->stop();
|
CHECK (ret, "pipe manager stop failed");
|
|
return 0;
|
}
|