diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2019-11-13 19:57:19 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-11-13 19:57:19 +0000 |
commit | 0940eea50f612285288f22259443410aa5052e3c (patch) | |
tree | b04baa77f748351ecd3d0788fbcf7acf248e34ce | |
parent | ecea4993be3fdd0bb18255484158104e7a0268a0 (diff) | |
parent | 553504d7c452d5b83a758b228d704c97aa5a4e4b (diff) | |
download | libxcam-0940eea50f612285288f22259443410aa5052e3c.tar.gz |
Merge "Upgrade libxcam to release_1.2.2"
279 files changed, 27694 insertions, 2761 deletions
@@ -19,6 +19,7 @@ config.* /pkgconfig/*.pc .deps .libs +.dirstamp # Object files *.o @@ -4,11 +4,12 @@ Maintainers: Wind Yuan <feng.yuan@intel.com> Contributors: (orders by first name) +Andrey Parfenov <a1994ndrey@gmail.com> Fei Wang <feix.w.wang@intel.com> Jia Meng <jia.meng@intel.com> John Ye <john.ye@intel.com> Juan Zhao <juan.j.zhao@intel.com> -Junkai Wu <wujunkai166@gmail.com> +Junkai Wu <wujunkai166@gmail.com> <junkai.wu@intel.com> Sameer Kibey <sameer.kibey@intel.com> Shincy Tu <shincy.tu@intel.com> Wei Zong <wei.zong@intel.com> @@ -1,5 +1,5 @@ - Copyright (c) 2014-2015 Intel Corporation + Copyright (c) 2014-2019 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1,3 +1,68 @@ +2019/04/02: release libxcam version 1.2.2 + * DNN inference framwork enabling. + - enable pedestrian and vehicle detection based on OpenVino + + * OpenCV feature match enabled for image stitching pipeline (GLES/Vulkan/CPU) + - support three versions of feature match: default, cluster, capi + + * Abstract OpenCV source in ocv module, and build into a separate static library + +2018/12/19: release libxcam version 1.2.1 + * Vulkan surround-view stitching enabling. + - enable features of multi-band blender and geometry remap. + - enable Vulkan image stitching. (feature-match may support later) + + * Surrond-view texture rendering. + - enable 3D surround view scene rendering and manipulation. + + * require OpenSceneGraph minimal version 3.3.2 + +2018/10/16: release libxcam version 1.2.0 + * GLES compute framework enabling. + - enable GL image processing framework. + - enable features of multi-band blender, geometry remap and data-copy. + + * GLES surround-view stitching enabling. + - GLES stitching enabled (feature-match may support later). + - performance optimized on compute shaders. + + * Vulkan compute framework enabling. + - enabled Vulkan image processing under xcam framework. + - vk-copy-handler as sample code. + + * suggest OpenCV version [3.0.0 - 3.4.3] + * support CPU stitching based on dual-const and dual-curve scaling factors. + * support OpenCL stitching based on auto-scale in vertical 2D-direction. + * change test-soft-image to test-surround-view + +2018/03/01: release libxcam version 1.1.0 + * CPU stitching enabled for automotive surround view in Linux/Android. + - enable CPU multi-thread image processing framework. + - enable multi-band blender, geometry remap, data-copy, OpenCV feature match. + - enable 3D-bowl model stitching. + - support generic Android platform. + - CPU version of surround view stitching upstream to Android Open Source Project. + + * surround-view OpenCL stitching feature enabled and quality improvement. + - add dewarp process based on bowl view model in geometry map. + - support multiple (4) cameras stitching. + - add new selection method based on clustering in feature match to improve quality of stitching. + - auto scale in x direction is done and y direction is WIP. + - quality tune on different datasets, both indoor and outdoor. + + * support standard OpenCL 2.0+ driver (VPG OCL driver) + - support standard OpenCL buffer. + - remove libdrm dependency. + - drm preview removed from test-device-manager, test-pipe-manager and usb camera. + + * enable deblurring feature based on OpenCV. (GSoC program) + - based on deconvolution algorithm filters + - support noise estimation + - support edgetaper + + * sourround view solution will be integrated into Android EVS (exterior view system) WIP + * add sample recipe for yocto build (libxcam/doc/yocto). + 2017/07/10: release libxcam version 1.0.0 * 360 video stitching performance and quality improvement. - enable geometry map to improve performance. @@ -1,5 +1,5 @@ - Copyright (c) 2014-2015 Intel Corporation + Copyright (c) 2014-2019 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1,18 +1,15 @@ name: "LibXCam" -description: - "libXCam is a project for extended camera and computer " - "vision features. This library can work on GPU, CPU and " - "other HW platforms to improve image/video quality. " - "OpenCL as one of the common parallel computing languages " - "is used to improve performance in different platforms. " - "Other shading language supports are in roadmap." - +description: "libXCam is a project for extended camera and computer vision features. This library can work on GPU, CPU and other HW platforms to improve image/video quality. OpenCL as one of the common parallel computing languages is used to improve performance in different platforms. Other shading language supports are in roadmap." third_party { url { type: GIT - value: "https://github.com/01org/libxcam.git" + value: "https://github.com/intel/libxcam" } - version: "1.0.0" - last_upgrade_date { year: 2017 month: 9 day: 11 } + version: "release_1.2.2" license_type: NOTICE + last_upgrade_date { + year: 2019 + month: 4 + day: 4 + } } diff --git a/Makefile.am b/Makefile.am index 3f59882..4285b9d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,23 +1,6 @@ -if HAVE_LIBCL -CLX_KERNEL_DIR = clx_kernel -else -CLX_KERNEL_DIR = -endif - -if HAVE_LIBCL -TESTS_DIR = tests -else -if ENABLE_IA_AIQ -TESTS_DIR = tests -else -TESTS_DIR = -endif -endif - if ENABLE_CAPI CAPI_DIR = capi -else -CAPI_DIR = endif -SUBDIRS = xcore $(CLX_KERNEL_DIR) modules plugins \ - wrapper $(CAPI_DIR) $(TESTS_DIR) pkgconfig + +SUBDIRS = xcore shaders modules plugins \ + wrapper $(CAPI_DIR) tests pkgconfig @@ -1,6 +1,6 @@ ## libXCam -Copyright (C) 2014-2017 Intel Corporation +Copyright (C) 2014-2019 Intel Corporation libxcam core source code under the terms of Apache License, Version 2.0 @@ -12,48 +12,60 @@ library makes GPU/CPU/ISP working together to improve image quality. OpenCL is used to improve performance in different platforms. #### Features: - * Image processing features. + * Image processing features - Advanced features - - 360 Image stiching: generate 360 degree panorama photography by - stitching multiple neighbor fisheye images. - - Digital Video Stabilization: + - Automotive surround view(360) stitching (OpenCL/CPU/GLES) + - Support bowl view 3D model stitching by 4 video input. + - Enable geometry remap for WFoV camera calibration(intrinsic and extrinsic data). + - Quality and performance improved (OpenCL/CPU/GLES). + - CPU version upstreamed into AOSP for automotive surround view. + - Enable Vulkan to improve performance. + - 360 video stitching (Equirectangular mode via OpenCL) + - Support 2-fisheye (>180 degree) video stream stitching. + - Performance and quality improved. + - DNN inference framework + - Support pedestrian and vehicle detection. + - Digital Video Stabilization - OpenCV feature-matched based video stabilization. - gyroscope 3-DoF (orientation) based video stabilization. - - Blender: multi-band blender. - - Noise reduction. + - Blender: multi-band blender (OpenCL/CPU/GLES) + - Noise reduction (OpenCL) - adaptive NR based on wavelet-haar and Bayersian shrinkage. - 3D-NR with inter-block and intra-block reference. - wavelet-hat NR (obsolete). - - Wide dynamic range (WDR). + - Wide dynamic range (WDR) (OpenCL) - histogram adjustment tone-mapping. - gaussian-based tone-mapping (obsolete). - - Fog removal: retinex and dark channel prior algorithm. + - Fog removal: retinex and dark channel prior algorithm (OpenCL) - dark channel prior algorithm based defog. - multi-scale retinex based defog (obsolete). - - Basic pipeline from bayer to YUV/RGB format. + - Basic pipeline from bayer to YUV/RGB format (OpenCL / AtomISP) - Gamma correction, MACC, color space, demosaicing, simple bilateral noise reduction, edge enhancement and temporal noise reduction. - - 3A features. + - 3A features - Auto whitebalance, auto exposure, auto focus, black level correction, color correction, 3a-statistics calculation. - * Support 3rd party 3A lib which can be loaded dynamically. + * Support 3rd party 3A lib which can be loaded dynamically - hybrid 3a plugin. - * Support 3a analysis tuning framework for different features. - * Support smart analysis framework. + * Support 3a analysis tuning framework for different features + * Support smart analysis framework - Face detection interface/plugin. - * Enable gstreamer plugin. + * Enable gstreamer plugin - xcamsrc, capture from usb/isp camera, process 3a/basic/advanced features. - xcamfilter, improve image quality by advanced features and smart analysis. #### Prerequisite: * install gcc/g++, automake, autoconf, libtool, gawk, pkg-config * Linux kernel > 3.10 - * install libdrm-dev * install ocl-icd-dev, ocl-icd-opencl-dev - * If --enable-libcl, need compile ocl driver <https://www.freedesktop.org/wiki/Software/Beignet/> - * If --enable-opencv, need compile opencv <http://opencv.org> (or: <https://github.com/opencv/opencv/wiki>) * If --enable-gst, need install libgstreamer1.0-dev, libgstreamer-plugins-base1.0-dev - * If --enable-aiq, need get ia_imaging lib which we don't support. + * If --enable-aiq, need get ia_imaging lib which we don't support + * If --enable-libcl, need compile [OpenCL](https://www.freedesktop.org/wiki/Software/Beignet) driver + * If --enable-opencv, suggest [OpenCV](http://opencv.org) versions [3.0.0 - 3.4.3] (or: [OpenCV Wiki](https://github.com/opencv/opencv/wiki)) + * If --enable-render, need compile [OpenSceneGraph](https://github.com/openscenegraph/OpenSceneGraph) library with configure option "-DOSG_WINDOWING_SYSTEM=X11" + * If --enable-gles, need to install [Mesa3D](https://www.mesa3d.org) library + * If --enable-vulkan, need to install [Mesa3D](https://www.mesa3d.org) library + * If --enable-dnn, need to install OpenVino SDK #### Building and installing: * Environment variable settings<BR> @@ -73,27 +85,53 @@ OpenCL is used to improve performance in different platforms. --prefix=PREFIX install architecture-independent files in PREFIX [default=/usr/local] --enable-debug enable debug, [default=no] --enable-profiling enable profiling, [default=no] - --enable-drm enable drm buffer, [default=yes] + --enable-drm enable drm buffer, [default=no] --enable-aiq enable Aiq 3A algorithm build, [default=no] --enable-gst enable gstreamer plugin build, [default=no] --enable-libcl enable libcl image processor, [default=yes] --enable-opencv enable opencv library, [default=no] + --enable-capi enable libxcam-capi library, [default=no] --enable-docs build Doxygen documentation [default=no] --enable-3alib enable 3A lib build, [default=no] --enable-smartlib enable smart analysis lib build, [default=no] + --enable-gles enable gles, [default=no] + --enable-vulkan enable vulkan, [default=no] + --enable-render enable 3D texture render, [default=no] + --enable-dnn enable dnn inference, [default=no] For example: - $ ./autogen.sh --prefix=/usr --enable-3alib --enable-aiq --enable-gst --enable-drm \ - --enable-libcl --enable-opencv --enable-profiling --enable-smartlib + $ ./autogen.sh --prefix=/usr --enable-gst --enable-libcl --enable-opencv \ + --enable-smartlib --enable-profiling --enable-gles --enable-render --enable-dnn * $ make * $ sudo make install #### Testing: - * For detailed test cases, please refer to:<BR> - <https://github.com/01org/libxcam/wiki/Tests> + * For detailed test cases, please go to [tests](https://github.com/intel/libxcam/wiki/Tests) page #### Reporting Bugs: - * Bugs or suggestions can be reported on the github issues page:<BR> - <https://github.com/01org/libxcam/issues> + * Bugs or suggestions can be reported on the github [issues](https://github.com/intel/libxcam/issues) page + * Security issues, please send email to wei.zong@intel.com directly + +#### Mailing list + * To post a message to all the list members, please send email to libxcam@lists.01.org + * To register libxcam public maillist, please go to [registration](https://lists.01.org/mailman/listinfo/libxcam) page + +#### Maintainer: + * Wind Yuan <feng.yuan@intel.com> + * Wei Zong <wei.zong@intel.com> + +#### Contributors: (orders by first name) + * Andrey Parfenov <a1994ndrey@gmail.com> + * Fei Wang <feix.w.wang@intel.com> + * Jia Meng <jia.meng@intel.com> + * John Ye <john.ye@intel.com> + * Juan Zhao <juan.j.zhao@intel.com> + * Junkai Wu <junkai.wu@intel.com> + * Sameer Kibey <sameer.kibey@intel.com> + * Shincy Tu <shincy.tu@intel.com> + * Wei Zong <wei.zong@intel.com> + * Yan Zhang <yan.y.zhang@intel.com> + * Yao Wang <yao.y.wang@intel.com> + * Yinhang Liu <yinhangx.liu@intel.com> diff --git a/capi/Makefile.am b/capi/Makefile.am index 029fd7a..6b04110 100644 --- a/capi/Makefile.am +++ b/capi/Makefile.am @@ -1,53 +1,51 @@ lib_LTLIBRARIES = libxcam_capi.la -XCAMCAPI_LIBS = \ - $(LIBCL_LIBS) \ - -ldl \ +XCAMCAPI_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(LIBCL_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ $(NULL) -XCAMCAPI_CXXFLAGS = \ - $(XCAM_CXXFLAGS) \ - $(LIBCL_CFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/modules \ +XCAMCAPI_LIBS = \ + $(LIBCL_LIBS) -ldl \ + $(top_builddir)/xcore/libxcam_core.la \ + $(top_builddir)/modules/ocl/libxcam_ocl.la \ $(NULL) if HAVE_LIBDRM XCAMCAPI_CXXFLAGS += $(LIBDRM_CFLAGS) -XCAMCAPI_LIBS += \ - -ldrm_intel \ - $(LIBDRM_LIBS) \ +XCAMCAPI_LIBS += \ + -ldrm_intel \ + $(LIBDRM_LIBS) \ $(NULL) endif -xcam_ocl_sources = \ - xcam_handle.cpp \ - context_priv.cpp \ - $(NULL) +xcam_ocl_sources = \ + xcam_handle.cpp \ + context_priv.cpp \ + $(NULL) -libxcam_capi_la_SOURCES = \ - $(xcam_ocl_sources) \ +libxcam_capi_la_SOURCES = \ + $(xcam_ocl_sources) \ $(NULL) -libxcam_capi_la_CXXFLAGS = \ - $(XCAMCAPI_CXXFLAGS) \ +libxcam_capi_la_CXXFLAGS = \ + $(XCAMCAPI_CXXFLAGS) \ $(NULL) -libxcam_capi_la_LIBADD = \ - $(top_builddir)/modules/ocl/libxcam_ocl.la \ - $(top_builddir)/xcore/libxcam_core.la \ - $(XCAMCAPI_LIBS) \ +libxcam_capi_la_LIBADD = \ + $(XCAMCAPI_LIBS) \ $(NULL) -libxcam_capi_la_LDFLAGS = \ - $(XCAM_LT_LDFLAGS) \ - $(PTHREAD_LDFLAGS) \ +libxcam_capi_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ $(NULL) libxcam_capiincludedir = $(includedir)/xcam/capi nobase_libxcam_capiinclude_HEADERS = \ - xcam_handle.h \ - $(NULL) + xcam_handle.h \ + $(NULL) libxcam_capi_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/capi/context_priv.cpp b/capi/context_priv.cpp index ecbffa6..2e685c1 100644 --- a/capi/context_priv.cpp +++ b/capi/context_priv.cpp @@ -59,8 +59,9 @@ ContextBase::ContextBase (HandleType type) , _alloc_out_buf (false) { if (!_inbuf_pool.ptr()) { - _inbuf_pool = new CLVideoBufferPool (); - XCAM_ASSERT (_inbuf_pool.ptr ()); + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + XCAM_ASSERT (pool.ptr ()); + _inbuf_pool = pool; } } @@ -222,10 +223,6 @@ StitchContext::create_handler (SmartPtr<CLContext> &context) image_360->set_output_size (sttch_width, sttch_height); XCAM_LOG_INFO ("stitch output size width:%d height:%d", sttch_width, sttch_height); -#if HAVE_OPENCV - image_360->set_feature_match_ocl (_fm_ocl); -#endif - return image_360; } diff --git a/capi/context_priv.h b/capi/context_priv.h index fe5c0a9..eb7514f 100644 --- a/capi/context_priv.h +++ b/capi/context_priv.h @@ -165,7 +165,6 @@ public: , _need_seam (false) , _fisheye_map (false) , _need_lsc (false) - , _fm_ocl (false) , _scale_mode (CLBlenderScaleLocal) , _res_mode (StitchRes1080P) {} @@ -176,7 +175,6 @@ private: bool _need_seam; bool _fisheye_map; bool _need_lsc; - bool _fm_ocl; CLBlenderScaleMode _scale_mode; StitchResMode _res_mode; }; diff --git a/clx_kernel/Makefile.am b/clx_kernel/Makefile.am deleted file mode 100644 index c87cf1a..0000000 --- a/clx_kernel/Makefile.am +++ /dev/null @@ -1,39 +0,0 @@ -clx_kernel_sources = \ - kernel_csc.clx \ - kernel_demo.clx \ - kernel_defog_dcp.clx \ - kernel_min_filter.clx \ - kernel_bi_filter.clx \ - kernel_tnr.clx \ - kernel_bayer_pipe.clx \ - kernel_bayer_basic.clx \ - kernel_fisheye.clx \ - kernel_rgb_pipe.clx \ - kernel_yuv_pipe.clx \ - kernel_tonemapping.clx \ - kernel_newtonemapping.clx \ - kernel_image_scaler.clx \ - kernel_retinex.clx \ - kernel_gauss.clx \ - kernel_gauss_lap_pyramid.clx \ - kernel_geo_map.clx \ - kernel_wavelet_denoise.clx \ - kernel_wavelet_haar.clx \ - kernel_wavelet_coeff.clx \ - kernel_wire_frame.clx \ - kernel_3d_denoise.clx \ - kernel_3d_denoise_slm.clx \ - kernel_image_warp.clx \ - $(NULL) - -cl_quotation_sh = \ - $(top_srcdir)/tools/cl-double-quotation.sh - -cl_kernel_dir = $(top_srcdir)/cl_kernel - -all-local: $(clx_kernel_sources) - -$(clx_kernel_sources): %.clx: $(cl_kernel_dir)/%.cl - @$(cl_quotation_sh) $< $@ - -CLEANFILES = $(clx_kernel_sources) diff --git a/configure.ac b/configure.ac index e98ad18..6c8c363 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. m4_define([xcam_major_version], [1]) -m4_define([xcam_minor_version], [1]) -m4_define([xcam_micro_version], [0]) +m4_define([xcam_minor_version], [2]) +m4_define([xcam_micro_version], [2]) m4_define([xcam_version], [xcam_major_version.xcam_minor_version.xcam_micro_version]) AC_PREREQ([2.60]) @@ -27,6 +27,13 @@ XCAM_LT_LDFLAGS="-version-number $XCAM_LT_VERSION" AC_SUBST(XCAM_LT_VERSION) AC_SUBST(XCAM_LT_LDFLAGS) +#xcam required OpenCV version +XCAM_REQUIRE_CV_MIN=3.0.0 +XCAM_REQUIRE_CV_MAX=3.4.3 + +#xcam required OpenSceneGraph version +XCAM_REQUIRE_OSG_MIN=3.3.2 + # Checks for programs. AC_PROG_CC AC_PROG_CXX @@ -65,6 +72,16 @@ AC_ARG_ENABLE(libcl, [enable libcl image processor, @<:@default=yes@:>@]), [], [enable_libcl="yes"]) +AC_ARG_ENABLE([gles], + AS_HELP_STRING([--enable-gles], + [enable gles, @<:@default=no@:>@]), + [], [enable_gles="no"]) + +AC_ARG_ENABLE([vulkan], + AS_HELP_STRING([--enable-vulkan], + [enable vulkan, @<:@default=no@:>@]), + [], [enable_vulkan="no"]) + AC_ARG_ENABLE(opencv, AS_HELP_STRING([--enable-opencv], [enable opencv library, @<:@default=no@:>@]), @@ -72,8 +89,18 @@ AC_ARG_ENABLE(opencv, AC_ARG_ENABLE(capi, AS_HELP_STRING([--enable-capi], - [enable libxcam-capi library, @<:@default=yes@:>@]), - [], [enable_capi="yes"]) + [enable libxcam-capi library, @<:@default=no@:>@]), + [], [enable_capi="no"]) + +AC_ARG_ENABLE([render], + AS_HELP_STRING([--enable-render], + [enable texture render with OpenSceneGraph library, @<:@default=no@:>@]), + [], [enable_render="no"]) + +AC_ARG_ENABLE([dnn], + AS_HELP_STRING([--enable-dnn], + [enable dnn with OpenVino library, @<:@default=no@:>@]), + [], [enable_dnn="no"]) # documentation AC_ARG_ENABLE(docs, @@ -118,6 +145,51 @@ if test "$enable_libcl" = "yes"; then PKG_CHECK_MODULES(LIBCL, [libcl], [HAVE_LIBCL=1], [HAVE_LIBCL=0]) fi +# check gl +HAVE_GLES=0 +if test "$enable_gles" = "yes"; then + PKG_CHECK_MODULES(LIBGL, [gl], [HAVE_GLES=1], [HAVE_GLES=0]) +fi + +# check vulkan +HAVE_VULKAN=0 +if test "$enable_vulkan" = "yes"; then + PKG_CHECK_MODULES(LIBVULKAN, [vulkan], [HAVE_VULKAN=1], [HAVE_VULKAN=0]) +fi + +# check open sence graph +ENABLE_RENDER=0 +if test "$enable_render" = "yes"; then + PKG_CHECK_MODULES( + [LIBOSG], + [openscenegraph-osg >= $XCAM_REQUIRE_OSG_MIN], + [HAVE_OSG=1], + [HAVE_OSG=0]) + + XCAM_OSG_VERSION=`$PKG_CONFIG --modversion openscenegraph-osg` + AC_MSG_NOTICE(OpenSceneGraph version: $XCAM_OSG_VERSION) + + if test "$HAVE_OSG" -eq 1; then + ENABLE_RENDER=1 + else + AC_MSG_WARN(OpenSceneGraph required version: >= $XCAM_REQUIRE_OSG_MIN) + ENABLE_RENDER=0 + fi +fi + +ENABLE_DNN=0 +if test "$enable_dnn" = "yes"; then + if test -z $OPENVINO_IE_INC_PATH; then + AC_MSG_WARN(Please export OPENVINO_IE_INC_PATH environment variables) + AC_MSG_ERROR(OpenVino inc path has not been set ... disable DNN module!) + fi + if test -z $OPENVINO_IE_LIBS_PATH; then + AC_MSG_WARN(Please export OPENVINO_IE_LIBS_PATH environment variables) + AC_MSG_ERROR(OpenVino library path has not been set ... disable DNN module!) + fi + ENABLE_DNN=1 +fi + if test "$enable_libcl" = "yes" && test "$HAVE_LIBCL" -eq 0; then PKG_CHECK_MODULES(LIBCL, [OpenCL], [HAVE_LIBCL=1], [HAVE_LIBCL=0]) fi @@ -143,12 +215,21 @@ if test "$HAVE_LIBCL" -eq 1; then fi fi -# check opencv minimum version number +# check opencv version number HAVE_OPENCV=0 if test "$enable_opencv" = "yes"; then - OPENCV_VERSION_STR=`$PKG_CONFIG --modversion opencv` - PKG_CHECK_MODULES([OPENCV], [opencv >= 3.0.0], [HAVE_OPENCV=1], [HAVE_OPENCV=0]) - echo "OpenCV version:"$OPENCV_VERSION_STR "minimum required version:3.0.0" "have opencv:"$HAVE_OPENCV + PKG_CHECK_MODULES( + [OPENCV], + [opencv >= $XCAM_REQUIRE_CV_MIN opencv <= $XCAM_REQUIRE_CV_MAX], + [HAVE_OPENCV=1], + [HAVE_OPENCV=0]) + + XCAM_CV_VERSION=`$PKG_CONFIG --modversion opencv` + AC_MSG_NOTICE(OpenCV version: $XCAM_CV_VERSION) + + if test "$HAVE_OPENCV" -eq 0; then + AC_MSG_ERROR(OpenCV required version: >= $XCAM_REQUIRE_CV_MIN && <= $XCAM_REQUIRE_CV_MAX) + fi fi # check opencv videostab module @@ -193,7 +274,8 @@ fi # check capi build ENABLE_CAPI=0 -if test "$enable_capi" = "yes"; then +if test "$enable_capi" = "yes" && test "$HAVE_LIBCL" -eq 1; then + AC_MSG_NOTICE(enable capi && have libcl: $HAVE_LIBCL) ENABLE_CAPI=1 fi @@ -305,7 +387,7 @@ fi AM_CONDITIONAL([ENABLE_GST], [test "$ENABLE_GST" -eq 1]) dnl set XCAM_CFLAGS and XCAM_CXXFLAGS -XCAM_CFLAGS=" -fPIC -DSTDC99 -W -Wall -D_REENTRANT -Wformat -Wformat-security -fstack-protector" +XCAM_CFLAGS=" -fPIC -Wall -fstack-protector" if test "$enable_debug" = "yes"; then XCAM_CFLAGS="$XCAM_CFLAGS -g -DDEBUG" fi @@ -313,9 +395,6 @@ XCAM_CXXFLAGS="$XCAM_CFLAGS -std=c++0x" AC_SUBST(XCAM_CFLAGS) AC_SUBST(XCAM_CXXFLAGS) -PTHREAD_LDFLAGS="$PTHREAD_LDFLAGS -pthread" -AC_SUBST(PTHREAD_LDFLAGS) - # define macor in config.h AC_DEFINE_UNQUOTED([ENABLE_PROFILING], $ENABLE_PROFILING, [enable profiling]) @@ -328,6 +407,22 @@ AC_DEFINE_UNQUOTED([HAVE_LIBCL], $HAVE_LIBCL, [have libcl]) AM_CONDITIONAL([HAVE_LIBCL], [test "$HAVE_LIBCL" -eq 1]) +AC_DEFINE_UNQUOTED([HAVE_GLES], $HAVE_GLES, + [have gles]) +AM_CONDITIONAL([HAVE_GLES], [test "$HAVE_GLES" -eq 1]) + +AC_DEFINE_UNQUOTED([HAVE_VULKAN], $HAVE_VULKAN, + [have vulkan]) +AM_CONDITIONAL([HAVE_VULKAN], [test "$HAVE_VULKAN" -eq 1]) + +AC_DEFINE_UNQUOTED([ENABLE_RENDER], $ENABLE_RENDER, + [enable texture render]) +AM_CONDITIONAL([ENABLE_RENDER], [test "$ENABLE_RENDER" -eq 1]) + +AC_DEFINE_UNQUOTED([ENABLE_DNN], $ENABLE_DNN, + [enable dnn]) +AM_CONDITIONAL([ENABLE_DNN], [test "$ENABLE_DNN" -eq 1]) + AC_DEFINE_UNQUOTED([HAVE_OPENCV], $HAVE_OPENCV, [have opencv]) AM_CONDITIONAL([HAVE_OPENCV], [test "$HAVE_OPENCV" -eq 1]) @@ -354,12 +449,19 @@ AM_CONDITIONAL([ENABLE_IA_AIQ], [test "$ENABLE_IA_AIQ" -eq 1]) AM_CONDITIONAL([USE_LOCAL_AIQ], [test "$USE_LOCAL_AIQ" -eq 1]) AC_CONFIG_FILES([Makefile - clx_kernel/Makefile + shaders/Makefile + shaders/clx/Makefile + shaders/glslx/Makefile xcore/Makefile modules/Makefile + modules/ocv/Makefile modules/soft/Makefile modules/isp/Makefile modules/ocl/Makefile + modules/gles/Makefile + modules/vulkan/Makefile + modules/render/Makefile + modules/dnn/Makefile wrapper/Makefile wrapper/gstreamer/Makefile wrapper/gstreamer/interface/Makefile @@ -383,8 +485,13 @@ if test "$HAVE_LIBDRM" -eq 1; then have_drm="yes"; else have_drm="no"; fi if test "$USE_LOCAL_AIQ" -eq 1; then use_local_aiq="yes"; else use_local_aiq="no"; fi if test "$USE_LOCAL_ATOMISP" -eq 1; then use_local_atomisp="yes"; else use_local_atomisp="no"; fi if test "$HAVE_LIBCL" -eq 1; then have_libcl="yes"; else have_libcl="no"; fi +if test "$HAVE_GLES" -eq 1; then have_gles="yes"; else have_gles="no"; fi +if test "$HAVE_VULKAN" -eq 1; then have_vulkan="yes"; else have_vulkan="no"; fi if test "$HAVE_OPENCV" -eq 1; then have_opencv="yes"; else have_opencv="no"; fi +if test "$ENABLE_RENDER" -eq 1; then enable_render="yes"; else enable_render="no"; fi +if test "$ENABLE_DNN" -eq 1; then enable_dnn="yes"; else enable_dnn="no"; fi if test "$ENABLE_DVS" -eq 1; then enable_dvs="yes"; else enable_dvs="no"; fi +if test "$ENABLE_CAPI" -eq 1; then enable_capi="yes"; else enable_capi="no"; fi echo " libxcam configuration summary @@ -396,8 +503,12 @@ echo " build aiq analyzer : $enable_aiq use local aiq : $use_local_aiq use local atomisp : $use_local_atomisp - have opencl lib : $have_libcl - have opencv lib : $have_opencv + enable OpenCV : $have_opencv + enable OpenCL : $have_libcl + enable GLES : $have_gles + enable Vulkan : $have_vulkan + enable OSG render : $enable_render + enable DNN : $enable_dnn enable 3a lib : $enable_3alib enable smart analysis lib : $enable_smartlib enable dvs : $enable_dvs diff --git a/doc/xcam_framework_20170407.png b/doc/xcam_framework_20170407.png Binary files differdeleted file mode 100644 index ea7b7ee..0000000 --- a/doc/xcam_framework_20170407.png +++ /dev/null diff --git a/doc/xcam_framework_20181017.png b/doc/xcam_framework_20181017.png Binary files differnew file mode 100644 index 0000000..1419323 --- /dev/null +++ b/doc/xcam_framework_20181017.png diff --git a/doc/xcam_framework_20190329.png b/doc/xcam_framework_20190329.png Binary files differnew file mode 100644 index 0000000..4bcacf1 --- /dev/null +++ b/doc/xcam_framework_20190329.png diff --git a/doc/yocto/libxcam_sample.bb b/doc/yocto/libxcam_sample.bb index 0ebdd31..26c728e 100644 --- a/doc/yocto/libxcam_sample.bb +++ b/doc/yocto/libxcam_sample.bb @@ -1,6 +1,6 @@ SUMMARY = "Libxcam" DESCRIPTION = "Libxcam: Extended camera features and cross platform computer vision project" -HOMEPAGE = "https://github.com/01org/libxcam/wiki" +HOMEPAGE = "https://github.com/intel/libxcam/wiki" LICENSE = "Apache-2.0" PR = "r0" @@ -8,7 +8,7 @@ S = "${WORKDIR}/git" LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=a739187a9544e0731270d11a8f5be792" -SRC_URI = "git://github.com/01org/libxcam.git;branch=master" +SRC_URI = "git://github.com/intel/libxcam.git;branch=master" SRCREV = "${AUTOREV}" DEPENDS = "glib-2.0 libdrm beignet opencv gstreamer1.0 gstreamer1.0-plugins-base" @@ -19,7 +19,7 @@ EXTRA_OECONF = "--enable-gst --enable-drm --enable-libcl --enable-smartlib --ena CFLAGS += "-fPIE -fPIC" CFLAGS += "-O2 -D_FORTIFY_SOURCE=2" -CFLAGS += "-Wformat -Wformat-security" +CFLAGS += "-Wall -Wno-unused-parameter" CFLAGS += "-fstack-protector" LDFLAGS += "-z noexecstack" diff --git a/modules/Makefile.am b/modules/Makefile.am index fd362f8..b4eda9b 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -1,13 +1,29 @@ +if HAVE_OPENCV +OCV_DIR = ocv +endif + if HAVE_LIBCL OCL_DIR = ocl -else -OCL_DIR = +endif + +if HAVE_GLES +GLES_DIR = gles +endif + +if HAVE_VULKAN +VULKAN_DIR = vulkan +endif + +if ENABLE_RENDER +RENDER_DIR = render endif if ENABLE_IA_AIQ ISP_DIR = isp -else -ISP_DIR = endif -SUBDIRS = soft $(ISP_DIR) $(OCL_DIR) +if ENABLE_DNN +DNN_DIR = dnn +endif + +SUBDIRS = $(OCV_DIR) soft $(OCL_DIR) $(GLES_DIR) $(VULKAN_DIR) $(RENDER_DIR) $(ISP_DIR) $(DNN_DIR) diff --git a/modules/dnn/Makefile.am b/modules/dnn/Makefile.am new file mode 100644 index 0000000..bcad5fd --- /dev/null +++ b/modules/dnn/Makefile.am @@ -0,0 +1,52 @@ +lib_LTLIBRARIES = libxcam_dnn.la + +XCAM_DNN_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + -I$(OPENVINO_IE_INC_PATH)/include \ + -I$(OPENVINO_IE_INC_PATH)/src/extension \ + -I$(OPENVINO_IE_INC_PATH)/samples/common/format_reader \ + $(NULL) + +XCAM_DNN_LIBS = \ + $(top_builddir)/xcore/libxcam_core.la \ + -L$(OPENVINO_IE_LIBS_PATH) \ + -linference_engine \ + -lclDNN64 \ + -lclDNNPlugin \ + -lcpu_extension \ + -lMKLDNNPlugin \ + -lformat_reader \ + $(NULL) + +xcam_dnn_sources = \ + dnn_inference_engine.cpp \ + dnn_object_detection.cpp \ + $(NULL) + +libxcam_dnn_la_SOURCES = \ + $(xcam_dnn_sources) \ + $(NULL) + +libxcam_dnn_la_CXXFLAGS = \ + $(XCAM_DNN_CXXFLAGS) \ + $(NULL) + +libxcam_dnn_la_LIBADD = \ + $(XCAM_DNN_LIBS) \ + $(NULL) + +libxcam_dnn_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ + -Wl,-rpath,$(OPENVINO_IE_LIBS_PATH) \ + $(NULL) + +libxcam_dnnincludedir = $(includedir)/xcam/dnn + +nobase_libxcam_dnninclude_HEADERS = \ + dnn_inference_engine.h \ + dnn_object_detection.h \ + $(NULL) + +libxcam_dnn_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/dnn/dnn_inference_engine.cpp b/modules/dnn/dnn_inference_engine.cpp new file mode 100755 index 0000000..8453161 --- /dev/null +++ b/modules/dnn/dnn_inference_engine.cpp @@ -0,0 +1,878 @@ +/* + * dnn_inference_engine.cpp - dnn inference engine + * + * Copyright (c) 2019 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: Zong Wei <wei.zong@intel.com> + */ + +#include <iomanip> + +#include <format_reader_ptr.h> +#include <ext_list.hpp> + +#include "dnn_inference_engine.h" + +using namespace std; +using namespace InferenceEngine; + +namespace XCam { + +DnnInferenceEngine::DnnInferenceEngine (DnnInferConfig& config) + : _model_created (false) + , _model_loaded (false) + , _input_image_width (0) + , _input_image_height (0) +{ + XCAM_LOG_DEBUG ("DnnInferenceEngine::DnnInferenceEngine"); + + create_model (config); +} + + +DnnInferenceEngine::~DnnInferenceEngine () +{ + +} + +XCamReturn +DnnInferenceEngine::create_model (DnnInferConfig& config) +{ + XCAM_LOG_DEBUG ("DnnInferenceEngine::create_model"); + if (_model_created) { + XCAM_LOG_INFO ("model already created!"); + return XCAM_RETURN_NO_ERROR; + } + + // 1. Read the Intermediate Representation + XCAM_LOG_DEBUG ("pre-trained model file name: %s", config.model_filename); + if (NULL == config.model_filename) { + XCAM_LOG_ERROR ("Model file name is empty!"); + return XCAM_RETURN_ERROR_PARAM; + } + + _network_reader.ReadNetwork (get_filename_prefix (config.model_filename) + ".xml"); + _network_reader.ReadWeights (get_filename_prefix (config.model_filename) + ".bin"); + + // 2. read network from model + _network = _network_reader.getNetwork (); + + // 3. Select Plugin - Select the plugin on which to load your network. + // 3.1. Create the plugin with the InferenceEngine::PluginDispatcher load helper class. + if (NULL == config.plugin_path) { + InferenceEngine::PluginDispatcher dispatcher ({""}); + _plugin = dispatcher.getPluginByDevice (getDeviceName (get_device_from_id (config.target_id))); + } else { + InferenceEngine::PluginDispatcher dispatcher ({config.plugin_path}); + _plugin = dispatcher.getPluginByDevice (getDeviceName (get_device_from_id (config.target_id))); + } + + // 3.2. Pass per device loading configurations specific to this device, + // and register extensions to this device. + if (DnnInferDeviceCPU == config.target_id) { + /** + * cpu_extensions library is compiled from "extension" folder containing + * custom MKLDNNPlugin layer implementations. These layers are not supported + * by mkldnn, but they can be useful for inferring custom topologies. + **/ + _plugin.AddExtension (std::make_shared<Extensions::Cpu::CpuExtensions>()); + + if (NULL != config.cpu_ext_path) { + std::string cpu_ext_path (config.cpu_ext_path); + // CPU(MKLDNN) extensions are loaded as a shared library and passed as a pointer to base extension + auto extensionPtr = InferenceEngine::make_so_pointer<InferenceEngine::IExtension>(cpu_ext_path); + _plugin.AddExtension (extensionPtr); + XCAM_LOG_DEBUG ("CPU Extension loaded: %s", cpu_ext_path); + } + } else if (DnnInferDeviceGPU == config.target_id) { + if (NULL != config.cldnn_ext_path) { + std::string cldnn_ext_path (config.cldnn_ext_path); + // clDNN Extensions are loaded from an .xml description and OpenCL kernel files + _plugin.SetConfig ({ { InferenceEngine::PluginConfigParams::KEY_CONFIG_FILE, cldnn_ext_path } }); + XCAM_LOG_DEBUG ("GPU Extension loaded: %s", cldnn_ext_path); + } + } + + if (config.perf_counter > 0) { + _plugin.SetConfig ({ { InferenceEngine::PluginConfigParams::KEY_PERF_COUNT, InferenceEngine::PluginConfigParams::YES } }); + } + + _model_created = true; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::load_model (DnnInferConfig& config) +{ + XCAM_LOG_DEBUG ("DnnInferenceEngine::load_model"); + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + if (_model_loaded) { + XCAM_LOG_INFO ("model already loaded!"); + return XCAM_RETURN_NO_ERROR; + } + + InferenceEngine::ExecutableNetwork execute_network = _plugin.LoadNetwork (_network, {}); + + _infer_request = execute_network.CreateInferRequest (); + + _model_loaded = true; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::get_info (DnnInferenceEngineInfo& info, DnnInferInfoType type) +{ + XCAM_LOG_DEBUG ("DnnInferenceEngine::get_info type %d", type); + + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + info.type = type; + if (DnnInferInfoEngine == type) { + info.major = GetInferenceEngineVersion ()->apiVersion.major; + info.minor = GetInferenceEngineVersion ()->apiVersion.minor; + } else if (DnnInferInfoPlugin == type) { + const InferenceEngine::Version *plugin_version = NULL; + static_cast<InferenceEngine::InferenceEnginePluginPtr>(_plugin)->GetVersion (plugin_version); + + info.major = plugin_version->apiVersion.major; + info.minor = plugin_version->apiVersion.minor; + info.desc = plugin_version->description; + } else if (DnnInferInfoNetwork == type) { + info.major = _network_reader.getVersion (); + info.desc = _network_reader.getDescription ().c_str (); + info.name = _network_reader.getName ().c_str (); + } else { + XCAM_LOG_WARNING ("DnnInferenceEngine::get_info type %d not supported!", type); + } + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::set_batch_size (const size_t size) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + _network.setBatchSize (size); + return XCAM_RETURN_NO_ERROR; +} + +size_t +DnnInferenceEngine::get_batch_size () +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return -1; + } + + return _network.getBatchSize (); +} + +XCamReturn +DnnInferenceEngine::start (bool sync) +{ + XCAM_LOG_DEBUG ("Start inference sync(%d)", sync); + + if (! _model_loaded) { + XCAM_LOG_ERROR ("Please load the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + if (sync) { + _infer_request.Infer (); + } else { + _infer_request.StartAsync (); + _infer_request.Wait (IInferRequest::WaitMode::RESULT_READY); + } + + return XCAM_RETURN_NO_ERROR; +} + +size_t +DnnInferenceEngine::get_input_size () +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return -1; + } + + InputsDataMap inputs_info (_network.getInputsInfo()); + return inputs_info.size (); +} + +size_t +DnnInferenceEngine::get_output_size () +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return -1; + } + + OutputsDataMap outputs_info (_network.getOutputsInfo()); + return outputs_info.size (); +} + +XCamReturn +DnnInferenceEngine::set_input_presion (uint32_t idx, DnnInferPrecisionType precision) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + uint32_t id = 0; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + if (idx > inputs_info.size ()) { + XCAM_LOG_ERROR ("Input is out of range"); + return XCAM_RETURN_ERROR_PARAM; + } + + for (auto & item : inputs_info) { + if (id == idx) { + Precision input_precision = convert_precision_type (precision); + item.second->setPrecision (input_precision); + break; + } + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +DnnInferPrecisionType +DnnInferenceEngine::get_input_presion (uint32_t idx) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return DnnInferPrecisionUnspecified; + } + + uint32_t id = 0; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + if (idx > inputs_info.size ()) { + XCAM_LOG_ERROR ("Input is out of range"); + return DnnInferPrecisionUnspecified; + } + + for (auto & item : inputs_info) { + if (id == idx) { + Precision input_precision = item.second->getPrecision (); + return convert_precision_type (input_precision); + } + id++; + } + return DnnInferPrecisionUnspecified; +} + +XCamReturn +DnnInferenceEngine::set_output_presion (uint32_t idx, DnnInferPrecisionType precision) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + uint32_t id = 0; + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + + if (idx > outputs_info.size ()) { + XCAM_LOG_ERROR ("Output is out of range"); + return XCAM_RETURN_ERROR_PARAM; + } + + for (auto & item : outputs_info) { + if (id == idx) { + Precision output_precision = convert_precision_type (precision); + item.second->setPrecision (output_precision); + break; + } + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +DnnInferPrecisionType +DnnInferenceEngine::get_output_presion (uint32_t idx) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return DnnInferPrecisionUnspecified; + } + + uint32_t id = 0; + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + + if (idx > outputs_info.size ()) { + XCAM_LOG_ERROR ("Input is out of range"); + return DnnInferPrecisionUnspecified; + } + + for (auto & item : outputs_info) { + if (id == idx) { + Precision output_precision = item.second->getPrecision (); + return convert_precision_type (output_precision); + } + id++; + } + return DnnInferPrecisionUnspecified; +} + +XCamReturn +DnnInferenceEngine::set_input_layout (uint32_t idx, DnnInferLayoutType layout) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + uint32_t id = 0; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + if (idx > inputs_info.size ()) { + XCAM_LOG_ERROR ("Input is out of range"); + return XCAM_RETURN_ERROR_PARAM; + } + + for (auto & item : inputs_info) { + if (id == idx) { + /** Creating first input blob **/ + Layout input_layout = convert_layout_type (layout); + item.second->setLayout (input_layout); + break; + } + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::set_output_layout (uint32_t idx, DnnInferLayoutType layout) +{ + if (! _model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + uint32_t id = 0; + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + + if (idx > outputs_info.size ()) { + XCAM_LOG_ERROR ("Output is out of range"); + return XCAM_RETURN_ERROR_PARAM; + } + + for (auto & item : outputs_info) { + if (id == idx) { + Layout output_layout = convert_layout_type (layout); + item.second->setLayout (output_layout); + break; + } + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::set_model_input_info (DnnInferInputOutputInfo& info) +{ + XCAM_LOG_DEBUG ("DnnInferenceEngine::set_model_input_info"); + + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + InputsDataMap inputs_info (_network.getInputsInfo ()); + + if (info.numbers != inputs_info.size ()) { + XCAM_LOG_ERROR ("Input size is not matched with model info numbers %d !", info.numbers); + return XCAM_RETURN_ERROR_PARAM; + } + int id = 0; + + for (auto & item : inputs_info) { + Precision precision = convert_precision_type (info.precision[id]); + item.second->setPrecision (precision); + Layout layout = convert_layout_type (info.layout[id]); + item.second->setLayout (layout); + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::set_model_output_info (DnnInferInputOutputInfo& info) +{ + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + + if (info.numbers != outputs_info.size()) { + XCAM_LOG_ERROR ("Output size is not matched with model!"); + return XCAM_RETURN_ERROR_PARAM; + } + + int id = 0; + for (auto & item : outputs_info) { + Precision precision = convert_precision_type (info.precision[id]); + item.second->setPrecision (precision); + Layout layout = convert_layout_type (info.layout[id]); + item.second->setLayout (layout); + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::set_input_blob (uint32_t idx, DnnInferData& data) +{ + unsigned int id = 0; + std::string item_name; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + if (idx > inputs_info.size()) { + XCAM_LOG_ERROR ("Input is out of range"); + return XCAM_RETURN_ERROR_PARAM; + } + + for (auto & item : inputs_info) { + if (id == idx) { + item_name = item.first; + break; + } + id++; + } + + if (item_name.empty ()) { + XCAM_LOG_ERROR ("item name is empty!"); + return XCAM_RETURN_ERROR_PARAM; + } + + if (data.batch_idx > get_batch_size ()) { + XCAM_LOG_ERROR ("Too many input, it is bigger than batch size!"); + return XCAM_RETURN_ERROR_PARAM; + } + + Blob::Ptr blob = _infer_request.GetBlob (item_name); + if (data.precision == DnnInferPrecisionFP32) { + if (data.data_type == DnnInferDataTypeImage) { + copy_image_to_blob<PrecisionTrait<Precision::FP32>::value_type>(data, blob, data.batch_idx); + } else { + copy_data_to_blob<PrecisionTrait<Precision::FP32>::value_type>(data, blob, data.batch_idx); + } + } else { + if (data.data_type == DnnInferDataTypeImage) { + copy_image_to_blob<uint8_t>(data, blob, data.batch_idx); + } else { + copy_data_to_blob<uint8_t>(data, blob, data.batch_idx); + } + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnInferenceEngine::set_inference_data (std::vector<std::string> images) +{ + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + uint32_t idx = 0; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + for (auto & i : images) { + FormatReader::ReaderPtr reader (i.c_str ()); + if (reader.get () == NULL) { + XCAM_LOG_WARNING ("Image %d cannot be read!", i); + continue; + } + + _input_image_width = reader->width (); + _input_image_height = reader->height (); + + uint32_t image_width = 0; + uint32_t image_height = 0; + + for (auto & item : inputs_info) { + image_width = inputs_info[item.first]->getDims()[0]; + image_height = inputs_info[item.first]->getDims()[1]; + } + + std::shared_ptr<unsigned char> data (reader->getData (image_width, image_height)); + + if (data.get () != NULL) { + DnnInferData image; + image.width = image_width; + image.height = image_height; + image.width_stride = image_width; + image.height_stride = image_height; + image.buffer = data.get (); + image.channel_num = 3; + image.batch_idx = idx; + image.image_format = DnnInferImageFormatBGRPacked; + + // set precision & data type + image.precision = get_input_presion (idx); + image.data_type = DnnInferDataTypeImage; + + set_input_blob (idx, image); + + idx ++; + } else { + XCAM_LOG_WARNING ("Valid input images were not found!"); + continue; + } + } + + return XCAM_RETURN_NO_ERROR; +} + +std::shared_ptr<uint8_t> +DnnInferenceEngine::read_inference_image (std::string image) +{ + FormatReader::ReaderPtr reader (image.c_str ()); + if (reader.get () == NULL) { + XCAM_LOG_WARNING ("Image cannot be read!"); + return NULL; + } + + uint32_t image_width = reader->width (); + uint32_t image_height = reader->height (); + + std::shared_ptr<uint8_t> data (reader->getData (image_width, image_height)); + + if (data.get () != NULL) { + return data; + } else { + XCAM_LOG_WARNING ("Valid input images were not found!"); + return NULL; + } +} + +InferenceEngine::TargetDevice +DnnInferenceEngine::get_device_from_string (const std::string &device_name) +{ + return InferenceEngine::TargetDeviceInfo::fromStr (device_name); +} + +InferenceEngine::TargetDevice +DnnInferenceEngine::get_device_from_id (DnnInferTargetDeviceType device) +{ + switch (device) { + case DnnInferDeviceDefault: + return InferenceEngine::TargetDevice::eDefault; + case DnnInferDeviceBalanced: + return InferenceEngine::TargetDevice::eBalanced; + case DnnInferDeviceCPU: + return InferenceEngine::TargetDevice::eCPU; + case DnnInferDeviceGPU: + return InferenceEngine::TargetDevice::eGPU; + case DnnInferDeviceFPGA: + return InferenceEngine::TargetDevice::eFPGA; + case DnnInferDeviceMyriad: + return InferenceEngine::TargetDevice::eMYRIAD; + case DnnInferDeviceHetero: + return InferenceEngine::TargetDevice::eHETERO; + default: + return InferenceEngine::TargetDevice::eCPU; + } +} + +InferenceEngine::Layout +DnnInferenceEngine::estimate_layout_type (const int ch_num) +{ + if (ch_num == 4) { + return InferenceEngine::Layout::NCHW; + } else if (ch_num == 3) { + return InferenceEngine::Layout::CHW; + } else if (ch_num == 2) { + return InferenceEngine::Layout::NC; + } else { + return InferenceEngine::Layout::ANY; + } +} + +InferenceEngine::Layout +DnnInferenceEngine::convert_layout_type (DnnInferLayoutType layout) +{ + switch (layout) { + case DnnInferLayoutNCHW: + return InferenceEngine::Layout::NCHW; + case DnnInferLayoutNHWC: + return InferenceEngine::Layout::NHWC; + case DnnInferLayoutOIHW: + return InferenceEngine::Layout::OIHW; + case DnnInferLayoutC: + return InferenceEngine::Layout::C; + case DnnInferLayoutCHW: + return InferenceEngine::Layout::CHW; + case DnnInferLayoutHW: + return InferenceEngine::Layout::HW; + case DnnInferLayoutNC: + return InferenceEngine::Layout::NC; + case DnnInferLayoutCN: + return InferenceEngine::Layout::CN; + case DnnInferLayoutBlocked: + return InferenceEngine::Layout::BLOCKED; + case DnnInferLayoutAny: + return InferenceEngine::Layout::ANY; + default: + return InferenceEngine::Layout::ANY; + } +} + +DnnInferLayoutType +DnnInferenceEngine::convert_layout_type (InferenceEngine::Layout layout) +{ + switch (layout) { + case InferenceEngine::Layout::NCHW: + return DnnInferLayoutNCHW; + case InferenceEngine::Layout::NHWC: + return DnnInferLayoutNHWC; + case InferenceEngine::Layout::OIHW: + return DnnInferLayoutOIHW; + case InferenceEngine::Layout::C: + return DnnInferLayoutC; + case InferenceEngine::Layout::CHW: + return DnnInferLayoutCHW; + case InferenceEngine::Layout::HW: + return DnnInferLayoutHW; + case InferenceEngine::Layout::NC: + return DnnInferLayoutNC; + case InferenceEngine::Layout::CN: + return DnnInferLayoutCN; + case InferenceEngine::Layout::BLOCKED: + return DnnInferLayoutBlocked; + case InferenceEngine::Layout::ANY: + return DnnInferLayoutAny; + default: + return DnnInferLayoutAny; + } +} + +InferenceEngine::Precision +DnnInferenceEngine::convert_precision_type (DnnInferPrecisionType precision) +{ + switch (precision) { + case DnnInferPrecisionMixed: + return InferenceEngine::Precision::MIXED; + case DnnInferPrecisionFP32: + return InferenceEngine::Precision::FP32; + case DnnInferPrecisionFP16: + return InferenceEngine::Precision::FP16; + case DnnInferPrecisionQ78: + return InferenceEngine::Precision::Q78; + case DnnInferPrecisionI16: + return InferenceEngine::Precision::I16; + case DnnInferPrecisionU8: + return InferenceEngine::Precision::U8; + case DnnInferPrecisionI8: + return InferenceEngine::Precision::I8; + case DnnInferPrecisionU16: + return InferenceEngine::Precision::U16; + case DnnInferPrecisionI32: + return InferenceEngine::Precision::I32; + case DnnInferPrecisionCustom: + return InferenceEngine::Precision::CUSTOM; + case DnnInferPrecisionUnspecified: + return InferenceEngine::Precision::UNSPECIFIED; + default: + return InferenceEngine::Precision::UNSPECIFIED; + } +} + +DnnInferPrecisionType +DnnInferenceEngine::convert_precision_type (InferenceEngine::Precision precision) +{ + switch (precision) { + case InferenceEngine::Precision::MIXED: + return DnnInferPrecisionMixed; + case InferenceEngine::Precision::FP32: + return DnnInferPrecisionFP32; + case InferenceEngine::Precision::FP16: + return DnnInferPrecisionFP16; + case InferenceEngine::Precision::Q78: + return DnnInferPrecisionQ78; + case InferenceEngine::Precision::I16: + return DnnInferPrecisionI16; + case InferenceEngine::Precision::U8: + return DnnInferPrecisionU8; + case InferenceEngine::Precision::I8: + return DnnInferPrecisionI8; + case InferenceEngine::Precision::U16: + return DnnInferPrecisionU16; + case InferenceEngine::Precision::I32: + return DnnInferPrecisionI32; + case InferenceEngine::Precision::CUSTOM: + return DnnInferPrecisionCustom; + case InferenceEngine::Precision::UNSPECIFIED: + return DnnInferPrecisionUnspecified; + default: + return DnnInferPrecisionUnspecified; + } +} + +std::string +DnnInferenceEngine::get_filename_prefix (const std::string &file_path) +{ + auto pos = file_path.rfind ('.'); + if (pos == std::string::npos) { + return file_path; + } + + return file_path.substr (0, pos); +} + +template <typename T> XCamReturn +DnnInferenceEngine::copy_image_to_blob (const DnnInferData& data, Blob::Ptr& blob, int batch_index) +{ + SizeVector blob_size = blob.get()->dims (); + const size_t width = blob_size[0]; + const size_t height = blob_size[1]; + const size_t channels = blob_size[2]; + const size_t image_size = width * height; + unsigned char* buffer = (unsigned char*)data.buffer; + T* blob_data = blob->buffer ().as<T*>(); + + if (width != data.width || height != data.height) { + XCAM_LOG_ERROR ("Input Image size (%dx%d) is not matched with model required size (%dx%d)!", + data.width, data.height, width, height); + return XCAM_RETURN_ERROR_PARAM; + } + + int batch_offset = batch_index * height * width * channels; + + if (DnnInferImageFormatBGRPlanar == data.image_format) { + // B G R planar input image + size_t image_stride_size = data.height_stride * data.width_stride; + + if (data.width == data.width_stride && + data.height == data.height_stride) { + std::memcpy (blob_data + batch_offset, buffer, image_size * channels); + } else if (data.width == data.width_stride) { + for (size_t ch = 0; ch < channels; ++ch) { + std::memcpy (blob_data + batch_offset + ch * image_size, buffer + ch * image_stride_size, image_size); + } + } else { + for (size_t ch = 0; ch < channels; ++ch) { + for (size_t h = 0; h < height; h++) { + std::memcpy (blob_data + batch_offset + ch * image_size + h * width, buffer + ch * image_stride_size + h * data.width_stride, width); + } + } + } + } else if (DnnInferImageFormatBGRPacked == data.image_format) { + for (size_t pid = 0; pid < image_size; pid++) { + for (size_t ch = 0; ch < channels; ++ch) { + blob_data[batch_offset + ch * image_size + pid] = buffer[pid * channels + ch]; + } + } + } + + return XCAM_RETURN_NO_ERROR; +} + +template <typename T> XCamReturn +DnnInferenceEngine::copy_data_to_blob (const DnnInferData& data, Blob::Ptr& blob, int batch_index) +{ + SizeVector blob_size = blob.get ()->dims (); + T * buffer = (T *)data.buffer; + T* blob_data = blob->buffer ().as<T*>(); + + int batch_offset = batch_index * data.size; + + memcpy (blob_data + batch_offset, buffer, data.size); + + return XCAM_RETURN_NO_ERROR; +} + +void +DnnInferenceEngine::print_performance_counts (const std::map<std::string, InferenceEngine::InferenceEngineProfileInfo>& performance_map) +{ + long long total_time = 0; + XCAM_LOG_DEBUG ("performance counts:"); + for (const auto & it : performance_map) { + std::string to_print(it.first); + const int max_layer_name = 30; + + if (it.first.length () >= max_layer_name) { + to_print = it.first.substr (0, max_layer_name - 4); + to_print += "..."; + } + + std::cout << std::setw(max_layer_name) << std::left << to_print; + switch (it.second.status) { + case InferenceEngine::InferenceEngineProfileInfo::EXECUTED: + std::cout << std::setw (15) << std::left << "EXECUTED"; + break; + case InferenceEngine::InferenceEngineProfileInfo::NOT_RUN: + std::cout << std::setw (15) << std::left << "NOT_RUN"; + break; + case InferenceEngine::InferenceEngineProfileInfo::OPTIMIZED_OUT: + std::cout << std::setw(15) << std::left << "OPTIMIZED_OUT"; + break; + } + std::cout << std::setw (30) << std::left << "layerType: " + std::string (it.second.layer_type) + " "; + std::cout << std::setw (20) << std::left << "realTime: " + std::to_string (it.second.realTime_uSec); + std::cout << std::setw (20) << std::left << " cpu: " + std::to_string (it.second.cpu_uSec); + std::cout << " execType: " << it.second.exec_type << std::endl; + if (it.second.realTime_uSec > 0) { + total_time += it.second.realTime_uSec; + } + } + std::cout << std::setw (20) << std::left << "Total time: " + std::to_string (total_time) << " microseconds" << std::endl; +} + +void +DnnInferenceEngine::print_log (uint32_t flag) +{ + std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> perfomance_map; + + if (flag == DnnInferLogLevelNone) { + return; + } + + if (flag & DnnInferLogLevelEngine) { + static_cast<InferenceEngine::InferenceEnginePluginPtr>(_plugin)->GetPerformanceCounts (perfomance_map, NULL); + print_performance_counts (perfomance_map); + } + + if (flag & DnnInferLogLevelLayer) { + perfomance_map = _infer_request.GetPerformanceCounts (); + print_performance_counts (perfomance_map); + } +} + +} // namespace XCam diff --git a/modules/dnn/dnn_inference_engine.h b/modules/dnn/dnn_inference_engine.h new file mode 100755 index 0000000..ed8ed36 --- /dev/null +++ b/modules/dnn/dnn_inference_engine.h @@ -0,0 +1,280 @@ +/* + * dnn_inference_engine.h - dnn inference engine + * + * Copyright (c) 2019 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: Zong Wei <wei.zong@intel.com> + */ + +#ifndef _XCMA_DNN_INFERENCE_ENGINE_H_ +#define _XCMA_DNN_INFERENCE_ENGINE_H_ + +#pragma once + +#include <vector> +#include <string> +#include <inference_engine.hpp> + +#include <xcam_std.h> + +namespace XCam { + +enum DnnInferTargetDeviceType { + DnnInferDeviceDefault = 0, + DnnInferDeviceBalanced = 1, + DnnInferDeviceCPU = 2, + DnnInferDeviceGPU = 3, + DnnInferDeviceFPGA = 4, + DnnInferDeviceMyriad = 5, + DnnInferDeviceHetero = 8 +}; + +enum DnnInferPrecisionType { + DnnInferPrecisionMixed = 0, + DnnInferPrecisionFP32 = 10, + DnnInferPrecisionFP16 = 11, + DnnInferPrecisionQ78 = 20, + DnnInferPrecisionI16 = 30, + DnnInferPrecisionU8 = 40, + DnnInferPrecisionI8 = 50, + DnnInferPrecisionU16 = 60, + DnnInferPrecisionI32 = 70, + DnnInferPrecisionCustom = 80, + DnnInferPrecisionUnspecified = 255 +}; + +enum DnnInferLayoutType { + DnnInferLayoutAny = 0, + DnnInferLayoutNCHW = 1, + DnnInferLayoutNHWC = 2, + DnnInferLayoutOIHW = 64, + DnnInferLayoutC = 96, + DnnInferLayoutCHW = 128, + DnnInferLayoutHW = 192, + DnnInferLayoutNC = 193, + DnnInferLayoutCN = 194, + DnnInferLayoutBlocked = 200 +}; + +enum DnnInferMemoryType { + DnnInferMemoryDefault = 0, + DnnInferMemoryHost = 1, + DnnInferMemoryGPU = 2, + DnnInferMemoryMYRIAD = 3, + DnnInferMemoryShared = 4 +}; + +enum DnnInferImageFormatType { + DnnInferImageFormatBGRPacked = 0, + DnnInferImageFormatBGRPlanar, + DnnInferImageFormatRGBPacked, + DnnInferImageFormatRGBPlanar, + DnnInferImageFormatGrayPlanar, + DnnInferImageFormatGeneric1D, + DnnInferImageFormatGeneric2D, + DnnInferImageFormatUnknown = -1 +}; + +enum DnnInferMode { + DnnInferModeSync = 0, + DnnInferModeAsync = 1 +}; + +enum DnnInferDataType { + DnnInferDataTypeNonImage = 0, + DnnInferDataTypeImage = 1 +}; + +enum DnnInferLogLevel { + DnnInferLogLevelNone = 0x0, + DnnInferLogLevelEngine = 0x1, + DnnInferLogLevelLayer = 0x2 +}; + +enum DnnInferInfoType { + DnnInferInfoEngine = 0x0, + DnnInferInfoPlugin = 0x1, + DnnInferInfoNetwork = 0x2 +}; + +struct DnnInferImageSize { + uint32_t image_width; + uint32_t image_height; + + DnnInferImageSize () { + image_width = 0; + image_height = 0; + } +}; + +struct DnnInferenceEngineInfo { + DnnInferInfoType type; + int32_t major; + int32_t minor; + const char* desc; + const char* name; + + DnnInferenceEngineInfo () { + type = DnnInferInfoEngine; + major = 0; + minor = 0; + desc = NULL; + name = NULL; + }; +}; + +#define DNN_INFER_MAX_INPUT_OUTPUT 10 +struct DnnInferInputOutputInfo { + uint32_t width[DNN_INFER_MAX_INPUT_OUTPUT]; + uint32_t height[DNN_INFER_MAX_INPUT_OUTPUT]; + uint32_t channels[DNN_INFER_MAX_INPUT_OUTPUT]; + uint32_t object_size[DNN_INFER_MAX_INPUT_OUTPUT]; + DnnInferPrecisionType precision[DNN_INFER_MAX_INPUT_OUTPUT]; + DnnInferLayoutType layout[DNN_INFER_MAX_INPUT_OUTPUT]; + DnnInferDataType data_type[DNN_INFER_MAX_INPUT_OUTPUT]; + uint32_t batch_size; + uint32_t numbers; +}; + +struct DnnInferData { + void * buffer; + uint32_t size; + uint32_t width; + uint32_t height; + uint32_t width_stride; + uint32_t height_stride; + uint32_t channel_num; + uint32_t batch_idx; + DnnInferPrecisionType precision; + DnnInferMemoryType mem_type; + DnnInferImageFormatType image_format; + DnnInferDataType data_type; + + DnnInferData () { + buffer = NULL; + }; +}; + +struct DnnInferConfig { + DnnInferTargetDeviceType target_id; + DnnInferInputOutputInfo input_infos; + DnnInferInputOutputInfo output_infos; + + char * plugin_path; + char * cpu_ext_path; + char * cldnn_ext_path; + char * model_filename; + char * output_layer_name; + uint32_t perf_counter; + uint32_t infer_req_num; + + DnnInferConfig () { + plugin_path = NULL; + cpu_ext_path = NULL; + cldnn_ext_path = NULL; + model_filename = NULL; + output_layer_name = NULL; + }; +}; + +class DnnInferenceEngine { +public: + explicit DnnInferenceEngine (DnnInferConfig& config); + virtual ~DnnInferenceEngine (); + + XCamReturn create_model (DnnInferConfig& config); + XCamReturn load_model (DnnInferConfig& config); + + XCamReturn get_info (DnnInferenceEngineInfo& info, DnnInferInfoType type); + + XCamReturn set_batch_size (const size_t size); + size_t get_batch_size (); + + bool ready_to_start () const { + return _model_created && _model_loaded; + }; + + XCamReturn start (bool sync = true); + + size_t get_input_size (); + size_t get_output_size (); + + XCamReturn set_input_presion (uint32_t idx, DnnInferPrecisionType precision); + DnnInferPrecisionType get_input_presion (uint32_t idx); + XCamReturn set_output_presion (uint32_t idx, DnnInferPrecisionType precision); + DnnInferPrecisionType get_output_presion (uint32_t idx); + + XCamReturn set_input_layout (uint32_t idx, DnnInferLayoutType layout); + XCamReturn set_output_layout (uint32_t idx, DnnInferLayoutType layout); + + uint32_t get_input_image_height () const { + return _input_image_height; + }; + uint32_t get_input_image_width () const { + return _input_image_width; + }; + + virtual XCamReturn set_model_input_info (DnnInferInputOutputInfo& info) = 0; + virtual XCamReturn get_model_input_info (DnnInferInputOutputInfo& info) = 0; + + virtual XCamReturn set_model_output_info (DnnInferInputOutputInfo& info) = 0; + virtual XCamReturn get_model_output_info (DnnInferInputOutputInfo& info) = 0; + + virtual XCamReturn set_inference_data (std::vector<std::string> images) = 0; + virtual void* get_inference_results (uint32_t idx, uint32_t& size) = 0; + + std::shared_ptr<uint8_t> read_inference_image (std::string image); + void print_log (uint32_t flag); + +protected: + + InferenceEngine::TargetDevice get_device_from_string (const std::string& device_name); + InferenceEngine::TargetDevice get_device_from_id (DnnInferTargetDeviceType device); + + InferenceEngine::Layout estimate_layout_type (const int ch_num); + InferenceEngine::Layout convert_layout_type (DnnInferLayoutType layout); + DnnInferLayoutType convert_layout_type (InferenceEngine::Layout layout); + + InferenceEngine::Precision convert_precision_type (DnnInferPrecisionType precision); + DnnInferPrecisionType convert_precision_type (InferenceEngine::Precision precision); + + std::string get_filename_prefix (const std::string &file_path); + + void print_performance_counts (const std::map<std::string, InferenceEngine::InferenceEngineProfileInfo>& performance_map); + + XCamReturn set_input_blob (uint32_t idx, DnnInferData& data); + +private: + template <typename T> XCamReturn copy_image_to_blob (const DnnInferData& data, InferenceEngine::Blob::Ptr& blob, int batch_index); + template <typename T> XCamReturn copy_data_to_blob (const DnnInferData& data, InferenceEngine::Blob::Ptr& blob, int batch_index); + +protected: + + bool _model_created; + bool _model_loaded; + + uint32_t _input_image_width; + uint32_t _input_image_height; + + InferenceEngine::InferencePlugin _plugin; + InferenceEngine::CNNNetReader _network_reader; + InferenceEngine::CNNNetwork _network; + InferenceEngine::InferRequest _infer_request; + std::vector<InferenceEngine::CNNLayerPtr> _layers; +}; + +} // namespace XCam + +#endif //_XCMA_DNN_INFERENCE_ENGINE_H_ diff --git a/modules/dnn/dnn_object_detection.cpp b/modules/dnn/dnn_object_detection.cpp new file mode 100644 index 0000000..42bf29d --- /dev/null +++ b/modules/dnn/dnn_object_detection.cpp @@ -0,0 +1,264 @@ +/* + * dnn_object_detection.cpp - object detection + * + * Copyright (c) 2019 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: Zong Wei <wei.zong@intel.com> + */ + +#include <format_reader_ptr.h> + +#include "dnn_object_detection.h" + +using namespace std; +using namespace InferenceEngine; + +namespace XCam { + +DnnObjectDetection::DnnObjectDetection (DnnInferConfig& config) + : DnnInferenceEngine (config) +{ + XCAM_LOG_DEBUG ("DnnObjectDetection::DnnObjectDetection"); + + create_model (config); +} + + +DnnObjectDetection::~DnnObjectDetection () +{ + +} + +XCamReturn +DnnObjectDetection::get_model_input_info (DnnInferInputOutputInfo& info) +{ + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + int id = 0; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + for (auto & item : inputs_info) { + auto& input = item.second; + const InferenceEngine::SizeVector input_dims = input->getDims (); + + info.width[id] = input_dims[0]; + info.height[id] = input_dims[1]; + info.channels[id] = input_dims[2]; + info.object_size[id] = input_dims[3]; + info.precision[id] = convert_precision_type (input->getPrecision()); + info.layout[id] = convert_layout_type (input->getLayout()); + + item.second->setPrecision(Precision::U8); + + id++; + } + info.batch_size = get_batch_size (); + info.numbers = inputs_info.size (); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnObjectDetection::set_model_input_info (DnnInferInputOutputInfo& info) +{ + XCAM_LOG_DEBUG ("DnnObjectDetection::set_model_input_info"); + + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + InputsDataMap inputs_info (_network.getInputsInfo ()); + if (info.numbers != inputs_info.size ()) { + XCAM_LOG_ERROR ("Input size is not matched with model info numbers %d !", info.numbers); + return XCAM_RETURN_ERROR_PARAM; + } + int id = 0; + + for (auto & item : inputs_info) { + Precision precision = convert_precision_type (info.precision[id]); + item.second->setPrecision (precision); + Layout layout = convert_layout_type (info.layout[id]); + item.second->setLayout (layout); + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnObjectDetection::get_model_output_info (DnnInferInputOutputInfo& info) +{ + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + int id = 0; + std::string output_name; + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + DataPtr output_info; + for (const auto& out : outputs_info) { + if (out.second->creatorLayer.lock()->type == "DetectionOutput") { + output_name = out.first; + output_info = out.second; + break; + } + } + if (output_info.get ()) { + const InferenceEngine::SizeVector output_dims = output_info->getTensorDesc().getDims(); + + info.width[id] = output_dims[0]; + info.height[id] = output_dims[1]; + info.channels[id] = output_dims[2]; + info.object_size[id] = output_dims[3]; + + info.precision[id] = convert_precision_type (output_info->getPrecision()); + info.layout[id] = convert_layout_type (output_info->getLayout()); + + info.batch_size = 1; + info.numbers = outputs_info.size (); + } else { + XCAM_LOG_ERROR ("Get output info error!"); + return XCAM_RETURN_ERROR_UNKNOWN; + } + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnObjectDetection::set_model_output_info (DnnInferInputOutputInfo& info) +{ + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + if (info.numbers != outputs_info.size ()) { + XCAM_LOG_ERROR ("Output size is not matched with model!"); + return XCAM_RETURN_ERROR_PARAM; + } + + int id = 0; + for (auto & item : outputs_info) { + Precision precision = convert_precision_type (info.precision[id]); + item.second->setPrecision (precision); + Layout layout = convert_layout_type (info.layout[id]); + item.second->setLayout (layout); + id++; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +DnnObjectDetection::set_inference_data (std::vector<std::string> images) +{ + if (!_model_created) { + XCAM_LOG_ERROR ("Please create the model firstly!"); + return XCAM_RETURN_ERROR_ORDER; + } + + uint32_t idx = 0; + InputsDataMap inputs_info (_network.getInputsInfo ()); + + for (auto & i : images) { + FormatReader::ReaderPtr reader (i.c_str ()); + if (reader.get () == NULL) { + XCAM_LOG_WARNING ("Image %d cannot be read!", i); + continue; + } + + _input_image_width = reader->width (); + _input_image_height = reader->height (); + + uint32_t image_width = 0; + uint32_t image_height = 0; + + for (auto & item : inputs_info) { + image_width = inputs_info[item.first]->getDims ()[0]; + image_height = inputs_info[item.first]->getDims ()[1]; + } + + std::shared_ptr<unsigned char> data (reader->getData (image_width, image_height)); + + if (data.get () != NULL) { + DnnInferData image; + image.width = image_width; + image.height = image_height; + image.width_stride = image_width; + image.height_stride = image_height; + image.buffer = data.get (); + image.channel_num = 3; + image.batch_idx = idx; + image.image_format = DnnInferImageFormatBGRPacked; + + // set precision & data type + image.precision = get_input_presion (idx); + image.data_type = DnnInferDataTypeImage; + + set_input_blob (idx, image); + + idx ++; + } else { + XCAM_LOG_WARNING ("Valid input images were not found!"); + continue; + } + } + + return XCAM_RETURN_NO_ERROR; +} + +void* +DnnObjectDetection::get_inference_results (uint32_t idx, uint32_t& size) +{ + if (! _model_created || ! _model_loaded) { + XCAM_LOG_ERROR ("Please create and load the model firstly!"); + return NULL; + } + uint32_t id = 0; + std::string item_name; + + OutputsDataMap outputs_info (_network.getOutputsInfo ()); + if (idx > outputs_info.size ()) { + XCAM_LOG_ERROR ("Output is out of range"); + return NULL; + } + + for (auto & item : outputs_info) { + if (item.second->creatorLayer.lock()->type == "DetectionOutput") { + item_name = item.first; + break; + } + id++; + } + + if (item_name.empty ()) { + XCAM_LOG_ERROR ("item name is empty!"); + return NULL; + } + + const Blob::Ptr blob = _infer_request.GetBlob (item_name); + float* output_result = static_cast<PrecisionTrait<Precision::FP32>::value_type*>(blob->buffer ()); + + size = blob->byteSize (); + + return (reinterpret_cast<void *>(output_result)); +} + +} // namespace XCam diff --git a/modules/dnn/dnn_object_detection.h b/modules/dnn/dnn_object_detection.h new file mode 100644 index 0000000..6980858 --- /dev/null +++ b/modules/dnn/dnn_object_detection.h @@ -0,0 +1,53 @@ +/* + * dnn_object_detection.h - object detection + * + * Copyright (c) 2019 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: Zong Wei <wei.zong@intel.com> + */ + +#ifndef _XCMA_DNN_OBJECT_DETECTION_H_ +#define _XCMA_DNN_OBJECT_DETECTION_H_ + +#pragma once + +#include <string> +#include <inference_engine.hpp> + +#include <xcam_std.h> +#include "dnn_inference_engine.h" + +namespace XCam { + +class DnnObjectDetection + : public DnnInferenceEngine +{ +public: + explicit DnnObjectDetection (DnnInferConfig& config); + virtual ~DnnObjectDetection (); + + XCamReturn set_model_input_info (DnnInferInputOutputInfo& info); + XCamReturn get_model_input_info (DnnInferInputOutputInfo& info); + + XCamReturn set_model_output_info (DnnInferInputOutputInfo& info); + XCamReturn get_model_output_info (DnnInferInputOutputInfo& info); + + XCamReturn set_inference_data (std::vector<std::string> images); + void* get_inference_results (uint32_t idx, uint32_t& size); +}; + +} // namespace XCam + +#endif //_XCMA_DNN_INFERENCE_ENGINE_H_ diff --git a/modules/gles/Makefile.am b/modules/gles/Makefile.am new file mode 100644 index 0000000..8bdf406 --- /dev/null +++ b/modules/gles/Makefile.am @@ -0,0 +1,81 @@ +lib_LTLIBRARIES = libxcam_gles.la + +XCAM_GLES_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(LIBGL_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + -I$(top_builddir)/shaders/glslx \ + $(NULL) + +XCAM_GLES_LIBS = \ + $(LIBGL_LIBS) -lEGL \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL) + +if HAVE_OPENCV +XCAM_GLES_LIBS += $(top_builddir)/modules/ocv/libxcam_ocv.la +endif + +xcam_gles_sources = \ + gles_std.cpp \ + gl_buffer.cpp \ + gl_program.cpp \ + gl_shader.cpp \ + gl_video_buffer.cpp \ + gl_compute_program.cpp \ + gl_command.cpp \ + gl_utils.cpp \ + gl_image_shader.cpp \ + gl_image_handler.cpp \ + gl_copy_handler.cpp \ + gl_geomap_handler.cpp \ + gl_blender_shaders_priv.cpp \ + gl_blender.cpp \ + gl_stitcher.cpp \ + egl/egl_utils.cpp \ + egl/egl_base.cpp \ + $(NULL) + +libxcam_gles_la_SOURCES = \ + $(xcam_gles_sources) \ + $(NULL) + +libxcam_gles_la_CXXFLAGS = \ + $(XCAM_GLES_CXXFLAGS) \ + $(NULL) + +libxcam_gles_la_LIBADD = \ + $(XCAM_GLES_LIBS) \ + $(NULL) + +libxcam_gles_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ + $(NULL) + +libxcam_glesincludedir = $(includedir)/xcam/gles + +nobase_libxcam_glesinclude_HEADERS = \ + gles_std.h \ + gl_buffer.h \ + gl_program.h \ + gl_shader.h \ + gl_video_buffer.h \ + gl_compute_program.h \ + gl_command.h \ + gl_utils.h \ + gl_image_shader.h \ + gl_image_handler.h \ + gl_copy_handler.h \ + gl_geomap_handler.h \ + gl_blender.h \ + gl_stitcher.h \ + egl/egl_utils.h \ + egl/egl_base.h \ + $(NULL) + +noinst_HEADERS = \ + gl_blender_shaders_priv.h \ + $(NULL) + +libxcam_gles_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/gles/egl/egl_base.cpp b/modules/gles/egl/egl_base.cpp new file mode 100644 index 0000000..6ee0b4c --- /dev/null +++ b/modules/gles/egl/egl_base.cpp @@ -0,0 +1,195 @@ +/* + * egl_base.cpp - EGL base implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "egl_base.h" + +namespace XCam { + +EGLBase::EGLBase () + : _display (EGL_NO_DISPLAY) + , _context (EGL_NO_CONTEXT) + , _surface (EGL_NO_SURFACE) +{ +} + +EGLBase::~EGLBase () +{ + if (_display != EGL_NO_DISPLAY) { + if (_context != EGL_NO_CONTEXT) { + destroy_context (_display, _context); + _context = EGL_NO_CONTEXT; + } + + if (_surface != EGL_NO_SURFACE) { + destroy_surface (_display, _surface); + _surface = EGL_NO_SURFACE; + } + + terminate (_display); + _display = EGL_NO_DISPLAY; + } +} + +bool +EGLBase::init () +{ + bool ret = get_display (EGL_DEFAULT_DISPLAY, _display); + XCAM_FAIL_RETURN (ERROR, ret, false, "EGLInit: get display failed"); + + EGLint major, minor; + ret = initialize (_display, &major, &minor); + XCAM_FAIL_RETURN (ERROR, ret, false, "EGLInit: EGL initialize failed"); + XCAM_LOG_INFO ("EGL version: %d.%d", major, minor); + + EGLConfig configs; + EGLint num_config; + EGLint cfg_attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE}; + ret = choose_config (_display, cfg_attribs, &configs, 1, &num_config); + XCAM_FAIL_RETURN (ERROR, ret, false, "EGLInit: choose config failed"); + + EGLint ctx_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; + ret = create_context (_display, configs, EGL_NO_CONTEXT, ctx_attribs, _context); + XCAM_FAIL_RETURN (ERROR, ret, false, "EGLInit: create context failed"); + + ret = make_current (_display, _surface, _surface, _context); + XCAM_FAIL_RETURN (ERROR, ret, false, "EGLInit: make current failed"); + + return true; +} + +bool +EGLBase::get_display (NativeDisplayType native_display, EGLDisplay &display) +{ + display = eglGetDisplay (native_display); + XCAM_FAIL_RETURN ( + ERROR, display != EGL_NO_DISPLAY, false, + "EGLInit: get display failed"); + return true; +} + +bool +EGLBase::initialize (EGLDisplay display, EGLint *major, EGLint *minor) +{ + EGLBoolean ret = eglInitialize (display, major, minor); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: initialize failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + return true; +} + +bool +EGLBase::choose_config ( + EGLDisplay display, EGLint const *attribs, EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + EGLBoolean ret = eglChooseConfig (display, attribs, configs, config_size, num_config); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: choose config failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + return true; +} + +bool +EGLBase::create_context ( + EGLDisplay display, EGLConfig config, EGLContext share_context, EGLint const *attribs, + EGLContext &context) +{ + context = eglCreateContext (display, config, share_context, attribs); + XCAM_FAIL_RETURN ( + ERROR, context != EGL_NO_CONTEXT, false, + "EGLInit: create context failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + return true; +} + +bool +EGLBase::create_window_surface ( + EGLDisplay display, EGLConfig config, NativeWindowType native_window, EGLint const *attribs, + EGLSurface &surface) +{ + surface = eglCreateWindowSurface (display, config, native_window, attribs); + XCAM_FAIL_RETURN ( + ERROR, surface != EGL_NO_SURFACE, false, + "EGLInit: create window surface failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + return true; +} + +bool +EGLBase::make_current (EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context) +{ + EGLBoolean ret = eglMakeCurrent (display, draw, read, context); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: make current failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + return true; +} + +bool +EGLBase::swap_buffers (EGLDisplay display, EGLSurface surface) +{ + EGLBoolean ret = eglSwapBuffers (display, surface); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: swap buffers failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + return true; +} + +bool +EGLBase::destroy_context (EGLDisplay display, EGLContext &context) +{ + EGLBoolean ret = eglDestroyContext (display, context); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: destroy context failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + XCAM_FAIL_RETURN (ERROR, ret == EGL_TRUE, false, "EGLInit: destroy context failed"); + return true; +} + +bool +EGLBase::destroy_surface (EGLDisplay display, EGLSurface &surface) +{ + EGLBoolean ret = eglDestroySurface (display, surface); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: destroy surface failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + XCAM_FAIL_RETURN (ERROR, ret == EGL_TRUE, false, "EGLInit: destroy surface failed"); + return true; +} + +bool +EGLBase::terminate (EGLDisplay display) +{ + EGLBoolean ret = eglTerminate (display); + XCAM_FAIL_RETURN ( + ERROR, ret == EGL_TRUE, false, + "EGLInit: terminate failed, error flag: %s", + EGL::error_string (EGL::get_error ())); + XCAM_FAIL_RETURN (ERROR, ret == EGL_TRUE, false, "EGLInit: terminate failed"); + return true; +} + +} diff --git a/modules/gles/egl/egl_base.h b/modules/gles/egl/egl_base.h new file mode 100644 index 0000000..baa9a10 --- /dev/null +++ b/modules/gles/egl/egl_base.h @@ -0,0 +1,61 @@ +/* + * egl_base.h - EGL base class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_EGL_BASE_H +#define XCAM_EGL_BASE_H + +#include <gles/egl/egl_utils.h> + +namespace XCam { + +class EGLBase { +public: + explicit EGLBase (); + ~EGLBase (); + + bool init (); + + bool get_display (NativeDisplayType native_display, EGLDisplay &display); + bool initialize (EGLDisplay display, EGLint *major, EGLint *minor); + bool choose_config ( + EGLDisplay display, EGLint const *attribs, EGLConfig *configs, + EGLint config_size, EGLint *num_config); + bool create_context ( + EGLDisplay display, EGLConfig config, EGLContext share_context, EGLint const *attribs, + EGLContext &context); + bool create_window_surface ( + EGLDisplay display, EGLConfig config, NativeWindowType native_window, EGLint const *attribs, + EGLSurface &surface); + bool make_current (EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context); + bool swap_buffers (EGLDisplay display, EGLSurface surface); + + bool destroy_context (EGLDisplay display, EGLContext &context); + bool destroy_surface (EGLDisplay display, EGLSurface &surface); + bool terminate (EGLDisplay display); + +private: + EGLDisplay _display; + EGLContext _context; + EGLSurface _surface; +}; + +} + +#endif // XCAM_EGL_BASE_H diff --git a/modules/gles/egl/egl_utils.cpp b/modules/gles/egl/egl_utils.cpp new file mode 100644 index 0000000..71bc4a7 --- /dev/null +++ b/modules/gles/egl/egl_utils.cpp @@ -0,0 +1,87 @@ +/* + * egl_utils.cpp - EGL utilities + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "egl_utils.h" + +namespace XCam { +namespace EGL { + +const char * +error_string (EGLint flag) +{ + static char str[64] = {'\0'}; + + switch (flag) + { + case EGL_SUCCESS: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_SUCCESS"); + break; + case EGL_NOT_INITIALIZED: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_NOT_INITIALIZED"); + break; + case EGL_BAD_ACCESS: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_ACCESS"); + break; + case EGL_BAD_ALLOC: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_ALLOC"); + break; + case EGL_BAD_ATTRIBUTE: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_ATTRIBUTE"); + break; + case EGL_BAD_CONTEXT: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_CONTEXT"); + break; + case EGL_BAD_CONFIG: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_CONFIG"); + break; + case EGL_BAD_CURRENT_SURFACE: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_CURRENT_SURFACE"); + break; + case EGL_BAD_DISPLAY: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_DISPLAY"); + break; + case EGL_BAD_SURFACE: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_SURFACE"); + break; + case EGL_BAD_MATCH: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_MATCH"); + break; + case EGL_BAD_PARAMETER: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_PARAMETER"); + break; + case EGL_BAD_NATIVE_PIXMAP: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_NATIVE_PIXMAP"); + break; + case EGL_BAD_NATIVE_WINDOW: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_BAD_NATIVE_WINDOW"); + break; + case EGL_CONTEXT_LOST: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "EGL_CONTEXT_LOST"); + break; + default: + snprintf (str, sizeof (str), "unknown flag:0x%04x", flag); + XCAM_LOG_ERROR ("%s", str); + } + + return str; +} + +} +} diff --git a/modules/gles/egl/egl_utils.h b/modules/gles/egl/egl_utils.h new file mode 100644 index 0000000..601f171 --- /dev/null +++ b/modules/gles/egl/egl_utils.h @@ -0,0 +1,40 @@ +/* + * egl_utils.h - EGL utilities + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_EGL_UTILS_H +#define XCAM_EGL_UTILS_H + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <xcam_std.h> + +namespace XCam { +namespace EGL { + +inline EGLint get_error () +{ + return eglGetError (); +} + +const char *error_string (EGLint flag); + +} +} +#endif // XCAM_EGL_UTILS_H diff --git a/modules/gles/gl_blender.cpp b/modules/gles/gl_blender.cpp new file mode 100644 index 0000000..7f83a47 --- /dev/null +++ b/modules/gles/gl_blender.cpp @@ -0,0 +1,852 @@ +/* + * gl_blender.cpp - gl blender implementation + * + * 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: Wind Yuan <feng.yuan@intel.com> + * Author: Yinhang Liu <yinhangx.liu@intel.com> + */ + +#include "xcam_utils.h" +#include "image_file_handle.h" +#include "gl_utils.h" +#include "gl_video_buffer.h" +#include "gl_blender_shaders_priv.h" +#include "gl_blender.h" +#include <map> + +#define OVERLAP_POOL_SIZE 6 +#define LAP_POOL_SIZE 4 + +#define GAUSS_RADIUS 2 +#define GAUSS_DIAMETER ((GAUSS_RADIUS)*2+1) + +const float gauss_coeffs[GAUSS_DIAMETER] = {0.152f, 0.222f, 0.252f, 0.222f, 0.152f}; + +#define DUMP_BUFFER 0 + +#define CHECK_RET(ret, format, ...) \ + if ((ret) < XCAM_RETURN_NO_ERROR) { \ + XCAM_LOG_ERROR (format, ## __VA_ARGS__); \ + } + +namespace XCam { + +using namespace XCamGLShaders; + +#if DUMP_BUFFER +#define dump_buf dump_buf_perfix_path + +static void +dump_level_buf (const SmartPtr<VideoBuffer> &buf, const char *name, uint32_t level, uint32_t idx) +{ + XCAM_ASSERT (name); + + char file_name[256]; + snprintf (file_name, 256, "%s-L%d-Idx%d", name, level, idx); + dump_buf_perfix_path (buf, file_name); +} +#else +static void +dump_level_buf (const SmartPtr<VideoBuffer> &buf, ...) { + XCAM_UNUSED (buf); +} + +static void +dump_buf (const SmartPtr<VideoBuffer> &buf, ...) { + XCAM_UNUSED (buf); +} +#endif + +DECLARE_WORK_CALLBACK (CbGaussScalePyr, GLBlender, gauss_scale_done); +DECLARE_WORK_CALLBACK (CbLapTransPyr, GLBlender, lap_trans_done); +DECLARE_WORK_CALLBACK (CbBlendPyr, GLBlender, blend_done); +DECLARE_WORK_CALLBACK (CbReconstructPyr, GLBlender, reconstruct_done); + +namespace GLBlenderPriv { + +typedef std::map<void*, SmartPtr<GLBlendPyrShader::Args>> MapBlendArgs; +typedef std::map<void*, SmartPtr<GLReconstructPyrShader::Args>> MapReconstructArgs; + +struct PyramidResource { + SmartPtr<BufferPool> overlap_pool; + SmartPtr<GLGaussScalePyrShader> gauss_scale[GLBlender::BufIdxCount]; + SmartPtr<GLLapTransPyrShader> lap_trans[GLBlender::BufIdxCount]; + SmartPtr<GLReconstructPyrShader> reconstruct; + SmartPtr<GLBuffer> coef_mask; + MapReconstructArgs reconstruct_args; +}; + +class BlenderPrivConfig { +public: + PyramidResource pyr_layer[XCAM_GL_PYRAMID_MAX_LEVEL]; + uint32_t pyr_levels; + + SmartPtr<GLBlendPyrShader> top_level_blend; + SmartPtr<BufferPool> first_lap_pool; + SmartPtr<GLBuffer> first_mask; + + Mutex map_args_mutex; + MapBlendArgs blend_args; + +private: + GLBlender *_blender; + SmartPtr<GLComputeProgram> _sync_prog; + +public: + BlenderPrivConfig (GLBlender *blender, uint32_t level) + : pyr_levels (level - 1) + , _blender (blender) + { + XCAM_ASSERT (level >= 2 && level <= XCAM_GL_PYRAMID_MAX_LEVEL); + } + + XCamReturn init_first_masks (uint32_t width, uint32_t height); + XCamReturn scale_down_masks (uint32_t level, uint32_t width, uint32_t height); + + XCamReturn start_gauss_scale ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &in_buf, + uint32_t level, GLBlender::BufIdx idx); + + XCamReturn start_lap_trans ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<GLGaussScalePyrShader::Args> &gauss_scale_args, + uint32_t level, GLBlender::BufIdx idx); + + XCamReturn start_blend ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &buf, GLBlender::BufIdx idx); + + XCamReturn start_reconstruct_by_lap ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &lap, + uint32_t level, GLBlender::BufIdx idx); + XCamReturn start_reconstruct_by_gauss ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &prev_blend_buf, uint32_t level); + XCamReturn start_reconstruct (const SmartPtr<GLReconstructPyrShader::Args> &args, uint32_t level); + XCamReturn stop (); + + const SmartPtr<GLComputeProgram> &get_sync_prog (); +}; + +XCamReturn +BlenderPrivConfig::stop () +{ + for (uint32_t i = 0; i < pyr_levels; ++i) { + pyr_layer[i].gauss_scale[GLBlender::Idx0].release (); + pyr_layer[i].gauss_scale[GLBlender::Idx1].release (); + pyr_layer[i].lap_trans[GLBlender::Idx0].release (); + pyr_layer[i].lap_trans[GLBlender::Idx1].release (); + pyr_layer[i].reconstruct.release (); + + if (pyr_layer[i].overlap_pool.ptr ()) { + pyr_layer[i].overlap_pool->stop (); + } + } + + top_level_blend.release (); + if (first_lap_pool.ptr ()) { + first_lap_pool->stop (); + } + + return XCAM_RETURN_NO_ERROR; +} + +const SmartPtr<GLComputeProgram> & +BlenderPrivConfig::get_sync_prog () +{ + if (_sync_prog.ptr ()) + return _sync_prog; + + _sync_prog = GLComputeProgram::create_compute_program ("sync_program"); + XCAM_FAIL_RETURN (ERROR, _sync_prog.ptr (), _sync_prog, "create sync program failed"); + + return _sync_prog; +} + +XCamReturn +BlenderPrivConfig::init_first_masks (uint32_t width, uint32_t height) +{ + XCAM_ASSERT (!first_mask.ptr ()); + XCAM_ASSERT (width && (width % GL_BLENDER_ALIGN_X == 0)); + XCAM_FAIL_RETURN ( + ERROR, height == 1, XCAM_RETURN_ERROR_PARAM, + "blender(%s) mask buffer only supports one-dimensional array", XCAM_STR (_blender->get_name ())); + + uint32_t buf_size = width * sizeof (uint8_t); + SmartPtr<GLBuffer> buf = GLBuffer::create_buffer (GL_SHADER_STORAGE_BUFFER, NULL, buf_size); + XCAM_ASSERT (buf.ptr ()); + + GLBufferDesc desc; + desc.width = width; + desc.height = 1; + desc.size = buf_size; + buf->set_buffer_desc (desc); + + std::vector<float> gauss_table; + uint32_t quater = width / 4; + XCAM_ASSERT (quater > 1); + + get_gauss_table (quater, (quater + 1) / 4.0f, gauss_table, false); + for (uint32_t i = 0; i < gauss_table.size (); ++i) { + float value = ((i < quater) ? (128.0f * (2.0f - gauss_table[i])) : (128.0f * gauss_table[i])); + value = XCAM_CLAMP (value, 0.0f, 255.0f); + gauss_table[i] = value; + } + + uint8_t *mask_ptr = (uint8_t *) buf->map_range (0, buf_size, GL_MAP_WRITE_BIT); + XCAM_FAIL_RETURN (ERROR, mask_ptr, XCAM_RETURN_ERROR_PARAM, "map range failed"); + + uint32_t gauss_start_pos = (width - gauss_table.size ()) / 2; + uint32_t idx = 0; + for (idx = 0; idx < gauss_start_pos; ++idx) { + mask_ptr[idx] = 255; + } + for (uint32_t i = 0; i < gauss_table.size (); ++idx, ++i) { + mask_ptr[idx] = (uint8_t) gauss_table[i]; + } + for (; idx < width; ++idx) { + mask_ptr[idx] = 0; + } + buf->unmap (); + + first_mask = buf; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderPrivConfig::scale_down_masks (uint32_t level, uint32_t width, uint32_t height) +{ + XCAM_ASSERT (width && (width % GL_BLENDER_ALIGN_X == 0)); + XCAM_FAIL_RETURN ( + ERROR, height == 1, XCAM_RETURN_ERROR_PARAM, + "blender(%s) mask buffer only supports one-dimensional array", XCAM_STR (_blender->get_name ())); + + uint32_t buf_size = width * sizeof (uint8_t); + SmartPtr<GLBuffer> buf = GLBuffer::create_buffer (GL_SHADER_STORAGE_BUFFER, NULL, buf_size); + XCAM_ASSERT (buf.ptr ()); + + GLBufferDesc desc; + desc.width = width; + desc.height = 1; + desc.size = buf_size; + buf->set_buffer_desc (desc); + + SmartPtr<GLBuffer> prev_mask; + if (level == 0) { + prev_mask = first_mask; + } else { + prev_mask = pyr_layer[level - 1].coef_mask; + } + XCAM_ASSERT (prev_mask.ptr ()); + + const GLBufferDesc prev_desc = prev_mask->get_buffer_desc (); + uint8_t *prev_ptr = (uint8_t *) prev_mask->map_range (0, prev_desc.size, GL_MAP_READ_BIT); + XCAM_FAIL_RETURN (ERROR, prev_ptr, XCAM_RETURN_ERROR_PARAM, "map range failed"); + + uint8_t *cur_ptr = (uint8_t *) buf->map_range (0, desc.size, GL_MAP_WRITE_BIT); + XCAM_FAIL_RETURN (ERROR, cur_ptr, XCAM_RETURN_ERROR_PARAM, "map range failed"); + + for (uint32_t i = 0; i < desc.width; ++i) { + int prev_start = i * 2 - 2; + float sum = 0.0f; + + for (int j = 0; j < GAUSS_DIAMETER; ++j) { + int prev_idx = XCAM_CLAMP (prev_start + j, 0, (int)prev_desc.width); + sum += prev_ptr[prev_idx] * gauss_coeffs[j]; + } + + cur_ptr[i] = XCAM_CLAMP (sum, 0.0f, 255.0f); + } + + buf->unmap (); + prev_mask->unmap (); + + pyr_layer[level].coef_mask = buf; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderPrivConfig::start_gauss_scale ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &in_buf, + uint32_t level, GLBlender::BufIdx idx) +{ + XCAM_ASSERT (in_buf.ptr ()); + XCAM_ASSERT (level < pyr_levels); + XCAM_ASSERT (idx < GLBlender::BufIdxCount); + XCAM_ASSERT (pyr_layer[level].gauss_scale[idx].ptr ()); + XCAM_ASSERT (pyr_layer[level].overlap_pool.ptr ()); + + SmartPtr<VideoBuffer> out_buf = pyr_layer[level].overlap_pool->get_buffer (); + XCAM_FAIL_RETURN ( + ERROR, out_buf.ptr (), XCAM_RETURN_ERROR_MEM, + "blender(%s) start_gauss_scale failed, output buffer is empty, level:%d, idx:%d", + XCAM_STR (_blender->get_name ()), level, (int)idx); + + SmartPtr<GLGaussScalePyrShader::Args> args = new GLGaussScalePyrShader::Args (param, level, idx); + XCAM_ASSERT (args.ptr ()); + args->in_glbuf = get_glbuffer (in_buf); + args->out_glbuf = get_glbuffer (out_buf); + args->out_video_buf = out_buf; + + if (level == 0) { + const Rect area = _blender->get_input_merge_area (idx); + XCAM_FAIL_RETURN ( + ERROR, + area.pos_y == 0 && area.width && area.height && + area.pos_x % GL_BLENDER_ALIGN_X == 0 && + area.width % GL_BLENDER_ALIGN_X == 0 && + area.height % GL_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid input merge area, pos_x:%d, pos_y:%d, width:%d, height:%d, level:%d, idx:%d", + XCAM_STR (_blender->get_name ()), area.pos_x, area.pos_y, area.width, area.height, level, (int)idx); + + args->merge_area = area; + } else { + const VideoBufferInfo &info = in_buf->get_video_info (); + XCAM_FAIL_RETURN ( + ERROR, + info.width && info.height && + info.width % GL_BLENDER_ALIGN_X == 0 && + info.height % GL_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid buffer info, width:%d, height:%d, level:%d, idx:%d", + XCAM_STR (_blender->get_name ()), info.width, info.height, level, (int)idx); + + args->merge_area = Rect (0, 0, info.width, info.height); + } + + return pyr_layer[level].gauss_scale[idx]->work (args); +} + +XCamReturn +BlenderPrivConfig::start_lap_trans ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<GLGaussScalePyrShader::Args> &gauss_scale_args, + uint32_t level, GLBlender::BufIdx idx) +{ + XCAM_ASSERT (level < pyr_levels); + XCAM_ASSERT (pyr_layer[level].lap_trans[idx].ptr ()); + XCAM_ASSERT (idx < GLBlender::BufIdxCount); + + SmartPtr<VideoBuffer> out_buf; + if (level == 0) { + XCAM_ASSERT (first_lap_pool.ptr ()); + out_buf = first_lap_pool->get_buffer (); + } else { + XCAM_ASSERT (pyr_layer[level - 1].overlap_pool.ptr ()); + out_buf = pyr_layer[level - 1].overlap_pool->get_buffer (); + } + XCAM_FAIL_RETURN ( + ERROR, out_buf.ptr (), XCAM_RETURN_ERROR_MEM, + "blender(%s) start_lap_trans failed, output buffer is empty, level:%d, idx:%d", + XCAM_STR (_blender->get_name ()), level, (int)idx); + + SmartPtr<GLLapTransPyrShader::Args> args = new GLLapTransPyrShader::Args (param, level, idx); + XCAM_ASSERT (args.ptr ()); + args->in_glbuf = gauss_scale_args->in_glbuf; + args->gaussscale_glbuf = gauss_scale_args->out_glbuf; + args->out_glbuf = get_glbuffer (out_buf); + args->merge_area = gauss_scale_args->merge_area; + args->out_video_buf = out_buf; + + return pyr_layer[level].lap_trans[idx]->work (args); +} + +XCamReturn +BlenderPrivConfig::start_blend ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &buf, GLBlender::BufIdx idx) +{ + XCAM_ASSERT (idx < GLBlender::BufIdxCount); + XCAM_ASSERT (top_level_blend.ptr ()); + + uint32_t top_level = pyr_levels - 1; + XCAM_ASSERT (pyr_layer[top_level].overlap_pool.ptr ()); + XCAM_ASSERT (pyr_layer[top_level].coef_mask.ptr ()); + + SmartPtr<GLBlendPyrShader::Args> args; + { + SmartLock locker (map_args_mutex); + MapBlendArgs::iterator i = blend_args.find (param.ptr ()); + if (i == blend_args.end ()) { + args = new GLBlendPyrShader::Args (param); + XCAM_ASSERT (args.ptr ()); + blend_args.insert (std::make_pair((void*)param.ptr (), args)); + XCAM_LOG_DEBUG ("blender(%s) init blend args, idx:%d", XCAM_STR (_blender->get_name ()), (int)idx); + } else { + args = (*i).second; + } + + if (idx == GLBlender::Idx0) { + args->in0_glbuf = get_glbuffer (buf); + } else { + args->in1_glbuf = get_glbuffer (buf); + } + + if (!args->in0_glbuf.ptr () || !args->in1_glbuf.ptr ()) + return XCAM_RETURN_BYPASS; + + blend_args.erase (i); + } + + args->mask_glbuf = pyr_layer[top_level].coef_mask; + + SmartPtr<VideoBuffer> out_buf = pyr_layer[top_level].overlap_pool->get_buffer (); + XCAM_FAIL_RETURN ( + ERROR, out_buf.ptr (), XCAM_RETURN_ERROR_MEM, + "blender(%s) start_blend failed, output buffer is empty, idx:%d", + XCAM_STR (_blender->get_name ()), (int)idx); + args->out_glbuf = get_glbuffer (out_buf); + args->out_video_buf = out_buf; + + return top_level_blend->work (args); +} + +XCamReturn +BlenderPrivConfig::start_reconstruct ( + const SmartPtr<GLReconstructPyrShader::Args> &args, uint32_t level) +{ + XCAM_ASSERT (args.ptr ()); + XCAM_ASSERT (level < pyr_levels); + XCAM_ASSERT (pyr_layer[level].reconstruct.ptr ()); + XCAM_ASSERT (args->lap0_glbuf.ptr () && args->lap1_glbuf.ptr () && args->prev_blend_glbuf.ptr ()); + + SmartPtr<VideoBuffer> out_buf; + if (level == 0) { + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr () && param->out_buf.ptr ()); + out_buf = param->out_buf; + + XCAM_ASSERT (first_mask.ptr ()); + args->mask_glbuf = first_mask; + + const Rect area = _blender->get_merge_window (); + XCAM_FAIL_RETURN ( + ERROR, + area.pos_y == 0 && area.width && area.height && + area.pos_x % GL_BLENDER_ALIGN_X == 0 && + area.width % GL_BLENDER_ALIGN_X == 0 && + area.height % GL_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid output merge area, pos_x:%d, pos_y:%d, width:%d, height:%d, level:%d", + XCAM_STR (_blender->get_name ()), area.pos_x, area.pos_y, area.width, area.height, level); + + args->merge_area = area; + } else { + out_buf = pyr_layer[level - 1].overlap_pool->get_buffer (); + XCAM_FAIL_RETURN ( + ERROR, out_buf.ptr (), XCAM_RETURN_ERROR_MEM, + "blender(%s) start_reconstruct failed, out buffer is empty, level:%d", + XCAM_STR (_blender->get_name ()), level); + + XCAM_ASSERT (pyr_layer[level - 1].coef_mask.ptr ()); + args->mask_glbuf = pyr_layer[level - 1].coef_mask; + + const VideoBufferInfo &info = out_buf->get_video_info (); + XCAM_FAIL_RETURN ( + ERROR, + info.width && info.height && + info.width % GL_BLENDER_ALIGN_X == 0 && + info.height % GL_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid buffer info, width:%d, height:%d, level:%d", + XCAM_STR (_blender->get_name ()), info.width, info.height, level); + + args->merge_area = Rect (0, 0, info.width, info.height); + } + args->out_glbuf = get_glbuffer (out_buf); + args->out_video_buf = out_buf; + + return pyr_layer[level].reconstruct->work (args); +} + +XCamReturn +BlenderPrivConfig::start_reconstruct_by_gauss ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &prev_blend_buf, uint32_t level) +{ + XCAM_ASSERT (prev_blend_buf.ptr ()); + XCAM_ASSERT (level < pyr_levels); + + SmartPtr<GLReconstructPyrShader::Args> args; + { + SmartLock locker (map_args_mutex); + MapReconstructArgs::iterator i = pyr_layer[level].reconstruct_args.find (param.ptr ()); + if (i == pyr_layer[level].reconstruct_args.end ()) { + args = new GLReconstructPyrShader::Args (param, level); + XCAM_ASSERT (args.ptr ()); + pyr_layer[level].reconstruct_args.insert (std::make_pair((void*)param.ptr (), args)); + XCAM_LOG_DEBUG ("blender(%s) init reconstruct_args, level:%d", XCAM_STR (_blender->get_name ()), level); + } else { + args = (*i).second; + } + + args->prev_blend_glbuf = get_glbuffer (prev_blend_buf); + + if (!args->lap0_glbuf.ptr () || !args->lap1_glbuf.ptr ()) + return XCAM_RETURN_BYPASS; + + pyr_layer[level].reconstruct_args.erase (i); + } + + return start_reconstruct (args, level); +} + +XCamReturn +BlenderPrivConfig::start_reconstruct_by_lap ( + const SmartPtr<ImageHandler::Parameters> ¶m, + const SmartPtr<VideoBuffer> &lap, + uint32_t level, GLBlender::BufIdx idx) +{ + XCAM_ASSERT (lap.ptr ()); + XCAM_ASSERT (level < pyr_levels); + XCAM_ASSERT (idx < GLBlender::BufIdxCount); + + SmartPtr<GLReconstructPyrShader::Args> args; + { + SmartLock locker (map_args_mutex); + MapReconstructArgs::iterator i = pyr_layer[level].reconstruct_args.find (param.ptr ()); + if (i == pyr_layer[level].reconstruct_args.end ()) { + args = new GLReconstructPyrShader::Args (param, level); + XCAM_ASSERT (args.ptr ()); + pyr_layer[level].reconstruct_args.insert (std::make_pair((void*)param.ptr (), args)); + XCAM_LOG_DEBUG ("blender(%s) init reconstruct_args, level:%d", XCAM_STR (_blender->get_name ()), level); + } else { + args = (*i).second; + } + + if (idx == GLBlender::Idx0) + args->lap0_glbuf = get_glbuffer (lap); + else + args->lap1_glbuf = get_glbuffer (lap); + + if (!args->lap0_glbuf.ptr () || !args->lap1_glbuf.ptr () || !args->prev_blend_glbuf.ptr ()) + return XCAM_RETURN_BYPASS; + + pyr_layer[level].reconstruct_args.erase (i); + } + + return start_reconstruct (args, level); +} + +} + +GLBlender::GLBlender (const char *name) + : GLImageHandler (name) + , Blender (GL_BLENDER_ALIGN_X, GL_BLENDER_ALIGN_Y) +{ + SmartPtr<GLBlenderPriv::BlenderPrivConfig> config = + new GLBlenderPriv::BlenderPrivConfig (this, XCAM_GL_PYRAMID_DEFAULT_LEVEL); + XCAM_ASSERT (config.ptr ()); + _priv_config = config; +} + +GLBlender::~GLBlender () +{ +} + +XCamReturn +GLBlender::finish () +{ + const SmartPtr<GLComputeProgram> prog = _priv_config->get_sync_prog (); + XCAM_ASSERT (prog.ptr ()); + prog->finish (); + + return GLImageHandler::finish (); +} + +XCamReturn +GLBlender::terminate () +{ + _priv_config->stop (); + return GLImageHandler::terminate (); +} + +XCamReturn +GLBlender::blend ( + const SmartPtr<VideoBuffer> &in0, + const SmartPtr<VideoBuffer> &in1, + SmartPtr<VideoBuffer> &out_buf) +{ + XCAM_ASSERT (in0.ptr () && in1.ptr ()); + + SmartPtr<BlenderParam> param = new BlenderParam (in0, in1, out_buf); + XCAM_ASSERT (param.ptr ()); + + XCamReturn ret = execute_buffer (param, true); + + finish (); + if (xcam_ret_is_ok (ret) && !out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +XCamReturn +GLBlender::start_work (const SmartPtr<ImageHandler::Parameters> &base) +{ + XCAM_ASSERT (base.ptr ()); + SmartPtr<BlenderParam> param = base.dynamic_cast_ptr<BlenderParam> (); + XCAM_ASSERT (param.ptr ()); + XCAM_ASSERT (param->in_buf.ptr () && param->in1_buf.ptr () && param->out_buf.ptr ()); + + dump_level_buf (param->in_buf, "input", 0, 0); + dump_level_buf (param->in1_buf, "input", 0, 1); + + // start gauss scale level:0 idx:0 + XCamReturn ret = _priv_config->start_gauss_scale (param, param->in_buf, 0, GLBlender::Idx0); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "blender(%s) start gauss scale failed, level:0 idx:0", XCAM_STR (get_name ())); + + // start gauss scale level:0 idx:1 + ret = _priv_config->start_gauss_scale (param, param->in1_buf, 0, GLBlender::Idx1); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "blender(%s) start gauss scale failed, level:0 idx:1", XCAM_STR (get_name ())); + + return ret; +}; + +XCamReturn +GLBlender::configure_resource (const SmartPtr<Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr ()); + XCAM_ASSERT (_priv_config->pyr_levels <= XCAM_GL_PYRAMID_MAX_LEVEL); + + const VideoBufferInfo &in0_info = param->in_buf->get_video_info (); + XCAM_FAIL_RETURN ( + ERROR, in0_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM, + "blender(%s) only support NV12 format, but input format is %s", + XCAM_STR(get_name ()), xcam_fourcc_to_string (in0_info.format)); + + Rect in0_area, in1_area, out_area; + in0_area = get_input_merge_area (Idx0); + in1_area = get_input_merge_area (Idx1); + out_area = get_merge_window (); + XCAM_FAIL_RETURN ( + ERROR, + in0_area.width && in0_area.height && + in0_area.width == in1_area.width && in0_area.height == in1_area.height && + in0_area.width == out_area.width && in0_area.height == out_area.height, + XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid input/output overlap area, input0:%dx%d, input1:%dx%d, output:%dx%d", + XCAM_STR(get_name ()), in0_area.width, in0_area.height, + in1_area.width, in1_area.height, out_area.width, out_area.height); + + VideoBufferInfo out_info; + uint32_t out_width, out_height; + get_output_size (out_width, out_height); + XCAM_FAIL_RETURN ( + ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid output size, output size:%dx%d", + XCAM_STR(get_name ()), out_width, out_height); + + out_info.init ( + in0_info.format, out_width, out_height, + XCAM_ALIGN_UP (out_width, GL_BLENDER_ALIGN_X), XCAM_ALIGN_UP (out_height, GL_BLENDER_ALIGN_Y)); + set_out_video_info (out_info); + + VideoBufferInfo overlap_info; + Rect merge_size = get_merge_window (); + XCAM_FAIL_RETURN ( + ERROR, + merge_size.width && merge_size.height && + merge_size.width % GL_BLENDER_ALIGN_X == 0 && + merge_size.height % GL_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "blender(%s) invalid merge size, width:%d, height:%d", + XCAM_STR (get_name ()), merge_size.width, merge_size.height); + + overlap_info.init (in0_info.format, merge_size.width, merge_size.height); + SmartPtr<BufferPool> first_lap_pool = new GLVideoBufferPool (overlap_info); + XCAM_ASSERT (first_lap_pool.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, first_lap_pool->reserve (LAP_POOL_SIZE), XCAM_RETURN_ERROR_MEM, + "blender(%s) reserve lap buffer pool failed, overlap size:%dx%d", + XCAM_STR(get_name ()), overlap_info.width, overlap_info.height); + _priv_config->first_lap_pool = first_lap_pool; + + SmartPtr<Worker::Callback> gauss_scale_cb = new CbGaussScalePyr (this); + SmartPtr<Worker::Callback> lap_trans_cb = new CbLapTransPyr (this); + SmartPtr<Worker::Callback> reconstruct_cb = new CbReconstructPyr (this); + XCAM_ASSERT (gauss_scale_cb.ptr () && lap_trans_cb.ptr () && reconstruct_cb.ptr ()); + + XCamReturn ret = _priv_config->init_first_masks (merge_size.width, 1); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "blender(%s) init first masks failed", XCAM_STR (get_name ())); + + for (uint32_t i = 0; i < _priv_config->pyr_levels; ++i) { + merge_size.width = XCAM_ALIGN_UP ((merge_size.width + 1) / 2, GL_BLENDER_ALIGN_X); + merge_size.height = XCAM_ALIGN_UP ((merge_size.height + 1) / 2, GL_BLENDER_ALIGN_Y); + overlap_info.init (in0_info.format, merge_size.width, merge_size.height); + + SmartPtr<BufferPool> pool = new GLVideoBufferPool (overlap_info); + XCAM_ASSERT (pool.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, pool->reserve (OVERLAP_POOL_SIZE), XCAM_RETURN_ERROR_MEM, + "blender(%s) reserve buffer pool failed, overlap size:%dx%d", + XCAM_STR(get_name ()), overlap_info.width, overlap_info.height); + _priv_config->pyr_layer[i].overlap_pool = pool; + + ret = _priv_config->scale_down_masks (i, merge_size.width, 1); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "blender(%s) scale down masks failed, level:%d", XCAM_STR (get_name ()), i); + + _priv_config->pyr_layer[i].gauss_scale[GLBlender::Idx0] = create_gauss_scale_pyr_shader (gauss_scale_cb); + XCAM_ASSERT (_priv_config->pyr_layer[i].gauss_scale[GLBlender::Idx0].ptr ()); + _priv_config->pyr_layer[i].gauss_scale[GLBlender::Idx1] = create_gauss_scale_pyr_shader (gauss_scale_cb); + XCAM_ASSERT (_priv_config->pyr_layer[i].gauss_scale[GLBlender::Idx1].ptr ()); + _priv_config->pyr_layer[i].lap_trans[GLBlender::Idx0] = create_lap_trans_pyr_shader (lap_trans_cb); + XCAM_ASSERT (_priv_config->pyr_layer[i].lap_trans[GLBlender::Idx0].ptr ()); + _priv_config->pyr_layer[i].lap_trans[GLBlender::Idx1] = create_lap_trans_pyr_shader (lap_trans_cb); + XCAM_ASSERT (_priv_config->pyr_layer[i].lap_trans[GLBlender::Idx1].ptr ()); + _priv_config->pyr_layer[i].reconstruct = create_reconstruct_pyr_shader (reconstruct_cb); + XCAM_ASSERT (_priv_config->pyr_layer[i].reconstruct.ptr ()); + } + + SmartPtr<Worker::Callback> blend_cb = new CbBlendPyr (this); + XCAM_ASSERT (blend_cb.ptr ()); + _priv_config->top_level_blend = create_blend_pyr_shader (blend_cb); + XCAM_ASSERT (_priv_config->top_level_blend.ptr ()); + + return XCAM_RETURN_NO_ERROR; +} + +void +GLBlender::gauss_scale_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_UNUSED (error); + XCAM_ASSERT (base.ptr ()); + + SmartPtr<GLGaussScalePyrShader::Args> args = base.dynamic_cast_ptr<GLGaussScalePyrShader::Args> (); + XCAM_ASSERT (args.ptr ()); + uint32_t level = args->level; + XCAM_ASSERT (level < _priv_config->pyr_levels); + uint32_t next_level = level + 1; + BufIdx idx = args->idx; + + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + dump_level_buf (args->out_video_buf, "gauss-scale", level, idx); + + XCamReturn ret = _priv_config->start_lap_trans (param, args, level, idx); + CHECK_RET (ret, "execute laplace transformation failed, level:%d idx:%d", level, idx); + + if (next_level == _priv_config->pyr_levels) { // top level + ret = _priv_config->start_blend (param, args->out_video_buf, idx); + CHECK_RET (ret, "execute blend failed, level:%d idx:%d", next_level, idx); + } else { + ret = _priv_config->start_gauss_scale (param, args->out_video_buf, next_level, idx); + CHECK_RET (ret, "execute gauss scale failed, level:%d idx:%d", next_level, idx); + } +} + +void +GLBlender::lap_trans_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_UNUSED (error); + XCAM_ASSERT (base.ptr ()); + + SmartPtr<GLLapTransPyrShader::Args> args = base.dynamic_cast_ptr<GLLapTransPyrShader::Args> (); + XCAM_ASSERT (args.ptr ()); + uint32_t level = args->level; + XCAM_ASSERT (level < _priv_config->pyr_levels); + BufIdx idx = args->idx; + + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + dump_level_buf (args->out_video_buf, "lap", level, idx); + + XCamReturn ret = _priv_config->start_reconstruct_by_lap (param, args->out_video_buf, level, idx); + CHECK_RET (ret, "execute reconstruct by lap failed, level:%d idx:%d", level, idx); +} + +void +GLBlender::blend_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_UNUSED (error); + XCAM_ASSERT (base.ptr ()); + + SmartPtr<GLBlendPyrShader::Args> args = base.dynamic_cast_ptr<GLBlendPyrShader::Args> (); + XCAM_ASSERT (args.ptr ()); + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + dump_buf (args->out_video_buf, "blend-top"); + + XCamReturn ret = _priv_config->start_reconstruct_by_gauss (param, args->out_video_buf, _priv_config->pyr_levels - 1); + CHECK_RET (ret, "execute reconstruct by gauss failed, level:%d", _priv_config->pyr_levels - 1); +} + +void +GLBlender::reconstruct_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_ASSERT (base.ptr ()); + + SmartPtr<GLReconstructPyrShader::Args> args = base.dynamic_cast_ptr<GLReconstructPyrShader::Args> (); + XCAM_ASSERT (args.ptr ()); + uint32_t level = args->level; + XCAM_ASSERT (level < _priv_config->pyr_levels); + + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + dump_level_buf (args->out_video_buf, "reconstruct", level, 0); + + if (level == 0) { + execute_done (param, error); + return; + } + + XCamReturn ret = _priv_config->start_reconstruct_by_gauss (param, args->out_video_buf, level - 1); + CHECK_RET (ret, "execute reconstruct by gauss failed, level:%d", level - 1); +} + +SmartPtr<GLImageHandler> +create_gl_blender () +{ + SmartPtr<GLBlender> blender = new GLBlender(); + XCAM_ASSERT (blender.ptr ()); + return blender; +} + +SmartPtr<Blender> +Blender::create_gl_blender () +{ + SmartPtr<GLImageHandler> handler = XCam::create_gl_blender (); + return handler.dynamic_cast_ptr<Blender> (); +} + +} diff --git a/modules/gles/gl_blender.h b/modules/gles/gl_blender.h new file mode 100644 index 0000000..54d5a27 --- /dev/null +++ b/modules/gles/gl_blender.h @@ -0,0 +1,98 @@ +/* + * gl_blender.h - gl blender class + * + * 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: Wind Yuan <feng.yuan@intel.com> + * Author: Yinhang Liu <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_BLENDER_H +#define XCAM_GL_BLENDER_H + +#include <interface/blender.h> +#include <gles/gl_image_handler.h> + +#define XCAM_GL_PYRAMID_MAX_LEVEL 4 +#define XCAM_GL_PYRAMID_DEFAULT_LEVEL 2 + +namespace XCam { + +namespace GLBlenderPriv { +class BlenderPrivConfig; +}; + +class GLBlender + : public GLImageHandler, public Blender +{ + friend class GLBlenderPriv::BlenderPrivConfig; + friend SmartPtr<GLImageHandler> create_gl_blender (); + +public: + struct BlenderParam : ImageHandler::Parameters { + SmartPtr<VideoBuffer> in1_buf; + + BlenderParam ( + const SmartPtr<VideoBuffer> &in0, + const SmartPtr<VideoBuffer> &in1, + const SmartPtr<VideoBuffer> &out) + : Parameters (in0, out) + , in1_buf (in1) + {} + }; + + enum BufIdx { + Idx0 = 0, + Idx1, + BufIdxCount + }; + +public: + ~GLBlender (); + + //derived from GLHandler + virtual XCamReturn finish (); + virtual XCamReturn terminate (); + + void gauss_scale_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + void lap_trans_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + void blend_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + void reconstruct_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + +protected: + explicit GLBlender (const char *name = "GLBlender"); + + //derived from Blender interface + XCamReturn blend ( + const SmartPtr<VideoBuffer> &in0, + const SmartPtr<VideoBuffer> &in1, + SmartPtr<VideoBuffer> &out_buf); + + //derived from SoftHandler + XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + SmartPtr<GLBlenderPriv::BlenderPrivConfig> _priv_config; +}; + +extern SmartPtr<GLImageHandler> create_gl_blender (); +} + +#endif // XCAM_GL_BLENDER_H diff --git a/modules/gles/gl_blender_shaders_priv.cpp b/modules/gles/gl_blender_shaders_priv.cpp new file mode 100644 index 0000000..db23416 --- /dev/null +++ b/modules/gles/gl_blender_shaders_priv.cpp @@ -0,0 +1,398 @@ +/* + * gl_blender_shaders_priv.cpp - gl blender shaders private class implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_blender_shaders_priv.h" + +namespace XCam { + +namespace XCamGLShaders { + +enum { + ShaderGaussScalePyr = 0, + ShaderLapTransPyr, + ShaderBlendPyr, + ShaderReconstructPyr +}; + +static const GLShaderInfo shaders_info[] = { + { + GL_COMPUTE_SHADER, + "shader_gauss_scale_pyr", +#include "shader_gauss_scale_pyr.comp.slx" + , 0 + }, + { + GL_COMPUTE_SHADER, + "shader_lap_trans_pyr", +#include "shader_lap_trans_pyr.comp.slx" + , 0 + }, + { + GL_COMPUTE_SHADER, + "shader_blend_pyr", +#include "shader_blend_pyr.comp.slx" + , 0 + }, + { + GL_COMPUTE_SHADER, + "shader_reconstruct_pyr", +#include "shader_reconstruct_pyr.comp.slx" + , 0 + } +}; + +bool +GLGaussScalePyrShader::check_desc ( + const GLBufferDesc &in_desc, const GLBufferDesc &out_desc, const Rect &merge_area) +{ + XCAM_FAIL_RETURN ( + ERROR, + merge_area.pos_y == 0 && merge_area.height == (int32_t)in_desc.height && + merge_area.pos_x + merge_area.width <= (int32_t)in_desc.width && + merge_area.width == (int32_t)out_desc.width * 2 && + merge_area.height == (int32_t)out_desc.height * 2, + false, "invalid buffer size: input:%dx%d, output:%dx%d, merge_area:%dx%d", + in_desc.width, in_desc.height, out_desc.width, out_desc.height, merge_area.width, merge_area.height); + + return true; +} + +XCamReturn +GLGaussScalePyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds) +{ + SmartPtr<GLGaussScalePyrShader::Args> args = base.dynamic_cast_ptr<GLGaussScalePyrShader::Args> (); + XCAM_ASSERT (args.ptr () && args->in_glbuf.ptr () && args->out_glbuf.ptr ()); + + const GLBufferDesc &in_desc = args->in_glbuf->get_buffer_desc (); + const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc (); + const Rect &merge_area = args->merge_area; + XCAM_FAIL_RETURN ( + ERROR, check_desc (in_desc, out_desc, merge_area), XCAM_RETURN_ERROR_PARAM, + "GLGaussScalePyrShader(%s) check buffer description failed, level:%d idx:%d", + XCAM_STR (get_name ()), args->level, (int)args->idx); + + cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 0, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 1, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 2, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 3, NV12PlaneUVIdx)); + + size_t unit_bytes = sizeof (uint32_t); + uint32_t in_img_width = XCAM_ALIGN_UP (in_desc.width, unit_bytes) / unit_bytes; + uint32_t in_offset_x = XCAM_ALIGN_UP (merge_area.pos_x, unit_bytes) / unit_bytes; + uint32_t out_img_width = XCAM_ALIGN_UP (out_desc.width, unit_bytes) / unit_bytes; + uint32_t merge_width = XCAM_ALIGN_UP (merge_area.width, unit_bytes) / unit_bytes; + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_height", in_desc.height)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_offset_x", in_offset_x)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_width", out_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("merge_width", merge_width)); + + GLGroupsSize groups_size; + groups_size.x = XCAM_ALIGN_UP (out_img_width, 8) / 8; + groups_size.y = XCAM_ALIGN_UP (out_desc.height, 16) / 16; + groups_size.z = 1; + + SmartPtr<GLComputeProgram> prog; + XCAM_FAIL_RETURN ( + ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM, + "GLGaussScalePyrShader(%s) get compute program failed", XCAM_STR (get_name ())); + prog->set_groups_size (groups_size); + + return XCAM_RETURN_NO_ERROR; +} + +bool +GLLapTransPyrShader::check_desc ( + const GLBufferDesc &in_desc, const GLBufferDesc &out_desc, + const GLBufferDesc &gs_desc, const Rect &merge_area) +{ + XCAM_FAIL_RETURN ( + ERROR, + merge_area.pos_y == 0 && merge_area.height == (int32_t)in_desc.height && + merge_area.pos_x + merge_area.width <= (int32_t)in_desc.width && + merge_area.width == (int32_t)out_desc.width && merge_area.height == (int32_t)out_desc.height && + merge_area.width == (int32_t)gs_desc.width * 2 && merge_area.height == (int32_t)gs_desc.height * 2, + false, + "invalid buffer size: intput:%dx%d, output:%dx%d, gaussscale:%dx%d, in_area:%dx%d", + in_desc.width, in_desc.height, out_desc.width, out_desc.height, + gs_desc.width, gs_desc.height, merge_area.width, merge_area.height); + + return true; +} + +XCamReturn +GLLapTransPyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds) +{ + SmartPtr<GLLapTransPyrShader::Args> args = base.dynamic_cast_ptr<GLLapTransPyrShader::Args> (); + XCAM_ASSERT (args.ptr () && args->in_glbuf.ptr () && args->gaussscale_glbuf.ptr () && args->out_glbuf.ptr ()); + + const GLBufferDesc &in_desc = args->in_glbuf->get_buffer_desc (); + const GLBufferDesc &gs_desc = args->gaussscale_glbuf->get_buffer_desc (); + const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc (); + const Rect &merge_area = args->merge_area; + XCAM_FAIL_RETURN ( + ERROR, check_desc (in_desc, out_desc, gs_desc, merge_area), XCAM_RETURN_ERROR_PARAM, + "GLLapTransPyrShader(%s) check buffer description failed, level:%d idx:%d", + XCAM_STR (get_name ()), args->level, (int)args->idx); + + cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 0, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->in_glbuf, 1, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->gaussscale_glbuf, 2, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->gaussscale_glbuf, 3, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 4, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 5, NV12PlaneUVIdx)); + + size_t unit_bytes = sizeof (uint32_t) * 2; + uint32_t in_img_width = XCAM_ALIGN_UP (in_desc.width, unit_bytes) / unit_bytes; + uint32_t in_offset_x = XCAM_ALIGN_UP (merge_area.pos_x, unit_bytes) / unit_bytes; + uint32_t gaussscale_img_width = XCAM_ALIGN_UP (gs_desc.width, sizeof (uint32_t)) / sizeof (uint32_t); + uint32_t merge_width = XCAM_ALIGN_UP (merge_area.width, unit_bytes) / unit_bytes; + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_height", in_desc.height)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_offset_x", in_offset_x)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("gaussscale_img_width", gaussscale_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("gaussscale_img_height", gs_desc.height)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("merge_width", merge_width)); + + GLGroupsSize groups_size; + groups_size.x = XCAM_ALIGN_UP (merge_width, 8) / 8; + groups_size.y = XCAM_ALIGN_UP (merge_area.height, 32) / 32; + groups_size.z = 1; + + SmartPtr<GLComputeProgram> prog; + XCAM_FAIL_RETURN ( + ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM, + "GLLapTransPyrShader(%s) get compute program failed", XCAM_STR (get_name ())); + prog->set_groups_size (groups_size); + + return XCAM_RETURN_NO_ERROR; +} + +bool +GLBlendPyrShader::check_desc ( + const GLBufferDesc &in0_desc, const GLBufferDesc &in1_desc, + const GLBufferDesc &out_desc, const GLBufferDesc &mask_desc) +{ + XCAM_FAIL_RETURN ( + ERROR, + in0_desc.width == in1_desc.width && in0_desc.height == in1_desc.height && + in0_desc.width == out_desc.width && in0_desc.height == out_desc.height && + in0_desc.width == mask_desc.width, + false, + "invalid buffer size: intput0:%dx%d, intput1:%dx%d, output:%dx%d, mask:%dx%d", + in0_desc.width, in0_desc.height, in1_desc.width, in1_desc.height, + out_desc.width, out_desc.height, mask_desc.width, mask_desc.height); + + XCAM_FAIL_RETURN ( + ERROR, mask_desc.height == 1, false, + "mask buffer only supports one-dimensional array"); + + return true; +} + +XCamReturn +GLBlendPyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds) +{ + SmartPtr<GLBlendPyrShader::Args> args = base.dynamic_cast_ptr<GLBlendPyrShader::Args> (); + XCAM_ASSERT (args.ptr () && args->in0_glbuf.ptr () && args->in1_glbuf.ptr () && args->out_glbuf.ptr ()); + XCAM_ASSERT (args->mask_glbuf.ptr ()); + + const GLBufferDesc &in0_desc = args->in0_glbuf->get_buffer_desc (); + const GLBufferDesc &in1_desc = args->in1_glbuf->get_buffer_desc (); + const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc (); + const GLBufferDesc &mask_desc = args->mask_glbuf->get_buffer_desc (); + XCAM_FAIL_RETURN ( + ERROR, check_desc (in0_desc, in1_desc, out_desc, mask_desc), XCAM_RETURN_ERROR_PARAM, + "GLBlendPyrShader(%s) check buffer description failed", XCAM_STR (get_name ())); + + cmds.push_back (new GLCmdBindBufRange (args->in0_glbuf, 0, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->in0_glbuf, 1, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->in1_glbuf, 2, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->in1_glbuf, 3, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 4, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 5, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufBase (args->mask_glbuf, 6)); + + size_t unit_bytes = sizeof (uint32_t) * 2; + uint32_t in_img_width = XCAM_ALIGN_UP (in0_desc.width, unit_bytes) / unit_bytes; + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width)); + + GLGroupsSize groups_size; + groups_size.x = XCAM_ALIGN_UP (in_img_width, 8) / 8; + groups_size.y = XCAM_ALIGN_UP (in0_desc.height, 16) / 16; + groups_size.z = 1; + + SmartPtr<GLComputeProgram> prog; + XCAM_FAIL_RETURN ( + ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM, + "GLBlendPyrShader(%s) get compute program failed", XCAM_STR (get_name ())); + prog->set_groups_size (groups_size); + + return XCAM_RETURN_NO_ERROR; +} + +bool +GLReconstructPyrShader::check_desc ( + const GLBufferDesc &lap0_desc, const GLBufferDesc &lap1_desc, const GLBufferDesc &out_desc, + const GLBufferDesc &prev_blend_desc, const GLBufferDesc &mask_desc, const Rect &merge_area) +{ + XCAM_FAIL_RETURN ( + ERROR, + merge_area.pos_y == 0 && merge_area.height == (int32_t)out_desc.height && + merge_area.pos_x + merge_area.width <= (int32_t)out_desc.width && + merge_area.width == (int32_t)lap0_desc.width && merge_area.height == (int32_t)lap0_desc.height && + lap0_desc.width == lap1_desc.width && lap0_desc.height == lap1_desc.height && + lap0_desc.width == prev_blend_desc.width * 2 && lap0_desc.height == prev_blend_desc.height * 2 && + lap0_desc.width == mask_desc.width, + false, + "invalid buffer size: lap0:%dx%d, lap1:%dx%d, output:%dx%d, prev_blend:%dx%d, mask:%dx%d, merge_area:%dx%d", + lap0_desc.width, lap0_desc.height, lap1_desc.width, lap1_desc.height, + out_desc.width, out_desc.height, prev_blend_desc.width, prev_blend_desc.height, + mask_desc.width, mask_desc.height, merge_area.width, merge_area.height); + + XCAM_FAIL_RETURN ( + ERROR, mask_desc.height == 1, false, + "mask buffer only supports one-dimensional array"); + + return true; +} + +XCamReturn +GLReconstructPyrShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds) +{ + SmartPtr<GLReconstructPyrShader::Args> args = base.dynamic_cast_ptr<GLReconstructPyrShader::Args> (); + XCAM_ASSERT (args.ptr () && args->lap0_glbuf.ptr () && args->lap1_glbuf.ptr () && args->out_glbuf.ptr ()); + XCAM_ASSERT (args->mask_glbuf.ptr ()); + + const GLBufferDesc &lap0_desc = args->lap0_glbuf->get_buffer_desc (); + const GLBufferDesc &lap1_desc = args->lap1_glbuf->get_buffer_desc (); + const GLBufferDesc &out_desc = args->out_glbuf->get_buffer_desc (); + const GLBufferDesc &prev_blend_desc = args->prev_blend_glbuf->get_buffer_desc (); + const GLBufferDesc &mask_desc = args->mask_glbuf->get_buffer_desc (); + const Rect &merge_area = args->merge_area; + XCAM_FAIL_RETURN ( + ERROR, check_desc (lap0_desc, lap1_desc, out_desc, prev_blend_desc, mask_desc, merge_area), + XCAM_RETURN_ERROR_PARAM, + "GLReconstructPyrShader(%s) check buffer description failed, level:%d", + XCAM_STR (get_name ()), args->level); + + cmds.push_back (new GLCmdBindBufRange (args->lap0_glbuf, 0, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->lap0_glbuf, 1, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->lap1_glbuf, 2, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->lap1_glbuf, 3, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 4, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_glbuf, 5, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->prev_blend_glbuf, 6, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->prev_blend_glbuf, 7, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufBase (args->mask_glbuf, 8)); + + size_t unit_bytes = sizeof (uint32_t) * 2; + uint32_t lap_img_width = XCAM_ALIGN_UP (lap0_desc.width, unit_bytes) / unit_bytes; + uint32_t out_img_width = XCAM_ALIGN_UP (out_desc.width, unit_bytes) / unit_bytes; + uint32_t out_offset_x = XCAM_ALIGN_UP (merge_area.pos_x, unit_bytes) / unit_bytes; + uint32_t prev_blend_img_width = XCAM_ALIGN_UP (prev_blend_desc.width, sizeof (uint32_t)) / sizeof (uint32_t); + cmds.push_back (new GLCmdUniformT<uint32_t> ("lap_img_width", lap_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("lap_img_height", lap0_desc.height)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_width", out_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_offset_x", out_offset_x)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("prev_blend_img_width", prev_blend_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("prev_blend_img_height", prev_blend_desc.height)); + + GLGroupsSize groups_size; + groups_size.x = XCAM_ALIGN_UP (lap_img_width, 8) / 8; + groups_size.y = XCAM_ALIGN_UP (lap0_desc.height, 32) / 32; + groups_size.z = 1; + + SmartPtr<GLComputeProgram> prog; + XCAM_FAIL_RETURN ( + ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM, + "GLReconstructPyrShader(%s) get compute program failed", XCAM_STR (get_name ())); + prog->set_groups_size (groups_size); + + return XCAM_RETURN_NO_ERROR; +} + +SmartPtr<GLGaussScalePyrShader> +create_gauss_scale_pyr_shader (SmartPtr<Worker::Callback> &cb) +{ + XCAM_ASSERT (cb.ptr ()); + + SmartPtr<GLGaussScalePyrShader> shader = new GLGaussScalePyrShader (cb); + XCAM_ASSERT (shader.ptr ()); + + XCamReturn ret = shader->create_compute_program (shaders_info[ShaderGaussScalePyr], "gauss_scale_pyr_program"); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, NULL, + "create gauss scale pyramid program failed"); + + return shader; +} + +SmartPtr<GLLapTransPyrShader> +create_lap_trans_pyr_shader (SmartPtr<Worker::Callback> &cb) +{ + XCAM_ASSERT (cb.ptr ()); + + SmartPtr<GLLapTransPyrShader> shader = new GLLapTransPyrShader (cb); + XCAM_ASSERT (shader.ptr ()); + + XCamReturn ret = shader->create_compute_program (shaders_info[ShaderLapTransPyr], "lap_trans_pyr_program"); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, NULL, + "create laplace transformation pyramid program failed"); + + return shader; +} + +SmartPtr<GLBlendPyrShader> +create_blend_pyr_shader (SmartPtr<Worker::Callback> &cb) +{ + XCAM_ASSERT (cb.ptr ()); + + SmartPtr<GLBlendPyrShader> shader = new GLBlendPyrShader (cb); + XCAM_ASSERT (shader.ptr ()); + + XCamReturn ret = shader->create_compute_program (shaders_info[ShaderBlendPyr], "blend_pyr_program"); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, NULL, + "create blend pyramid program failed"); + + return shader; +} + +SmartPtr<GLReconstructPyrShader> +create_reconstruct_pyr_shader (SmartPtr<Worker::Callback> &cb) +{ + XCAM_ASSERT (cb.ptr ()); + + SmartPtr<GLReconstructPyrShader> shader = new GLReconstructPyrShader (cb); + XCAM_ASSERT (shader.ptr ()); + + XCamReturn ret = shader->create_compute_program (shaders_info[ShaderReconstructPyr], "reconstruct_pyr_program"); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, NULL, + "create reconstruct pyramid program failed"); + + return shader; +} + +} + +} diff --git a/modules/gles/gl_blender_shaders_priv.h b/modules/gles/gl_blender_shaders_priv.h new file mode 100644 index 0000000..f3e363a --- /dev/null +++ b/modules/gles/gl_blender_shaders_priv.h @@ -0,0 +1,182 @@ +/* + * gl_blender_shaders_priv.h - gl blender shaders private class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_BLENDER_SHADERS_PRIV_H +#define XCAM_GL_BLENDER_SHADERS_PRIV_H + +#include <interface/data_types.h> +#include <gles/gl_image_shader.h> +#include <gles/gl_image_handler.h> +#include <gles/gl_buffer.h> +#include <gles/gl_blender.h> + +#define GL_BLENDER_ALIGN_X 8 +#define GL_BLENDER_ALIGN_Y 4 + +namespace XCam { + +namespace XCamGLShaders { + +class GLGaussScalePyrShader + : public GLImageShader +{ +public: + struct Args : GLArgs { + SmartPtr<GLBuffer> in_glbuf; + SmartPtr<GLBuffer> out_glbuf; + Rect merge_area; + + const uint32_t level; + const GLBlender::BufIdx idx; + SmartPtr<VideoBuffer> out_video_buf; + + Args ( + const SmartPtr<ImageHandler::Parameters> ¶m, + uint32_t l, GLBlender::BufIdx i) + : GLArgs (param) + , level (l) + , idx (i) + {} + }; + +public: + explicit GLGaussScalePyrShader (const SmartPtr<Worker::Callback> &cb) + : GLImageShader ("GLGaussScalePyrShader", cb) + {} + +private: + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); + bool check_desc (const GLBufferDesc &in_desc, const GLBufferDesc &out_desc, const Rect &merge_area); +}; + +class GLLapTransPyrShader + : public GLImageShader +{ +public: + struct Args : GLArgs { + SmartPtr<GLBuffer> in_glbuf; + SmartPtr<GLBuffer> out_glbuf; + SmartPtr<GLBuffer> gaussscale_glbuf; + Rect merge_area; + + const uint32_t level; + const GLBlender::BufIdx idx; + SmartPtr<VideoBuffer> out_video_buf; + + Args ( + const SmartPtr<ImageHandler::Parameters> ¶m, + uint32_t l, GLBlender::BufIdx i) + : GLArgs (param) + , level (l) + , idx (i) + {} + }; + +public: + explicit GLLapTransPyrShader (const SmartPtr<Worker::Callback> &cb) + : GLImageShader ("GLLapTransPyrShader", cb) + {} + +private: + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); + bool check_desc ( + const GLBufferDesc &in_desc, const GLBufferDesc &out_desc, + const GLBufferDesc &gs_desc, const Rect &merge_area); +}; + +class GLBlendPyrShader + : public GLImageShader +{ +public: + struct Args : GLArgs { + SmartPtr<GLBuffer> in0_glbuf; + SmartPtr<GLBuffer> in1_glbuf; + SmartPtr<GLBuffer> out_glbuf; + SmartPtr<GLBuffer> mask_glbuf; + + SmartPtr<VideoBuffer> out_video_buf; + + Args (const SmartPtr<ImageHandler::Parameters> ¶m) + : GLArgs (param) + {} + }; + +public: + explicit GLBlendPyrShader (const SmartPtr<Worker::Callback> &cb) + : GLImageShader ("GLBlendPyrShader", cb) + {} + +private: + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); + bool check_desc ( + const GLBufferDesc &in0_desc, const GLBufferDesc &in1_desc, + const GLBufferDesc &out_desc, const GLBufferDesc &mask_desc); +}; + +class GLReconstructPyrShader + : public GLImageShader +{ +public: + struct Args : GLArgs { + SmartPtr<GLBuffer> lap0_glbuf; + SmartPtr<GLBuffer> lap1_glbuf; + SmartPtr<GLBuffer> out_glbuf; + SmartPtr<GLBuffer> prev_blend_glbuf; + SmartPtr<GLBuffer> mask_glbuf; + Rect merge_area; + + const uint32_t level; + SmartPtr<VideoBuffer> out_video_buf; + + Args (const SmartPtr<ImageHandler::Parameters> ¶m, uint32_t l) + : GLArgs (param) + , level (l) + {} + }; + +public: + explicit GLReconstructPyrShader (const SmartPtr<Worker::Callback> &cb) + : GLImageShader ("GLReconstructPyrShader", cb) + {} + +private: + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); + bool check_desc ( + const GLBufferDesc &lap0_desc, const GLBufferDesc &lap1_desc, const GLBufferDesc &out_desc, + const GLBufferDesc &prev_blend_desc, const GLBufferDesc &mask_desc, const Rect &merge_area); +}; + +SmartPtr<GLGaussScalePyrShader> +create_gauss_scale_pyr_shader (SmartPtr<Worker::Callback> &cb); + +SmartPtr<GLLapTransPyrShader> +create_lap_trans_pyr_shader (SmartPtr<Worker::Callback> &cb); + +SmartPtr<GLBlendPyrShader> +create_blend_pyr_shader (SmartPtr<Worker::Callback> &cb); + +SmartPtr<GLReconstructPyrShader> +create_reconstruct_pyr_shader (SmartPtr<Worker::Callback> &cb); + +} + +} + +#endif // XCAM_GL_BLENDER_SHADERS_PRIV_H diff --git a/modules/gles/gl_buffer.cpp b/modules/gles/gl_buffer.cpp new file mode 100644 index 0000000..7cb8c8e --- /dev/null +++ b/modules/gles/gl_buffer.cpp @@ -0,0 +1,246 @@ +/* + * gl_buffer.cpp - GL buffer + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "gl_buffer.h" + +namespace XCam { + +GLBufferDesc::GLBufferDesc () + : format (V4L2_PIX_FMT_NV12) + , width (0) + , height (0) + , aligned_width (0) + , aligned_height (0) + , size (0) +{ + xcam_mem_clear (strides); + xcam_mem_clear (slice_size); + xcam_mem_clear (offsets); +} + +GLBuffer::MapRange::MapRange () + : offset (0) + , len (0) + , flags (0) + , ptr (0) +{ +} + +void +GLBuffer::MapRange::clear () +{ + offset = 0; + len = 0; + flags = 0; + ptr = NULL; +} + +bool +GLBuffer::MapRange::is_mapped () const +{ + return ptr; +} + +GLBuffer::GLBuffer (GLuint id, GLenum target, GLenum usage, uint32_t size) + : _target (target) + , _usage (usage) + , _buf_id (id) + , _size (size) +{ +} + +XCamReturn +GLBuffer::bind () +{ + glBindBuffer (_target, _buf_id); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GL bind buffer:%d failed, error flag: %s", _buf_id, gl_error_string (error)); + return XCAM_RETURN_NO_ERROR; +} + +GLBuffer::~GLBuffer () +{ + if (_buf_id) { + glDeleteBuffers (1, &_buf_id); + + GLenum error = gl_error (); + if (error != GL_NO_ERROR) { + XCAM_LOG_WARNING ( + "GL Buffer delete buffer failed, error flag: %s", gl_error_string (error)); + } + } +} + +SmartPtr<GLBuffer> +GLBuffer::create_buffer ( + GLenum target, + const GLvoid *data, uint32_t size, + GLenum usage) +{ + XCAM_ASSERT (size > 0); + + GLuint buf_id = 0; + glGenBuffers (1, &buf_id); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, buf_id && (error == GL_NO_ERROR), NULL, + "GL buffer creation failed, error flag: %s", gl_error_string (error)); + + glBindBuffer (target, buf_id); + XCAM_FAIL_RETURN ( + ERROR, (error = gl_error ()) == GL_NO_ERROR, NULL, + "GL buffer creation failed when bind buffer:%d, error flag: %s", + buf_id, gl_error_string (error)); + + glBufferData (target, size, data, usage); + XCAM_FAIL_RETURN ( + ERROR, (error = gl_error ()) == GL_NO_ERROR, NULL, + "GL buffer creation failed in glBufferData, id:%d, error flag: %s", + buf_id, gl_error_string (error)); + + SmartPtr<GLBuffer> buf_obj = + new GLBuffer (buf_id, target, usage, size); + + return buf_obj; +} + +void * +GLBuffer::map_range (uint32_t offset, uint32_t length, GLbitfield flags) +{ + if (length == 0) + length = _size; + + if (_mapped_range.is_mapped () && + _mapped_range.flags == flags && + _mapped_range.offset == offset && + _mapped_range.len == length) { + return _mapped_range.ptr; + } + _mapped_range.clear (); + + XCamReturn ret = bind (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), NULL, + "GL bind buffer failed, buf_id:%d", _buf_id); + + void *ptr = glMapBufferRange (_target, offset, length, flags); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, ptr && (error == GL_NO_ERROR), NULL, + "GL buffer map range failed, buf_id:%d, offset:%d, len:%d, flags:%d, error flag: %s", + _buf_id, offset, length, flags, gl_error_string (error)); + + _mapped_range.offset = offset; + _mapped_range.len = length; + _mapped_range.flags = flags; + _mapped_range.ptr = ptr; + + return ptr; +} + +XCamReturn +GLBuffer::flush_map () +{ + if (!_mapped_range.is_mapped ()) + return XCAM_RETURN_ERROR_ORDER; + + XCAM_FAIL_RETURN ( + ERROR, _mapped_range.flags & GL_MAP_FLUSH_EXPLICIT_BIT, + XCAM_RETURN_ERROR_GLES, + "GL buffer flush_map buf:%d failed, invalid flags(:%d)", + _buf_id, _mapped_range.flags); + + XCamReturn ret = bind (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GL bind buffer failed, buf_id:%d", _buf_id); + + glFlushMappedBufferRange (_target, _mapped_range.offset, _mapped_range.len); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, + XCAM_RETURN_ERROR_GLES, + "GL buffer flush_map buf:%d failed, error flag: %s", + _buf_id, gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLBuffer::unmap () +{ + if (!_mapped_range.is_mapped ()) + return XCAM_RETURN_ERROR_ORDER; + + XCamReturn ret = bind (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GL bind buffer failed, buf_id:%d", _buf_id); + + XCAM_FAIL_RETURN ( + ERROR, glUnmapBuffer (_target), XCAM_RETURN_ERROR_GLES, + "GL buffer unmap buf:%d failed, error flag: %s", + _buf_id, gl_error_string (gl_error ())); + + _mapped_range.clear (); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLBuffer::bind_buffer_base (uint32_t index) +{ + XCamReturn ret = bind (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GL bind buffer failed, buf_id:%d", _buf_id); + + glBindBufferBase (_target, index, _buf_id); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GL bind buffer base failed. buf_id:%d failed, idx:%d, error flag: %s", + _buf_id, index, gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLBuffer::bind_buffer_range (uint32_t index, uint32_t offset, uint32_t size) +{ + XCamReturn ret = bind (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GL bind buffer failed, buf_id:%d", _buf_id); + + glBindBufferRange (_target, index, _buf_id, offset, size); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GL bind buffer range failed. buf_id:%d failed, idx:%d, error flag: %s", + _buf_id, index, gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +} + diff --git a/modules/gles/gl_buffer.h b/modules/gles/gl_buffer.h new file mode 100644 index 0000000..5bd3d48 --- /dev/null +++ b/modules/gles/gl_buffer.h @@ -0,0 +1,110 @@ +/* + * gl_buffer.h - GL buffer + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_GL_BUFFER_H +#define XCAM_GL_BUFFER_H + +#include <gles/gles_std.h> +#include <map> + +#define XCAM_GL_MAX_COMPONENTS 4 + +namespace XCam { + +struct GLBufferDesc { + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t aligned_width; + uint32_t aligned_height; + uint32_t size; + uint32_t strides[XCAM_GL_MAX_COMPONENTS]; + uint32_t offsets[XCAM_GL_MAX_COMPONENTS]; + uint32_t slice_size[XCAM_GL_MAX_COMPONENTS]; + + GLBufferDesc (); +}; + +class GLBuffer +{ +public: + ~GLBuffer (); + static SmartPtr<GLBuffer> create_buffer ( + GLenum target, const GLvoid *data = NULL, uint32_t size = 0, GLenum usage = GL_STATIC_DRAW); + + GLuint get_buffer_id () const { + return _buf_id; + } + GLenum get_target () const { + return _target; + } + GLenum get_usage () const { + return _usage; + } + uint32_t get_size () const { + return _size; + } + + void set_buffer_desc (const GLBufferDesc &desc) { + _desc = desc; + } + const GLBufferDesc &get_buffer_desc () { + return _desc; + } + + void *map_range ( + uint32_t offset = 0, uint32_t length = 0, + GLbitfield flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + XCamReturn flush_map (); + XCamReturn unmap (); + + XCamReturn bind (); + XCamReturn bind_buffer_base (uint32_t index); + XCamReturn bind_buffer_range (uint32_t index, uint32_t offset, uint32_t size); + +private: + explicit GLBuffer (GLuint id, GLenum type, GLenum usage, uint32_t size); + +private: + XCAM_DEAD_COPY (GLBuffer); + + struct MapRange { + uint32_t offset; + uint32_t len; + GLbitfield flags; + void *ptr; + + MapRange (); + void clear (); + bool is_mapped () const; + }; + +private: + GLenum _target; + GLenum _usage; + GLuint _buf_id; + uint32_t _size; + MapRange _mapped_range; + GLBufferDesc _desc; +}; + +} + +#endif //XCAM_GL_BUFFER_H diff --git a/modules/gles/gl_command.cpp b/modules/gles/gl_command.cpp new file mode 100644 index 0000000..38b92b0 --- /dev/null +++ b/modules/gles/gl_command.cpp @@ -0,0 +1,265 @@ +/* + * gl_command.cpp - GL command implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_command.h" +#include "gl_buffer.h" + +namespace XCam { + +namespace UniformOps { + +template <> +GLenum uniform <GLfloat> (GLint location, GLfloat value) +{ + glUniform1f (location, value); + return gl_error (); +} + +template <> +GLenum uniform <GLint> (GLint location, GLint value) +{ + glUniform1i (location, value); + return gl_error (); +} + +template <> +GLenum uniform <GLuint> (GLint location, GLuint value) +{ + glUniform1ui (location, value); + return gl_error (); +} + +template <> +GLenum uniform_array <GLfloat> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniform1fv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_array <GLint> (GLint location, const GLint *value, GLsizei count) +{ + glUniform1iv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_array <GLuint> (GLint location, const GLuint *value, GLsizei count) +{ + glUniform1uiv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLfloat, 2> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniform2fv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLfloat, 3> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniform3fv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLfloat, 4> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniform4fv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLint, 2> (GLint location, const GLint *value, GLsizei count) +{ + glUniform2iv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLint, 3> (GLint location, const GLint *value, GLsizei count) +{ + glUniform3iv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLint, 4> (GLint location, const GLint *value, GLsizei count) +{ + glUniform4iv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLuint, 2> (GLint location, const GLuint *value, GLsizei count) +{ + glUniform2uiv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLuint, 3> (GLint location, const GLuint *value, GLsizei count) +{ + glUniform3uiv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_vect <GLuint, 4> (GLint location, const GLuint *value, GLsizei count) +{ + glUniform4uiv (location, count, value); + return gl_error (); +} + +template <> +GLenum uniform_mat <GLfloat, 2> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniformMatrix2fv (location, count, GL_FALSE, value); + return gl_error (); +} + +template <> +GLenum uniform_mat <GLfloat, 3> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniformMatrix3fv (location, count, GL_FALSE, value); + return gl_error (); +} + +template <> +GLenum uniform_mat <GLfloat, 4> (GLint location, const GLfloat *value, GLsizei count) +{ + glUniformMatrix4fv (location, count, GL_FALSE, value); + return gl_error (); +} + +} + +GLCmdUniform::GLCmdUniform (const GLchar *name) +{ + XCAM_ASSERT (name); + strncpy (_name, name, XCAM_GL_NAME_LENGTH - 1); +} + +GLCmdUniform::~GLCmdUniform () +{ +} + +XCamReturn +GLCmdUniform::run (GLuint program) +{ + GLint location = get_uniform_location (program, _name); + XCAM_FAIL_RETURN (ERROR, location >= 0, XCAM_RETURN_ERROR_UNKNOWN, "get_uniform_location failed"); + + GLenum error = uniform (location); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_UNKNOWN, + "uniform failed, name:%s, error flag: %s", _name, gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +GLint +GLCmdUniform::get_uniform_location (GLuint program, const GLchar *name) +{ + GLint location = glGetUniformLocation (program, name); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, -1, + "get_uniform_location failed, name:%s, error flag: %s", + XCAM_STR (name), gl_error_string (error)); + + XCAM_FAIL_RETURN ( + WARNING, location >= 0, -1, + "get_uniform_location invalid or unnecessary parameter, name:%s location:%d", + XCAM_STR (name), location); + + return location; +} + +GLCmdBindBufBase::GLCmdBindBufBase (const SmartPtr<GLBuffer> &buf, uint32_t index) + : _index (index) +{ + XCAM_ASSERT (buf.ptr ()); + _buf = buf; +} + +GLCmdBindBufBase::~GLCmdBindBufBase () +{ +} + +XCamReturn +GLCmdBindBufBase::run (GLuint program) +{ + XCAM_UNUSED (program); + + XCamReturn ret = _buf->bind_buffer_base (_index); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLCmdBindBufBase failed, idx:%d", _index); + + return XCAM_RETURN_NO_ERROR; +} + +GLCmdBindBufRange::GLCmdBindBufRange (const SmartPtr<GLBuffer> &buf, uint32_t index, uint32_t offset_x) + : _index (index) + , _offset (offset_x) + , _size (0) +{ + XCAM_ASSERT (buf.ptr ()); + _buf = buf; + + const GLBufferDesc &desc = buf->get_buffer_desc (); + _size = desc.size - offset_x; +} + +GLCmdBindBufRange::GLCmdBindBufRange ( + const SmartPtr<GLBuffer> &buf, uint32_t index, NV12PlaneIdx plane, uint32_t offset_in_plane) + : _index (index) + , _offset (0) + , _size (0) +{ + XCAM_ASSERT (buf.ptr ()); + _buf = buf; + + const GLBufferDesc &desc = buf->get_buffer_desc (); + _offset = desc.offsets [plane] + offset_in_plane; + _size = desc.slice_size [plane] - offset_in_plane; +} + +GLCmdBindBufRange::~GLCmdBindBufRange () +{ +} + +XCamReturn +GLCmdBindBufRange::run (GLuint program) +{ + XCAM_UNUSED (program); + + XCamReturn ret = _buf->bind_buffer_range (_index, _offset, _size); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLCmdBindBufRange failed, idx:%d", _index); + + return XCAM_RETURN_NO_ERROR; +} + +} diff --git a/modules/gles/gl_command.h b/modules/gles/gl_command.h new file mode 100644 index 0000000..8906eee --- /dev/null +++ b/modules/gles/gl_command.h @@ -0,0 +1,206 @@ +/* + * gl_command.h - GL command class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_COMMAND_H +#define XCAM_GL_COMMAND_H + +#include <list> +#include <gles/gles_std.h> + +namespace XCam { + +namespace UniformOps { + +template <typename TType> +GLenum uniform (GLint location, TType value); + +template <typename TType> +GLenum uniform_array (GLint location, const TType *value, GLsizei count); + +template <typename TType, uint32_t TDim> +GLenum uniform_vect (GLint location, const TType *value, GLsizei count = 1); + +template <typename TType, uint32_t TDim> +GLenum uniform_mat (GLint location, const TType *value, GLsizei count = 1); +} + +class GLCommand +{ +public: + virtual ~GLCommand () {} + virtual XCamReturn run (GLuint program) = 0; + +protected: + explicit GLCommand () {} + +private: + XCAM_DEAD_COPY (GLCommand); +}; +typedef std::list<SmartPtr<GLCommand> > GLCmdList; + +class GLCmdUniform + : public GLCommand +{ +public: + virtual ~GLCmdUniform (); + virtual XCamReturn run (GLuint program); + +protected: + explicit GLCmdUniform (const GLchar *name); + +private: + GLint get_uniform_location (GLuint program, const GLchar *name); + virtual GLenum uniform (GLint location) = 0; + +protected: + GLchar _name[XCAM_GL_NAME_LENGTH]; +}; + +/* uniform single variable */ +template <typename TType> +class GLCmdUniformT + : public GLCmdUniform +{ +public: + GLCmdUniformT (const GLchar *name, TType value) + : GLCmdUniform (name) + , _value (value) + {} + ~GLCmdUniformT () {} + +private: + virtual GLenum uniform (GLint location) { + return UniformOps::uniform <TType> (location, _value); + } + +private: + TType _value; +}; + +/* uniform array: TType array[TCount] */ +template <typename TType, int TCount> +class GLCmdUniformTArray + : public GLCmdUniform +{ +public: + GLCmdUniformTArray (const GLchar *name, const TType *value) + : GLCmdUniform (name) + { + XCAM_ASSERT (value); + memcpy (&_value[0], value, sizeof (TType) * TCount); + } + ~GLCmdUniformTArray () {} + +private: + virtual GLenum uniform (GLint location) { + return UniformOps::uniform_array <TType> (location, _value, TCount); + } + +private: + TType _value[TCount]; +}; + +/* uniform vectors: TType vec{TDim}[TCount]*/ +template <typename TType, int TDim, int TCount = 1> +class GLCmdUniformTVect + : public GLCmdUniform +{ +public: + GLCmdUniformTVect (const GLchar *name, const TType *value) + : GLCmdUniform (name) + { + XCAM_ASSERT (value); + memcpy (&_value[0], value, sizeof (TType) * TDim * TCount); + } + ~GLCmdUniformTVect () {} + +private: + virtual GLenum uniform (GLint location) { + return UniformOps::uniform_vect <TType, TDim> (location, _value, TCount); + } + +private: + TType _value[TDim * TCount]; +}; + +/* uniform matrix: TType mat{TColumns}x{TRows}[TCount], only support square matrix */ +template <typename TType, int TColumns, int TRows, int TCount = 1> +class GLCmdUniformTMat + : public GLCmdUniform +{ +public: + GLCmdUniformTMat (const GLchar *name, const TType *value) + : GLCmdUniform (name) + { + XCAM_ASSERT (value); + memcpy (&_value[0], value, sizeof (TType) * TColumns * TRows * TCount); + } + ~GLCmdUniformTMat () {} + +private: + virtual GLenum uniform (GLint location) { + XCAM_FAIL_RETURN ( + ERROR, TColumns == TRows, -1, + "uniform_mat only support square matrix, invalid dimension:%dx%d", TColumns, TRows); + + return UniformOps::uniform_mat <TType, TColumns> (location, _value, TCount); + } + +private: + TType _value[TColumns * TRows * TCount]; +}; + +class GLBuffer; + +class GLCmdBindBufBase + : public GLCommand +{ +public: + GLCmdBindBufBase (const SmartPtr<GLBuffer> &buf, uint32_t index); + virtual ~GLCmdBindBufBase (); + + virtual XCamReturn run (GLuint program); + +private: + SmartPtr<GLBuffer> _buf; + uint32_t _index; +}; + +class GLCmdBindBufRange + : public GLCommand +{ +public: + GLCmdBindBufRange (const SmartPtr<GLBuffer> &buf, uint32_t index, uint32_t offset_x = 0); + GLCmdBindBufRange ( + const SmartPtr<GLBuffer> &buf, uint32_t index, NV12PlaneIdx plane, uint32_t offset_in_plane = 0); + virtual ~GLCmdBindBufRange (); + + virtual XCamReturn run (GLuint program); + +private: + SmartPtr<GLBuffer> _buf; + uint32_t _index; + uint32_t _offset; + uint32_t _size; +}; + +} + +#endif // XCAM_GL_COMMAND_H
\ No newline at end of file diff --git a/modules/gles/gl_compute_program.cpp b/modules/gles/gl_compute_program.cpp new file mode 100644 index 0000000..13649ad --- /dev/null +++ b/modules/gles/gl_compute_program.cpp @@ -0,0 +1,178 @@ +/* + * gl_compute_program.cpp - GL compute program implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_compute_program.h" + +namespace XCam { + +GLGroupsSize GLComputeProgram::_max_groups_size; + +GLComputeProgram::GLComputeProgram (GLuint id, const char *name) + : GLProgram (id, name) + , _barrier (false) + , _barrier_bit (GL_SHADER_STORAGE_BARRIER_BIT) +{ + if (_max_groups_size.x == 0 && _max_groups_size.y == 0 && _max_groups_size.z == 0) { + get_max_groups_size (_max_groups_size); + } +} + +GLComputeProgram::~GLComputeProgram () +{ +} + +SmartPtr<GLComputeProgram> +GLComputeProgram::create_compute_program (const char *name) +{ + GLuint prog_id = glCreateProgram (); + XCAM_FAIL_RETURN ( + ERROR, prog_id, NULL, + "create GL program(%s) failed, prog_id: %d, error flag: %s", + XCAM_STR (name), prog_id, gl_error_string (gl_error ())); + + SmartPtr<GLComputeProgram> compute_prog = new GLComputeProgram (prog_id, name); + XCAM_FAIL_RETURN ( + ERROR, compute_prog.ptr (), NULL, + "create GL compute program(%s) failed", XCAM_STR (name)); + + return compute_prog; +} + +bool query_max_groups_size (GLuint idx, GLint &value) +{ + glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, idx, &value); + + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, false, + "GLComputeProgram query max groups size failed, idx:%d, error flag: %s", + idx, gl_error_string (error)); + + return true; +} + +bool +GLComputeProgram::get_max_groups_size (GLGroupsSize &size) +{ + XCAM_FAIL_RETURN ( + ERROR, + query_max_groups_size (0, size.x) && + query_max_groups_size (1, size.y) && + query_max_groups_size (2, size.z), + false, + "GLComputeProgram(%s) get max groups size failed", XCAM_STR (get_name ())); + + return true; +} + +bool +GLComputeProgram::check_groups_size (const GLGroupsSize &size) +{ + XCAM_FAIL_RETURN ( + ERROR, + size.x > 0 && size.x <= _max_groups_size.x && + size.y > 0 && size.y <= _max_groups_size.y && + size.z > 0 && size.z <= _max_groups_size.z, + false, + "GLComputeProgram(%s) invalid groups size: %dx%dx%d", + XCAM_STR (get_name ()), size.x, size.y, size.z); + + return true; +} + +bool +GLComputeProgram::set_groups_size (const GLGroupsSize &size) +{ + XCAM_FAIL_RETURN ( + ERROR, check_groups_size (size), false, + "GLComputeProgram(%s) set groups size failed, groups size: %dx%dx%d", + XCAM_STR (get_name ()), size.x, size.y, size.z); + + _groups_size = size; + + return true; +} + +XCamReturn +GLComputeProgram::work () +{ + XCamReturn ret = dispatch (); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLComputeProgram(%s) dispatch failed", XCAM_STR (get_name ())); + + if (_barrier) { + ret = barrier (_barrier_bit); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLComputeProgram(%s) barrier failed", XCAM_STR (get_name ())); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLComputeProgram::barrier (GLbitfield barrier_bit) +{ + glMemoryBarrier (barrier_bit); + + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GLComputeProgram(%s) barrier failed, barrier bit: %d, error flag: %s", + XCAM_STR (get_name ()), barrier_bit, gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLComputeProgram::finish () +{ + glFinish (); + + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GLComputeProgram(%s) finish failed, error flag: %s", + XCAM_STR (get_name ()), gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLComputeProgram::dispatch () +{ + XCAM_FAIL_RETURN ( + ERROR, check_groups_size (_groups_size), XCAM_RETURN_ERROR_PARAM, + "GLComputeProgram(%s) dispatch invalid groups size: %dx%dx%d", + XCAM_STR (get_name ()), _groups_size.x, _groups_size.y, _groups_size.z); + + glDispatchCompute (_groups_size.x, _groups_size.y, _groups_size.z); + + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GLComputeProgram(%s) dispatch failed, groups size: %dx%dx%d, error flag: %s", + XCAM_STR (get_name ()), _groups_size.x, _groups_size.y, _groups_size.z, gl_error_string (error)); + + return XCAM_RETURN_NO_ERROR; +} + +} diff --git a/modules/gles/gl_compute_program.h b/modules/gles/gl_compute_program.h new file mode 100644 index 0000000..66a5c81 --- /dev/null +++ b/modules/gles/gl_compute_program.h @@ -0,0 +1,70 @@ +/* + * gl_compute_program.h - GL compute program class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_COMPUTE_PROGRAM_H +#define XCAM_GL_COMPUTE_PROGRAM_H + +#include <gles/gl_program.h> + +namespace XCam { + +struct GLGroupsSize { + GLint x, y, z; + GLGroupsSize () : x (0), y (0), z (0) {} +}; + +class GLComputeProgram + : public GLProgram +{ +public: + static SmartPtr<GLComputeProgram> create_compute_program (const char *name = NULL); + ~GLComputeProgram (); + + bool set_groups_size (const GLGroupsSize &size); + void set_barrier (bool barrier, GLbitfield barrier_bit = GL_SHADER_STORAGE_BARRIER_BIT) { + _barrier = barrier; + _barrier_bit = barrier_bit; + } + + virtual XCamReturn work (); + virtual XCamReturn finish (); + +private: + explicit GLComputeProgram (GLuint id, const char *name); + + XCamReturn dispatch (); + XCamReturn barrier (GLbitfield barrier_bit); + + bool get_max_groups_size (GLGroupsSize &size); + bool check_groups_size (const GLGroupsSize &size); + +private: + XCAM_DEAD_COPY (GLComputeProgram); + +private: + bool _barrier; + GLbitfield _barrier_bit; + GLGroupsSize _groups_size; + static GLGroupsSize _max_groups_size; +}; + +} + +#endif // XCAM_GL_COMPUTE_PROGRAM_H diff --git a/modules/gles/gl_copy_handler.cpp b/modules/gles/gl_copy_handler.cpp new file mode 100644 index 0000000..a29c23a --- /dev/null +++ b/modules/gles/gl_copy_handler.cpp @@ -0,0 +1,228 @@ +/* + * gl_copy_handler.cpp - gl copy handler implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_copy_handler.h" +#include "gl_utils.h" + +#define INVALID_INDEX (uint32_t)(-1) + +namespace XCam { + +DECLARE_WORK_CALLBACK (CbCopyShader, GLCopyHandler, copy_shader_done); + +const GLShaderInfo shader_info = { + GL_COMPUTE_SHADER, + "shader_copy", +#include "shader_copy.comp.slx" + , 0 +}; + +XCamReturn +GLCopyShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds) +{ + SmartPtr<GLCopyShader::Args> args = base.dynamic_cast_ptr<GLCopyShader::Args> (); + XCAM_ASSERT (args.ptr () && args->in_buf.ptr () && args->out_buf.ptr ()); + + const GLBufferDesc &in_desc = args->in_buf->get_buffer_desc (); + const GLBufferDesc &out_desc = args->out_buf->get_buffer_desc (); + const Rect &in_area = args->in_area; + const Rect &out_area = args->out_area; + + XCAM_ASSERT (in_area.pos_y == 0 && out_area.pos_y == 0); + XCAM_ASSERT (in_area.width == out_area.width && in_area.height == out_area.height); + XCAM_ASSERT (uint32_t(in_area.height) == in_desc.height && uint32_t(out_area.height) == out_desc.height); + + cmds.push_back (new GLCmdBindBufRange (args->in_buf, 0)); + cmds.push_back (new GLCmdBindBufRange (args->out_buf, 1)); + + size_t unit_bytes = 4 * sizeof (uint32_t); + uint32_t in_img_width = XCAM_ALIGN_UP (in_desc.aligned_width, unit_bytes) / unit_bytes; + uint32_t in_x_offset = XCAM_ALIGN_UP (in_area.pos_x, unit_bytes) / unit_bytes; + uint32_t out_img_width = XCAM_ALIGN_UP (out_desc.aligned_width, unit_bytes) / unit_bytes; + uint32_t out_x_offset = XCAM_ALIGN_UP (out_area.pos_x, unit_bytes) / unit_bytes; + uint32_t copy_width = XCAM_ALIGN_UP (in_area.width, unit_bytes) / unit_bytes; + uint32_t copy_height = XCAM_ALIGN_UP (in_area.height, 2) / 2 * 3; + + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_x_offset", in_x_offset)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_width", out_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_x_offset", out_x_offset)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("copy_width", copy_width)); + + GLGroupsSize groups_size; + groups_size.x = XCAM_ALIGN_UP (copy_width, 8) / 8; + groups_size.y = XCAM_ALIGN_UP (copy_height, 8) / 8; + groups_size.z = 1; + + SmartPtr<GLComputeProgram> prog; + XCAM_FAIL_RETURN ( + ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM, + "GLCopyShader(%s) get compute program (idx:%d) failed", XCAM_STR (get_name ()), args->index); + prog->set_groups_size (groups_size); + + return XCAM_RETURN_NO_ERROR; +} + +GLCopyHandler::GLCopyHandler (const char *name) + : GLImageHandler (name) + , _index (INVALID_INDEX) +{ +} + +GLCopyHandler::~GLCopyHandler () +{ +} + +XCamReturn +GLCopyHandler::copy (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf) +{ + SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in_buf, out_buf); + XCAM_ASSERT (param.ptr ()); + + XCamReturn ret = execute_buffer (param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GLCopyHandler(%s) copy failed", XCAM_STR (get_name ())); + + _copy_shader->finish (); + if (!out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +bool +GLCopyHandler::set_copy_area (uint32_t idx, const Rect &in_area, const Rect &out_area) +{ + XCAM_FAIL_RETURN ( + ERROR, + idx != INVALID_INDEX && + in_area.width == out_area.width && in_area.height == out_area.height, + false, + "GLCopyHandler(%s): set copy area(idx:%d) failed, input size:%dx%d output size:%dx%d", + XCAM_STR (get_name ()), idx, in_area.width, in_area.height, out_area.width, out_area.height); + + _index = idx; + _in_area = in_area; + _out_area = out_area; + + XCAM_LOG_DEBUG ("GLCopyHandler: copy area (idx:%d) input area(%d, %d, %d, %d) output area(%d, %d, %d, %d)", + idx, + in_area.pos_x, in_area.pos_y, in_area.width, in_area.height, + out_area.pos_x, out_area.pos_y, out_area.width, out_area.height); + + return true; +} + +XCamReturn +GLCopyHandler::configure_resource (const SmartPtr<Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr ()); + XCAM_ASSERT (!_copy_shader.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, + _index != INVALID_INDEX && + _in_area.width && _in_area.height && _out_area.width && _out_area.height, + XCAM_RETURN_ERROR_PARAM, + "GLCopyHandler(%s) invalid copy area, need set copy area first", XCAM_STR (get_name ())); + + _copy_shader = create_copy_shader (); + XCAM_FAIL_RETURN ( + ERROR, _copy_shader.ptr (), XCAM_RETURN_ERROR_PARAM, + "GLCopyHandler(%s) create copy shader (idx:%d) failed", XCAM_STR (get_name ()), _index); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLCopyHandler::start_work (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ()); + + XCamReturn ret = start_copy_shader (param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GLCopyHandler(%s) start work (idx:%d) failed", XCAM_STR (get_name ()), _index); + + param->in_buf.release (); + + return ret; +}; + +XCamReturn +GLCopyHandler::terminate () +{ + if (_copy_shader.ptr ()) { + _copy_shader.release (); + } + return GLImageHandler::terminate (); +} + +SmartPtr<GLCopyShader> +GLCopyHandler::create_copy_shader () +{ + SmartPtr<Worker::Callback> cb = new CbCopyShader (this); + XCAM_ASSERT (cb.ptr ()); + + SmartPtr<GLCopyShader> shader = new GLCopyShader (cb); + XCAM_ASSERT (shader.ptr ()); + + XCamReturn ret = shader->create_compute_program (shader_info, "copy_program"); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, NULL, + "GLCopyHandler(%s) create compute program failed", XCAM_STR (get_name ())); + + return shader; +} + +XCamReturn +GLCopyHandler::start_copy_shader (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ()); + XCAM_ASSERT (_copy_shader.ptr ()); + + SmartPtr<GLCopyShader::Args> args = new GLCopyShader::Args (param); + XCAM_ASSERT (args.ptr ()); + args->in_buf = get_glbuffer (param->in_buf); + args->out_buf = get_glbuffer (param->out_buf); + args->index = _index; + args->in_area = _in_area; + args->out_area = _out_area; + + return _copy_shader->work (args); +} + +void +GLCopyHandler::copy_shader_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_ASSERT (worker.ptr () == _copy_shader.ptr ()); + + SmartPtr<GLCopyShader::Args> args = base.dynamic_cast_ptr<GLCopyShader::Args> (); + XCAM_ASSERT (args.ptr ()); + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); +} + +} diff --git a/modules/gles/gl_copy_handler.h b/modules/gles/gl_copy_handler.h new file mode 100644 index 0000000..9235cfb --- /dev/null +++ b/modules/gles/gl_copy_handler.h @@ -0,0 +1,93 @@ +/* + * gl_copy_handler.h - gl copy handler class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_COPY_HANDER_H +#define XCAM_GL_COPY_HANDER_H + +#include <xcam_utils.h> +#include <gles/gl_image_shader.h> +#include <gles/gl_image_handler.h> + +namespace XCam { + +class GLCopyShader + : public GLImageShader +{ +public: + struct Args : GLArgs { + uint32_t index; + Rect in_area, out_area; + SmartPtr<GLBuffer> in_buf, out_buf; + + Args (const SmartPtr<ImageHandler::Parameters> ¶m) + : GLArgs (param) + , index (0) + {} + }; + +public: + explicit GLCopyShader (const SmartPtr<Worker::Callback> &cb) + : GLImageShader ("GLCopyShader", cb) + {} + + ~GLCopyShader () {} + +private: + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); +}; + +class GLCopyHandler + : public GLImageHandler +{ + friend class CbCopyShader; + +public: + GLCopyHandler (const char *name = "GLCopyHandler"); + ~GLCopyHandler (); + + bool set_copy_area (uint32_t idx, const Rect &in_area, const Rect &out_area); + uint32_t get_index () { + return _index; + } + XCamReturn copy (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf); + + //derived from ImageHandler + virtual XCamReturn terminate (); + +protected: + //derived from GLImageHandler + virtual XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + virtual XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + SmartPtr<GLCopyShader> create_copy_shader (); + XCamReturn start_copy_shader (const SmartPtr<ImageHandler::Parameters> ¶m); + void copy_shader_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &args, const XCamReturn error); + +private: + uint32_t _index; + Rect _in_area; + Rect _out_area; + SmartPtr<GLCopyShader> _copy_shader; +}; + +} +#endif // XCAM_GL_COPY_HANDER_H diff --git a/modules/gles/gl_geomap_handler.cpp b/modules/gles/gl_geomap_handler.cpp new file mode 100644 index 0000000..67a06de --- /dev/null +++ b/modules/gles/gl_geomap_handler.cpp @@ -0,0 +1,403 @@ +/* + * gl_geomap_handler.cpp - gl geometry map handler implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_geomap_handler.h" +#include "gl_utils.h" + +#define XCAM_GL_GEOMAP_ALIGN_X 4 +#define XCAM_GL_GEOMAP_ALIGN_Y 2 + +namespace XCam { + +DECLARE_WORK_CALLBACK (CbGeoMapShader, GLGeoMapHandler, geomap_shader_done); + +const GLShaderInfo shader_info = { + GL_COMPUTE_SHADER, + "shader_geomap", +#include "shader_geomap.comp.slx" + , 0 +}; + +bool +GLGeoMapShader::set_std_step (float factor_x, float factor_y) +{ + XCAM_FAIL_RETURN ( + ERROR, !XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f), false, + "GLGeoMapShader(%s) invalid standard factors: x:%f, y:%f", XCAM_STR (get_name ()), factor_x, factor_y); + + _lut_std_step[0] = 1.0f / factor_x; + _lut_std_step[1] = 1.0f / factor_y; + + return true; +} + +XCamReturn +GLGeoMapShader::prepare_arguments (const SmartPtr<Worker::Arguments> &base, GLCmdList &cmds) +{ + SmartPtr<GLGeoMapShader::Args> args = base.dynamic_cast_ptr<GLGeoMapShader::Args> (); + XCAM_ASSERT (args.ptr () && args->in_buf.ptr () && args->out_buf.ptr () && args->lut_buf.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, + !XCAM_DOUBLE_EQUAL_AROUND (args->factors[0], 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (args->factors[1], 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (args->factors[2], 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (args->factors[3], 0.0f), + XCAM_RETURN_ERROR_PARAM, + "GLGeoMapHandler(%s) invalid factors: %f, %f, %f, %f", + XCAM_STR (get_name ()), args->factors[0], args->factors[1], args->factors[2], args->factors[3]); + + const GLBufferDesc &in_desc = args->in_buf->get_buffer_desc (); + const GLBufferDesc &out_desc = args->out_buf->get_buffer_desc (); + const GLBufferDesc &lut_desc = args->lut_buf->get_buffer_desc (); + + cmds.push_back (new GLCmdBindBufRange (args->in_buf, 0, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->in_buf, 1, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_buf, 2, NV12PlaneYIdx)); + cmds.push_back (new GLCmdBindBufRange (args->out_buf, 3, NV12PlaneUVIdx)); + cmds.push_back (new GLCmdBindBufBase (args->lut_buf, 4)); + + size_t unit_bytes = sizeof (uint32_t); + uint32_t in_img_width = XCAM_ALIGN_UP (in_desc.width, unit_bytes) / unit_bytes; + uint32_t out_img_width = XCAM_ALIGN_UP (out_desc.width, unit_bytes) / unit_bytes; + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_width", in_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("in_img_height", in_desc.height)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_width", out_img_width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("out_img_height", out_desc.height)); + + cmds.push_back (new GLCmdUniformT<uint32_t> ("lut_width", lut_desc.width)); + cmds.push_back (new GLCmdUniformT<uint32_t> ("lut_height", lut_desc.height)); + + float lut_step[4]; + lut_step[0] = 1.0f / args->factors[0]; + lut_step[1] = 1.0f / args->factors[1]; + lut_step[2] = 1.0f / args->factors[2]; + lut_step[3] = 1.0f / args->factors[3]; + cmds.push_back (new GLCmdUniformTVect<float, 4> ("lut_step", lut_step)); + cmds.push_back (new GLCmdUniformTVect<float, 2> ("lut_std_step", _lut_std_step)); + + GLGroupsSize groups_size; + groups_size.x = XCAM_ALIGN_UP (out_img_width, 8) / 8; + groups_size.y = XCAM_ALIGN_UP (out_desc.height, 16) / 16; + groups_size.z = 1; + + SmartPtr<GLComputeProgram> prog; + XCAM_FAIL_RETURN ( + ERROR, get_compute_program (prog), XCAM_RETURN_ERROR_PARAM, + "GLGeoMapShader(%s) get compute program failed", XCAM_STR (get_name ())); + prog->set_groups_size (groups_size); + + return XCAM_RETURN_NO_ERROR; +} + +GLGeoMapHandler::GLGeoMapHandler (const char *name) + : GLImageHandler (name) +{ +} + +GLGeoMapHandler::~GLGeoMapHandler () +{ +} + +XCamReturn +GLGeoMapHandler::remap (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf) +{ + SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in_buf, out_buf); + XCAM_ASSERT (param.ptr ()); + + XCamReturn ret = execute_buffer (param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GLGeoMapHandler(%s) remap failed", XCAM_STR (get_name ())); + + _geomap_shader->finish (); + if (!out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +bool +GLGeoMapHandler::set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height) +{ + XCAM_FAIL_RETURN ( + ERROR, data && width && height, false, + "GLGeoMapHandler(%s) set look up table failed, data ptr:%p, width:%d, height:%d", + XCAM_STR (get_name ()), data, width, height); + XCAM_ASSERT (!_lut_buf.ptr ()); + + uint32_t lut_size = width * height * 2 * sizeof (float); + SmartPtr<GLBuffer> buf = GLBuffer::create_buffer (GL_SHADER_STORAGE_BUFFER, NULL, lut_size); + XCAM_ASSERT (buf.ptr ()); + + GLBufferDesc desc; + desc.width = width; + desc.height = height; + desc.size = lut_size; + buf->set_buffer_desc (desc); + + float *ptr = (float *) buf->map_range (0, lut_size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + XCAM_FAIL_RETURN (ERROR, ptr, false, "GLGeoMapHandler(%s) map range failed", XCAM_STR (get_name ())); + for (uint32_t i = 0; i < height; ++i) { + float *ret = &ptr[i * width * 2]; + const PointFloat2 *line = &data[i * width]; + + for (uint32_t j = 0; j < width; ++j) { + ret[j * 2] = line[j].x; + ret[j * 2 + 1] = line[j].y; + } + } + buf->unmap (); + _lut_buf = buf; + + return true; +} + +bool +GLGeoMapHandler::init_factors () +{ + float factor_x, factor_y; + get_factors (factor_x, factor_y); + + if (!XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f)) + return true; + + const GLBufferDesc &lut_desc = _lut_buf->get_buffer_desc (); + return auto_calculate_factors (lut_desc.width, lut_desc.height); +} + +XCamReturn +GLGeoMapHandler::configure_resource (const SmartPtr<Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, _lut_buf.ptr (), XCAM_RETURN_ERROR_PARAM, + "GLGeoMapHandler(%s) configure failed, look up table is empty", XCAM_STR (get_name ())); + + const VideoBufferInfo &in_info = param->in_buf->get_video_info (); + XCAM_FAIL_RETURN ( + ERROR, in_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM, + "GLGeoMapHandler(%s) only support NV12 format, but input format is %s", + XCAM_STR (get_name ()), xcam_fourcc_to_string (in_info.format)); + + uint32_t width, height; + get_output_size (width, height); + VideoBufferInfo out_info; + out_info.init ( + in_info.format, width, height, + XCAM_ALIGN_UP (width, XCAM_GL_GEOMAP_ALIGN_X), + XCAM_ALIGN_UP (height, XCAM_GL_GEOMAP_ALIGN_Y)); + set_out_video_info (out_info); + + init_factors (); + + XCAM_ASSERT (!_geomap_shader.ptr ()); + _geomap_shader = create_geomap_shader (); + XCAM_FAIL_RETURN ( + ERROR, _geomap_shader.ptr (), XCAM_RETURN_ERROR_PARAM, + "GLGeoMapHandler(%s) create geomap shader failed", XCAM_STR (get_name ())); + + float factor_x, factor_y; + get_factors (factor_x, factor_y); + _geomap_shader->set_std_step (factor_x, factor_y); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLGeoMapHandler::start_work (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ()); + + XCamReturn ret = start_geomap_shader (param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "GLGeoMapHandler(%s) start work failed", XCAM_STR (get_name ())); + + param->in_buf.release (); + + return ret; +}; + +XCamReturn +GLGeoMapHandler::terminate () +{ + if (_geomap_shader.ptr ()) { + _geomap_shader.release (); + } + + return GLImageHandler::terminate (); +} + +SmartPtr<GLGeoMapShader> +GLGeoMapHandler::create_geomap_shader () +{ + SmartPtr<Worker::Callback> cb = new CbGeoMapShader (this); + XCAM_ASSERT (cb.ptr ()); + SmartPtr<GLGeoMapShader> shader = new GLGeoMapShader (cb); + XCAM_ASSERT (shader.ptr ()); + + XCamReturn ret = shader->create_compute_program (shader_info, "geomap_program"); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, NULL, + "GLGeoMapHandler(%s) create compute program failed", XCAM_STR (get_name ())); + + return shader; +} + +XCamReturn +GLGeoMapHandler::start_geomap_shader (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ()); + XCAM_ASSERT (_geomap_shader.ptr ()); + XCAM_ASSERT (_lut_buf.ptr ()); + + float factor_x, factor_y; + get_factors (factor_x, factor_y); + + SmartPtr<GLGeoMapShader::Args> args = new GLGeoMapShader::Args (param); + XCAM_ASSERT (args.ptr ()); + args->in_buf = get_glbuffer (param->in_buf); + args->out_buf = get_glbuffer (param->out_buf); + args->lut_buf = _lut_buf; + args->factors[0] = factor_x; + args->factors[1] = factor_y; + args->factors[2] = args->factors[0]; + args->factors[3] = args->factors[1]; + + return _geomap_shader->work (args); +} + +void +GLGeoMapHandler::geomap_shader_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_ASSERT (worker.ptr () == _geomap_shader.ptr ()); + + SmartPtr<GLGeoMapShader::Args> args = base.dynamic_cast_ptr<GLGeoMapShader::Args> (); + XCAM_ASSERT (args.ptr ()); + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); +} + +GLDualConstGeoMapHandler::GLDualConstGeoMapHandler (const char *name) + : GLGeoMapHandler (name) + , _left_factor_x (0.0f) + , _left_factor_y (0.0f) + , _right_factor_x (0.0f) + , _right_factor_y (0.0f) +{ +} + +GLDualConstGeoMapHandler::~GLDualConstGeoMapHandler () +{ +} + +bool +GLDualConstGeoMapHandler::set_left_factors (float x, float y) +{ + XCAM_FAIL_RETURN ( + ERROR, !XCAM_DOUBLE_EQUAL_AROUND (x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (y, 0.0f), false, + "GLGeoMapHandler(%s) set factors failed: x:%f, y:%f", XCAM_STR (get_name ()), x, y); + + _left_factor_x = x; + _left_factor_y = y; + + return true; +} + +bool +GLDualConstGeoMapHandler::set_right_factors (float x, float y) +{ + XCAM_FAIL_RETURN ( + ERROR, !XCAM_DOUBLE_EQUAL_AROUND (x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (y, 0.0f), false, + "GLGeoMapHandler(%s) set factors failed: x:%f, y:%f", XCAM_STR (get_name ()), x, y); + + _right_factor_x = x; + _right_factor_y = y; + + return true; +} + +bool +GLDualConstGeoMapHandler::init_factors () +{ + float factor_x, factor_y; + get_factors (factor_x, factor_y); + + if (!XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f)) + return true; + + const GLBufferDesc &lut_desc = _lut_buf->get_buffer_desc (); + XCAM_FAIL_RETURN ( + ERROR, auto_calculate_factors (lut_desc.width, lut_desc.height), false, + "GLGeoMapHandler(%s) auto calculate factors failed"); + + get_factors (factor_x, factor_y); + _left_factor_x = factor_x; + _left_factor_y = factor_y; + _right_factor_x = _left_factor_x; + _right_factor_y = _left_factor_y; + + return true; +} + +XCamReturn +GLDualConstGeoMapHandler::start_geomap_shader (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ()); + XCAM_ASSERT (_geomap_shader.ptr ()); + XCAM_ASSERT (_lut_buf.ptr ()); + + SmartPtr<GLGeoMapShader::Args> args = new GLGeoMapShader::Args (param); + XCAM_ASSERT (args.ptr ()); + args->in_buf = get_glbuffer (param->in_buf); + args->out_buf = get_glbuffer (param->out_buf); + args->lut_buf = _lut_buf; + + float factor_x, factor_y; + get_left_factors (factor_x, factor_y); + args->factors[0] = factor_x; + args->factors[1] = factor_y; + + get_right_factors (factor_x, factor_y); + args->factors[2] = factor_x; + args->factors[3] = factor_y; + + return _geomap_shader->work (args); +} + +SmartPtr<GLImageHandler> create_gl_geo_mapper () +{ + SmartPtr<GLImageHandler> mapper = new GLGeoMapHandler (); + XCAM_ASSERT (mapper.ptr ()); + + return mapper; +} + +SmartPtr<GeoMapper> +GeoMapper::create_gl_geo_mapper () +{ + SmartPtr<GLImageHandler> handler = XCam::create_gl_geo_mapper (); + return handler.dynamic_cast_ptr<GeoMapper> (); +} + +} diff --git a/modules/gles/gl_geomap_handler.h b/modules/gles/gl_geomap_handler.h new file mode 100644 index 0000000..30ee221 --- /dev/null +++ b/modules/gles/gl_geomap_handler.h @@ -0,0 +1,130 @@ +/* + * gl_geomap_handler.h - gl geometry map handler class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_GEOMAP_HANDER_H +#define XCAM_GL_GEOMAP_HANDER_H + +#include <interface/geo_mapper.h> +#include <gles/gl_image_shader.h> +#include <gles/gl_image_handler.h> + +namespace XCam { + +class GLGeoMapShader + : public GLImageShader +{ +public: + struct Args : GLArgs { + SmartPtr<GLBuffer> in_buf, out_buf; + SmartPtr<GLBuffer> lut_buf; + float factors[4]; + + Args (const SmartPtr<ImageHandler::Parameters> ¶m) + : GLArgs (param) + {} + }; + +public: + explicit GLGeoMapShader (const SmartPtr<Worker::Callback> &cb) + : GLImageShader ("GLGeoMapShader", cb) + { + xcam_mem_clear (_lut_std_step); + } + + ~GLGeoMapShader () {} + bool set_std_step (float factor_x, float factor_y); + +private: + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); + XCAM_DEAD_COPY (GLGeoMapShader); + +private: + float _lut_std_step[2]; +}; + +class GLGeoMapHandler + : public GLImageHandler, public GeoMapper +{ + friend class CbGeoMapShader; + +public: + GLGeoMapHandler (const char *name = "GLGeoMapHandler"); + ~GLGeoMapHandler (); + + bool set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height); + + XCamReturn remap (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf); + + //derived from ImageHandler + virtual XCamReturn terminate (); + +protected: + //derived from GLImageHandler + virtual XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + virtual XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + virtual bool init_factors (); + + virtual SmartPtr<GLGeoMapShader> create_geomap_shader (); + virtual XCamReturn start_geomap_shader (const SmartPtr<ImageHandler::Parameters> ¶m); + virtual void geomap_shader_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &args, const XCamReturn error); + + XCAM_DEAD_COPY (GLGeoMapHandler); + +protected: + SmartPtr<GLBuffer> _lut_buf; + SmartPtr<GLGeoMapShader> _geomap_shader; +}; + +class GLDualConstGeoMapHandler + : public GLGeoMapHandler +{ +public: + GLDualConstGeoMapHandler (const char *name = "GLDualConstGeoMapHandler"); + ~GLDualConstGeoMapHandler (); + + bool set_left_factors (float x, float y); + void get_left_factors (float &x, float &y) { + x = _left_factor_x; + y = _left_factor_y; + } + bool set_right_factors (float x, float y); + void get_right_factors (float &x, float &y) { + x = _right_factor_x; + y = _right_factor_y; + } + +private: + virtual bool init_factors (); + virtual XCamReturn start_geomap_shader (const SmartPtr<ImageHandler::Parameters> ¶m); + +private: + float _left_factor_x; + float _left_factor_y; + float _right_factor_x; + float _right_factor_y; +}; + +extern SmartPtr<GLImageHandler> create_gl_geo_mapper (); + +} +#endif // XCAM_GL_GEOMAP_HANDER_H diff --git a/modules/gles/gl_image_handler.cpp b/modules/gles/gl_image_handler.cpp new file mode 100644 index 0000000..d95b151 --- /dev/null +++ b/modules/gles/gl_image_handler.cpp @@ -0,0 +1,41 @@ +/* + * gl_image_handler.cpp - GL image handler implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_image_handler.h" +#include "gl_video_buffer.h" + +namespace XCam { + +GLImageHandler::GLImageHandler (const char* name) + : ImageHandler (name) +{ +} + +GLImageHandler::~GLImageHandler () +{ +} + +SmartPtr<BufferPool> +GLImageHandler::create_allocator () +{ + return new GLVideoBufferPool; +} + +} diff --git a/modules/gles/gl_image_handler.h b/modules/gles/gl_image_handler.h new file mode 100644 index 0000000..db5ee54 --- /dev/null +++ b/modules/gles/gl_image_handler.h @@ -0,0 +1,47 @@ +/* + * gl_image_handler.h - GL image handler class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_IMAGE_HANDLER_H +#define XCAM_GL_IMAGE_HANDLER_H + +#include <image_handler.h> +#include <gles/gles_std.h> + +namespace XCam { + +class GLImageHandler + : public ImageHandler +{ +public: + explicit GLImageHandler (const char* name); + ~GLImageHandler (); + +private: + SmartPtr<BufferPool> create_allocator (); + +private: + XCAM_DEAD_COPY (GLImageHandler); + +private: +}; + +} + +#endif // XCAM_GL_IMAGE_HANDLER_H diff --git a/modules/gles/gl_image_shader.cpp b/modules/gles/gl_image_shader.cpp new file mode 100644 index 0000000..3b1a92f --- /dev/null +++ b/modules/gles/gl_image_shader.cpp @@ -0,0 +1,191 @@ +/* + * gl_image_shader.cpp - gl image shader implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_image_shader.h" + +#define ENABLE_DEBUG_SHADER 0 + +namespace XCam { + +GLImageShader::GLImageShader (const char *name, const SmartPtr<Callback> &cb) + : Worker (name, cb) +{ + XCAM_OBJ_PROFILING_INIT; +} + +GLImageShader::~GLImageShader () +{ +} + +XCamReturn +GLImageShader::finish () +{ + _program->finish (); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLImageShader::stop () +{ + return XCAM_RETURN_NO_ERROR; +} + +bool +GLImageShader::get_compute_program (SmartPtr<GLComputeProgram> &prog) +{ + prog = _program.dynamic_cast_ptr<GLComputeProgram> (); + XCAM_FAIL_RETURN ( + ERROR, prog.ptr (), false, + "GLImageShader(%s) convert to GLComputeProgram failed", XCAM_STR (get_name ())); + + return true; +} + +XCamReturn +GLImageShader::work (const SmartPtr<Worker::Arguments> &args) +{ + XCamReturn ret = _program->use (); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) use program failed", XCAM_STR (get_name ())); + + ret = pre_work (args); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) pre-work failed", XCAM_STR (get_name ())); + +#if ENABLE_DEBUG_SHADER + XCAM_OBJ_PROFILING_START; +#endif + + ret = _program->work (); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) work failed", XCAM_STR (get_name ())); + +#if ENABLE_DEBUG_SHADER + ret = _program->finish (); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) finish failed", XCAM_STR (get_name ())); + + char name[XCAM_GL_NAME_LENGTH] = {'\0'}; + snprintf (name, sizeof (name), "%s-%p", XCAM_STR (get_name ()), this); + XCAM_OBJ_PROFILING_END (name, XCAM_OBJ_DUR_FRAME_NUM); +#endif + + ret = _program->disuse (); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) disuse program failed", XCAM_STR (get_name ())); + + status_check (args, ret); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLImageShader::pre_work (const SmartPtr<Worker::Arguments> &args) +{ + GLCmdList cmds; + + XCamReturn ret = prepare_arguments (args, cmds); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) prepare arguments failed", XCAM_STR (get_name ())); + + ret = set_commands (cmds); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) set commands failed", XCAM_STR (get_name ())); + + return ret; +} +XCamReturn +GLImageShader::prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds) +{ + XCAM_UNUSED (args); + XCAM_UNUSED (cmds); + + XCAM_LOG_ERROR ("GLImageShader(%s) prepare arguments error", XCAM_STR (get_name ())); + return XCAM_RETURN_ERROR_GLES; +} + +XCamReturn +GLImageShader::set_commands (const GLCmdList &cmds) +{ + GLuint prog_id = _program->get_program_id(); + XCAM_FAIL_RETURN ( + WARNING, prog_id, XCAM_RETURN_ERROR_PARAM, + "GLImageShader(%s) invalid program id:%d", XCAM_STR (get_name ()), prog_id); + + uint32_t i_count = 0; + for (GLCmdList::const_iterator iter = cmds.begin (); iter != cmds.end (); ++iter, ++i_count) { + const SmartPtr<GLCommand> &cmd = *iter; + XCAM_FAIL_RETURN ( + WARNING, cmd.ptr (), XCAM_RETURN_ERROR_MEM, + "GLImageShader(%s) command(idx:%d) is NULL", XCAM_STR (get_name ()), i_count); + + XCamReturn ret = cmd->run (prog_id); + XCAM_FAIL_RETURN ( + WARNING, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) command(idx:%d) run failed", XCAM_STR (get_name ())); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLImageShader::create_compute_program (const GLShaderInfo &info, const char *name) +{ + SmartPtr<GLComputeProgram> program = GLComputeProgram::create_compute_program (name); + XCAM_FAIL_RETURN ( + ERROR, program.ptr (), XCAM_RETURN_ERROR_GLES, + "GLImageShader(%s) create compute program(%s) failed", XCAM_STR (get_name ()), XCAM_STR (name)); + + XCamReturn ret = program->link_shader (info); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) program(%s) pour shader failed", XCAM_STR (get_name ()), XCAM_STR (name)); + + _program = program; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLImageShader::create_compute_program (const GLShaderInfoList &infos, const char *name) +{ + SmartPtr<GLComputeProgram> program = GLComputeProgram::create_compute_program (name); + XCAM_FAIL_RETURN ( + ERROR, program.ptr (), XCAM_RETURN_ERROR_GLES, + "GLImageShader(%s) create compute program(%s) failed", XCAM_STR (get_name ()), XCAM_STR (name)); + + XCamReturn ret = program->link_shaders (infos); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLImageShader(%s) program(%s) pour shaders failed", XCAM_STR (get_name ()), XCAM_STR (name)); + + _program = program; + + return XCAM_RETURN_NO_ERROR; +} + +}; diff --git a/modules/gles/gl_image_shader.h b/modules/gles/gl_image_shader.h new file mode 100644 index 0000000..47666d3 --- /dev/null +++ b/modules/gles/gl_image_shader.h @@ -0,0 +1,81 @@ +/* + * gl_image_shader.h - gl image shader class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_IMAGE_SHADER_H +#define XCAM_GL_IMAGE_SHADER_H + +#include <worker.h> +#include <image_handler.h> +#include <gles/gles_std.h> +#include <gles/gl_command.h> +#include <gles/gl_compute_program.h> + +namespace XCam { + +struct GLArgs + : Worker::Arguments +{ +private: + SmartPtr<ImageHandler::Parameters> _param; + +public: + explicit GLArgs (const SmartPtr<ImageHandler::Parameters> ¶m = NULL) : _param (param) {} + inline const SmartPtr<ImageHandler::Parameters> &get_param () const { + return _param; + } + inline void set_param (const SmartPtr<ImageHandler::Parameters> ¶m) { + XCAM_ASSERT (param.ptr ()); + _param = param; + } +}; + +class GLImageShader + : public Worker +{ +public: + explicit GLImageShader (const char *name, const SmartPtr<Callback> &cb = NULL); + virtual ~GLImageShader (); + + XCamReturn set_commands (const GLCmdList &cmds); + bool get_compute_program (SmartPtr<GLComputeProgram> &prog); + + // derived from Worker + virtual XCamReturn work (const SmartPtr<Arguments> &args); + virtual XCamReturn finish (); + virtual XCamReturn stop (); + + XCamReturn create_compute_program (const GLShaderInfo &info, const char *name = NULL); + XCamReturn create_compute_program (const GLShaderInfoList &infos, const char *name = NULL); + +private: + XCamReturn pre_work (const SmartPtr<Worker::Arguments> &args); + virtual XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, GLCmdList &cmds); + +private: + XCAM_DEAD_COPY (GLImageShader); + +private: + SmartPtr<GLProgram> _program; + + XCAM_OBJ_PROFILING_DEFINES; +}; + +} +#endif // XCAM_GL_IMAGE_SHADER_H diff --git a/modules/gles/gl_program.cpp b/modules/gles/gl_program.cpp new file mode 100644 index 0000000..f6b9166 --- /dev/null +++ b/modules/gles/gl_program.cpp @@ -0,0 +1,247 @@ +/* + * gl_program.cpp - GL Program + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "gl_program.h" + +namespace XCam { + +GLProgram::GLProgram (GLuint id, const char *name) + : _program_id (id) + , _state (GLProgram::StateIntiated) +{ + strncpy (_name, XCAM_STR (name), XCAM_GL_NAME_LENGTH - 1); +} + +GLProgram::~GLProgram () +{ + disuse (); + clear_shaders (); + if (_program_id) { + glDeleteProgram (_program_id); + + GLenum error = gl_error (); + if (error != GL_NO_ERROR) { + XCAM_LOG_WARNING ( + "GL Program delete program failed, error flag: %s", + gl_error_string (error)); + } + } +} + +SmartPtr<GLProgram> +GLProgram::create_program (const char *name) +{ + GLuint program_id = glCreateProgram (); + XCAM_FAIL_RETURN ( + ERROR, program_id, NULL, + "Create GL program(%s) failed, error flag: %s", + XCAM_STR (name), gl_error_string (gl_error ())); + + return new GLProgram (program_id, name ? name : "null"); +} + +XCamReturn +GLProgram::attach_shader (const SmartPtr<GLShader> &shader) +{ + GLuint shader_id = shader->get_shader_id (); + XCAM_ASSERT (shader_id); + XCAM_FAIL_RETURN ( + ERROR, _shaders.find (shader_id) == _shaders.end (), + XCAM_RETURN_ERROR_PARAM, + "GL program(:%s) already have shader (id:%d), do not attach twice", + get_name(), shader_id); + + glAttachShader (_program_id, shader_id); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GL program(:%s) attach shader (id:%d) failed, error flag: %s", + get_name(), shader_id, gl_error_string (error)); + + _shaders.insert (ShaderList::value_type (shader_id, shader)); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::detach_shader (const SmartPtr<GLShader> &shader) +{ + GLuint shader_id = shader->get_shader_id (); + XCAM_ASSERT (shader_id); + ShaderList::iterator pos = _shaders.find (shader_id); + + XCAM_FAIL_RETURN ( + WARNING, pos == _shaders.end (), + XCAM_RETURN_ERROR_PARAM, + "GL program(:%s) do not need to detach shader (id:%d) which is not exist", + get_name(), shader_id); + + glDetachShader (_program_id, shader_id); + GLenum error = gl_error (); + if (error != GL_NO_ERROR) { + XCAM_LOG_WARNING ( + "GL program(:%s) detach shader (id:%d) failed but continued, error flag: %s", + get_name(), shader_id, gl_error_string (error)); + } + _shaders.erase (pos); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::clear_shaders () +{ + for (ShaderList::iterator i = _shaders.begin (); i != _shaders.end (); ++i) { + SmartPtr<GLShader> shader = i->second; + glDetachShader (_program_id, shader->get_shader_id ()); + + GLenum error = gl_error (); + if (error != GL_NO_ERROR) { + XCAM_LOG_WARNING ( + "GL program(:%s) detach shader (id:%d) failed, error flag: %s", + get_name(), shader->get_shader_id (), gl_error_string (error)); + } + } + _shaders.clear (); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::link () +{ + XCAM_ASSERT (_program_id); + + glLinkProgram (_program_id); + GLenum error = gl_error (); + + GLint status; + std::vector<char> link_log; + glGetProgramiv (_program_id, GL_LINK_STATUS, &status); + if(status == GL_FALSE) { + GLint length; + glGetProgramiv (_program_id, GL_INFO_LOG_LENGTH, &length); + link_log.resize (length + 1); + glGetProgramInfoLog (_program_id, length, &length, &link_log[0]); + XCAM_LOG_ERROR( + "GL program(:%s) link failed, error flag: %s, link log:%s", + get_name(), gl_error_string (error), link_log.data()); + return XCAM_RETURN_ERROR_GLES; + } + + _state = StateLinked; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::use () +{ + XCAM_ASSERT (_program_id); + XCAM_FAIL_RETURN ( + WARNING, _state == StateLinked && !_shaders.empty (), XCAM_RETURN_ERROR_PARAM, + "GL program(:%s) use must be called after link", get_name()); + + glUseProgram (_program_id); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, error == GL_NO_ERROR, XCAM_RETURN_ERROR_GLES, + "GL program(:%s) use failed, error flag: %s", + get_name(), gl_error_string (error)); + + _state = StateInUse; + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::disuse () +{ + if (_state != StateInUse) + return XCAM_RETURN_BYPASS; + + glUseProgram (0); + GLenum error = gl_error (); + if (error != GL_NO_ERROR) { + XCAM_LOG_WARNING ( + "GL program(:%s) disuse failed, error flag: %s", + get_name(), gl_error_string (error)); + } + + _state = StateLinked; + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::link_shader (const GLShaderInfo &info) +{ + SmartPtr<GLShader> shader = GLShader::compile_shader (info); + XCAM_FAIL_RETURN ( + ERROR, shader->get_shader_id (), XCAM_RETURN_ERROR_GLES, + "GLProgram(%s) create shader(%s) failed", get_name (), info.name); + + XCamReturn ret = attach_shader (shader); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLProgram(%s) attach shader(%s) failed", get_name (), info.name); + + ret = link (); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLProgram(%s) link program failed", get_name ()); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::link_shaders (const GLShaderInfoList &infos) +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + for (GLShaderInfoList::const_iterator iter = infos.begin (); iter != infos.end (); ++iter) { + const GLShaderInfo &info = *(*iter); + + SmartPtr<GLShader> shader = GLShader::compile_shader (info); + XCAM_FAIL_RETURN ( + ERROR, shader->get_shader_id (), XCAM_RETURN_ERROR_GLES, + "GLProgram(%s) create shader(%s) failed", get_name (), info.name); + + ret = attach_shader (shader); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLProgram(%s) attach shader(%s) failed", get_name (), info.name); + } + + ret = link (); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, + "GLProgram(%s) link program(%s) failed", get_name ()); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::work () +{ + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GLProgram::finish () +{ + return XCAM_RETURN_NO_ERROR; +} + +} diff --git a/modules/gles/gl_program.h b/modules/gles/gl_program.h new file mode 100644 index 0000000..39090c7 --- /dev/null +++ b/modules/gles/gl_program.h @@ -0,0 +1,79 @@ +/* + * gl_program.h - GL Program + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_GL_PROGRAM_H +#define XCAM_GL_PROGRAM_H + +#include <gles/gles_std.h> +#include <gles/gl_shader.h> +#include <map> + +namespace XCam { + +class GLProgram +{ +public: + typedef std::map<GLuint, SmartPtr<GLShader>> ShaderList; + enum State { + StateIntiated = 0, + StateLinked = 2, + StateInUse = 3, + }; + + virtual ~GLProgram (); + static SmartPtr<GLProgram> create_program (const char *name = NULL); + GLuint get_program_id () const { + return _program_id; + } + const char *get_name () { + return _name; + } + + XCamReturn link_shader (const GLShaderInfo &info); + XCamReturn link_shaders (const GLShaderInfoList &infos); + + XCamReturn use (); + XCamReturn disuse (); + + virtual XCamReturn work (); + virtual XCamReturn finish (); + +protected: + explicit GLProgram (GLuint id, const char *name); + +private: + XCamReturn attach_shader (const SmartPtr<GLShader> &shader); + XCamReturn detach_shader (const SmartPtr<GLShader> &shader); + XCamReturn clear_shaders (); + XCamReturn link (); + +private: + XCAM_DEAD_COPY (GLProgram); + +private: + ShaderList _shaders; + GLuint _program_id; + State _state; + char _name [XCAM_GL_NAME_LENGTH]; +}; + +} + +#endif //XCAM_GL_PROGRAM_H diff --git a/modules/gles/gl_shader.cpp b/modules/gles/gl_shader.cpp new file mode 100644 index 0000000..1810c70 --- /dev/null +++ b/modules/gles/gl_shader.cpp @@ -0,0 +1,86 @@ +/* + * gl_shader.cpp - GL shader + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "gl_shader.h" + +namespace XCam { + +GLShader::GLShader (GLuint id, GLenum type, const char *name) + : _shader_type (type) + , _shader_id (id) +{ + XCAM_ASSERT (name); + strncpy (_name, name, XCAM_GL_NAME_LENGTH - 1); +} + +GLShader::~GLShader () +{ + if (_shader_id) { + glDeleteShader (_shader_id); + + GLenum error = gl_error (); + if (error != GL_NO_ERROR) { + XCAM_LOG_WARNING ( + "GL Shader delete shader failed, error flag: %s", + gl_error_string (error)); + } + } +} + +SmartPtr<GLShader> +GLShader::compile_shader (const GLShaderInfo &info) +{ + GLuint shader_id = glCreateShader (info.type); + GLenum error = gl_error (); + XCAM_FAIL_RETURN ( + ERROR, shader_id && (error == GL_NO_ERROR), NULL, + "GL create shader(:%s) failed, error flag: %s", + XCAM_STR (info.name), gl_error_string (error)); + + GLint tmp_len = info.len ? info.len : strlen (info.src); + glShaderSource (shader_id, 1, &info.src, &tmp_len); + XCAM_FAIL_RETURN ( + ERROR, (error = gl_error ()) == GL_NO_ERROR, NULL, + "GL create shader(:%s) failed in source loading, error flag: %s", + XCAM_STR (info.name), gl_error_string (error)); + + glCompileShader (shader_id); + error = gl_error (); + + GLint status; + glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLint length; + std::vector<char> compile_log; + glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &length); + compile_log.resize (length + 1); + glGetShaderInfoLog (shader_id, length, &length, &compile_log[0]); + XCAM_LOG_ERROR ( + "GL create sharder(:%s) compile failed, error flag: %s, log: %s", + XCAM_STR (info.name), gl_error_string (error), compile_log.data()); + return NULL; + } + + SmartPtr<GLShader> shader = + new GLShader (shader_id, info.type, (info.name ? info.name : "null")); + return shader; +} + +} diff --git a/modules/gles/gl_shader.h b/modules/gles/gl_shader.h new file mode 100644 index 0000000..b379c44 --- /dev/null +++ b/modules/gles/gl_shader.h @@ -0,0 +1,78 @@ +/* + * gl_shader.h - GL shader + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_GL_SHADER_H +#define XCAM_GL_SHADER_H + +#include <gles/gles_std.h> +#include <list> +#include <map> + +namespace XCam { + +XCAM_BEGIN_DECLARE + +typedef struct _GLShaderInfo { + GLenum type; + const GLchar *name; + const GLchar *src; + GLint len; +} GLShaderInfo; + +XCAM_END_DECLARE + +typedef std::list<const GLShaderInfo *> GLShaderInfoList; + +class GLShader +{ +public: + ~GLShader (); + static SmartPtr<GLShader> compile_shader (const GLShaderInfo &info); + +#if 0 + static SmartPtr<GLShader> create_binary_shader ( + GLenum format, const uint8_t *binary, uint32_t length, const char *name = NULL); +#endif + + GLuint get_shader_id () const { + return _shader_id; + } + const char *get_name () const { + return _name; + } + GLenum get_type () const { + return _shader_type; + } + +private: + explicit GLShader (GLuint id, GLenum type, const char *name); + +private: + XCAM_DEAD_COPY (GLShader); + +private: + GLenum _shader_type; + GLuint _shader_id; + char _name [XCAM_GL_NAME_LENGTH]; +}; + +} + +#endif //XCAM_GL_SHADER_H diff --git a/modules/gles/gl_stitcher.cpp b/modules/gles/gl_stitcher.cpp new file mode 100644 index 0000000..ff357ce --- /dev/null +++ b/modules/gles/gl_stitcher.cpp @@ -0,0 +1,894 @@ +/* + * gl_stitcher.cpp - GL stitcher implementation + * + * 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: Wind Yuan <feng.yuan@intel.com> + * Author: Yinhang Liu <yinhangx.liu@intel.com> + */ + +#include "surview_fisheye_dewarp.h" +#include "gl_video_buffer.h" +#include "gl_geomap_handler.h" +#include "gl_blender.h" +#include "gl_copy_handler.h" +#include "gl_stitcher.h" +#include "interface/feature_match.h" + +#define GL_STITCHER_ALIGNMENT_X 16 +#define GL_STITCHER_ALIGNMENT_Y 4 + +#define MAP_FACTOR_X 16 +#define MAP_FACTOR_Y 16 + +#define DUMP_BUFFER 0 + +namespace XCam { + +#if DUMP_BUFFER +static void +dump_buf (const SmartPtr<VideoBuffer> buf, uint32_t idx, const char *prefix) +{ + XCAM_ASSERT (buf.ptr ()); + XCAM_ASSERT (prefix); + + char name[256]; + snprintf (name, 256, "%s-%d", prefix, idx); + dump_buf_perfix_path (buf, name); +} +#else +static void +dump_buf (const SmartPtr<VideoBuffer> buf, ...) { + XCAM_UNUSED (buf); +} +#endif + +namespace GLSitcherPriv { + +DECLARE_HANDLER_CALLBACK (CbGeoMap, GLStitcher, dewarp_done); +DECLARE_HANDLER_CALLBACK (CbBlender, GLStitcher, blender_done); +DECLARE_HANDLER_CALLBACK (CbCopier, GLStitcher, copier_done); + +struct BlenderParam + : GLBlender::BlenderParam +{ + SmartPtr<GLStitcher::StitcherParam> stitch_param; + uint32_t idx; + + BlenderParam ( + uint32_t i, + const SmartPtr<VideoBuffer> &in0, + const SmartPtr<VideoBuffer> &in1, + const SmartPtr<VideoBuffer> &out) + : GLBlender::BlenderParam (in0, in1, out) + , idx (i) + {} +}; +typedef std::map<void*, SmartPtr<BlenderParam>> BlenderParams; + +struct HandlerParam + : ImageHandler::Parameters +{ + SmartPtr<GLStitcher::StitcherParam> stitch_param; + uint32_t idx; + + HandlerParam (uint32_t i) + : idx (i) + {} +}; + +struct Factor { + float x, y; + + Factor () : x (1.0f), y (1.0f) {} + void reset () { + x = 1.0f; + y = 1.0f; + } +}; + +struct Overlap { + SmartPtr<FeatureMatch> matcher; + SmartPtr<GLBlender> blender; + BlenderParams param_map; + + SmartPtr<BlenderParam> find_blender_param_in_map ( + const SmartPtr<GLStitcher::StitcherParam> &key, + const uint32_t idx); +}; + +struct FisheyeDewarp { + SmartPtr<GLGeoMapHandler> dewarp; + SmartPtr<BufferPool> buf_pool; + Factor left_match_factor; + Factor right_match_factor; + + bool set_dewarp_factor (); + XCamReturn set_dewarp_geo_table ( + const SmartPtr<GLGeoMapHandler> &mapper, const CameraInfo &cam_info, + const Stitcher::RoundViewSlice &view_slice, const BowlDataConfig &bowl); +}; + +typedef std::vector<SmartPtr<GLCopyHandler>> Copiers; + +class StitcherImpl { + friend class XCam::GLStitcher; + +public: + StitcherImpl (GLStitcher *handler) + : _stitcher (handler) + {} + + XCamReturn init_config (uint32_t count); + XCamReturn start_dewarps (const SmartPtr<GLStitcher::StitcherParam> ¶m); + XCamReturn start_blenders ( + const SmartPtr<GLStitcher::StitcherParam> ¶m, + uint32_t idx, const SmartPtr<VideoBuffer> &buf); + XCamReturn start_copier ( + const SmartPtr<GLStitcher::StitcherParam> ¶m, + uint32_t idx, const SmartPtr<VideoBuffer> &buf); + + XCamReturn start_single_blender (uint32_t idx, const SmartPtr<BlenderParam> ¶m); + XCamReturn stop (); + + XCamReturn fisheye_dewarp_to_table (); + + XCamReturn start_feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, uint32_t idx); + + const SmartPtr<GLComputeProgram> &get_sync_prog (); + +private: + SmartPtr<GLGeoMapHandler> create_geo_mapper (const Stitcher::RoundViewSlice &view_slice); + + XCamReturn init_fisheye (uint32_t idx); + bool init_dewarp_factors (uint32_t idx); + + void calc_dewarp_factors ( + uint32_t idx, const Factor &last_left_factor, const Factor &last_right_factor, + Factor &cur_left, Factor &cur_right); + + void init_feature_match (uint32_t idx); + bool get_and_reset_fm_factors (uint32_t idx, Factor &left, Factor &right); + +private: + FisheyeDewarp _fisheye[XCAM_STITCH_MAX_CAMERAS]; + Overlap _overlaps[XCAM_STITCH_MAX_CAMERAS]; + Copiers _copiers; + + GLStitcher *_stitcher; + SmartPtr<GLComputeProgram> _sync_prog; +}; + +const SmartPtr<GLComputeProgram> & +StitcherImpl::get_sync_prog () +{ + if (_sync_prog.ptr ()) + return _sync_prog; + + _sync_prog = GLComputeProgram::create_compute_program ("sync_program"); + XCAM_FAIL_RETURN ( + ERROR, _sync_prog.ptr (), _sync_prog, + "gl-stitcher(%s) create sync program failed", + XCAM_STR (_stitcher->get_name ())); + + return _sync_prog; +} + +bool +StitcherImpl::get_and_reset_fm_factors (uint32_t idx, Factor &left, Factor &right) +{ + uint32_t cam_num = _stitcher->get_camera_num (); + XCAM_FAIL_RETURN ( + ERROR, idx < cam_num, false, + "gl-stitcher(%s) invalid camera index, idx(%d) > camera_num(%d)", + XCAM_STR (_stitcher->get_name ()), idx, cam_num); + + left = _fisheye[idx].left_match_factor; + right = _fisheye[idx].right_match_factor; + + _fisheye[idx].left_match_factor.reset (); + _fisheye[idx].right_match_factor.reset (); + + return true; +} + +void +StitcherImpl::calc_dewarp_factors ( + uint32_t idx, const Factor &last_left_factor, const Factor &last_right_factor, + Factor &cur_left, Factor &cur_right) +{ + Factor match_left_factor, match_right_factor; + get_and_reset_fm_factors (idx, match_left_factor, match_right_factor); + + cur_left.x = last_left_factor.x * match_left_factor.x; + cur_left.y = last_left_factor.y * match_left_factor.y; + cur_right.x = last_right_factor.x * match_right_factor.x; + cur_right.y = last_right_factor.y * match_right_factor.y; +} + +bool +StitcherImpl::init_dewarp_factors (uint32_t idx) +{ + XCAM_FAIL_RETURN ( + ERROR, _fisheye[idx].dewarp.ptr (), false, + "gl-stitcher(%s) dewarp handler is empty", + XCAM_STR (_stitcher->get_name ())); + + Factor last_left_factor, last_right_factor, cur_left, cur_right; + if (_stitcher->get_scale_mode () == ScaleSingleConst) { + Factor unify_factor; + _fisheye[idx].dewarp->get_factors (unify_factor.x, unify_factor.y); + if (XCAM_DOUBLE_EQUAL_AROUND (unify_factor.x, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (unify_factor.y, 0.0f)) { // not started. + return true; + } + last_left_factor = last_right_factor = unify_factor; + + calc_dewarp_factors (idx, last_left_factor, last_right_factor, cur_left, cur_right); + unify_factor.x = (cur_left.x + cur_right.x) / 2.0f; + unify_factor.y = (cur_left.y + cur_right.y) / 2.0f; + + _fisheye[idx].dewarp->set_factors (unify_factor.x, unify_factor.y); + } else { + SmartPtr<GLDualConstGeoMapHandler> dewarp = _fisheye[idx].dewarp.dynamic_cast_ptr<GLDualConstGeoMapHandler> (); + XCAM_ASSERT (dewarp.ptr ()); + + dewarp->get_left_factors (last_left_factor.x, last_left_factor.y); + dewarp->get_right_factors (last_right_factor.x, last_right_factor.y); + if (XCAM_DOUBLE_EQUAL_AROUND (last_left_factor.x, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (last_left_factor.y, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (last_right_factor.y, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (last_right_factor.y, 0.0f)) { // not started. + return true; + } + + calc_dewarp_factors (idx, last_left_factor, last_right_factor, cur_left, cur_right); + dewarp->set_left_factors (cur_left.x, cur_left.y); + dewarp->set_right_factors (cur_right.x, cur_right.y); + } + + return true; +} + + +XCamReturn +FisheyeDewarp::set_dewarp_geo_table ( + const SmartPtr<GLGeoMapHandler> &mapper, const CameraInfo &cam_info, + const Stitcher::RoundViewSlice &view_slice, const BowlDataConfig &bowl) +{ + PolyFisheyeDewarp fd; + fd.set_intrinsic_param (cam_info.calibration.intrinsic); + fd.set_extrinsic_param (cam_info.calibration.extrinsic); + + uint32_t table_width, table_height; + table_width = view_slice.width / MAP_FACTOR_X; + table_height = view_slice.height / MAP_FACTOR_Y; + + SurViewFisheyeDewarp::MapTable map_table(table_width * table_height); + fd.fisheye_dewarp ( + map_table, table_width, table_height, + view_slice.width, view_slice.height, bowl); + + XCAM_FAIL_RETURN ( + ERROR, + mapper->set_lookup_table (map_table.data (), table_width, table_height), + XCAM_RETURN_ERROR_UNKNOWN, + "set fisheye dewarp lookup table failed"); + + return XCAM_RETURN_NO_ERROR; +} + +SmartPtr<GLGeoMapHandler> +StitcherImpl::create_geo_mapper (const Stitcher::RoundViewSlice &view_slice) +{ + XCAM_UNUSED (view_slice); + + SmartPtr<GLGeoMapHandler> dewarp; + GeoMapScaleMode scale_mode = _stitcher->get_scale_mode (); + if (scale_mode == ScaleSingleConst) + dewarp = new GLGeoMapHandler ("sitcher_singleconst_remapper"); + else if (scale_mode == ScaleDualConst) { + dewarp = new GLDualConstGeoMapHandler ("sitcher_dualconst_remapper"); + } else { + XCAM_LOG_ERROR ( + "gl-stitcher(%s) unsupported GeoMapScaleMode: %d", + XCAM_STR (_stitcher->get_name ()), scale_mode); + } + XCAM_ASSERT (dewarp.ptr ()); + + return dewarp; +} + +XCamReturn +StitcherImpl::init_fisheye (uint32_t idx) +{ + FisheyeDewarp &fisheye = _fisheye[idx]; + Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (idx); + + SmartPtr<ImageHandler::Callback> dewarp_cb = new CbGeoMap (_stitcher); + fisheye.dewarp = create_geo_mapper (view_slice); + fisheye.dewarp->set_callback (dewarp_cb); + + VideoBufferInfo buf_info; + buf_info.init ( + V4L2_PIX_FMT_NV12, view_slice.width, view_slice.height, + XCAM_ALIGN_UP (view_slice.width, GL_STITCHER_ALIGNMENT_X), + XCAM_ALIGN_UP (view_slice.height, GL_STITCHER_ALIGNMENT_Y)); + + SmartPtr<BufferPool> pool = new GLVideoBufferPool (buf_info); + XCAM_ASSERT (pool.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, pool->reserve (XCAM_GL_RESERVED_BUF_COUNT), XCAM_RETURN_ERROR_MEM, + "gl-stitcher(%s) reserve dewarp buffer pool failed, width:%d, height:%d", + XCAM_STR (_stitcher->get_name ()), buf_info.width, buf_info.height); + fisheye.buf_pool = pool; + + return XCAM_RETURN_NO_ERROR; +} + +void +StitcherImpl::init_feature_match (uint32_t idx) +{ +#if HAVE_OPENCV +#ifndef ANDROID + FeatureMatchMode fm_mode = _stitcher->get_fm_mode (); + if (fm_mode == FMNone) + return ; + else if (fm_mode == FMDefault) + _overlaps[idx].matcher = FeatureMatch::create_default_feature_match (); + else if (fm_mode == FMCluster) + _overlaps[idx].matcher = FeatureMatch::create_cluster_feature_match (); + else if (fm_mode == FMCapi) + _overlaps[idx].matcher = FeatureMatch::create_capi_feature_match (); + else { + XCAM_LOG_ERROR ( + "gl-stitcher(%s) unsupported FeatureMatchMode: %d", + XCAM_STR (_stitcher->get_name ()), fm_mode); + } +#else + _overlaps[idx].matcher = FeatureMatch::create_capi_feature_match (); +#endif + XCAM_ASSERT (_overlaps[idx].matcher.ptr ()); + + FMConfig config; + config.sitch_min_width = 136; + config.min_corners = 4; + config.offset_factor = 0.8f; + config.delta_mean_offset = 120.0f; + config.recur_offset_error = 8.0f; + config.max_adjusted_offset = 24.0f; + config.max_valid_offset_y = 20.0f; + config.max_track_error = 28.0f; +#ifdef ANDROID + config.max_track_error = 3600.0f; +#endif + _overlaps[idx].matcher->set_config (config); + _overlaps[idx].matcher->set_fm_index (idx); + + const BowlDataConfig bowl = _stitcher->get_bowl_config (); + const Stitcher::ImageOverlapInfo &info = _stitcher->get_overlap (idx); + Rect left_ovlap = info.left; + Rect right_ovlap = info.right; + left_ovlap.pos_y = 0; + left_ovlap.height = int32_t (bowl.wall_height / (bowl.wall_height + bowl.ground_length) * left_ovlap.height); + right_ovlap.pos_y = 0; + right_ovlap.height = left_ovlap.height; + _overlaps[idx].matcher->set_crop_rect (left_ovlap, right_ovlap); +#else + XCAM_LOG_ERROR ("gl-stitcher(%s) feature match is unsupported", XCAM_STR (_stitcher->get_name ())); + XCAM_ASSERT (false); +#endif +} + +XCamReturn +StitcherImpl::init_config (uint32_t count) +{ + for (uint32_t i = 0; i < count; ++i) { + XCamReturn ret = init_fisheye (i); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) init fisheye failed, idx:%d.", XCAM_STR (_stitcher->get_name ()), i); + +#if HAVE_OPENCV + init_feature_match (i); +#endif + + _overlaps[i].blender = create_gl_blender ().dynamic_cast_ptr<GLBlender>(); + XCAM_ASSERT (_overlaps[i].blender.ptr ()); + SmartPtr<ImageHandler::Callback> blender_cb = new CbBlender (_stitcher); + XCAM_ASSERT (blender_cb.ptr ()); + _overlaps[i].blender->set_callback (blender_cb); + _overlaps[i].param_map.clear (); + } + + Stitcher::CopyAreaArray areas = _stitcher->get_copy_area (); + uint32_t size = areas.size (); + for (uint32_t i = 0; i < size; ++i) { + XCAM_ASSERT (areas[i].in_idx < size); + + SmartPtr<ImageHandler::Callback> copier_cb = new CbCopier (_stitcher); + XCAM_ASSERT (copier_cb.ptr ()); + SmartPtr<GLCopyHandler> copier = new GLCopyHandler ("stitch_copy"); + XCAM_ASSERT (copier.ptr ()); + + copier->enable_allocator (false); + copier->set_callback (copier_cb); + copier->set_copy_area (areas[i].in_idx, areas[i].in_area, areas[i].out_area); + _copiers.push_back (copier); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::fisheye_dewarp_to_table () +{ + uint32_t camera_num = _stitcher->get_camera_num (); + for (uint32_t i = 0; i < camera_num; ++i) { + CameraInfo cam_info; + _stitcher->get_camera_info (i, cam_info); + Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (i); + + BowlDataConfig bowl = _stitcher->get_bowl_config (); + bowl.angle_start = view_slice.hori_angle_start; + bowl.angle_end = format_angle (view_slice.hori_angle_start + view_slice.hori_angle_range); + + uint32_t out_width, out_height; + _stitcher->get_output_size (out_width, out_height); + + XCAM_ASSERT (_fisheye[i].dewarp.ptr ()); + _fisheye[i].dewarp->set_output_size (view_slice.width, view_slice.height); + + if (bowl.angle_end < bowl.angle_start) + bowl.angle_start -= 360.0f; + + XCAM_LOG_DEBUG ( + "gl-stitcher(%s) camera(idx:%d) info(angle start:%.2f, range:%.2f), bowl info(angle start:%.2f, end:%.2f)", + XCAM_STR (_stitcher->get_name ()), i, + view_slice.hori_angle_start, view_slice.hori_angle_range, + bowl.angle_start, bowl.angle_end); + + XCamReturn ret = _fisheye[i].set_dewarp_geo_table (_fisheye[i].dewarp, cam_info, view_slice, bowl); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) set dewarp geo table failed, idx:%d", XCAM_STR (_stitcher->get_name ()), i); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_dewarps (const SmartPtr<GLStitcher::StitcherParam> ¶m) +{ + uint32_t camera_num = _stitcher->get_camera_num (); + + for (uint32_t i = 0; i < camera_num; ++i) { + SmartPtr<VideoBuffer> out_buf = _fisheye[i].buf_pool->get_buffer (); + SmartPtr<HandlerParam> dewarp_params = new HandlerParam (i); + dewarp_params->in_buf = param->in_bufs[i]; + dewarp_params->out_buf = out_buf; + dewarp_params->stitch_param = param; + + init_dewarp_factors (i); + XCamReturn ret = _fisheye[i].dewarp->execute_buffer (dewarp_params, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) fisheye dewarp buffer failed, idx:%d", + XCAM_STR (_stitcher->get_name ()), i); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, uint32_t idx) +{ +#if HAVE_OPENCV + _overlaps[idx].matcher->reset_offsets (); + _overlaps[idx].matcher->feature_match (left_buf, right_buf); + + Rect left_ovlap, right_ovlap; + _overlaps[idx].matcher->get_crop_rect (left_ovlap, right_ovlap); + + float left_offsetx = _overlaps[idx].matcher->get_current_left_offset_x (); + Factor left_factor, right_factor; + + uint32_t left_idx = idx; + float center_x = (float) _stitcher->get_center (left_idx).slice_center_x; + float feature_center_x = (float)left_ovlap.pos_x + (left_ovlap.width / 2.0f); + float range = feature_center_x - center_x; + XCAM_ASSERT (range > 1.0f); + right_factor.x = (range + left_offsetx / 2.0f) / range; + right_factor.y = 1.0f; + XCAM_ASSERT (right_factor.x > 0.0f && right_factor.x < 2.0f); + + uint32_t right_idx = (idx + 1) % _stitcher->get_camera_num (); + center_x = (float) _stitcher->get_center (right_idx).slice_center_x; + feature_center_x = (float)right_ovlap.pos_x + (right_ovlap.width / 2.0f); + range = center_x - feature_center_x; + XCAM_ASSERT (range > 1.0f); + left_factor.x = (range + left_offsetx / 2.0f) / range; + left_factor.y = 1.0f; + XCAM_ASSERT (left_factor.x > 0.0f && left_factor.x < 2.0f); + + _fisheye[left_idx].right_match_factor = right_factor; + _fisheye[right_idx].left_match_factor = left_factor; + + return XCAM_RETURN_NO_ERROR; +#else + XCAM_LOG_ERROR ("gl-stitcher(%s) feature match is unsupported", XCAM_STR (_stitcher->get_name ())); + return XCAM_RETURN_ERROR_PARAM; +#endif +} + +SmartPtr<BlenderParam> +Overlap::find_blender_param_in_map ( + const SmartPtr<GLStitcher::StitcherParam> &key, uint32_t idx) +{ + SmartPtr<BlenderParam> param; + BlenderParams::iterator i = param_map.find (key.ptr ()); + if (i == param_map.end ()) { + param = new BlenderParam (idx, NULL, NULL, NULL); + XCAM_ASSERT (param.ptr ()); + param->stitch_param = key; + param_map.insert (std::make_pair ((void*)key.ptr (), param)); + } else { + param = (*i).second; + } + + return param; +} + +XCamReturn +StitcherImpl::start_single_blender ( + uint32_t idx, const SmartPtr<BlenderParam> ¶m) +{ + SmartPtr<GLBlender> blender = _overlaps[idx].blender; + const Stitcher::ImageOverlapInfo &overlap_info = _stitcher->get_overlap (idx); + uint32_t out_width, out_height; + _stitcher->get_output_size (out_width, out_height); + + blender->set_output_size (out_width, out_height); + blender->set_merge_window (overlap_info.out_area); + blender->set_input_valid_area (overlap_info.left, 0); + blender->set_input_valid_area (overlap_info.right, 1); + blender->set_input_merge_area (overlap_info.left, 0); + blender->set_input_merge_area (overlap_info.right, 1); + + return blender->execute_buffer (param, false); +} + +XCamReturn +StitcherImpl::start_blenders ( + const SmartPtr<GLStitcher::StitcherParam> ¶m, + uint32_t idx, const SmartPtr<VideoBuffer> &buf) +{ + SmartPtr<BlenderParam> cur_param, prev_param; + const uint32_t camera_num = _stitcher->get_camera_num (); + uint32_t pre_idx = (idx + camera_num - 1) % camera_num; + + SmartPtr<BlenderParam> param_tmp = _overlaps[idx].find_blender_param_in_map (param, idx); + param_tmp->in_buf = buf; + if (param_tmp->in_buf.ptr () && param_tmp->in1_buf.ptr ()) { + cur_param = param_tmp; + _overlaps[idx].param_map.erase (param.ptr ()); + } + + param_tmp = _overlaps[pre_idx].find_blender_param_in_map (param, pre_idx); + param_tmp->in1_buf = buf; + if (param_tmp->in_buf.ptr () && param_tmp->in1_buf.ptr ()) { + prev_param = param_tmp; + _overlaps[pre_idx].param_map.erase (param.ptr ()); + } + + if (cur_param.ptr ()) { + cur_param->out_buf = param->out_buf; + XCamReturn ret = start_single_blender (idx, cur_param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) blend overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), idx); + } + + if (prev_param.ptr ()) { + prev_param->out_buf = param->out_buf; + XCamReturn ret = start_single_blender (pre_idx, prev_param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) blend overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), pre_idx); + } + +#if HAVE_OPENCV + if (_stitcher->get_fm_mode ()) { + if (cur_param.ptr ()) { + XCamReturn ret = start_feature_match (cur_param->in_buf, cur_param->in1_buf, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), idx); + } + + if (prev_param.ptr ()) { + XCamReturn ret = start_feature_match (prev_param->in_buf, prev_param->in1_buf, pre_idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), pre_idx); + } + } +#endif + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_copier ( + const SmartPtr<GLStitcher::StitcherParam> ¶m, + uint32_t idx, const SmartPtr<VideoBuffer> &buf) +{ + XCAM_ASSERT (param.ptr ()); + XCAM_ASSERT (buf.ptr ()); + + uint32_t size = _stitcher->get_copy_area ().size (); + XCAM_FAIL_RETURN ( + ERROR, idx <= size, XCAM_RETURN_ERROR_PARAM, + "gl-stitcher(%s) invalid idx:%d", XCAM_STR (_stitcher->get_name ()), idx); + + for (uint32_t i = 0; i < size; ++i) { + if(_copiers[i]->get_index () != idx) + continue; + + SmartPtr<HandlerParam> copy_params = new HandlerParam (i); + copy_params->in_buf = buf; + copy_params->out_buf = param->out_buf; + copy_params->stitch_param = param; + + XCamReturn ret = _copiers[i]->execute_buffer (copy_params, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) execute copier failed, i:%d idx:%d", + XCAM_STR (_stitcher->get_name ()), i, idx); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::stop () +{ + uint32_t cam_num = _stitcher->get_camera_num (); + for (uint32_t i = 0; i < cam_num; ++i) { + if (_fisheye[i].dewarp.ptr ()) { + _fisheye[i].dewarp->terminate (); + _fisheye[i].dewarp.release (); + } + if (_fisheye[i].buf_pool.ptr ()) { + _fisheye[i].buf_pool->stop (); + } + + if (_overlaps[i].blender.ptr ()) { + _overlaps[i].blender->terminate (); + _overlaps[i].blender.release (); + } + } + + for (Copiers::iterator i_copier = _copiers.begin (); i_copier != _copiers.end (); ++i_copier) { + SmartPtr<GLCopyHandler> &copier = *i_copier; + if (copier.ptr ()) { + copier->terminate (); + copier.release (); + } + } + + return XCAM_RETURN_NO_ERROR; +} + +}; + +GLStitcher::GLStitcher (const char *name) + : GLImageHandler (name) + , Stitcher (GL_STITCHER_ALIGNMENT_X, GL_STITCHER_ALIGNMENT_X) +{ + SmartPtr<GLSitcherPriv::StitcherImpl> impl = new GLSitcherPriv::StitcherImpl (this); + XCAM_ASSERT (impl.ptr ()); + _impl = impl; +} + +GLStitcher::~GLStitcher () +{ +} + +XCamReturn +GLStitcher::terminate () +{ + _impl->stop (); + return GLImageHandler::terminate (); +} + +XCamReturn +GLStitcher::stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf) +{ + XCAM_FAIL_RETURN ( + ERROR, !in_bufs.empty (), XCAM_RETURN_ERROR_PARAM, + "gl-stitcher(%s) stitch buffer failed, input buffers is empty", XCAM_STR (get_name ())); + + SmartPtr<StitcherParam> param = new StitcherParam; + XCAM_ASSERT (param.ptr ()); + param->out_buf = out_buf; + + uint32_t count = 0; + for (VideoBufferList::const_iterator iter = in_bufs.begin(); iter != in_bufs.end (); ++iter) { + SmartPtr<VideoBuffer> buf = *iter; + XCAM_ASSERT (buf.ptr ()); + param->in_bufs[count++] = buf; + } + param->in_buf_num = count; + + XCamReturn ret = execute_buffer (param, false); + if (!out_buf.ptr () && xcam_ret_is_ok (ret)) { + out_buf = param->out_buf; + } + + return ret; +} + +XCamReturn +GLStitcher::configure_resource (const SmartPtr<Parameters> ¶m) +{ + XCAM_UNUSED (param); + XCAM_ASSERT (_impl.ptr ()); + + XCamReturn ret = estimate_round_slices (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) estimate round view slices failed", XCAM_STR (get_name ())); + + ret = estimate_coarse_crops (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) estimate coarse crops failed", XCAM_STR (get_name ())); + + ret = mark_centers (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) mark centers failed", XCAM_STR (get_name ())); + + ret = estimate_overlap (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) estimake coarse overlap failed", XCAM_STR (get_name ())); + + ret = update_copy_areas (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) update copy areas failed", XCAM_STR (get_name ())); + + uint32_t camera_count = get_camera_num (); + ret = _impl->init_config (camera_count); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) initialize private config failed", XCAM_STR (get_name ())); + + ret = _impl->fisheye_dewarp_to_table (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "gl-stitcher(%s) fisheye_dewarp_to_table failed", XCAM_STR (get_name ())); + + VideoBufferInfo out_info; + uint32_t out_width, out_height; + get_output_size (out_width, out_height); + XCAM_FAIL_RETURN ( + ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM, + "gl-stitcher(%s) output size was not set", XCAM_STR (get_name ())); + + out_info.init ( + V4L2_PIX_FMT_NV12, out_width, out_height, + XCAM_ALIGN_UP (out_width, GL_STITCHER_ALIGNMENT_X), + XCAM_ALIGN_UP (out_height, GL_STITCHER_ALIGNMENT_Y)); + set_out_video_info (out_info); + + return ret; +} + +XCamReturn +GLStitcher::start_work (const SmartPtr<Parameters> &base) +{ + XCAM_ASSERT (base.ptr ()); + + SmartPtr<StitcherParam> param = base.dynamic_cast_ptr<StitcherParam> (); + XCAM_FAIL_RETURN ( + ERROR, param.ptr () && param->in_buf_num > 0 && param->in_bufs[0].ptr (), XCAM_RETURN_ERROR_PARAM, + "gl-stitcher(%s) start work failed, invalid parameters", XCAM_STR (get_name ())); + + XCamReturn ret = _impl->start_dewarps (param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_PARAM, + "gl_stitcher(%s) start dewarps failed", XCAM_STR (get_name ())); + + const SmartPtr<GLComputeProgram> prog = _impl->get_sync_prog (); + XCAM_ASSERT (prog.ptr ()); + ret = prog->finish (); + + return ret; +} + +void +GLStitcher::dewarp_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> &base, const XCamReturn error) +{ + XCAM_UNUSED (handler); + + SmartPtr<GLSitcherPriv::HandlerParam> dewarp_param = base.dynamic_cast_ptr<GLSitcherPriv::HandlerParam> (); + XCAM_ASSERT (dewarp_param.ptr ()); + SmartPtr<GLStitcher::StitcherParam> param = dewarp_param->stitch_param; + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); + + XCAM_LOG_DEBUG ("gl-stitcher(%s) camera(idx:%d) dewarp done", XCAM_STR (get_name ()), dewarp_param->idx); + dump_buf (dewarp_param->out_buf, dewarp_param->idx, "stitcher-dewarp"); + + XCamReturn ret = _impl->start_blenders (param, dewarp_param->idx, dewarp_param->out_buf); + if (!xcam_ret_is_ok (ret)) + XCAM_LOG_ERROR ("start_blenders failed"); + + ret = _impl->start_copier (param, dewarp_param->idx, dewarp_param->out_buf); + if (!xcam_ret_is_ok (ret)) + XCAM_LOG_ERROR ("start_copier failed"); +} + +void +GLStitcher::blender_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> &base, const XCamReturn error) +{ + XCAM_UNUSED (handler); + + SmartPtr<GLSitcherPriv::BlenderParam> blender_param = base.dynamic_cast_ptr<GLSitcherPriv::BlenderParam> (); + XCAM_ASSERT (blender_param.ptr ()); + SmartPtr<GLStitcher::StitcherParam> param = blender_param->stitch_param; + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); + + XCAM_LOG_DEBUG ("gl-stitcher(%s) overlap:%d done", XCAM_STR (handler->get_name ()), blender_param->idx); + dump_buf (blender_param->out_buf, blender_param->idx, "stitcher-blend"); +} + +void +GLStitcher::copier_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> &base, const XCamReturn error) +{ + XCAM_UNUSED (handler); + + SmartPtr<GLSitcherPriv::HandlerParam> copy_param = base.dynamic_cast_ptr<GLSitcherPriv::HandlerParam> (); + XCAM_ASSERT (copy_param.ptr ()); + SmartPtr<GLStitcher::StitcherParam> param = copy_param->stitch_param; + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); + + XCAM_LOG_DEBUG ("gl-stitcher(%s) camera(idx:%d) copy done", XCAM_STR (get_name ()), copy_param->idx); +} + +SmartPtr<Stitcher> +Stitcher::create_gl_stitcher () +{ + return new GLStitcher; +} + +} diff --git a/modules/gles/gl_stitcher.h b/modules/gles/gl_stitcher.h new file mode 100644 index 0000000..08a0406 --- /dev/null +++ b/modules/gles/gl_stitcher.h @@ -0,0 +1,91 @@ +/* + * gl_stitcher.h - GL stitcher class + * + * 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: Wind Yuan <feng.yuan@intel.com> + * Author: Yinhang Liu <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_STITCHER_H +#define XCAM_GL_STITCHER_H + +#include <interface/stitcher.h> +#include <gles/gles_std.h> +#include <gles/gl_image_handler.h> + +namespace XCam { + +namespace GLSitcherPriv { +class StitcherImpl; +class CbGeoMap; +class CbBlender; +class CbCopier; +}; + +class GLStitcher + : public GLImageHandler + , public Stitcher +{ + friend class GLSitcherPriv::StitcherImpl; + friend class GLSitcherPriv::CbGeoMap; + friend class GLSitcherPriv::CbBlender; + friend class GLSitcherPriv::CbCopier; + +public: + struct StitcherParam + : ImageHandler::Parameters + { + uint32_t in_buf_num; + SmartPtr<VideoBuffer> in_bufs[XCAM_STITCH_MAX_CAMERAS]; + + StitcherParam () + : Parameters (NULL, NULL) + , in_buf_num (0) + {} + }; + +public: + explicit GLStitcher (const char *name = "GLStitcher"); + ~GLStitcher (); + + // derived from GLImageHandler + virtual XCamReturn terminate (); + +protected: + // interface derive from Stitcher + XCamReturn stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf); + + // derived from GLImageHandler + XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + void dewarp_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> ¶m, const XCamReturn error); + void blender_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> ¶m, const XCamReturn error); + void copier_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> ¶m, const XCamReturn error); + +private: + SmartPtr<GLSitcherPriv::StitcherImpl> _impl; +}; + +} +#endif // XCAM_GL_STITCHER_H
\ No newline at end of file diff --git a/modules/gles/gl_utils.cpp b/modules/gles/gl_utils.cpp new file mode 100644 index 0000000..bafaf10 --- /dev/null +++ b/modules/gles/gl_utils.cpp @@ -0,0 +1,41 @@ +/* + * gl_utils.h - GL utilities implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_utils.h" + +namespace XCam { + +SmartPtr<GLBuffer> get_glbuffer (const SmartPtr<VideoBuffer> &buf) +{ + SmartPtr<GLVideoBuffer> gl_video_buf = buf.dynamic_cast_ptr<GLVideoBuffer> (); + XCAM_FAIL_RETURN ( + ERROR, gl_video_buf.ptr (), NULL, + "convert VideoBuffer to GLVideoBuffer failed"); + + SmartPtr<GLBuffer> gl_buf = gl_video_buf->get_gl_buffer (); + XCAM_ASSERT (gl_buf.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, gl_buf.ptr (), NULL, + "get GLBuffer from GLVideoBuffer failed"); + + return gl_buf; +} + +} diff --git a/modules/gles/gl_utils.h b/modules/gles/gl_utils.h new file mode 100644 index 0000000..84ba093 --- /dev/null +++ b/modules/gles/gl_utils.h @@ -0,0 +1,32 @@ +/* + * gl_utils.h - GL utilities class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_UTILS_H +#define XCAM_GL_UTILS_H + +#include <gles/gl_video_buffer.h> + +namespace XCam { + +SmartPtr<GLBuffer> get_glbuffer (const SmartPtr<VideoBuffer> &buf); + +} + +#endif // XCAM_GL_UTILS_H
\ No newline at end of file diff --git a/modules/gles/gl_video_buffer.cpp b/modules/gles/gl_video_buffer.cpp new file mode 100644 index 0000000..9029e72 --- /dev/null +++ b/modules/gles/gl_video_buffer.cpp @@ -0,0 +1,160 @@ +/* + * gl_video_buffer.cpp - GL video buffer implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "gl_video_buffer.h" + +namespace XCam { + +class GLVideoBufferData + : public BufferData +{ +public: + explicit GLVideoBufferData (SmartPtr<GLBuffer> &body); + ~GLVideoBufferData (); + + virtual uint8_t *map (); + virtual bool unmap (); + + SmartPtr<GLBuffer> &get_buf () { + return _buf; + } + +private: + uint8_t *_buf_ptr; + SmartPtr<GLBuffer> _buf; +}; + +GLVideoBufferData::GLVideoBufferData (SmartPtr<GLBuffer> &body) + : _buf_ptr (NULL) + , _buf (body) +{ + XCAM_ASSERT (body.ptr ()); +} + +GLVideoBufferData::~GLVideoBufferData () +{ + unmap (); + _buf.release (); +} + +uint8_t * +GLVideoBufferData::map () +{ + if (_buf_ptr) + return _buf_ptr; + + uint32_t size = _buf->get_size (); + _buf_ptr = (uint8_t *) _buf->map_range (0, size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + XCAM_FAIL_RETURN (ERROR, _buf_ptr, NULL, "GLVideoBufferData map data failed"); + + return _buf_ptr; +} + +bool +GLVideoBufferData::unmap () +{ + if (!_buf_ptr) + return true; + + XCamReturn ret = _buf->unmap (); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, false, + "GLVideoBufferData unmap data failed"); + + _buf_ptr = NULL; + return true; +} + +GLVideoBuffer::GLVideoBuffer (const VideoBufferInfo &info, const SmartPtr<BufferData> &data) + : BufferProxy (info, data) +{ +} + +SmartPtr<GLBuffer> +GLVideoBuffer::get_gl_buffer () +{ + SmartPtr<BufferData> data = get_buffer_data (); + SmartPtr<GLVideoBufferData> gl_data = data.dynamic_cast_ptr<GLVideoBufferData> (); + XCAM_FAIL_RETURN ( + WARNING, gl_data.ptr (), NULL, + "GLVideoBuffer get_buffer_data failed with NULL"); + + return gl_data->get_buf (); +} + +GLVideoBufferPool::GLVideoBufferPool () + : _target (GL_SHADER_STORAGE_BUFFER) +{ +} + +GLVideoBufferPool::GLVideoBufferPool (const VideoBufferInfo &info, GLenum target) + : _target (target) +{ + set_video_info (info); +} + +GLVideoBufferPool::~GLVideoBufferPool () +{ +} + +SmartPtr<BufferData> +GLVideoBufferPool::allocate_data (const VideoBufferInfo &info) +{ + XCAM_FAIL_RETURN ( + ERROR, info.format == V4L2_PIX_FMT_NV12, NULL, + "GLVideoBufferPool unsupported format:%s, try NV12", + xcam_fourcc_to_string (info.format)); + + SmartPtr<GLBuffer> buf = + XCam::GLBuffer::create_buffer (_target, NULL, info.size, GL_STATIC_DRAW); + XCAM_ASSERT (buf.ptr ()); + + GLBufferDesc desc; + desc.format = info.format; + desc.width = info.width; + desc.height = info.height; + desc.aligned_width = info.aligned_width; + desc.aligned_height = info.aligned_height; + desc.size = info.size; + desc.strides[0] = info.strides[0]; + desc.strides[1] = info.strides[1]; + desc.offsets[0] = info.offsets[0]; + desc.offsets[1] = info.offsets[1]; + desc.slice_size[0] = info.strides [0] * info.aligned_height; + desc.slice_size[1] = info.size - info.offsets[1]; + + buf->set_buffer_desc (desc); + + return new GLVideoBufferData (buf); +} + +SmartPtr<BufferProxy> +GLVideoBufferPool::create_buffer_from_data (SmartPtr<BufferData> &data) +{ + XCAM_ASSERT (data.ptr ()); + + const VideoBufferInfo &info = get_video_info (); + SmartPtr<GLVideoBuffer> buf = new GLVideoBuffer (info, data); + XCAM_ASSERT (buf.ptr ()); + + return buf; +} + +}; diff --git a/modules/gles/gl_video_buffer.h b/modules/gles/gl_video_buffer.h new file mode 100644 index 0000000..0cc227b --- /dev/null +++ b/modules/gles/gl_video_buffer.h @@ -0,0 +1,63 @@ +/* + * gl_video_buffer.h - GL video buffer class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_GL_VIDEO_BUFFER_H +#define XCAM_GL_VIDEO_BUFFER_H + +#include <buffer_pool.h> +#include <gles/gl_buffer.h> + +namespace XCam { + +class GLVideoBuffer + : public BufferProxy +{ + friend class GLVideoBufferPool; + +public: + virtual ~GLVideoBuffer () {} + SmartPtr<GLBuffer> get_gl_buffer (); + +protected: + explicit GLVideoBuffer (const VideoBufferInfo &info, const SmartPtr<BufferData> &data); +}; + +class GLVideoBufferPool + : public BufferPool +{ +public: + explicit GLVideoBufferPool (); + explicit GLVideoBufferPool (const VideoBufferInfo &info, GLenum target = GL_SHADER_STORAGE_BUFFER); + virtual ~GLVideoBufferPool (); + + void set_binding_target (GLenum target) { + _target = target; + } + +private: + virtual SmartPtr<BufferData> allocate_data (const VideoBufferInfo &info); + virtual SmartPtr<BufferProxy> create_buffer_from_data (SmartPtr<BufferData> &data); + +private: + GLenum _target; +}; + +}; +#endif // XCAM_GL_VIDEO_BUFFER_H
\ No newline at end of file diff --git a/modules/gles/gles_std.cpp b/modules/gles/gles_std.cpp new file mode 100644 index 0000000..03ed14a --- /dev/null +++ b/modules/gles/gles_std.cpp @@ -0,0 +1,58 @@ +/* + * gles_std.cpp - GLES std + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "gles_std.h" + +namespace XCam { + +const char * +gl_error_string (GLenum flag) +{ + static char str[XCAM_GL_NAME_LENGTH] = {'\0'}; + + switch (flag) + { + case GL_NO_ERROR: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "GL_NO_ERROR"); + break; + case GL_INVALID_ENUM: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "GL_INVALID_ENUM"); + break; + case GL_INVALID_VALUE: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "GL_INVALID_VALUE"); + break; + case GL_INVALID_OPERATION: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "GL_INVALID_OPERATION"); + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "GL_INVALID_FRAMEBUFFER_OPERATION"); + break; + case GL_OUT_OF_MEMORY: + snprintf (str, sizeof (str), "0x%04x:%s", flag, "GL_OUT_OF_MEMORY"); + break; + default: + snprintf (str, sizeof (str), "unknown flag:0x%04x", flag); + XCAM_LOG_ERROR ("%s", str); + } + + return str; +} + +} diff --git a/modules/gles/gles_std.h b/modules/gles/gles_std.h new file mode 100644 index 0000000..bad9483 --- /dev/null +++ b/modules/gles/gles_std.h @@ -0,0 +1,48 @@ +/* + * gles_std.h - GLES std + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_GLES_STD_H +#define XCAM_GLES_STD_H + +#include <xcam_std.h> +#include <smartptr.h> +#include <GLES3/gl3.h> + +#if HAVE_GLES_32 +#include <GLES3/gl32.h> +#else +#include <GLES3/gl31.h> +#endif + +#define XCAM_GL_NAME_LENGTH 64 +#define XCAM_GL_RESERVED_BUF_COUNT 4 + +namespace XCam { + +inline GLenum gl_error () +{ + return glGetError (); +} + +const char *gl_error_string (GLenum flag); + +} + +#endif // XCAM_GLES_STD_H diff --git a/modules/isp/Makefile.am b/modules/isp/Makefile.am index 9ad978c..0cee211 100644 --- a/modules/isp/Makefile.am +++ b/modules/isp/Makefile.am @@ -1,81 +1,70 @@ lib_LTLIBRARIES = libxcam_isp.la -XCAMISP_CXXFLAGS = $(XCAM_CXXFLAGS) +XCAMISP_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(IA_IMAGING_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules/isp \ + $(NULL) + XCAMISP_LIBS = \ + $(IA_IMAGING_LIBS) \ + $(top_builddir)/xcore/libxcam_core.la \ $(NULL) if USE_LOCAL_ATOMISP XCAMISP_CXXFLAGS += \ - -I$(top_srcdir)/ext/atomisp \ + -I$(top_srcdir)/ext/atomisp \ $(NULL) endif -if ENABLE_IA_AIQ -XCAMISP_CXXFLAGS += \ - $(IA_IMAGING_CFLAGS) \ - $(NULL) - +if HAVE_LIBDRM +XCAMISP_CXXFLAGS += $(LIBDRM_CFLAGS) XCAMISP_LIBS += \ - $(IA_IMAGING_LIBS) \ + -ldrm_intel \ + $(LIBDRM_LIBS) \ $(NULL) endif xcam_isp_sources = \ - aiq3a_utils.cpp \ - atomisp_device.cpp \ - isp_poll_thread.cpp \ - isp_image_processor.cpp \ - isp_controller.cpp \ - isp_config_translator.cpp \ - x3a_isp_config.cpp \ - sensor_descriptor.cpp \ - iq/x3a_analyze_tuner.cpp \ - iq/x3a_ciq_tuning_handler.cpp \ - iq/x3a_ciq_tnr_tuning_handler.cpp \ - iq/x3a_ciq_bnr_ee_tuning_handler.cpp \ - iq/x3a_ciq_wavelet_tuning_handler.cpp \ - x3a_statistics_queue.cpp \ - libtbd.c \ - xcam_cpf_reader.c \ - $(NULL) - -if ENABLE_IA_AIQ -xcam_isp_sources += \ - aiq_handler.cpp \ - hybrid_analyzer.cpp \ - hybrid_analyzer_loader.cpp \ - x3a_analyzer_aiq.cpp \ + aiq3a_utils.cpp \ + atomisp_device.cpp \ + isp_poll_thread.cpp \ + isp_image_processor.cpp \ + isp_controller.cpp \ + isp_config_translator.cpp \ + x3a_isp_config.cpp \ + sensor_descriptor.cpp \ + iq/x3a_analyze_tuner.cpp \ + iq/x3a_ciq_tuning_handler.cpp \ + iq/x3a_ciq_tnr_tuning_handler.cpp \ + iq/x3a_ciq_bnr_ee_tuning_handler.cpp \ + iq/x3a_ciq_wavelet_tuning_handler.cpp \ + x3a_statistics_queue.cpp \ + aiq_handler.cpp \ + hybrid_analyzer.cpp \ + hybrid_analyzer_loader.cpp \ + x3a_analyzer_aiq.cpp \ + libtbd.c \ + xcam_cpf_reader.c \ $(NULL) -endif - -if HAVE_LIBDRM -XCAMISP_CXXFLAGS += $(LIBDRM_CFLAGS) -XCAMISP_LIBS += \ - -ldrm_intel \ - $(LIBDRM_LIBS) \ - $(NULL) -endif libxcam_isp_la_SOURCES = \ - $(xcam_isp_sources) \ + $(xcam_isp_sources) \ $(NULL) libxcam_isp_la_CXXFLAGS = \ - $(XCAMISP_CXXFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/modules/isp \ + $(XCAMISP_CXXFLAGS) \ $(NULL) libxcam_isp_la_CFLAGS = $(libxcam_isp_la_CXXFLAGS) libxcam_isp_la_LIBADD = \ - $(top_builddir)/xcore/libxcam_core.la \ - $(XCAMISP_LIBS) \ + $(XCAMISP_LIBS) \ $(NULL) libxcam_isp_la_LDFLAGS = \ - $(XCAM_LT_LDFLAGS) \ - $(PTHREAD_LDFLAGS) \ + $(XCAM_LT_LDFLAGS) \ $(NULL) libxcam_isp_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/isp/aiq_handler.cpp b/modules/isp/aiq_handler.cpp index 3a4d89b..d186532 100644 --- a/modules/isp/aiq_handler.cpp +++ b/modules/isp/aiq_handler.cpp @@ -1526,8 +1526,9 @@ AiqCompositor::limit_nr_levels (struct atomisp_parameters *isp_param) isp_param->tnr_config->threshold_y = 0; isp_param->tnr_config->threshold_uv = 0; } + + XCAM_LOG_DEBUG ("set TNR gain:%u", isp_param->tnr_config->gain); } - XCAM_LOG_DEBUG ("set TNR gain:%u", isp_param->tnr_config->gain); } return XCAM_RETURN_NO_ERROR; diff --git a/modules/isp/hybrid_analyzer.cpp b/modules/isp/hybrid_analyzer.cpp index 9e0a0f6..4a936b3 100644 --- a/modules/isp/hybrid_analyzer.cpp +++ b/modules/isp/hybrid_analyzer.cpp @@ -79,8 +79,9 @@ HybridAnalyzer::setup_stats_pool (const XCam3AStats *stats) grid_info.deci_factor_log2 = log2 (grid_info.bqs_per_grid_cell); grid_info.elem_bit_depth = stats_info.bit_depth; - _stats_pool = new X3aStatisticsQueue; - XCAM_ASSERT (_stats_pool.ptr ()); + SmartPtr<X3aStatisticsQueue> stats_pool = new X3aStatisticsQueue; + XCAM_ASSERT (stats_pool.ptr ()); + _stats_pool = stats_pool; _stats_pool->set_grid_info (grid_info); if (!_stats_pool->reserve (6)) { diff --git a/modules/isp/isp_poll_thread.cpp b/modules/isp/isp_poll_thread.cpp index 754452e..722a0b2 100644 --- a/modules/isp/isp_poll_thread.cpp +++ b/modules/isp/isp_poll_thread.cpp @@ -50,7 +50,9 @@ IspPollThread::set_isp_controller (SmartPtr<IspController> &isp) XCamReturn IspPollThread::start () { - _3a_stats_pool = new X3aStatisticsQueue; + SmartPtr<X3aStatsPool> stats_pool = new X3aStatisticsQueue; + XCAM_ASSERT (stats_pool.ptr ()); + _3a_stats_pool = stats_pool; return PollThread::start (); } diff --git a/modules/ocl/Makefile.am b/modules/ocl/Makefile.am index dc09d6d..5d727e6 100644 --- a/modules/ocl/Makefile.am +++ b/modules/ocl/Makefile.am @@ -1,109 +1,99 @@ lib_LTLIBRARIES = libxcam_ocl.la -XCAMOCL_CXXFLAGS = $(XCAM_CXXFLAGS) -XCAMOCL_LIBS = -ldl \ - $(NULL) - -XCAMOCL_CXXFLAGS += \ +XCAMOCL_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ $(LIBCL_CFLAGS) \ -I$(top_srcdir)/xcore \ -I$(top_srcdir)/modules \ - -I$(top_builddir)/clx_kernel \ + -I$(top_builddir)/shaders/clx \ + $(NULL) + +XCAMOCL_LIBS = \ + $(LIBCL_LIBS) -ldl \ + $(top_builddir)/xcore/libxcam_core.la \ $(NULL) +if HAVE_OPENCV +XCAMOCL_CXXFLAGS += $(OPENCV_CFLAGS) XCAMOCL_LIBS += \ - $(LIBCL_LIBS) \ + $(OPENCV_LIBS) \ + $(top_builddir)/modules/ocv/libxcam_ocv.la \ $(NULL) +endif if HAVE_LIBDRM XCAMOCL_CXXFLAGS += $(LIBDRM_CFLAGS) XCAMOCL_LIBS += \ - -ldrm_intel \ - $(LIBDRM_LIBS) \ + -ldrm_intel \ + $(LIBDRM_LIBS) \ $(NULL) endif -if HAVE_OPENCV -XCAMOCL_CXXFLAGS += $(OPENCV_CFLAGS) -XCAMOCL_LIBS += $(OPENCV_LIBS) -endif - xcam_ocl_sources = \ - cl_argument.cpp \ - cl_context.cpp \ - cl_device.cpp \ - cl_kernel.cpp \ - cl_memory.cpp \ - cl_event.cpp \ - cl_utils.cpp \ - cl_image_handler.cpp \ - cl_image_processor.cpp \ - cl_3a_image_processor.cpp \ - cl_post_image_processor.cpp \ - cl_multi_image_handler.cpp \ - cl_csc_image_processor.cpp \ - cl_3a_stats_context.cpp \ - cl_demo_handler.cpp \ - cl_blender.cpp \ - cl_pyramid_blender.cpp \ - cl_geo_map_handler.cpp \ - cl_csc_handler.cpp \ - cl_tnr_handler.cpp \ - cl_defog_dcp_handler.cpp \ - cl_bayer_pipe_handler.cpp \ - cl_bayer_basic_handler.cpp \ - cl_yuv_pipe_handler.cpp \ - cl_rgb_pipe_handler.cpp \ - cl_tonemapping_handler.cpp \ - cl_newtonemapping_handler.cpp \ - cl_fisheye_handler.cpp \ - cl_image_scaler.cpp \ - cl_image_360_stitch.cpp \ - cl_retinex_handler.cpp \ - cl_gauss_handler.cpp \ - cl_wavelet_denoise_handler.cpp \ - cl_newwavelet_denoise_handler.cpp \ - cl_wire_frame_handler.cpp \ - cl_3d_denoise_handler.cpp \ - cl_image_warp_handler.cpp \ - cl_video_stabilizer.cpp \ - cl_video_buffer.cpp \ - priority_buffer_queue.cpp \ + cl_argument.cpp \ + cl_context.cpp \ + cl_device.cpp \ + cl_kernel.cpp \ + cl_memory.cpp \ + cl_event.cpp \ + cl_utils.cpp \ + cl_image_handler.cpp \ + cl_image_processor.cpp \ + cl_3a_image_processor.cpp \ + cl_post_image_processor.cpp \ + cl_multi_image_handler.cpp \ + cl_csc_image_processor.cpp \ + cl_3a_stats_context.cpp \ + cl_demo_handler.cpp \ + cl_blender.cpp \ + cl_pyramid_blender.cpp \ + cl_geo_map_handler.cpp \ + cl_csc_handler.cpp \ + cl_tnr_handler.cpp \ + cl_defog_dcp_handler.cpp \ + cl_bayer_pipe_handler.cpp \ + cl_bayer_basic_handler.cpp \ + cl_yuv_pipe_handler.cpp \ + cl_rgb_pipe_handler.cpp \ + cl_tonemapping_handler.cpp \ + cl_newtonemapping_handler.cpp \ + cl_fisheye_handler.cpp \ + cl_image_scaler.cpp \ + cl_image_360_stitch.cpp \ + cl_retinex_handler.cpp \ + cl_gauss_handler.cpp \ + cl_wavelet_denoise_handler.cpp \ + cl_newwavelet_denoise_handler.cpp \ + cl_wire_frame_handler.cpp \ + cl_3d_denoise_handler.cpp \ + cl_image_warp_handler.cpp \ + cl_video_stabilizer.cpp \ + cl_video_buffer.cpp \ + priority_buffer_queue.cpp \ $(NULL) -if HAVE_OPENCV -xcam_ocl_sources += cv_context.cpp -xcam_ocl_sources += cv_base_class.cpp -xcam_ocl_sources += cv_image_process_helper.cpp -xcam_ocl_sources += cv_image_sharp.cpp -xcam_ocl_sources += cv_edgetaper.cpp -xcam_ocl_sources += cv_wiener_filter.cpp -xcam_ocl_sources += cv_feature_match.cpp -xcam_ocl_sources += cv_image_deblurring.cpp -endif - if HAVE_LIBDRM -xcam_ocl_sources += intel/cl_intel_context.cpp -xcam_ocl_sources += intel/cl_va_memory.cpp -xcam_ocl_sources += cl_image_bo_buffer.cpp +xcam_ocl_sources += \ + intel/cl_intel_context.cpp \ + intel/cl_va_memory.cpp \ + cl_image_bo_buffer.cpp \ + $(NULL) endif libxcam_ocl_la_SOURCES = \ - $(xcam_ocl_sources) \ + $(xcam_ocl_sources) \ $(NULL) libxcam_ocl_la_CXXFLAGS = \ - $(XCAMOCL_CXXFLAGS) \ + $(XCAMOCL_CXXFLAGS) \ $(NULL) libxcam_ocl_la_LIBADD = \ - $(top_builddir)/xcore/libxcam_core.la \ - $(XCAMOCL_LIBS) \ + $(XCAMOCL_LIBS) \ $(NULL) libxcam_ocl_la_LDFLAGS = \ $(XCAM_LT_LDFLAGS) \ - $(PTHREAD_LDFLAGS) \ $(NULL) libxcam_oclincludedir = $(includedir)/xcam/ocl @@ -150,26 +140,16 @@ nobase_libxcam_oclinclude_HEADERS = \ cl_video_buffer.h \ $(NULL) -if HAVE_OPENCV -nobase_libxcam_oclinclude_HEADERS += cv_context.h -nobase_libxcam_oclinclude_HEADERS += cv_base_class.h -nobase_libxcam_oclinclude_HEADERS += cv_image_process_helper.h -nobase_libxcam_oclinclude_HEADERS += cv_image_sharp.h -nobase_libxcam_oclinclude_HEADERS += cv_edgetaper.h -nobase_libxcam_oclinclude_HEADERS += cv_wiener_filter.h -nobase_libxcam_oclinclude_HEADERS += cv_feature_match.h -nobase_libxcam_oclinclude_HEADERS += cv_image_deblurring.h -endif - if HAVE_LIBDRM -nobase_libxcam_oclinclude_HEADERS += intel/cl_intel_context.h -nobase_libxcam_oclinclude_HEADERS += intel/cl_va_memory.h -nobase_libxcam_oclinclude_HEADERS += cl_image_bo_buffer.h +nobase_libxcam_oclinclude_HEADERS += \ + intel/cl_intel_context.h \ + intel/cl_va_memory.h \ + cl_image_bo_buffer.h \ + $(NULL) endif -noinst_HEADERS = \ - cl_pyramid_blender.h \ +noinst_HEADERS = \ + cl_pyramid_blender.h \ $(NULL) - libxcam_ocl_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/ocl/cl_3a_stats_context.cpp b/modules/ocl/cl_3a_stats_context.cpp index 4d43e6a..fe2a07c 100644 --- a/modules/ocl/cl_3a_stats_context.cpp +++ b/modules/ocl/cl_3a_stats_context.cpp @@ -30,7 +30,9 @@ CL3AStatsCalculatorContext::CL3AStatsCalculatorContext (const SmartPtr<CLContext , _factor_shift (0) , _data_allocated (false) { - _stats_pool = new X3aStatsPool (); + SmartPtr<X3aStatsPool> pool = new X3aStatsPool (); + XCAM_ASSERT (pool.ptr ()); + _stats_pool = pool; } CL3AStatsCalculatorContext::~CL3AStatsCalculatorContext () diff --git a/modules/ocl/cl_bayer_basic_handler.cpp b/modules/ocl/cl_bayer_basic_handler.cpp index efc2536..7e33fa7 100644 --- a/modules/ocl/cl_bayer_basic_handler.cpp +++ b/modules/ocl/cl_bayer_basic_handler.cpp @@ -191,10 +191,13 @@ CLBayerBasicImageHandler::CLBayerBasicImageHandler ( _gamma_table[i] = (float)i / 256.0f; _gamma_table[XCAM_GAMMA_TABLE_SIZE] = 0.9999f; - _3a_stats_context = new CL3AStatsCalculatorContext (context); - XCAM_ASSERT (_3a_stats_context.ptr ()); - _3a_stats_thread = new CLBayer3AStatsThread (this); - XCAM_ASSERT (_3a_stats_thread.ptr ()); + SmartPtr<CL3AStatsCalculatorContext> stats_context = new CL3AStatsCalculatorContext (context); + XCAM_ASSERT (stats_context.ptr ()); + _3a_stats_context = stats_context; + + SmartPtr<CLBayer3AStatsThread> stats_thread = new CLBayer3AStatsThread (this); + XCAM_ASSERT (stats_thread.ptr ()); + _3a_stats_thread = stats_thread; XCAM_OBJ_PROFILING_INIT; } diff --git a/modules/ocl/cl_defog_dcp_handler.cpp b/modules/ocl/cl_defog_dcp_handler.cpp index 7300485..eeb4d78 100644 --- a/modules/ocl/cl_defog_dcp_handler.cpp +++ b/modules/ocl/cl_defog_dcp_handler.cpp @@ -387,6 +387,7 @@ create_kernel_dark_channel (const SmartPtr<CLContext> &context, SmartPtr<CLDefog return kernel; } +#if 0 static SmartPtr<CLMinFilterKernel> create_kernel_min_filter ( const SmartPtr<CLContext> &context, @@ -410,6 +411,7 @@ create_kernel_min_filter ( return kernel; } +#endif static SmartPtr<CLBiFilterKernel> create_kernel_bi_filter ( diff --git a/modules/ocl/cl_fisheye_handler.cpp b/modules/ocl/cl_fisheye_handler.cpp index a7866c5..321ac78 100644 --- a/modules/ocl/cl_fisheye_handler.cpp +++ b/modules/ocl/cl_fisheye_handler.cpp @@ -128,7 +128,7 @@ CLFisheye2GPSKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size) return XCAM_RETURN_NO_ERROR; } -CLFisheyeHandler::CLFisheyeHandler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc) +CLFisheyeHandler::CLFisheyeHandler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc, bool need_scale) : CLImageHandler (context, "CLFisheyeHandler") , _output_width (0) , _output_height (0) @@ -137,8 +137,12 @@ CLFisheyeHandler::CLFisheyeHandler (const SmartPtr<CLContext> &context, Surround , _map_factor (DEFAULT_FISHEYE_TABLE_SCALE) , _use_map (use_map) , _need_lsc (need_lsc ? 1 : 0) + , _need_scale (need_scale ? 1 : 0) , _lsc_array_size (0) , _lsc_array (NULL) + , _stable_y_start (0.0f) + , _left_scale_factor (1.0f, 1.0f) + , _right_scale_factor (1.0f, 1.0f) , _surround_mode (surround_mode) { xcam_mem_clear (_gray_threshold); @@ -203,6 +207,24 @@ CLFisheyeHandler::set_lsc_gray_threshold (float min_threshold, float max_thresho _gray_threshold[1] = max_threshold; } +void +CLFisheyeHandler::set_stable_y_start (float y_start) +{ + _stable_y_start = y_start; +} + +void +CLFisheyeHandler::set_left_scale_factor (PointFloat2 factor) +{ + _left_scale_factor = factor; +} + +void +CLFisheyeHandler::set_right_scale_factor (PointFloat2 factor) +{ + _right_scale_factor = factor; +} + XCamReturn CLFisheyeHandler::prepare_buffer_pool_video_info ( const VideoBufferInfo &input, @@ -585,16 +607,16 @@ create_fishey_gps_kernel (const SmartPtr<CLContext> &context, SmartPtr<CLFisheye } SmartPtr<CLImageHandler> -create_fisheye_handler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc) +create_fisheye_handler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc, bool need_scale) { SmartPtr<CLFisheyeHandler> handler; SmartPtr<CLImageKernel> kernel; - handler = new CLFisheyeHandler (context, surround_mode, use_map, need_lsc); + handler = new CLFisheyeHandler (context, surround_mode, use_map, need_lsc, need_scale); XCAM_ASSERT (handler.ptr ()); if (use_map) { - kernel = create_geo_map_kernel (context, handler, need_lsc); + kernel = create_geo_map_kernel (context, handler, need_lsc, need_scale); } else { kernel = create_fishey_gps_kernel (context, handler); } diff --git a/modules/ocl/cl_fisheye_handler.h b/modules/ocl/cl_fisheye_handler.h index be7452f..a8eb7c4 100644 --- a/modules/ocl/cl_fisheye_handler.h +++ b/modules/ocl/cl_fisheye_handler.h @@ -49,7 +49,7 @@ class CLFisheyeHandler { friend class CLFisheye2GPSKernel; public: - explicit CLFisheyeHandler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc); + explicit CLFisheyeHandler (const SmartPtr<CLContext> &context, SurroundMode surround_mode, bool use_map, bool need_lsc, bool need_scale); virtual ~CLFisheyeHandler(); void set_output_size (uint32_t width, uint32_t height); @@ -65,9 +65,25 @@ public: void set_lsc_table (float *table, uint32_t table_size); void set_lsc_gray_threshold (float min_threshold, float max_threshold); + void set_stable_y_start (float y_start); + virtual float get_stable_y_start () { + return _stable_y_start; + } + + void set_left_scale_factor (PointFloat2 factor); + void set_right_scale_factor (PointFloat2 factor); + + virtual PointFloat2 get_left_scale_factor () { + return _left_scale_factor; + } + virtual PointFloat2 get_right_scale_factor () { + return _right_scale_factor; + } + void set_bowl_config(const BowlDataConfig bowl_data_config) { _bowl_data_config = bowl_data_config; } + const BowlDataConfig &get_bowl_config() { return _bowl_data_config; } @@ -137,9 +153,14 @@ private: float _map_factor; bool _use_map; uint32_t _need_lsc; + uint32_t _need_scale; uint32_t _lsc_array_size; float _gray_threshold[2]; // [min_gray_threshold, max_gray_threshold] float *_lsc_array; + float _stable_y_start; + + PointFloat2 _left_scale_factor; + PointFloat2 _right_scale_factor; BowlDataConfig _bowl_data_config; @@ -155,7 +176,7 @@ private: }; SmartPtr<CLImageHandler> -create_fisheye_handler (const SmartPtr<CLContext> &context, SurroundMode surround_mode = SphereView, bool use_map = false, bool need_lsc = false); +create_fisheye_handler (const SmartPtr<CLContext> &context, SurroundMode surround_mode = SphereView, bool use_map = false, bool need_lsc = false, bool need_scale = false); } diff --git a/modules/ocl/cl_geo_map_handler.cpp b/modules/ocl/cl_geo_map_handler.cpp index 8151425..abba53f 100644 --- a/modules/ocl/cl_geo_map_handler.cpp +++ b/modules/ocl/cl_geo_map_handler.cpp @@ -34,10 +34,11 @@ static const XCamKernelInfo kernel_geo_map_info = { #define GEO_MAP_CHANNEL 4 /* only use channel_0, channel_1 */ CLGeoMapKernel::CLGeoMapKernel ( - const SmartPtr<CLContext> &context, const SmartPtr<GeoKernelParamCallback> handler, bool need_lsc) + const SmartPtr<CLContext> &context, const SmartPtr<GeoKernelParamCallback> handler, bool need_lsc, bool need_scale) : CLImageKernel (context) , _handler (handler) , _need_lsc (need_lsc) + , _need_scale (need_scale) { XCAM_ASSERT (handler.ptr ()); } @@ -62,6 +63,16 @@ CLGeoMapKernel::prepare_arguments (CLArgList &args, CLWorkSize &work_size) args.push_back (new CLMemArgument (geo_image)); args.push_back (new CLArgumentTArray<float, 2> (geo_scale_size)); + if (_need_scale) { + PointFloat2 left_scale_factor = _handler->get_left_scale_factor (); + PointFloat2 right_scale_factor = _handler->get_right_scale_factor (); + float stable_y_start = _handler->get_stable_y_start (); + + args.push_back (new CLArgumentT<PointFloat2> (left_scale_factor)); + args.push_back (new CLArgumentT<PointFloat2> (right_scale_factor)); + args.push_back (new CLArgumentT<float> (stable_y_start)); + } + if (_need_lsc) { SmartPtr<CLImage> lsc_image = _handler->get_lsc_table (); float *gray_threshold = _handler->get_lsc_gray_threshold (); @@ -319,14 +330,14 @@ CLGeoMapHandler::execute_done (SmartPtr<VideoBuffer> &output) SmartPtr<CLImageKernel> create_geo_map_kernel ( - const SmartPtr<CLContext> &context, SmartPtr<GeoKernelParamCallback> param_cb, bool need_lsc) + const SmartPtr<CLContext> &context, SmartPtr<GeoKernelParamCallback> param_cb, bool need_lsc, bool need_scale) { SmartPtr<CLImageKernel> kernel; - kernel = new CLGeoMapKernel (context, param_cb, need_lsc); + kernel = new CLGeoMapKernel (context, param_cb, need_lsc, need_scale); XCAM_ASSERT (kernel.ptr ()); char build_options[1024]; - snprintf (build_options, sizeof(build_options), "-DENABLE_LSC=%d", need_lsc ? 1 : 0); + snprintf (build_options, sizeof(build_options), "-DENABLE_LSC=%d -DENABLE_SCALE=%d", need_lsc ? 1 : 0, need_scale ? 1 : 0); XCAM_FAIL_RETURN ( ERROR, kernel->build_kernel (kernel_geo_map_info, build_options) == XCAM_RETURN_NO_ERROR, NULL, "build geo map kernel failed"); @@ -335,7 +346,7 @@ create_geo_map_kernel ( } SmartPtr<CLImageHandler> -create_geo_map_handler (const SmartPtr<CLContext> &context, bool need_lsc) +create_geo_map_handler (const SmartPtr<CLContext> &context, bool need_lsc, bool need_scale) { SmartPtr<CLGeoMapHandler> handler; SmartPtr<CLImageKernel> kernel; @@ -343,7 +354,7 @@ create_geo_map_handler (const SmartPtr<CLContext> &context, bool need_lsc) handler = new CLGeoMapHandler (context); XCAM_ASSERT (handler.ptr ()); - kernel = create_geo_map_kernel (context, handler, need_lsc); + kernel = create_geo_map_kernel (context, handler, need_lsc, need_scale); XCAM_FAIL_RETURN ( ERROR, kernel.ptr (), NULL, "CLMapHandler build geo map kernel failed"); handler->add_kernel (kernel); diff --git a/modules/ocl/cl_geo_map_handler.h b/modules/ocl/cl_geo_map_handler.h index a41ad27..4a79545 100644 --- a/modules/ocl/cl_geo_map_handler.h +++ b/modules/ocl/cl_geo_map_handler.h @@ -52,6 +52,10 @@ protected: virtual SmartPtr<CLImage> get_lsc_table () = 0; virtual float* get_lsc_gray_threshold() = 0; + virtual PointFloat2 get_left_scale_factor () = 0; + virtual PointFloat2 get_right_scale_factor () = 0; + + virtual float get_stable_y_start () = 0; private: XCAM_DEAD_COPY (GeoKernelParamCallback); }; @@ -64,7 +68,7 @@ public: explicit CLGeoMapKernel ( const SmartPtr<CLContext> &context, const SmartPtr<GeoKernelParamCallback> handler, - bool need_lsc); + bool need_lsc, bool need_scale); protected: virtual XCamReturn prepare_arguments (CLArgList &args, CLWorkSize &work_size); @@ -72,6 +76,7 @@ protected: private: SmartPtr<GeoKernelParamCallback> _handler; bool _need_lsc; + bool _need_scale; }; class CLGeoMapHandler @@ -122,6 +127,22 @@ protected: return NULL; } + virtual PointFloat2 get_left_scale_factor () { + XCAM_ASSERT (false && "CLGeoMapHandler::left_scale_factor is not supported"); + return PointFloat2 (0.0f, 0.0f); + } + + virtual PointFloat2 get_right_scale_factor () { + XCAM_ASSERT (false && "CLGeoMapHandler::right_scale_factor is not supported"); + return PointFloat2 (0.0f, 0.0f); + } + + virtual float get_stable_y_start () { + XCAM_ASSERT (false && "CLGeoMapHandler::get_stable_y_start is not supported"); + return 0.0f; + } + + protected: virtual XCamReturn prepare_buffer_pool_video_info ( const VideoBufferInfo &input, @@ -150,11 +171,11 @@ private: SmartPtr<CLImageKernel> create_geo_map_kernel ( - const SmartPtr<CLContext> &context, SmartPtr<GeoKernelParamCallback> param_cb, bool need_lsc); + const SmartPtr<CLContext> &context, SmartPtr<GeoKernelParamCallback> param_cb, bool need_lsc, bool need_scale); SmartPtr<CLImageHandler> -create_geo_map_handler (const SmartPtr<CLContext> &context, bool need_lsc = false); +create_geo_map_handler (const SmartPtr<CLContext> &context, bool need_lsc = false, bool need_scale = false); } -#endif //XCAM_CL_GEO_MAP_HANDLER_H
\ No newline at end of file +#endif //XCAM_CL_GEO_MAP_HANDLER_H diff --git a/modules/ocl/cl_image_360_stitch.cpp b/modules/ocl/cl_image_360_stitch.cpp index ae19b27..242e1b9 100644 --- a/modules/ocl/cl_image_360_stitch.cpp +++ b/modules/ocl/cl_image_360_stitch.cpp @@ -19,9 +19,12 @@ */ #include "cl_utils.h" +#include "cl_device.h" #include "cl_image_360_stitch.h" #if HAVE_OPENCV -#include "cv_feature_match.h" +#include "ocv/cv_feature_match.h" +#include "ocv/cv_feature_match_cluster.h" +#include <opencv2/core/ocl.hpp> #endif #define XCAM_BLENDER_GLOBAL_SCALE_EXT_WIDTH 64 @@ -109,10 +112,10 @@ CLBlenderGlobalScaleKernel::get_output_info ( } #if HAVE_OPENCV -static CVFMConfig -get_fm_default_config (StitchResMode res_mode) +static FMConfig +get_fm_sphere_config (StitchResMode res_mode) { - CVFMConfig config; + FMConfig config; switch (res_mode) { case StitchRes1080P: { @@ -158,6 +161,22 @@ get_fm_default_config (StitchResMode res_mode) return config; } + +static FMConfig +get_fm_bowl_config () +{ + FMConfig config; + config.sitch_min_width = 136; + config.min_corners = 4; + config.offset_factor = 0.95f; + config.delta_mean_offset = 120.0f; + config.recur_offset_error = 8.0f; + config.max_adjusted_offset = 24.0f; + config.max_valid_offset_y = 20.0f; + config.max_track_error = 28.0f; + + return config; +} #endif static StitchInfo @@ -280,17 +299,25 @@ CLImage360Stitch::CLImage360Stitch ( , _scale_mode (scale_mode) , _surround_mode (surround_mode) , _res_mode (res_mode) + , _enable_fm (true) , _is_stitch_inited (false) , _fisheye_num (fisheye_num) , _all_in_one_img (all_in_one_img) { +#if !HAVE_OPENCV + _enable_fm = false; +#endif +} + +void +CLImage360Stitch::set_feature_match (bool enable) +{ #if HAVE_OPENCV - for (int i = 0; i < fisheye_num; i++) { - _feature_match[i] = new CVFeatureMatch (); - XCAM_ASSERT (_feature_match[i].ptr ()); - _feature_match[i]->set_config (get_fm_default_config (res_mode)); - _feature_match[i]->set_fm_index (i); - } + _enable_fm = enable; +#else + if (enable) + XCAM_LOG_WARNING ("non-OpenCV mode, feature match is unsupported, disable feature match"); + _enable_fm = false; #endif } @@ -371,33 +398,6 @@ CLImage360Stitch::set_image_overlap (const int idx, const Rect &overlap0, const } void -CLImage360Stitch::set_feature_match_ocl (bool fm_ocl) -{ -#if HAVE_OPENCV - for (int i = 0; i < _fisheye_num; i++) { - _feature_match[i]->set_ocl (fm_ocl); - } -#else - XCAM_UNUSED (fm_ocl); - XCAM_LOG_WARNING ("non-OpenCV mode, failed to set ocl for feature match"); -#endif -} - -#if HAVE_OPENCV -void -CLImage360Stitch::set_feature_match_config (const int idx, CVFMConfig config) -{ - _feature_match[idx]->set_config (config); -} - -CVFMConfig -CLImage360Stitch::get_feature_match_config (const int idx) -{ - return _feature_match[idx]->get_config (); -} -#endif - -void CLImage360Stitch::calc_fisheye_initial_info (SmartPtr<VideoBuffer> &output) { const VideoBufferInfo &out_info = output->get_video_info (); @@ -431,23 +431,15 @@ CLImage360Stitch::calc_fisheye_initial_info (SmartPtr<VideoBuffer> &output) } else { _fisheye[0].height = out_info.height + _stitch_info.crop[0].top + _stitch_info.crop[0].bottom; - float view_angle[XCAM_STITCH_FISHEYE_MAX_NUM]; - - view_angle[0] = 68.0f; - _fisheye[0].width = view_angle[0] / 360.0f * out_info.width; - _fisheye[0].width = XCAM_ALIGN_UP (_fisheye[0].width, 32); - - view_angle[1] = 152.0f; - _fisheye[1].width = view_angle[1] / 360.0f * out_info.width; - _fisheye[1].width = XCAM_ALIGN_UP (_fisheye[1].width, 32); + float view_angle[XCAM_STITCH_FISHEYE_MAX_NUM] = { + 64.0f, 158.0f, 60.0f, 158.0f + }; - view_angle[2] = 68.0f; - _fisheye[2].width = view_angle[2] / 360.0f * out_info.width; - _fisheye[2].width = XCAM_ALIGN_UP (_fisheye[2].width, 32); - - view_angle[3] = 152.0f; - _fisheye[3].width = view_angle[3] / 360.0f * out_info.width; - _fisheye[3].width = XCAM_ALIGN_UP (_fisheye[3].width, 32); + XCAM_ASSERT (_fisheye_num <= XCAM_STITCH_FISHEYE_MAX_NUM); + for (int i = 0; i < _fisheye_num; i++) { + _fisheye[i].width = view_angle[i] / 360.0f * out_info.width; + _fisheye[i].width = XCAM_ALIGN_UP (_fisheye[i].width, 32); + } XCAM_LOG_INFO ( "fisheye correction output size width:%d height:%d", @@ -465,13 +457,26 @@ CLImage360Stitch::calc_fisheye_initial_info (SmartPtr<VideoBuffer> &output) bowl_data_config[i].angle_end = angle_center + view_angle[i] / 2; } + float wall_image_height = bowl_data_config[0].wall_height / + (float)(bowl_data_config[0].wall_height + bowl_data_config[0].ground_length) * + _fisheye[0].height; + float stable_y_start = (wall_image_height + _fisheye[0].height ) / 2.0f; + + if (stable_y_start < 0.5f) + stable_y_start = 1.0f; + for(int i = 0; i < _fisheye_num; i++) { + _fisheye[i].handler->set_stable_y_start (stable_y_start); _fisheye[i].handler->set_bowl_config(bowl_data_config[i]); _fisheye[i].handler->set_output_size (_fisheye[i].width, _fisheye[i].height); } - for(int i = 0; i < _fisheye_num; i++) { - _stitch_info.merge_width[i] = XCAM_ALIGN_UP((uint32_t)(20.0f / 360.0f * out_info.width), 32); + int idx_next; + for (int i = 0; i < _fisheye_num; i++) { + idx_next = (i == (_fisheye_num - 1)) ? 0 : (i + 1); + + _stitch_info.merge_width[idx_next] = _fisheye[i].width / 2 + _fisheye[idx_next].width / 2 - out_info.width / _fisheye_num; + _stitch_info.merge_width[idx_next] = XCAM_ALIGN_UP (_stitch_info.merge_width[idx_next], 32); } } } @@ -677,13 +682,14 @@ CLImage360Stitch::create_buffer_pool (SmartPtr<BufferPool> &buf_pool, uint32_t w buf_info.init (V4L2_PIX_FMT_NV12, width, height, XCAM_ALIGN_UP (width, 16), XCAM_ALIGN_UP (height, 16)); - buf_pool = new CLVideoBufferPool (); - XCAM_ASSERT (buf_pool.ptr ()); - buf_pool->set_video_info (buf_info); - if (!buf_pool->reserve (6)) { + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + XCAM_ASSERT (pool.ptr ()); + pool->set_video_info (buf_info); + if (!pool->reserve (6)) { XCAM_LOG_ERROR ("CLImage360Stitch init buffer pool failed"); return false; } + buf_pool = pool; return true; } @@ -710,12 +716,63 @@ CLImage360Stitch::reset_buffer_info (SmartPtr<VideoBuffer> &input) return XCAM_RETURN_NO_ERROR; } +void +CLImage360Stitch::init_opencv_ocl () +{ +#if HAVE_OPENCV + if (!cv::ocl::haveOpenCL ()) { + XCAM_LOG_ERROR ("OpenCV does not support OpenCL"); + XCAM_ASSERT (false); + } + + char *platform_name = CLDevice::instance()->get_platform_name (); + cl_platform_id platform_id = CLDevice::instance()->get_platform_id (); + cl_device_id device_id = CLDevice::instance()->get_device_id (); + cl_context context_id = _context->get_context_id (); + cv::ocl::attachContext (platform_name, platform_id, context_id, device_id); + cv::ocl::setUseOpenCL (false); +#else + XCAM_LOG_ERROR ("non-OpenCV mode, failed to initialize opencv ocl"); +#endif +} + +void +CLImage360Stitch::init_feature_match () +{ +#if HAVE_OPENCV + bool is_sphere = (_surround_mode == SphereView); + const FMConfig &config = is_sphere ? get_fm_sphere_config (_res_mode) : get_fm_bowl_config (); + + for (int i = 0; i < _fisheye_num; i++) { + if (is_sphere) { + _feature_match[i] = FeatureMatch::create_default_feature_match (); + _feature_match[i]->enable_adjust_crop_area (); + } else { + _feature_match[i] = FeatureMatch::create_cluster_feature_match (); + } + XCAM_ASSERT (_feature_match[i].ptr ()); + + _feature_match[i]->set_fm_index (i); + _feature_match[i]->set_config (config); + } +#else + XCAM_LOG_ERROR ("non-OpenCV mode, failed to initialize feature match"); +#endif +} + XCamReturn CLImage360Stitch::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output) { XCamReturn ret = XCAM_RETURN_NO_ERROR; - if (!_is_stitch_inited) + if (!_is_stitch_inited) { +#if HAVE_OPENCV + if (_enable_fm) { + init_opencv_ocl (); + init_feature_match (); + } +#endif set_stitch_info (get_default_stitch_info (_res_mode)); + } ret = ensure_fisheye_parameters (input, output); STITCH_CHECK (ret, "ensure fisheye parameters failed"); @@ -768,44 +825,106 @@ CLImage360Stitch::prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<Vid XCamReturn CLImage360Stitch::execute_done (SmartPtr<VideoBuffer> &output) { + get_context ()->finish (); + return CLMultiImageHandler::execute_done (output); +} + +void +CLImage360Stitch::update_scale_factors (uint32_t fm_idx, const Rect &crop_left, const Rect &crop_right) +{ #if HAVE_OPENCV - for (int i = 0; i < _fisheye_num; i++) { - if (!_feature_match[i]->is_ocl_path ()) { - get_context ()->finish (); - break; - } - } + float left_offsetx = _feature_match[fm_idx]->get_current_left_offset_x (); + float left_offsety = _feature_match[fm_idx]->get_current_left_offset_y (); + PointFloat2 left_factor, right_factor; + + uint32_t left_idx = fm_idx; + float center_x = (float) _fisheye[left_idx].width / 2; + float feature_center_x = (float)crop_left.pos_x + crop_left.width / 2.0f; + float range = feature_center_x - center_x; + XCAM_ASSERT (range > 1.0f); + right_factor.x = (range + left_offsetx / 2.0f) / range; + right_factor.y = (_fisheye[left_idx].handler->get_stable_y_start () - left_offsety / 2.0f) / + _fisheye[left_idx].handler->get_stable_y_start (); + XCAM_ASSERT (right_factor.x > 0.0f && right_factor.x < 2.0f); + + uint32_t right_idx = (fm_idx + 1) % _fisheye_num; + center_x = (float)_fisheye[right_idx].width / 2; + feature_center_x = (float)crop_right.pos_x + crop_right.width / 2.0f; + range = center_x - feature_center_x; + XCAM_ASSERT (range > 1.0f); + left_factor.x = (range + left_offsetx / 2.0f) / range; + left_factor.y = (_fisheye[left_idx].handler->get_stable_y_start () + left_offsety / 2.0f) / + _fisheye[left_idx].handler->get_stable_y_start (); + XCAM_ASSERT (left_factor.x > 0.0f && left_factor.x < 2.0f); + + PointFloat2 last_left_factor, last_right_factor; + last_left_factor = _fisheye[right_idx].handler->get_left_scale_factor (); + last_right_factor = _fisheye[left_idx].handler->get_right_scale_factor (); + + left_factor.x *= last_left_factor.x; + left_factor.y *= last_left_factor.y; + right_factor.x *= last_right_factor.x; + right_factor.y *= last_right_factor.y; + + _fisheye[left_idx].handler->set_right_scale_factor (right_factor); + _fisheye[right_idx].handler->set_left_scale_factor (left_factor); +#else + XCAM_LOG_ERROR ("non-OpenCV mode, failed to update scale factors"); #endif +} + +void +CLImage360Stitch::set_fm_buf_mem ( + const SmartPtr<VideoBuffer> &buf_left, const SmartPtr<VideoBuffer> &buf_right, int fm_idx) +{ +#if HAVE_OPENCV + SmartPtr<CVFeatureMatch> fm = _feature_match[fm_idx].dynamic_cast_ptr<CVFeatureMatch> (); + XCAM_ASSERT (fm.ptr ()); - _scale_global_input.release (); - _scale_global_output.release (); + SmartPtr<CLBuffer> cl_buf_left = convert_to_clbuffer (_context, buf_left); + SmartPtr<CLBuffer> cl_buf_right = convert_to_clbuffer (_context, buf_right); + XCAM_ASSERT (cl_buf_left.ptr () && cl_buf_left.ptr ()); + cl_mem mem_left = cl_buf_left->get_mem_id (); + cl_mem mem_right = cl_buf_right->get_mem_id (); - return CLMultiImageHandler::execute_done (output); + fm->set_cl_buf_mem (mem_left, CVFeatureMatch::BufIdLeft); + fm->set_cl_buf_mem (mem_right, CVFeatureMatch::BufIdRight); +#else + XCAM_LOG_ERROR ("non-OpenCV mode, failed to set feature match buffer memory"); +#endif } +#if HAVE_OPENCV static void -convert_to_stitch_rect (Rect xcam_rect, Rect &stitch_rect) +convert_to_stitch_rect (const Rect &xcam_rect, Rect &stitch_rect, SurroundMode surround_mode) { stitch_rect.pos_x = xcam_rect.pos_x; - stitch_rect.pos_y = xcam_rect.pos_y + xcam_rect.height / 3; stitch_rect.width = xcam_rect.width; - stitch_rect.height = xcam_rect.height / 3; + if (surround_mode == SphereView) { + stitch_rect.pos_y = xcam_rect.pos_y + xcam_rect.height / 3; + stitch_rect.height = xcam_rect.height / 3; + } else { + stitch_rect.pos_y = xcam_rect.pos_y + xcam_rect.height / 5; + stitch_rect.height = xcam_rect.height / 2; + } } static void -convert_to_xcam_rect (Rect stitch_rect, Rect &xcam_rect) +convert_to_xcam_rect (const Rect &stitch_rect, Rect &xcam_rect) { xcam_rect.pos_x = stitch_rect.pos_x; xcam_rect.width = stitch_rect.width; } - +#endif XCamReturn CLImage360Stitch::sub_handler_execute_done (SmartPtr<CLImageHandler> &handler) { #if HAVE_OPENCV - XCAM_ASSERT (handler.ptr ()); + if (!_enable_fm) + return XCAM_RETURN_NO_ERROR; + XCAM_ASSERT (handler.ptr ()); if (handler.ptr () == _fisheye[_fisheye_num - 1].handler.ptr ()) { int idx_next = 1; Rect crop_left, crop_right; @@ -813,14 +932,25 @@ CLImage360Stitch::sub_handler_execute_done (SmartPtr<CLImageHandler> &handler) for (int i = 0; i < _fisheye_num; i++) { idx_next = (i == (_fisheye_num - 1)) ? 0 : (i + 1); - convert_to_stitch_rect (_img_merge_info[i].right, crop_left); - convert_to_stitch_rect (_img_merge_info[idx_next].left, crop_right); + set_fm_buf_mem (_fisheye[i].buf, _fisheye[idx_next].buf, i); - _feature_match[i]->optical_flow_feature_match ( - _fisheye[i].buf, _fisheye[idx_next].buf, crop_left, crop_right, _fisheye[i].width); + convert_to_stitch_rect (_img_merge_info[i].right, crop_left, _surround_mode); + convert_to_stitch_rect (_img_merge_info[idx_next].left, crop_right, _surround_mode); + if (_surround_mode == SphereView) { + _feature_match[i]->set_dst_width (_fisheye[i].width); + _feature_match[i]->set_crop_rect (crop_left, crop_right); + _feature_match[i]->feature_match (_fisheye[i].buf, _fisheye[idx_next].buf); - convert_to_xcam_rect (crop_left, _img_merge_info[i].right); - convert_to_xcam_rect (crop_right, _img_merge_info[idx_next].left); + _feature_match[i]->get_crop_rect (crop_left, crop_right); + convert_to_xcam_rect (crop_left, _img_merge_info[i].right); + convert_to_xcam_rect (crop_right, _img_merge_info[idx_next].left); + } else { + _feature_match[i]->reset_offsets (); + _feature_match[i]->set_crop_rect (crop_left, crop_right); + _feature_match[i]->feature_match (_fisheye[i].buf, _fisheye[idx_next].buf); + + update_scale_factors (i, crop_left, crop_right); + } } } #else @@ -871,8 +1001,10 @@ create_image_360_stitch ( context, scale_mode, surround_mode, res_mode, fisheye_num, all_in_one_img); XCAM_ASSERT (stitch.ptr ()); + bool need_scale = (surround_mode == BowlView) ? true : false; + for (int index = 0; index < fisheye_num; ++index) { - fisheye = create_fisheye_handler (context, surround_mode, fisheye_map, need_lsc).dynamic_cast_ptr<CLFisheyeHandler> (); + fisheye = create_fisheye_handler (context, surround_mode, fisheye_map, need_lsc, need_scale).dynamic_cast_ptr<CLFisheyeHandler> (); XCAM_FAIL_RETURN (ERROR, fisheye.ptr (), NULL, "image_360_stitch create fisheye handler failed"); fisheye->disable_buf_pool (true); stitch->set_fisheye_handler (fisheye, index); diff --git a/modules/ocl/cl_image_360_stitch.h b/modules/ocl/cl_image_360_stitch.h index 2c6babf..c164d4b 100644 --- a/modules/ocl/cl_image_360_stitch.h +++ b/modules/ocl/cl_image_360_stitch.h @@ -66,6 +66,8 @@ public: const SmartPtr<CLContext> &context, CLBlenderScaleMode scale_mode, SurroundMode surround_mode, StitchResMode res_mode, int fisheye_num, bool all_in_one_img); + void set_feature_match (bool enable); + bool set_stitch_info (StitchInfo stitch_info); StitchInfo get_stitch_info (); void set_output_size (uint32_t width, uint32_t height) { @@ -94,12 +96,6 @@ public: return _scale_global_output; } - void set_feature_match_ocl (bool use_ocl); -#if HAVE_OPENCV - void set_feature_match_config (const int idx, CVFMConfig config); - CVFMConfig get_feature_match_config (const int idx); -#endif - protected: virtual XCamReturn prepare_buffer_pool_video_info (const VideoBufferInfo &input, VideoBufferInfo &output); virtual XCamReturn prepare_parameters (SmartPtr<VideoBuffer> &input, SmartPtr<VideoBuffer> &output); @@ -121,13 +117,19 @@ protected: void update_image_overlap (); private: + void init_opencv_ocl (); + void init_feature_match (); + void update_scale_factors (uint32_t fm_idx, const Rect &crop_left, const Rect &crop_right); + void set_fm_buf_mem ( + const SmartPtr<VideoBuffer> &buf_left, const SmartPtr<VideoBuffer> &buf_right, int fm_idx); + +private: XCAM_DEAD_COPY (CLImage360Stitch); private: SmartPtr<CLContext> _context; CLFisheyeParams _fisheye[XCAM_STITCH_FISHEYE_MAX_NUM]; SmartPtr<CLBlender> _blender[XCAM_STITCH_FISHEYE_MAX_NUM]; - SmartPtr<FeatureMatch> _feature_match[XCAM_STITCH_FISHEYE_MAX_NUM]; uint32_t _output_width; uint32_t _output_height; @@ -142,6 +144,9 @@ private: SurroundMode _surround_mode; StitchResMode _res_mode; + bool _enable_fm; + SmartPtr<FeatureMatch> _feature_match[XCAM_STITCH_FISHEYE_MAX_NUM]; + bool _is_stitch_inited; int _fisheye_num; bool _all_in_one_img; diff --git a/modules/ocl/cl_image_handler.cpp b/modules/ocl/cl_image_handler.cpp index f9fc56c..2fb87ab 100644 --- a/modules/ocl/cl_image_handler.cpp +++ b/modules/ocl/cl_image_handler.cpp @@ -25,6 +25,7 @@ #include "drm_bo_buffer.h" #endif #include "cl_device.h" +#include "cl_video_buffer.h" #include "swapped_buffer.h" namespace XCam { @@ -167,9 +168,9 @@ CLImageHandler::create_buffer_pool (const VideoBufferInfo &video_info) if (_buf_pool.ptr ()) return XCAM_RETURN_ERROR_PARAM; - SmartPtr<BufferPool> buffer_pool; if (_buf_pool_type == CLImageHandler::CLVideoPoolType) { - buffer_pool = new CLVideoBufferPool (); + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + _buf_pool = pool.ptr() ? pool : _buf_pool; } #if HAVE_LIBDRM else { @@ -181,30 +182,29 @@ CLImageHandler::create_buffer_pool (const VideoBufferInfo &video_info) "CLImageHandler(%s) failed to get drm dispay", XCAM_STR (_name)); if (_buf_pool_type == CLImageHandler::DrmBoPoolType) { - buffer_pool = new DrmBoBufferPool (display); + SmartPtr<BufferPool> pool = new DrmBoBufferPool (display); + _buf_pool = pool.ptr() ? pool : _buf_pool; } else if (_buf_pool_type == CLImageHandler::CLBoPoolType) { - buffer_pool = new CLBoBufferPool (display, get_context ()); + SmartPtr<BufferPool> pool = new CLBoBufferPool (display, get_context ()); + _buf_pool = pool.ptr() ? pool : _buf_pool; } } #endif XCAM_FAIL_RETURN( WARNING, - buffer_pool.ptr (), + _buf_pool.ptr (), XCAM_RETURN_ERROR_CL, "CLImageHandler(%s) create buffer pool failed, pool_type:%d", XCAM_STR (_name), (int32_t)_buf_pool_type); - XCAM_ASSERT (buffer_pool.ptr ()); // buffer_pool->set_swap_flags (_buf_swap_flags, _buf_swap_init_order); - buffer_pool->set_video_info (video_info); - + _buf_pool->set_video_info (video_info); XCAM_FAIL_RETURN( WARNING, - buffer_pool->reserve (_buf_pool_size), + _buf_pool->reserve (_buf_pool_size), XCAM_RETURN_ERROR_CL, "CLImageHandler(%s) failed to init drm buffer pool", XCAM_STR (_name)); - _buf_pool = buffer_pool; return XCAM_RETURN_NO_ERROR; } diff --git a/modules/ocl/cl_image_handler.h b/modules/ocl/cl_image_handler.h index 45c1b31..dd32da7 100644 --- a/modules/ocl/cl_image_handler.h +++ b/modules/ocl/cl_image_handler.h @@ -27,11 +27,11 @@ #include <ocl/cl_kernel.h> #include <ocl/cl_argument.h> #include <ocl/cl_memory.h> -#include <ocl/cl_video_buffer.h> namespace XCam { class CLImageHandler; +class X3aResult; class CLImageKernel : public CLKernel diff --git a/modules/ocl/cl_image_processor.cpp b/modules/ocl/cl_image_processor.cpp index c0cbd98..a4c178d 100644 --- a/modules/ocl/cl_image_processor.cpp +++ b/modules/ocl/cl_image_processor.cpp @@ -83,11 +83,13 @@ CLImageProcessor::CLImageProcessor (const char* name) _context = CLDevice::instance ()->get_context (); XCAM_ASSERT (_context.ptr()); - _handler_thread = new CLHandlerThread (this); - XCAM_ASSERT (_handler_thread.ptr ()); + SmartPtr<CLHandlerThread> handler_thread = new CLHandlerThread (this); + XCAM_ASSERT (handler_thread.ptr ()); + _handler_thread = handler_thread; - _done_buf_thread = new CLBufferNotifyThread (this); - XCAM_ASSERT (_done_buf_thread.ptr ()); + SmartPtr<CLBufferNotifyThread> done_buf_thread = new CLBufferNotifyThread (this); + XCAM_ASSERT (done_buf_thread.ptr ()); + _done_buf_thread = done_buf_thread; XCAM_LOG_DEBUG ("CLImageProcessor constructed"); XCAM_OBJ_PROFILING_INIT; diff --git a/modules/ocl/cl_image_scaler.cpp b/modules/ocl/cl_image_scaler.cpp index c888b36..171ca30 100644 --- a/modules/ocl/cl_image_scaler.cpp +++ b/modules/ocl/cl_image_scaler.cpp @@ -219,10 +219,11 @@ CLImageScaler::prepare_scaler_buf (const VideoBufferInfo &video_info, SmartPtr<V scaler_video_info.init (video_info.format, new_width, new_height); - _scaler_buf_pool = new CLVideoBufferPool (); - XCAM_ASSERT (_scaler_buf_pool.ptr ()); - _scaler_buf_pool->set_video_info (scaler_video_info); - _scaler_buf_pool->reserve (6); + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + XCAM_ASSERT (pool.ptr ()); + pool->set_video_info (scaler_video_info); + pool->reserve (6); + _scaler_buf_pool = pool; } output = _scaler_buf_pool->get_buffer (_scaler_buf_pool); diff --git a/modules/ocl/cl_kernel.cpp b/modules/ocl/cl_kernel.cpp index fdda8ec..47574b6 100644 --- a/modules/ocl/cl_kernel.cpp +++ b/modules/ocl/cl_kernel.cpp @@ -34,14 +34,16 @@ namespace XCam { CLKernel::KernelMap CLKernel::_kernel_map; Mutex CLKernel::_kernel_map_mutex; -static char* +static const char* default_cache_path () { - static char path[XCAM_MAX_STR_SIZE] = {0}; - snprintf ( - path, XCAM_MAX_STR_SIZE - 1, - "%s/%s", std::getenv ("HOME"), ".xcam/"); + static std::string path = "/tmp"; + const char *home_dir = std::getenv ("HOME"); + if (home_dir) + path.assign (home_dir, strlen (home_dir)); + + path += "/.xcam"; - return path; + return path.c_str (); } const char* CLKernel::_kernel_cache_path = default_cache_path (); @@ -134,15 +136,15 @@ CLKernel::build_kernel (const XCamKernelInfo& info, const char* options) bool load_cache = false; struct timeval ts; - const char* cache_path = std::getenv ("XCAM_CL_KERNEL_CACHE_PATH"); - if (NULL == cache_path) { - cache_path = _kernel_cache_path; - } + std::string cache_path = _kernel_cache_path; + const char *env = std::getenv ("XCAM_CL_KERNEL_CACHE_PATH"); + if (env) + cache_path.assign (env, strlen (env)); snprintf ( cache_filename, XCAM_MAX_STR_SIZE - 1, "%s/%s", - cache_path, key_str); + cache_path.c_str (), key_str); { SmartLock locker (_kernel_map_mutex); @@ -153,8 +155,8 @@ CLKernel::build_kernel (const XCamKernelInfo& info, const char* options) single_kernel = new CLKernel (context, info.kernel_name); XCAM_ASSERT (single_kernel.ptr ()); - if (access (cache_path, F_OK) == -1) { - mkdir (cache_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (access (cache_path.c_str (), F_OK) == -1) { + mkdir (cache_path.c_str (), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } ret = cache_file.open (cache_filename, "r"); diff --git a/modules/ocl/cl_post_image_processor.cpp b/modules/ocl/cl_post_image_processor.cpp index ebe9319..21d230b 100644 --- a/modules/ocl/cl_post_image_processor.cpp +++ b/modules/ocl/cl_post_image_processor.cpp @@ -59,7 +59,6 @@ CLPostImageProcessor::CLPostImageProcessor () , _stitch_enable_seam (false) , _stitch_fisheye_map (false) , _stitch_lsc (false) - , _stitch_fm_ocl (false) , _stitch_scale_mode (CLBlenderScaleLocal) , _stitch_width (0) , _stitch_height (0) @@ -411,9 +410,6 @@ CLPostImageProcessor::create_handlers () XCAM_RETURN_ERROR_CL, "CLPostImageProcessor create image stitch handler failed"); _stitch->set_output_size (_stitch_width, _stitch_height); -#if HAVE_OPENCV - _stitch->set_feature_match_ocl (_stitch_fm_ocl); -#endif image_handler->set_pool_type (CLImageHandler::CLVideoPoolType); image_handler->set_pool_size (XCAM_CL_POST_IMAGE_MAX_POOL_SIZE); image_handler->enable_handler (_enable_stitch); @@ -512,7 +508,7 @@ CLPostImageProcessor::set_image_warp (bool enable) bool CLPostImageProcessor::set_image_stitch ( bool enable_stitch, bool enable_seam, CLBlenderScaleMode scale_mode, bool enable_fisheye_map, - bool lsc, bool fm_ocl, uint32_t stitch_width, uint32_t stitch_height, uint32_t res_mode) + bool lsc, uint32_t stitch_width, uint32_t stitch_height, uint32_t res_mode) { XCAM_ASSERT (scale_mode < CLBlenderScaleMax); @@ -529,12 +525,6 @@ CLPostImageProcessor::set_image_stitch ( _stitch_height = stitch_height; _stitch_res_mode = res_mode; -#if HAVE_OPENCV - _stitch_fm_ocl = fm_ocl; -#else - XCAM_UNUSED (fm_ocl); -#endif - STREAM_LOCK; return true; diff --git a/modules/ocl/cl_post_image_processor.h b/modules/ocl/cl_post_image_processor.h index a06e007..43e7052 100644 --- a/modules/ocl/cl_post_image_processor.h +++ b/modules/ocl/cl_post_image_processor.h @@ -95,7 +95,7 @@ public: virtual bool set_image_warp (bool enable); virtual bool set_image_stitch ( bool enable_stitch, bool enable_seam, CLBlenderScaleMode scale_mode, bool enable_fisheye_map, - bool lsc, bool fm_ocl, uint32_t stitch_width, uint32_t stitch_height, uint32_t res_mode); + bool lsc, uint32_t stitch_width, uint32_t stitch_height, uint32_t res_mode); protected: virtual bool can_process_result (SmartPtr<X3aResult> &result); @@ -141,7 +141,6 @@ private: bool _stitch_enable_seam; bool _stitch_fisheye_map; bool _stitch_lsc; - bool _stitch_fm_ocl; CLBlenderScaleMode _stitch_scale_mode; uint32_t _stitch_width; uint32_t _stitch_height; diff --git a/modules/ocl/cl_retinex_handler.cpp b/modules/ocl/cl_retinex_handler.cpp index 79b5dd1..547d033 100644 --- a/modules/ocl/cl_retinex_handler.cpp +++ b/modules/ocl/cl_retinex_handler.cpp @@ -234,10 +234,11 @@ CLRetinexImageHandler::prepare_scaler_buf (const VideoBufferInfo &video_info) scaler_video_info.init (video_info.format, new_width, new_height); - _scaler_buf_pool = new CLVideoBufferPool (); - XCAM_ASSERT (_scaler_buf_pool.ptr ()); - _scaler_buf_pool->set_video_info (scaler_video_info); - _scaler_buf_pool->reserve (XCAM_RETINEX_MAX_SCALE + 1); + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + XCAM_ASSERT (pool.ptr ()); + pool->set_video_info (scaler_video_info); + pool->reserve (XCAM_RETINEX_MAX_SCALE + 1); + _scaler_buf_pool = pool; _scaler_buf1 = _scaler_buf_pool->get_buffer (_scaler_buf_pool); XCAM_ASSERT (_scaler_buf1.ptr ()); diff --git a/modules/ocl/cl_utils.cpp b/modules/ocl/cl_utils.cpp index b8ce3a9..831850e 100644 --- a/modules/ocl/cl_utils.cpp +++ b/modules/ocl/cl_utils.cpp @@ -317,8 +317,8 @@ generate_rectifiedview_map_table ( for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { float plane_point_coords[3]; - plane_point_coords[0] = (center_x - col) * length_per_pixel_x * cos (PI / 2 - degree2radian (angle_center)) + plane_center_coords[0]; - plane_point_coords[1] = (center_x - col) * length_per_pixel_x * sin (PI / 2 - degree2radian (angle_center)) + plane_center_coords[1]; + plane_point_coords[0] = (center_x - col) * length_per_pixel_x * cos (XCAM_PI / 2 - degree2radian (angle_center)) + plane_center_coords[0]; + plane_point_coords[1] = (center_x - col) * length_per_pixel_x * sin (XCAM_PI / 2 - degree2radian (angle_center)) + plane_center_coords[1]; plane_point_coords[2] = (center_y - row) * length_per_pixel_y + plane_center_coords[2]; float rate_xz, rate_yz; diff --git a/modules/ocl/cl_video_buffer.cpp b/modules/ocl/cl_video_buffer.cpp index 032dd3d..c16d665 100644 --- a/modules/ocl/cl_video_buffer.cpp +++ b/modules/ocl/cl_video_buffer.cpp @@ -22,6 +22,7 @@ #include "ocl/cl_memory.h" #include "ocl/cl_device.h" #include "ocl/cl_video_buffer.h" +#include "x3a_stats_pool.h" namespace XCam { diff --git a/modules/ocl/cl_video_buffer.h b/modules/ocl/cl_video_buffer.h index 969bff1..e44e023 100644 --- a/modules/ocl/cl_video_buffer.h +++ b/modules/ocl/cl_video_buffer.h @@ -25,13 +25,13 @@ #include <safe_list.h> #include <xcam_mutex.h> #include <buffer_pool.h> -#include <x3a_stats_pool.h> #include <ocl/cl_context.h> namespace XCam { class CLBuffer; class CLVideoBufferPool; +class X3aStats; class CLVideoBufferData : public BufferData diff --git a/modules/ocl/cv_base_class.cpp b/modules/ocl/cv_base_class.cpp deleted file mode 100644 index 7dbecaa..0000000 --- a/modules/ocl/cv_base_class.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * cv_base_class.cpp - base class for all OpenCV related features - * - * Copyright (c) 2016-2017 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: Andrey Parfenov <a1994ndrey@gmail.com> - * Author: Wind Yuan <feng.yuan@intel.com> - */ - -#include "cv_base_class.h" - -namespace XCam { - -CVBaseClass::CVBaseClass () -{ - _cv_context = CVContext::instance (); - XCAM_ASSERT (_cv_context.ptr ()); - _use_ocl = _cv_context->is_ocl_enabled (); -} - -bool -CVBaseClass::set_ocl (bool use_ocl) -{ - if (use_ocl && !_cv_context->is_ocl_enabled ()) { - return false; - } - _use_ocl = use_ocl; - return true; -} - -bool -CVBaseClass::convert_to_mat (SmartPtr<VideoBuffer> buffer, cv::Mat &image) -{ - - VideoBufferInfo info = buffer->get_video_info (); - XCAM_FAIL_RETURN (WARNING, info.format == V4L2_PIX_FMT_NV12, false, "convert_to_mat only support NV12 format"); - - uint8_t *ptr = buffer->map (); - XCAM_FAIL_RETURN (WARNING, ptr, false, "convert_to_mat buffer map failed"); - - cv::Mat mat = cv::Mat (info.aligned_height * 3 / 2, info.width, CV_8UC1, ptr, info.strides[0]); - cv::cvtColor (mat, image, cv::COLOR_YUV2BGR_NV12); - //buffer->unmap (); - - return true; -} - -bool -convert_to_mat (SmartPtr<VideoBuffer> buffer, cv::Mat &image) -{ - CVBaseClass cv_obj; - return cv_obj.convert_to_mat (buffer, image); -} - -} diff --git a/modules/ocl/cv_base_class.h b/modules/ocl/cv_base_class.h deleted file mode 100644 index 70641c2..0000000 --- a/modules/ocl/cv_base_class.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * cv_base_class.h - base class for all OpenCV related features - * - * Copyright (c) 2016-2017 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: Andrey Parfenov <a1994ndrey@gmail.com> - * Author: Wind Yuan <feng.yuan@intel.com> - */ - -#ifndef XCAM_CV_BASE_CLASS_H -#define XCAM_CV_BASE_CLASS_H - -#include <xcam_std.h> -#include <video_buffer.h> -#include <ocl/cv_context.h> - -namespace XCam { - -class CVBaseClass -{ -public: - explicit CVBaseClass (); - bool set_ocl (bool use_ocl); - bool is_ocl_path () { - return _use_ocl; - } - bool convert_to_mat (SmartPtr<VideoBuffer> buffer, cv::Mat &image); - -protected: - XCAM_DEAD_COPY (CVBaseClass); - SmartPtr<CVContext> _cv_context; - bool _use_ocl; -}; - -extern bool -convert_to_mat (SmartPtr<VideoBuffer> buffer, cv::Mat &image); - -} - -#endif // XCAM_CV_BASE_CLASS_H diff --git a/modules/ocl/cv_context.cpp b/modules/ocl/cv_context.cpp deleted file mode 100644 index babf5ef..0000000 --- a/modules/ocl/cv_context.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * cv_context.cpp - used to init_opencv_ocl once - * - * Copyright (c) 2016-2017 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: Andrey Parfenov <a1994ndrey@gmail.com> - * Author: Wind Yuan <feng.yuan@intel.com> - */ - -#include "cv_context.h" -#include "cl_device.h" -#include "cl_memory.h" - -namespace XCam { - -Mutex CVContext::_init_mutex; -SmartPtr<CVContext> CVContext::_instance; - - -SmartPtr<CVContext> -CVContext::instance () -{ - SmartLock locker (_init_mutex); - if (_instance.ptr()) - return _instance; - - _instance = new CVContext (); - _instance->init_opencv_ocl (); - return _instance; -} - -void -CVContext::init_opencv_ocl () -{ - _context = CLDevice::instance()->get_context(); - cl_platform_id platform_id = CLDevice::instance()->get_platform_id (); - char *platform_name = CLDevice::instance()->get_platform_name (); - cl_device_id device_id = CLDevice::instance()->get_device_id (); - cl_context _context_id = _context->get_context_id (); - cv::ocl::attachContext (platform_name, platform_id, _context_id, device_id); - cv::ocl::setUseOpenCL (cv::ocl::haveOpenCL()); - XCAM_LOG_DEBUG("Use OpenCL is: %s", cv::ocl::haveOpenCL() ? "true" : "false"); -} - -bool -CVContext::enable_ocl (bool flag) -{ - if (flag && !cv::ocl::haveOpenCL()) { - return false; - } - cv::ocl::setUseOpenCL (flag); - return true; -} - -bool -CVContext::is_ocl_enabled () const -{ - return cv::ocl::useOpenCL (); -} - -CVContext::CVContext () -{ - -} - -CVContext::~CVContext () { - -} - -} diff --git a/modules/ocl/cv_context.h b/modules/ocl/cv_context.h deleted file mode 100644 index 17363be..0000000 --- a/modules/ocl/cv_context.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * cv_context.h - used to init_opencv_ocl once - * - * Copyright (c) 2016-2017 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: Andrey Parfenov <a1994ndrey@gmail.com> - * Author: Wind Yuan <feng.yuan@intel.com> - */ - -#ifndef XCAM_CV_CONTEXT_H -#define XCAM_CV_CONTEXT_H - -#include <xcam_std.h> -#include <xcam_obj_debug.h> -#include <xcam_mutex.h> -#include <ocl/cl_context.h> - -#include <opencv2/opencv.hpp> -#include <opencv2/core/ocl.hpp> - -namespace XCam { - -class CVContext -{ -public: - static SmartPtr<CVContext> instance (); - - SmartPtr<CLContext> get_cl_context () { - return _context; - } - ~CVContext(); - bool enable_ocl (bool flag); - bool is_ocl_enabled () const; - -private: - CVContext (); - void init_opencv_ocl (); - - static Mutex _init_mutex; - static SmartPtr<CVContext> _instance; - - SmartPtr<CLContext> _context; - - XCAM_DEAD_COPY (CVContext); - -}; - -} - -#endif // XCAM_CV_CONTEXT_H diff --git a/modules/ocl/cv_feature_match.h b/modules/ocl/cv_feature_match.h deleted file mode 100644 index ed53fae..0000000 --- a/modules/ocl/cv_feature_match.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * cv_feature_match.h - optical flow feature match - * - * Copyright (c) 2016-2017 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: Wind Yuan <feng.yuan@intel.com> - * Author: Yinhang Liu <yinhangx.liu@intel.com> - */ - -#ifndef XCAM_CV_FEATURE_MATCH_H -#define XCAM_CV_FEATURE_MATCH_H - -#include <xcam_std.h> -#include <video_buffer.h> -#include <ocl/cv_base_class.h> -#include <interface/feature_match.h> -#include <interface/data_types.h> - -#include <ocl/cl_context.h> -#include <ocl/cl_device.h> -#include <ocl/cl_memory.h> - -namespace XCam { - -class CVFeatureMatch - : public CVBaseClass - , public FeatureMatch -{ -public: - explicit CVFeatureMatch (); - - void optical_flow_feature_match ( - const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, - Rect &left_img_crop, Rect &right_img_crop, int dst_width); - - void set_ocl (bool use_ocl) { - CVBaseClass::set_ocl (use_ocl); - } - bool is_ocl_path () { - return CVBaseClass::is_ocl_path (); - } - -protected: - bool get_crop_image (const SmartPtr<VideoBuffer> &buffer, const Rect &crop_rect, cv::UMat &img); - - void add_detected_data (cv::InputArray image, cv::Ptr<cv::Feature2D> detector, std::vector<cv::Point2f> &corners); - void get_valid_offsets (std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, - std::vector<uchar> &status, std::vector<float> &error, - std::vector<float> &offsets, float &sum, int &count, - cv::InputOutputArray debug_img, cv::Size &img0_size); - - void calc_of_match (cv::InputArray image0, cv::InputArray image1, - std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, - std::vector<uchar> &status, std::vector<float> &error, - int &last_count, float &last_mean_offset, float &out_x_offset); - - void detect_and_match (cv::InputArray img_left, cv::InputArray img_right, Rect &crop_left, Rect &crop_right, - int &valid_count, float &mean_offset, float &x_offset, int dst_width); - -private: - XCAM_DEAD_COPY (CVFeatureMatch); - -}; - -} - -#endif // XCAM_CV_FEATURE_MATCH_H diff --git a/modules/ocv/Makefile.am b/modules/ocv/Makefile.am new file mode 100644 index 0000000..fbbdacb --- /dev/null +++ b/modules/ocv/Makefile.am @@ -0,0 +1,29 @@ +noinst_LTLIBRARIES = libxcam_ocv.la + +xcam_ocv_sources = \ + cv_utils.cpp \ + cv_image_process_helper.cpp \ + cv_image_sharp.cpp \ + cv_edgetaper.cpp \ + cv_wiener_filter.cpp \ + cv_image_deblurring.cpp \ + cv_feature_match.cpp \ + cv_feature_match_cluster.cpp \ + cv_capi_feature_match.cpp \ + $(NULL) + +libxcam_ocv_la_SOURCES = \ + $(xcam_ocv_sources) \ + $(NULL) + +libxcam_ocv_la_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(OPENCV_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + $(NULL) + +libxcam_ocv_la_LIBADD = \ + $(OPENCV_LIBS) \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL)
\ No newline at end of file diff --git a/modules/soft/cv_capi_feature_match.cpp b/modules/ocv/cv_capi_feature_match.cpp index 0e0081c..d478f3c 100644 --- a/modules/soft/cv_capi_feature_match.cpp +++ b/modules/ocv/cv_capi_feature_match.cpp @@ -24,19 +24,10 @@ #define XCAM_CV_CAPI_FM_DEBUG 0 -#if XCAM_CV_CAPI_FM_DEBUG -#include "ocl/cv_base_class.h" -#endif - namespace XCam { -#if XCAM_CV_CAPI_FM_DEBUG -static void -debug_write_image ( - const SmartPtr<VideoBuffer> &buf, const Rect &rect, char *img_name, char *frame_str, char *fm_idx_str); -#endif CVCapiFeatureMatch::CVCapiFeatureMatch () - : FeatureMatch() + : FeatureMatch () { } @@ -63,8 +54,7 @@ CVCapiFeatureMatch::get_crop_image ( } void -CVCapiFeatureMatch::add_detected_data ( - CvArr* image, std::vector<CvPoint2D32f> &corners) +CVCapiFeatureMatch::add_detected_data (CvArr* image, std::vector<CvPoint2D32f> &corners) { std::vector<CvPoint2D32f> keypoints; @@ -127,10 +117,8 @@ CVCapiFeatureMatch::get_valid_offsets ( void CVCapiFeatureMatch::calc_of_match ( - CvArr* image0, CvArr* image1, - std::vector<CvPoint2D32f> &corner0, std::vector<CvPoint2D32f> &corner1, - std::vector<char> &status, std::vector<float> &error, - int &last_count, float &last_mean_offset, float &out_x_offset) + CvArr* image0, CvArr* image1, std::vector<CvPoint2D32f> &corner0, std::vector<CvPoint2D32f> &corner1, + std::vector<char> &status, std::vector<float> &error) { CvMat debug_image; CvSize img0_size = cvSize(((CvMat*)image0)->width, ((CvMat*)image0)->height); @@ -141,6 +129,7 @@ CVCapiFeatureMatch::calc_of_match ( float offset_sum = 0.0f; int count = 0; float mean_offset = 0.0f; + float last_mean_offset = _mean_offset; offsets.reserve (corner0.size ()); #if XCAM_CV_CAPI_FM_DEBUG @@ -165,21 +154,19 @@ CVCapiFeatureMatch::calc_of_match ( bool ret = get_mean_offset (offsets, offset_sum, count, mean_offset); if (ret) { if (fabs (mean_offset - last_mean_offset) < _config.delta_mean_offset) { - out_x_offset = out_x_offset * _config.offset_factor + mean_offset * (1.0f - _config.offset_factor); + _x_offset = _x_offset * _config.offset_factor + mean_offset * (1.0f - _config.offset_factor); - if (fabs (out_x_offset) > _config.max_adjusted_offset) - out_x_offset = (out_x_offset > 0.0f) ? _config.max_adjusted_offset : (-_config.max_adjusted_offset); + if (fabs (_x_offset) > _config.max_adjusted_offset) + _x_offset = (_x_offset > 0.0f) ? _config.max_adjusted_offset : (-_config.max_adjusted_offset); } } - last_count = count; - last_mean_offset = mean_offset; + _valid_count = count; + _mean_offset = mean_offset; } void -CVCapiFeatureMatch::detect_and_match ( - CvArr* img_left, CvArr* img_right, Rect &crop_left, Rect &crop_right, - int &valid_count, float &mean_offset, float &x_offset, int dst_width) +CVCapiFeatureMatch::detect_and_match (CvArr* img_left, CvArr* img_right) { std::vector<float> err; std::vector<char> status; @@ -211,31 +198,26 @@ CVCapiFeatureMatch::detect_and_match ( XCAM_LOG_INFO ("FeatureMatch(idx:%d): matched corners:%d", _fm_idx, count); #endif - calc_of_match (img_left, img_right, corner_left, corner_right, - status, err, valid_count, mean_offset, x_offset); - - adjust_stitch_area (dst_width, x_offset, crop_left, crop_right); + calc_of_match (img_left, img_right, corner_left, corner_right, status, err); #if XCAM_CV_CAPI_FM_DEBUG - XCAM_LOG_INFO ( - "FeatureMatch(idx:%d): stiching area: left_area(pos_x:%d, width:%d), right_area(pos_x:%d, width:%d)", - _fm_idx, crop_left.pos_x, crop_left.width, crop_right.pos_x, crop_right.width); + XCAM_LOG_INFO ("FeatureMatch(idx:%d): x_offset:%0.2f", _fm_idx, _x_offset); #endif } void -CVCapiFeatureMatch::optical_flow_feature_match ( - const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, - Rect &left_crop_rect, Rect &right_crop_rect, int dst_width) +CVCapiFeatureMatch::feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf) { - CvMat left_img, right_img; + XCAM_ASSERT (_left_rect.width && _left_rect.height); + XCAM_ASSERT (_right_rect.width && _right_rect.height); - if (!get_crop_image (left_buf, left_crop_rect, _left_crop_image, left_img) - || !get_crop_image (right_buf, right_crop_rect, _right_crop_image, right_img)) + CvMat left_img, right_img; + if (!get_crop_image (left_buf, _left_rect, _left_crop_image, left_img) + || !get_crop_image (right_buf, _right_rect, _right_crop_image, right_img)) return; - detect_and_match ((CvArr*)(&left_img), (CvArr*)(&right_img), left_crop_rect, right_crop_rect, - _valid_count, _mean_offset, _x_offset, dst_width); + detect_and_match ((CvArr*)(&left_img), (CvArr*)(&right_img)); #if XCAM_CV_CAPI_FM_DEBUG XCAM_ASSERT (_fm_idx >= 0); @@ -247,10 +229,9 @@ CVCapiFeatureMatch::optical_flow_feature_match ( char img_name[256] = {'\0'}; std::snprintf (img_name, 256, "fm_in_stitch_area_%d_%d_0.jpg", _frame_num, _fm_idx); - debug_write_image (left_buf, left_crop_rect, img_name, frame_str, fm_idx_str); - + write_image (left_buf, _left_rect, img_name, frame_str, fm_idx_str); std::snprintf (img_name, 256, "fm_in_stitch_area_%d_%d_1.jpg", _frame_num, _fm_idx); - debug_write_image (right_buf, right_crop_rect, img_name, frame_str, fm_idx_str); + write_image (right_buf, _right_rect, img_name, frame_str, fm_idx_str); XCAM_LOG_INFO ("FeatureMatch(idx:%d): frame number:%d done", _fm_idx, _frame_num); @@ -258,30 +239,13 @@ CVCapiFeatureMatch::optical_flow_feature_match ( #endif } -#if XCAM_CV_CAPI_FM_DEBUG -static void -debug_write_image ( - const SmartPtr<VideoBuffer> &buf, const Rect &rect, char *img_name, char *frame_str, char *fm_idx_str) +SmartPtr<FeatureMatch> +FeatureMatch::create_capi_feature_match () { - cv::Scalar color = cv::Scalar(0, 0, 255); - VideoBufferInfo info = buf->get_video_info (); - - cv::Mat mat; - CVBaseClass cv_obj; - cv_obj.convert_to_mat (buf, mat); + SmartPtr<CVCapiFeatureMatch> matcher = new CVCapiFeatureMatch (); + XCAM_ASSERT (matcher.ptr ()); - cv::putText (mat, frame_str, cv::Point(rect.pos_x, 30), cv::FONT_HERSHEY_COMPLEX, 0.8f, color, 2, 8, false); - cv::putText (mat, fm_idx_str, cv::Point(rect.pos_x, 70), cv::FONT_HERSHEY_COMPLEX, 0.8f, color, 2, 8, false); - - cv::line (mat, cv::Point(rect.pos_x, rect.pos_y), cv::Point(rect.pos_x + rect.width, rect.pos_y), color, 1); - cv::line (mat, cv::Point(rect.pos_x, rect.pos_y + rect.height), - cv::Point(rect.pos_x + rect.width, rect.pos_y + rect.height), color, 1); - - cv::line (mat, cv::Point(rect.pos_x, 0), cv::Point(rect.pos_x, info.height), color, 2); - cv::line (mat, cv::Point(rect.pos_x + rect.width, 0), cv::Point(rect.pos_x + rect.width, info.height), color, 2); - - cv::imwrite (img_name, mat); + return matcher; } -#endif } diff --git a/modules/ocv/cv_capi_feature_match.h b/modules/ocv/cv_capi_feature_match.h new file mode 100644 index 0000000..f1f8794 --- /dev/null +++ b/modules/ocv/cv_capi_feature_match.h @@ -0,0 +1,74 @@ +/* + * cv_capi_feature_match.h - optical flow feature match + * + * Copyright (c) 2016-2017 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: Wind Yuan <feng.yuan@intel.com> + * Author: Yinhang Liu <yinhangx.liu@intel.com> + * Author: Zong Wei <wei.zong@intel.com> + */ + +#ifndef CV_CAPI_FEATURE_MATCH_H +#define CV_CAPI_FEATURE_MATCH_H + +#include <video_buffer.h> +#include <interface/feature_match.h> +#include "cv_utils.h" + +#ifdef ANDROID +#include <cv.h> +#else +#include <opencv2/imgproc/imgproc_c.h> +#include <opencv2/video/tracking_c.h> +#endif + +namespace XCam { + +class CVCapiFeatureMatch + : public FeatureMatch +{ +public: + explicit CVCapiFeatureMatch (); + + virtual void feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf); + +private: + bool get_crop_image ( + const SmartPtr<VideoBuffer> &buffer, const Rect &crop_rect, std::vector<char> &crop_image, CvMat &img); + + void detect_and_match (CvArr* img_left, CvArr* img_right); + void add_detected_data (CvArr* image, std::vector<CvPoint2D32f> &corners); + + void calc_of_match ( + CvArr* image0, CvArr* image1, std::vector<CvPoint2D32f> &corner0, std::vector<CvPoint2D32f> &corner1, + std::vector<char> &status, std::vector<float> &error); + + void get_valid_offsets ( + std::vector<CvPoint2D32f> &corner0, std::vector<CvPoint2D32f> &corner1, + std::vector<char> &status, std::vector<float> &error, + std::vector<float> &offsets, float &sum, int &count, + CvArr* out_image, CvSize &img0_size); + +private: + XCAM_DEAD_COPY (CVCapiFeatureMatch); + + std::vector<char> _left_crop_image; + std::vector<char> _right_crop_image; +}; + +} + +#endif // CV_CAPI_FEATURE_MATCH_H diff --git a/modules/ocl/cv_edgetaper.cpp b/modules/ocv/cv_edgetaper.cpp index ab79238..524caa7 100644 --- a/modules/ocl/cv_edgetaper.cpp +++ b/modules/ocv/cv_edgetaper.cpp @@ -23,13 +23,6 @@ namespace XCam { - -CVEdgetaper::CVEdgetaper () - : CVBaseClass () -{ - -} - void CVEdgetaper::create_weights (const cv::Mat &image, const cv::Mat &psf, cv::Mat &coefficients) { @@ -37,13 +30,13 @@ CVEdgetaper::create_weights (const cv::Mat &image, const cv::Mat &psf, cv::Mat & cv::Mat rows_proj_border, cols_proj_border; cv::Mat rows_cor, cols_cor; // get psf rows and cols projections - cv::reduce (psf, rows_proj, 1, CV_REDUCE_SUM, -1); - cv::reduce (psf, cols_proj, 0, CV_REDUCE_SUM, -1); + cv::reduce (psf, rows_proj, 1, cv::REDUCE_SUM, -1); + cv::reduce (psf, cols_proj, 0, cv::REDUCE_SUM, -1); // calculate correlation for psf projections cv::copyMakeBorder (rows_proj, rows_proj_border, (psf.rows - 1) / 2, (psf.rows - 1) / 2, 0, 0, cv::BORDER_CONSTANT, cv::Scalar::all (0)); cv::copyMakeBorder (cols_proj, cols_proj_border, 0, 0, (psf.cols - 1) / 2, (psf.cols - 1) / 2, cv::BORDER_CONSTANT, cv::Scalar::all (0)); - cv::matchTemplate (rows_proj_border, rows_proj, rows_cor, CV_TM_CCORR); - cv::matchTemplate (cols_proj_border, cols_proj, cols_cor, CV_TM_CCORR); + cv::matchTemplate (rows_proj_border, rows_proj, rows_cor, cv::TM_CCORR); + cv::matchTemplate (cols_proj_border, cols_proj, cols_cor, cv::TM_CCORR); // make it symmetric on both sides cv::Mat rows_add = cv::Mat_<float>(1, 1) << rows_proj.at<float> (0, 0); cv::Mat cols_add = cv::Mat_<float>(1, 1) << cols_proj.at<float> (0, 0); diff --git a/modules/ocl/cv_edgetaper.h b/modules/ocv/cv_edgetaper.h index 1ead29f..641c266 100644 --- a/modules/ocl/cv_edgetaper.h +++ b/modules/ocv/cv_edgetaper.h @@ -22,20 +22,14 @@ #ifndef XCAM_CV_EDGETAPER_H #define XCAM_CV_EDGETAPER_H -#include <xcam_std.h> -#include <ocl/cv_base_class.h> - -#include <opencv2/opencv.hpp> -#include <opencv2/core/ocl.hpp> +#include "cv_std.h" namespace XCam { - -class CVEdgetaper : public CVBaseClass +class CVEdgetaper { - public: - explicit CVEdgetaper (); + explicit CVEdgetaper () {} void edgetaper (const cv::Mat &image, const cv::Mat &psf, cv::Mat &output); private: diff --git a/modules/ocl/cv_feature_match.cpp b/modules/ocv/cv_feature_match.cpp index e4e2ea8..ea04c0e 100644 --- a/modules/ocl/cv_feature_match.cpp +++ b/modules/ocv/cv_feature_match.cpp @@ -19,37 +19,63 @@ * Author: Yinhang Liu <yinhangx.liu@intel.com> */ -#include "cv_feature_match.h" #include "xcam_obj_debug.h" #include "image_file_handle.h" -#include "cl_utils.h" +#include "cv_feature_match.h" +#if HAVE_LIBCL +#include <opencv2/core/ocl.hpp> +#endif #define XCAM_CV_FM_DEBUG 0 #define XCAM_CV_OF_DRAW_SCALE 2 namespace XCam { -#if XCAM_CV_FM_DEBUG -static void debug_write_image ( - const SmartPtr<VideoBuffer> &buf, const Rect &rect, char *img_name, char *frame_str, char *fm_idx_str); -#endif - CVFeatureMatch::CVFeatureMatch () - : CVBaseClass () - , FeatureMatch () + : FeatureMatch () + , _dst_width (0) + , _need_adjust (false) +{ + xcam_mem_clear (_cl_buf_mem); +} + +CVFeatureMatch::~CVFeatureMatch () +{ + xcam_mem_clear (_cl_buf_mem); +} + + +void +CVFeatureMatch::set_dst_width (int width) { - XCAM_ASSERT (_cv_context.ptr ()); + _dst_width = width; +} + +void +CVFeatureMatch::enable_adjust_crop_area () +{ + _need_adjust = true; +} + +void +CVFeatureMatch::set_cl_buf_mem (void *mem, BufId id) +{ +#if HAVE_LIBCL + XCAM_ASSERT (mem); + _cl_buf_mem[id] = mem; +#else + XCAM_LOG_DEBUG ("non-OpenCL mode, failed to set cl buffer memory"); +#endif } bool -CVFeatureMatch::get_crop_image ( - const SmartPtr<VideoBuffer> &buffer, const Rect &crop_rect, cv::UMat &img) +CVFeatureMatch::get_crop_image_umat ( + const SmartPtr<VideoBuffer> &buffer, const Rect &crop_rect, cv::UMat &img, BufId id) { - SmartPtr<CLBuffer> cl_buffer = convert_to_clbuffer (_cv_context->get_cl_context (), buffer); +#if HAVE_LIBCL VideoBufferInfo info = buffer->get_video_info (); - cl_mem cl_mem_id = cl_buffer->get_mem_id (); cv::UMat umat; - cv::ocl::convertFromBuffer (cl_mem_id, info.strides[0], info.height, info.width, CV_8U, umat); + cv::ocl::convertFromBuffer (_cl_buf_mem[id], info.strides[0], info.height, info.width, CV_8U, umat); if (umat.empty ()) { XCAM_LOG_ERROR ("FeatureMatch(idx:%d): convert bo buffer to UMat failed", _fm_idx); return false; @@ -58,11 +84,15 @@ CVFeatureMatch::get_crop_image ( img = umat (cv::Rect(crop_rect.pos_x, crop_rect.pos_y, crop_rect.width, crop_rect.height)); return true; +#else + XCAM_LOG_ERROR ("FeatureMatch(idx:%d): non-OpenCL mode, failed to get umat", _fm_idx); + return false; +#endif } void CVFeatureMatch::add_detected_data ( - cv::InputArray image, cv::Ptr<cv::Feature2D> detector, std::vector<cv::Point2f> &corners) + cv::Mat image, cv::Ptr<cv::Feature2D> detector, std::vector<cv::Point2f> &corners) { std::vector<cv::KeyPoint> keypoints; detector->detect (image, keypoints); @@ -78,7 +108,7 @@ CVFeatureMatch::get_valid_offsets ( std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, std::vector<uchar> &status, std::vector<float> &error, std::vector<float> &offsets, float &sum, int &count, - cv::InputOutputArray debug_img, cv::Size &img0_size) + cv::Mat debug_img, cv::Size &img0_size) { count = 0; sum = 0.0f; @@ -114,37 +144,24 @@ CVFeatureMatch::get_valid_offsets ( void CVFeatureMatch::calc_of_match ( - cv::InputArray image0, cv::InputArray image1, - std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, - std::vector<uchar> &status, std::vector<float> &error, - int &last_count, float &last_mean_offset, float &out_x_offset) + cv::Mat image0, cv::Mat image1, std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, + std::vector<uchar> &status, std::vector<float> &error) { - cv::_InputOutputArray debug_img; + cv::Mat debug_img; cv::Size img0_size = image0.size (); - XCAM_ASSERT (img0_size.height == image1.rows ()); - XCAM_UNUSED (image1); + cv::Size img1_size = image1.size (); + XCAM_ASSERT (img0_size.height == img1_size.height); #if XCAM_CV_FM_DEBUG cv::Mat mat; - cv::UMat umat; - cv::Size img1_size = image1.size (); cv::Size size (img0_size.width + img1_size.width, img0_size.height); - if (image0.isUMat ()) { - umat.create (size, image0.type ()); - debug_img = cv::_InputOutputArray (umat); + mat.create (size, image0.type ()); + debug_img = cv::Mat (mat); - image0.copyTo (umat (cv::Rect(0, 0, img0_size.width, img0_size.height))); - image1.copyTo (umat (cv::Rect(img0_size.width, 0, img1_size.width, img1_size.height))); - umat.copyTo (debug_img); - } else { - mat.create (size, image0.type ()); - debug_img = cv::_InputOutputArray (mat); - - image0.copyTo (mat (cv::Rect(0, 0, img0_size.width, img0_size.height))); - image1.copyTo (mat (cv::Rect(img0_size.width, 0, img1_size.width, img1_size.height))); - mat.copyTo (debug_img); - } + image0.copyTo (mat (cv::Rect(0, 0, img0_size.width, img0_size.height))); + image1.copyTo (mat (cv::Rect(img0_size.width, 0, img1_size.width, img1_size.height))); + mat.copyTo (debug_img); cv::Size scale_size = size * XCAM_CV_OF_DRAW_SCALE; cv::resize (debug_img, debug_img, scale_size, 0, 0); @@ -154,6 +171,7 @@ CVFeatureMatch::calc_of_match ( float offset_sum = 0.0f; int count = 0; float mean_offset = 0.0f; + float last_mean_offset = _mean_offset; offsets.reserve (corner0.size ()); get_valid_offsets (corner0, corner1, status, error, offsets, offset_sum, count, debug_img, img0_size); @@ -167,21 +185,48 @@ CVFeatureMatch::calc_of_match ( bool ret = get_mean_offset (offsets, offset_sum, count, mean_offset); if (ret) { if (fabs (mean_offset - last_mean_offset) < _config.delta_mean_offset) { - out_x_offset = out_x_offset * _config.offset_factor + mean_offset * (1.0f - _config.offset_factor); + _x_offset = _x_offset * _config.offset_factor + mean_offset * (1.0f - _config.offset_factor); - if (fabs (out_x_offset) > _config.max_adjusted_offset) - out_x_offset = (out_x_offset > 0.0f) ? _config.max_adjusted_offset : (-_config.max_adjusted_offset); + if (fabs (_x_offset) > _config.max_adjusted_offset) + _x_offset = (_x_offset > 0.0f) ? _config.max_adjusted_offset : (-_config.max_adjusted_offset); } } - last_count = count; - last_mean_offset = mean_offset; + _valid_count = count; + _mean_offset = mean_offset; +} + +void +CVFeatureMatch::adjust_crop_area () +{ + if (fabs (_x_offset) < 5.0f) + return; + + XCAM_ASSERT (_dst_width); + + int last_overlap_width = _right_rect.pos_x + _right_rect.width + + (_dst_width - (_left_rect.pos_x + _left_rect.width)); + // int final_overlap_width = _right_rect.pos_x + _right_rect.width + + // (dst_width - (_left_rect.pos_x - x_offset + _left_rect.width)); + if ((_left_rect.pos_x - _x_offset + _left_rect.width) > _dst_width) + _x_offset = _dst_width - (_left_rect.pos_x + _left_rect.width); + int final_overlap_width = last_overlap_width + _x_offset; + final_overlap_width = XCAM_ALIGN_AROUND (final_overlap_width, 8); + XCAM_ASSERT (final_overlap_width >= _config.sitch_min_width); + int center = final_overlap_width / 2; + XCAM_ASSERT (center >= _config.sitch_min_width / 2); + + _right_rect.pos_x = XCAM_ALIGN_AROUND (center - _config.sitch_min_width / 2, 8); + _right_rect.width = _config.sitch_min_width; + _left_rect.pos_x = _dst_width - final_overlap_width + _right_rect.pos_x; + _left_rect.width = _config.sitch_min_width; + + float delta_offset = final_overlap_width - last_overlap_width; + _x_offset -= delta_offset; } void -CVFeatureMatch::detect_and_match ( - cv::InputArray img_left, cv::InputArray img_right, Rect &crop_left, Rect &crop_right, - int &valid_count, float &mean_offset, float &x_offset, int dst_width) +CVFeatureMatch::detect_and_match (cv::Mat img_left, cv::Mat img_right) { std::vector<float> err; std::vector<uchar> status; @@ -189,9 +234,6 @@ CVFeatureMatch::detect_and_match ( cv::Ptr<cv::Feature2D> fast_detector; cv::Size win_size = cv::Size (5, 5); - if (img_left.isUMat ()) - win_size = cv::Size (16, 16); - fast_detector = cv::FastFeatureDetector::create (20, true); add_detected_data (img_left, fast_detector, corner_left); @@ -202,91 +244,82 @@ CVFeatureMatch::detect_and_match ( cv::calcOpticalFlowPyrLK ( img_left, img_right, corner_left, corner_right, status, err, win_size, 3, cv::TermCriteria (cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 10, 0.01f)); - cv::ocl::finish(); - calc_of_match (img_left, img_right, corner_left, corner_right, - status, err, valid_count, mean_offset, x_offset); + calc_of_match (img_left, img_right, corner_left, corner_right, status, err); - adjust_stitch_area (dst_width, x_offset, crop_left, crop_right); + if (_need_adjust) + adjust_crop_area (); #if XCAM_CV_FM_DEBUG - XCAM_LOG_INFO ( - "FeatureMatch(idx:%d): stiching area: left_area(pos_x:%d, width:%d), right_area(pos_x:%d, width:%d)", - _fm_idx, crop_left.pos_x, crop_left.width, crop_right.pos_x, crop_right.width); + XCAM_LOG_INFO ("FeatureMatch(idx:%d): x_offset:%0.2f", _fm_idx, _x_offset); + if (_need_adjust) { + XCAM_LOG_INFO ( + "FeatureMatch(idx:%d): stiching area: left_area(pos_x:%d, width:%d), right_area(pos_x:%d, width:%d)", + _fm_idx, _left_rect.pos_x, _left_rect.width, _right_rect.pos_x, _right_rect.width); + } #endif } void -CVFeatureMatch::optical_flow_feature_match ( - const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, - Rect &left_crop_rect, Rect &right_crop_rect, int dst_width) +CVFeatureMatch::feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf) { + XCAM_ASSERT (_left_rect.width && _left_rect.height); + XCAM_ASSERT (_right_rect.width && _right_rect.height); + cv::UMat left_umat, right_umat; - cv::Mat left_mat, right_mat; - cv::_InputArray left_img, right_img; + cv::Mat left_img, right_img; - if (!get_crop_image (left_buf, left_crop_rect, left_umat) - || !get_crop_image (right_buf, right_crop_rect, right_umat)) - return; + if (_cl_buf_mem[BufIdLeft] && _cl_buf_mem[BufIdRight]) { + if (!get_crop_image_umat (left_buf, _left_rect, left_umat, BufIdLeft) + || !get_crop_image_umat (right_buf, _right_rect, right_umat, BufIdRight)) + return; - if (_use_ocl) { - left_img = cv::_InputArray (left_umat); - right_img = cv::_InputArray (right_umat); + left_img = left_umat.getMat (cv::ACCESS_READ); + right_img = right_umat.getMat (cv::ACCESS_READ); } else { - left_mat = left_umat.getMat (cv::ACCESS_READ); - right_mat = right_umat.getMat (cv::ACCESS_READ); - - left_img = cv::_InputArray (left_mat); - right_img = cv::_InputArray (right_mat); + if (!convert_range_to_mat (left_buf, _left_rect, left_img) + || !convert_range_to_mat (right_buf, _right_rect, right_img)) + return; } - detect_and_match (left_img, right_img, left_crop_rect, right_crop_rect, - _valid_count, _mean_offset, _x_offset, dst_width); + detect_and_match (left_img, right_img); #if XCAM_CV_FM_DEBUG - XCAM_ASSERT (_fm_idx >= 0); + debug_write_image (left_buf, right_buf, _left_rect, _right_rect, _frame_num, _fm_idx); + _frame_num++; +#endif +} + +void +CVFeatureMatch::debug_write_image ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, + const Rect &left_rect, const Rect &right_rect, uint32_t frame_num, int fm_idx) +{ + XCAM_ASSERT (fm_idx >= 0); char frame_str[64] = {'\0'}; - std::snprintf (frame_str, 64, "frame:%d", _frame_num); + std::snprintf (frame_str, 64, "frame:%d", frame_num); char fm_idx_str[64] = {'\0'}; - std::snprintf (fm_idx_str, 64, "fm_idx:%d", _fm_idx); + std::snprintf (fm_idx_str, 64, "fm_idx:%d", fm_idx); char img_name[256] = {'\0'}; - std::snprintf (img_name, 256, "fm_in_stitch_area_%d_%d_0.jpg", _frame_num, _fm_idx); - debug_write_image (left_buf, left_crop_rect, img_name, frame_str, fm_idx_str); + std::snprintf (img_name, 256, "fm_in_stitch_area_%d_%d_0.jpg", frame_num, fm_idx); + write_image (left_buf, left_rect, img_name, frame_str, fm_idx_str); - std::snprintf (img_name, 256, "fm_in_stitch_area_%d_%d_1.jpg", _frame_num, _fm_idx); - debug_write_image (right_buf, right_crop_rect, img_name, frame_str, fm_idx_str); + std::snprintf (img_name, 256, "fm_in_stitch_area_%d_%d_1.jpg", frame_num, fm_idx); + write_image (right_buf, right_rect, img_name, frame_str, fm_idx_str); - XCAM_LOG_INFO ("FeatureMatch(idx:%d): frame number:%d done", _fm_idx, _frame_num); - _frame_num++; -#endif + XCAM_LOG_INFO ("FeatureMatch(idx:%d): frame number:%d done", fm_idx, frame_num); } -#if XCAM_CV_FM_DEBUG -static void -debug_write_image ( - const SmartPtr<VideoBuffer> &buf, const Rect &rect, char *img_name, char *frame_str, char *fm_idx_str) +SmartPtr<FeatureMatch> +FeatureMatch::create_default_feature_match () { - cv::Scalar color = cv::Scalar(0, 0, 255); - VideoBufferInfo info = buf->get_video_info (); - - cv::Mat mat; - CVBaseClass cv_obj; - cv_obj.convert_to_mat (buf, mat); - - cv::putText (mat, frame_str, cv::Point(rect.pos_x, 30), cv::FONT_HERSHEY_COMPLEX, 0.8f, color, 2, 8, false); - cv::putText (mat, fm_idx_str, cv::Point(rect.pos_x, 70), cv::FONT_HERSHEY_COMPLEX, 0.8f, color, 2, 8, false); + SmartPtr<CVFeatureMatch> matcher = new CVFeatureMatch (); + XCAM_ASSERT (matcher.ptr ()); - cv::line (mat, cv::Point(rect.pos_x, rect.pos_y), cv::Point(rect.pos_x + rect.width, rect.pos_y), color, 1); - cv::line (mat, cv::Point(rect.pos_x, rect.pos_y + rect.height), - cv::Point(rect.pos_x + rect.width, rect.pos_y + rect.height), color, 1); - - cv::line (mat, cv::Point(rect.pos_x, 0), cv::Point(rect.pos_x, info.height), color, 2); - cv::line (mat, cv::Point(rect.pos_x + rect.width, 0), cv::Point(rect.pos_x + rect.width, info.height), color, 2); - - cv::imwrite (img_name, mat); + return matcher; } -#endif } diff --git a/modules/ocv/cv_feature_match.h b/modules/ocv/cv_feature_match.h new file mode 100644 index 0000000..5d2fbc7 --- /dev/null +++ b/modules/ocv/cv_feature_match.h @@ -0,0 +1,88 @@ +/* + * cv_feature_match.h - optical flow feature match + * + * Copyright (c) 2016-2017 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: Wind Yuan <feng.yuan@intel.com> + * Author: Yinhang Liu <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_CV_FEATURE_MATCH_H +#define XCAM_CV_FEATURE_MATCH_H + +#include <video_buffer.h> +#include <interface/feature_match.h> +#include "cv_utils.h" + +namespace XCam { + +class CVFeatureMatch + : public FeatureMatch +{ +public: + enum BufId { + BufIdLeft = 0, + BufIdRight, + BufIdMax + }; + +public: + explicit CVFeatureMatch (); + virtual ~CVFeatureMatch (); + + virtual void feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf); + + void set_cl_buf_mem (void *mem, BufId id); + +protected: + bool get_crop_image_umat (const SmartPtr<VideoBuffer> &buffer, const Rect &crop_rect, cv::UMat &img, BufId id); + void add_detected_data (cv::Mat image, cv::Ptr<cv::Feature2D> detector, std::vector<cv::Point2f> &corners); + + void debug_write_image ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, + const Rect &left_rect, const Rect &right_rect, uint32_t frame_num, int fm_idx); + +private: + virtual void detect_and_match (cv::Mat img_left, cv::Mat img_right); + virtual void calc_of_match ( + cv::Mat image0, cv::Mat image1, std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, + std::vector<uchar> &status, std::vector<float> &error); + + void get_valid_offsets ( + std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, + std::vector<uchar> &status, std::vector<float> &error, + std::vector<float> &offsets, float &sum, int &count, + cv::Mat debug_img, cv::Size &img0_size); + + void adjust_crop_area (); + + virtual void set_dst_width (int width); + virtual void enable_adjust_crop_area (); + +private: + XCAM_DEAD_COPY (CVFeatureMatch); + +protected: + void *_cl_buf_mem[BufIdMax]; + +private: + int _dst_width; + bool _need_adjust; +}; + +} + +#endif // XCAM_CV_FEATURE_MATCH_H diff --git a/modules/ocv/cv_feature_match_cluster.cpp b/modules/ocv/cv_feature_match_cluster.cpp new file mode 100644 index 0000000..6bc0415 --- /dev/null +++ b/modules/ocv/cv_feature_match_cluster.cpp @@ -0,0 +1,316 @@ +/* + * cv_feature_match_cluster.cpp - optical flow feature match selected by clustering + * + * Copyright (c) 2016-2017 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: Wu Junkai <junkai.wu@intel.com> + */ + +#include "xcam_obj_debug.h" +#include "image_file_handle.h" +#include "cv_feature_match_cluster.h" + +#define XCAM_CV_FM_DEBUG 0 +#define XCAM_CV_OF_DRAW_SCALE 2 + +namespace XCam { +CVFeatureMatchCluster::CVFeatureMatchCluster () + : CVFeatureMatch () +{ +} + +bool +CVFeatureMatchCluster::calc_mean_offset ( + std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, + std::vector<uchar> &status, std::vector<float> &error, + float &mean_offset_x, float &mean_offset_y, + cv::Mat debug_img, cv::Size &img0_size, cv::Size &img1_size) +{ + std::vector<std::vector<uint32_t>> clusters; + std::vector<std::vector<cv::Point2f>> clusters_offsets; + std::vector<uint32_t> valid_seeds (status.size ()); + std::vector<uint32_t> valid_corners (status.size ()); + + for (uint32_t i = 0; i < status.size (); ++i) { + if (!status[i] || (error[i] > _config.max_track_error) || corner1[i].x < 0.0f || corner1[i].x > img0_size.width) { + valid_corners[i] = 0; + valid_seeds[i] = 0; + } else { + valid_corners[i] = 1; + valid_seeds[i] = 1; + } + } + + float seed_x_offset = 0.0f; + float seed_y_offset = 0.0f; + + std::vector<uint32_t> cluster (1); + std::vector<cv::Point2f> cluster_offset (1); + + float thres = 8.0f; + while (cluster.size() > 0) { + cluster.clear (); + cluster_offset.clear (); + + for (uint32_t i = 0; i < status.size (); ++i) { + if (valid_seeds[i]) { + seed_x_offset = corner1[i].x - corner0[i].x; + seed_y_offset = corner1[i].y - corner0[i].y; + cluster.push_back (i); + cluster_offset.push_back (cv::Point2f(seed_x_offset, seed_y_offset)); + valid_corners[i] = 0; + valid_seeds[i] = 0; + break; + } + } + + if (cluster.size() > 0) { + for (uint32_t i = 0; i < status.size (); ++i) { + if (!valid_corners[i]) + continue; + + float x_offset = corner1[i].x - corner0[i].x; + float y_offset = corner1[i].y - corner0[i].y; + + if (fabs (x_offset - seed_x_offset) > thres || fabs (y_offset - seed_y_offset) > thres / 2.0f) + continue; + + cluster.push_back (i); + cluster_offset.push_back (cv::Point2f(x_offset, y_offset)); + valid_seeds[i] = 0; + } + + clusters.push_back (cluster); + clusters_offsets.push_back (cluster_offset); + } + } + + if (clusters_offsets.size () == 0) + return false; + + uint32_t max_size = 0; + uint32_t max_index = 0; + + for (uint32_t i = 0; i < clusters.size (); ++i) { + if (clusters[i].size () > max_size) { + max_size = clusters[i].size (); + max_index = i; + } + } + + if (clusters_offsets[max_index].size () < (uint32_t)_config.min_corners) + return false; + + float sum_x = 0.0f; + float sum_y = 0.0f; + for (uint32_t i = 0; i < clusters_offsets[max_index].size (); ++i) { + sum_x += clusters_offsets[max_index][i].x; + sum_y += clusters_offsets[max_index][i].y; + } + + mean_offset_x = sum_x / clusters_offsets[max_index].size (); + mean_offset_y = sum_y / clusters_offsets[max_index].size (); + +#if XCAM_CV_FM_DEBUG + for (uint32_t i = 0; i < status.size (); ++i) { + if(!status[i]) + continue; + + cv::Point start = cv::Point(corner0[i]) * XCAM_CV_OF_DRAW_SCALE; + cv::circle (debug_img, start, 4, cv::Scalar(0), XCAM_CV_OF_DRAW_SCALE); + cv::Point end = (cv::Point(corner1[i]) + cv::Point (img0_size.width, 0)) * XCAM_CV_OF_DRAW_SCALE; + cv::line (debug_img, start, end, cv::Scalar(0), XCAM_CV_OF_DRAW_SCALE); + } + + for (uint32_t i = 0; i < status.size (); ++i) { + if (!status[i]) + continue; + + cv::Point start = cv::Point(corner0[i]) * XCAM_CV_OF_DRAW_SCALE; + cv::circle (debug_img, start, 4, cv::Scalar(0), XCAM_CV_OF_DRAW_SCALE); + if (error[i] > _config.max_track_error) + continue; + if (fabs(corner0[i].y - corner1[i].y) >= _config.max_valid_offset_y) + continue; + if (corner1[i].x < 0.0f || corner1[i].x > img0_size.width) + continue; + + cv::Point end = (cv::Point(corner1[i]) + cv::Point (img0_size.width, 0)) * XCAM_CV_OF_DRAW_SCALE; + cv::line (debug_img, start, end, cv::Scalar(255), XCAM_CV_OF_DRAW_SCALE); + } + + for (uint32_t i = 0; i < status.size (); ++i) { + if(!status[i]) + continue; + + cv::Point start = (cv::Point(corner0[i]) + cv::Point (img0_size.width + img1_size.width, 0)) * XCAM_CV_OF_DRAW_SCALE; + cv::circle (debug_img, start, 4, cv::Scalar(0), XCAM_CV_OF_DRAW_SCALE); + cv::Point end = (cv::Point(corner1[i]) + cv::Point (2 * img0_size.width + img1_size.width, 0)) * XCAM_CV_OF_DRAW_SCALE; + cv::line (debug_img, start, end, cv::Scalar(0), XCAM_CV_OF_DRAW_SCALE); + } + + if (clusters.size () != 0) + cluster = clusters[max_index]; + for (uint32_t i = 0; i < cluster.size (); ++i) { + cv::Point start = (cv::Point(corner0[cluster[i]]) + cv::Point(img0_size.width + img1_size.width, 0)) * XCAM_CV_OF_DRAW_SCALE; + cv::circle (debug_img, start, 4, cv::Scalar(0), XCAM_CV_OF_DRAW_SCALE); + cv::Point end = (cv::Point(corner1[cluster[i]]) + cv::Point (2 * img0_size.width + img1_size.width, 0)) * XCAM_CV_OF_DRAW_SCALE; + cv::line (debug_img, start, end, cv::Scalar(255), XCAM_CV_OF_DRAW_SCALE); + } + +#endif + + XCAM_UNUSED (debug_img); + XCAM_UNUSED (img0_size); + XCAM_UNUSED (img1_size); + + clusters.clear (); + clusters_offsets.clear (); + + return true; +} + +void +CVFeatureMatchCluster::calc_of_match ( + cv::Mat image0, cv::Mat image1, std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, + std::vector<uchar> &status, std::vector<float> &error) +{ + cv::Mat debug_img; + cv::Size img0_size = image0.size (); + cv::Size img1_size = image1.size (); + XCAM_ASSERT (img0_size.height == img1_size.height); + +#if XCAM_CV_FM_DEBUG + cv::Mat mat; + cv::Size size ((img0_size.width + img1_size.width) * 2, img0_size.height); + + mat.create (size, image0.type ()); + debug_img = cv::Mat (mat); + + image0.copyTo (mat (cv::Rect(0, 0, img0_size.width, img0_size.height))); + image1.copyTo (mat (cv::Rect(img0_size.width, 0, img1_size.width, img1_size.height))); + image0.copyTo (mat (cv::Rect(img0_size.width + img1_size.width, 0, img0_size.width, img0_size.height))); + image1.copyTo (mat (cv::Rect(2 * img0_size.width + img1_size.width, 0, img1_size.width, img1_size.height))); + + mat.copyTo (debug_img); + + cv::Size scale_size = size * XCAM_CV_OF_DRAW_SCALE; + cv::resize (debug_img, debug_img, scale_size, 0, 0); +#endif + + float mean_offset_x = 0.0f; + float mean_offset_y = 0.0f; + float last_mean_offset_x = _mean_offset; + float last_mean_offset_y = _mean_offset_y; + bool ret = calc_mean_offset (corner0, corner1, status, error, mean_offset_x, mean_offset_y, + debug_img, img0_size, img1_size); + +#if XCAM_CV_FM_DEBUG + char file_name[256]; + std::snprintf (file_name, 256, "fm_optical_flow_%d_%d.jpg", _frame_num, _fm_idx); + cv::imwrite (file_name, debug_img); +#endif + + if (ret) { + if (fabs (mean_offset_x - last_mean_offset_x) < _config.delta_mean_offset) { + _x_offset = _x_offset * _config.offset_factor + mean_offset_x * (1.0f - _config.offset_factor); + + if (fabs (_x_offset) > _config.max_adjusted_offset) + _x_offset = (_x_offset > 0.0f) ? _config.max_adjusted_offset : (-_config.max_adjusted_offset); + } + + if (fabs (mean_offset_y - last_mean_offset_y) < _config.delta_mean_offset) { + _y_offset = _y_offset * _config.offset_factor + mean_offset_y * (1.0f - _config.offset_factor); + + if (fabs (_y_offset) > _config.max_adjusted_offset) + _y_offset = (_y_offset > 0.0f) ? _config.max_adjusted_offset : (-_config.max_adjusted_offset); + } + } + + _mean_offset = mean_offset_x; + _mean_offset_y = mean_offset_y; +} + +void +CVFeatureMatchCluster::detect_and_match (cv::Mat img_left, cv::Mat img_right) +{ + std::vector<float> err; + std::vector<uchar> status; + std::vector<cv::Point2f> corner_left, corner_right; + cv::Ptr<cv::Feature2D> fast_detector; + cv::Size win_size = cv::Size (21, 21); + + fast_detector = cv::FastFeatureDetector::create (20, true); + add_detected_data (img_left, fast_detector, corner_left); + + if (corner_left.empty ()) { + return; + } + + cv::calcOpticalFlowPyrLK ( + img_left, img_right, corner_left, corner_right, status, err, win_size, 3, + cv::TermCriteria (cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 0.01f)); + + calc_of_match (img_left, img_right, corner_left, corner_right, status, err); + +#if XCAM_CV_FM_DEBUG + XCAM_LOG_INFO ("x_offset:%0.2f", _x_offset); + XCAM_LOG_INFO ( + "FeatureMatch(idx:%d): stiching area: left_area(pos_x:%d, width:%d), right_area(pos_x:%d, width:%d)", + _fm_idx, _left_rect.pos_x, _left_rect.width, _right_rect.pos_x, _right_rect.width); +#endif +} + +void +CVFeatureMatchCluster::feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf) +{ + XCAM_ASSERT (_left_rect.width && _left_rect.height); + XCAM_ASSERT (_right_rect.width && _right_rect.height); + + cv::UMat left_umat, right_umat; + cv::Mat left_img, right_img; + + if (_cl_buf_mem[BufIdLeft] && _cl_buf_mem[BufIdRight]) { + if (!get_crop_image_umat (left_buf, _left_rect, left_umat, BufIdLeft) + || !get_crop_image_umat (right_buf, _right_rect, right_umat, BufIdRight)) + return; + + left_img = left_umat.getMat (cv::ACCESS_READ); + right_img = right_umat.getMat (cv::ACCESS_READ); + } else { + if (!convert_range_to_mat (left_buf, _left_rect, left_img) + || !convert_range_to_mat (right_buf, _right_rect, right_img)) + return; + } + + detect_and_match (left_img, right_img); + +#if XCAM_CV_FM_DEBUG + debug_write_image (left_buf, right_buf, _left_rect, _right_rect, _frame_num, _fm_idx); + _frame_num++; +#endif +} + +SmartPtr<FeatureMatch> +FeatureMatch::create_cluster_feature_match () +{ + SmartPtr<CVFeatureMatchCluster> matcher = new CVFeatureMatchCluster (); + XCAM_ASSERT (matcher.ptr ()); + + return matcher; +} + +} diff --git a/modules/ocv/cv_feature_match_cluster.h b/modules/ocv/cv_feature_match_cluster.h new file mode 100644 index 0000000..1b1fcdb --- /dev/null +++ b/modules/ocv/cv_feature_match_cluster.h @@ -0,0 +1,55 @@ +/* + * cv_feature_match_cluster.h - optical flow feature match selected by clustering + * + * Copyright (c) 2016-2017 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: Wu Junkai <junkai.Wu@intel.com> + */ + +#ifndef XCAM_CV_FEATURE_MATCH_CLUSTER_H +#define XCAM_CV_FEATURE_MATCH_CLUSTER_H + +#include "cv_feature_match.h" + +namespace XCam { + +class CVFeatureMatchCluster + : public CVFeatureMatch +{ +public: + explicit CVFeatureMatchCluster (); + + virtual void feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf); + +private: + virtual void detect_and_match (cv::Mat img_left, cv::Mat img_right); + virtual void calc_of_match ( + cv::Mat image0, cv::Mat image1, std::vector<cv::Point2f> &corner0, + std::vector<cv::Point2f> &corner1, std::vector<uchar> &status, std::vector<float> &error); + + bool calc_mean_offset ( + std::vector<cv::Point2f> &corner0, std::vector<cv::Point2f> &corner1, std::vector<uchar> &status, + std::vector<float> &error, float &mean_offset_x, float &mean_offset_y, + cv::Mat debug_img, cv::Size &img0_size, cv::Size &img1_size); + +private: + XCAM_DEAD_COPY (CVFeatureMatchCluster); + +}; + +} + +#endif // XCAM_CV_FEATURE_MATCH_CLUSTER_H diff --git a/modules/ocl/cv_image_deblurring.cpp b/modules/ocv/cv_image_deblurring.cpp index 730eb42..4c4dbf0 100644 --- a/modules/ocl/cv_image_deblurring.cpp +++ b/modules/ocv/cv_image_deblurring.cpp @@ -23,9 +23,7 @@ namespace XCam { - CVImageDeblurring::CVImageDeblurring () - : CVBaseClass () { _helper = new CVImageProcessHelper (); _sharp = new CVImageSharp (); @@ -155,7 +153,7 @@ void CVImageDeblurring::blind_deblurring (const cv::Mat &blurred, cv::Mat &deblurred, cv::Mat &kernel, int kernel_size, float noise_power, bool use_edgetaper) { cv::Mat gray_blurred; - cv::cvtColor (blurred, gray_blurred, CV_BGR2GRAY); + cv::cvtColor (blurred, gray_blurred, cv::COLOR_BGR2GRAY); if (noise_power < 0) { cv::Mat median_blurred; @@ -196,7 +194,7 @@ CVImageDeblurring::blind_deblurring (const cv::Mat &blurred, cv::Mat &deblurred, } cv::merge (deblurred_rgb, result_deblurred); result_deblurred.convertTo (result_deblurred, CV_8UC3); - fastNlMeansDenoisingColored (result_deblurred, deblurred, 3, 3, 7, 21); + cv::fastNlMeansDenoisingColored (result_deblurred, deblurred, 3, 3, 7, 21); kernel = result_kernel.clone (); } diff --git a/modules/ocl/cv_image_deblurring.h b/modules/ocv/cv_image_deblurring.h index afac22c..cd28786 100644 --- a/modules/ocl/cv_image_deblurring.h +++ b/modules/ocv/cv_image_deblurring.h @@ -22,13 +22,12 @@ #ifndef XCAM_CV_FEATURE_DEBLURRING_H #define XCAM_CV_FEATURE_DEBLURRING_H -#include <xcam_std.h> #include <video_buffer.h> -#include <ocl/cv_base_class.h> -#include <ocl/cv_image_process_helper.h> -#include <ocl/cv_image_sharp.h> -#include <ocl/cv_edgetaper.h> -#include <ocl/cv_wiener_filter.h> +#include "cv_std.h" +#include "cv_image_process_helper.h" +#include "cv_image_sharp.h" +#include "cv_edgetaper.h" +#include "cv_wiener_filter.h" namespace XCam { @@ -41,9 +40,8 @@ struct CVIDConfig { } }; -class CVImageDeblurring : public CVBaseClass +class CVImageDeblurring { - public: explicit CVImageDeblurring (); void set_config (CVIDConfig config); diff --git a/modules/ocl/cv_image_process_helper.cpp b/modules/ocv/cv_image_process_helper.cpp index 0d08289..33377a9 100644 --- a/modules/ocl/cv_image_process_helper.cpp +++ b/modules/ocv/cv_image_process_helper.cpp @@ -23,13 +23,6 @@ namespace XCam { - -CVImageProcessHelper::CVImageProcessHelper () - : CVBaseClass () -{ - -} - cv::Mat CVImageProcessHelper::erosion (const cv::Mat &image, int erosion_size, int erosion_type) { diff --git a/modules/ocl/cv_image_process_helper.h b/modules/ocv/cv_image_process_helper.h index 137ff6b..cb1cf8a 100644 --- a/modules/ocl/cv_image_process_helper.h +++ b/modules/ocv/cv_image_process_helper.h @@ -22,18 +22,15 @@ #ifndef XCAM_CV_IMAGE_PROCESS_HELPER_H #define XCAM_CV_IMAGE_PROCESS_HELPER_H -#include <xcam_std.h> #include <video_buffer.h> -#include <ocl/cv_base_class.h> +#include "cv_std.h" namespace XCam { - -class CVImageProcessHelper : public CVBaseClass +class CVImageProcessHelper { - public: - explicit CVImageProcessHelper (); + explicit CVImageProcessHelper () {} void compute_dft (const cv::Mat &image, cv::Mat &result); void compute_idft (cv::Mat *input, cv::Mat &result); diff --git a/modules/ocl/cv_image_sharp.cpp b/modules/ocv/cv_image_sharp.cpp index 0a309af..2bf0076 100644 --- a/modules/ocl/cv_image_sharp.cpp +++ b/modules/ocv/cv_image_sharp.cpp @@ -23,13 +23,6 @@ namespace XCam { - -CVImageSharp::CVImageSharp () - : CVBaseClass () -{ - -} - cv::Mat CVImageSharp::sharp_image_gray (const cv::Mat &image, float sigmar) { diff --git a/modules/ocl/cv_image_sharp.h b/modules/ocv/cv_image_sharp.h index 74e0ce4..7a68e23 100644 --- a/modules/ocl/cv_image_sharp.h +++ b/modules/ocv/cv_image_sharp.h @@ -22,17 +22,15 @@ #ifndef XCAM_CV_IMAGE_SHARP_H #define XCAM_CV_IMAGE_SHARP_H -#include <xcam_std.h> #include <video_buffer.h> -#include <ocl/cv_base_class.h> +#include "cv_std.h" namespace XCam { -class CVImageSharp : public CVBaseClass +class CVImageSharp { - public: - explicit CVImageSharp (); + explicit CVImageSharp () {} float measure_sharp (const cv::Mat &image); cv::Mat sharp_image_gray (const cv::Mat &image, float sigmar); diff --git a/modules/ocv/cv_std.h b/modules/ocv/cv_std.h new file mode 100644 index 0000000..eba4861 --- /dev/null +++ b/modules/ocv/cv_std.h @@ -0,0 +1,27 @@ +/* + * cv_std.h - OpenCV std + * + * Copyright (c) 2019 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> + */ + +#ifndef XCAM_CV_STD_H +#define XCAM_CV_STD_H + +#include <xcam_std.h> +#include <opencv2/opencv.hpp> + +#endif // XCAM_CV_STD_H diff --git a/modules/ocv/cv_utils.cpp b/modules/ocv/cv_utils.cpp new file mode 100644 index 0000000..ab70679 --- /dev/null +++ b/modules/ocv/cv_utils.cpp @@ -0,0 +1,97 @@ +/* + * cv_utils.cpp - OpenCV Utilities + * + * Copyright (c) 2019 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 "cv_utils.h" + +const static cv::Scalar color = cv::Scalar (0, 0, 255); +const static int fontFace = cv::FONT_HERSHEY_COMPLEX; + +namespace XCam { + +bool convert_to_mat (const SmartPtr<VideoBuffer> &buffer, cv::Mat &img) +{ + VideoBufferInfo info = buffer->get_video_info (); + XCAM_FAIL_RETURN (ERROR, info.format == V4L2_PIX_FMT_NV12, false, "convert_to_mat only support NV12 format"); + + uint8_t *mem = buffer->map (); + XCAM_FAIL_RETURN (ERROR, mem, false, "convert_to_mat buffer map failed"); + + cv::Mat mat = cv::Mat (info.aligned_height * 3 / 2, info.width, CV_8UC1, mem, info.strides[0]); + cv::cvtColor (mat, img, cv::COLOR_YUV2BGR_NV12); + buffer->unmap (); + + return true; +} + +bool convert_range_to_mat (const SmartPtr<VideoBuffer> &buffer, const Rect &range, cv::Mat &img) +{ + VideoBufferInfo info = buffer->get_video_info (); + + uint8_t *mem = buffer->map (); + XCAM_FAIL_RETURN (ERROR, mem, false, "convert_range_to_mat buffer map failed"); + + uint8_t *start = mem + range.pos_y * info.strides[0] + range.pos_x; + img = cv::Mat (range.height, range.width, CV_8UC1, start, info.strides[0]); + // buffer->unmap (); + + return true; +} + +void write_image ( + const SmartPtr<VideoBuffer> &buf, const char *img_name, const char *frame_str, const char *idx_str) +{ + XCAM_ASSERT (img_name); + + cv::Mat mat; + convert_to_mat (buf, mat); + + if(frame_str) + cv::putText (mat, frame_str, cv::Point(20, 50), fontFace, 2.0, color, 2, 8, false); + if(idx_str) + cv::putText (mat, idx_str, cv::Point(20, 110), fontFace, 2.0, color, 2, 8, false); + + cv::imwrite (img_name, mat); +} + +void write_image ( + const SmartPtr<VideoBuffer> &buf, const Rect &draw_rect, + const char *img_name, const char *frame_str, const char *idx_str) +{ + XCAM_ASSERT (img_name && frame_str && idx_str); + + cv::Mat mat; + convert_to_mat (buf, mat); + + const Rect &rect = draw_rect; + cv::putText (mat, frame_str, cv::Point(rect.pos_x, 30), fontFace, 0.8f, color, 2, 8, false); + cv::putText (mat, idx_str, cv::Point(rect.pos_x, 70), fontFace, 0.8f, color, 2, 8, false); + + cv::line (mat, cv::Point(rect.pos_x, rect.pos_y), cv::Point(rect.pos_x + rect.width, rect.pos_y), color, 1); + cv::line (mat, cv::Point(rect.pos_x, rect.pos_y + rect.height), + cv::Point(rect.pos_x + rect.width, rect.pos_y + rect.height), color, 1); + + VideoBufferInfo info = buf->get_video_info (); + cv::line (mat, cv::Point(rect.pos_x, 0), cv::Point(rect.pos_x, info.height), color, 2); + cv::line (mat, cv::Point(rect.pos_x + rect.width, 0), cv::Point(rect.pos_x + rect.width, info.height), color, 2); + + cv::imwrite (img_name, mat); +} + +} diff --git a/modules/ocv/cv_utils.h b/modules/ocv/cv_utils.h new file mode 100644 index 0000000..8b36b90 --- /dev/null +++ b/modules/ocv/cv_utils.h @@ -0,0 +1,41 @@ +/* + * cv_utils.h - OpenCV Utilities + * + * Copyright (c) 2019 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> + */ + +#ifndef XCAM_CV_UTILS_H +#define XCAM_CV_UTILS_H + +#include <interface/data_types.h> +#include <video_buffer.h> +#include "cv_std.h" + +namespace XCam { + + bool convert_to_mat (const SmartPtr<VideoBuffer> &buffer, cv::Mat &img); + bool convert_range_to_mat (const SmartPtr<VideoBuffer> &buffer, const Rect &range, cv::Mat &img); + + void write_image ( + const SmartPtr<VideoBuffer> &buf, const char *img_name, const char *frame_str, const char *idx_str); + void write_image ( + const SmartPtr<VideoBuffer> &buf, const Rect &draw_rect, + const char *img_name, const char *frame_str, const char *idx_str); + +} + +#endif // XCAM_CV_UTILS_H diff --git a/modules/ocl/cv_wiener_filter.cpp b/modules/ocv/cv_wiener_filter.cpp index ff96e5c..cf33649 100644 --- a/modules/ocl/cv_wiener_filter.cpp +++ b/modules/ocv/cv_wiener_filter.cpp @@ -23,9 +23,7 @@ namespace XCam { - CVWienerFilter::CVWienerFilter () - : CVBaseClass () { _helpers = new CVImageProcessHelper (); } diff --git a/modules/ocl/cv_wiener_filter.h b/modules/ocv/cv_wiener_filter.h index fa70812..3720c35 100644 --- a/modules/ocl/cv_wiener_filter.h +++ b/modules/ocv/cv_wiener_filter.h @@ -22,16 +22,14 @@ #ifndef XCAM_CV_WIENER_FILTER_H #define XCAM_CV_WIENER_FILTER_H -#include <xcam_std.h> #include <video_buffer.h> -#include <ocl/cv_base_class.h> -#include <ocl/cv_image_process_helper.h> +#include "cv_std.h" +#include "cv_image_process_helper.h" namespace XCam { -class CVWienerFilter : public CVBaseClass +class CVWienerFilter { - public: explicit CVWienerFilter (); diff --git a/modules/render/Makefile.am b/modules/render/Makefile.am new file mode 100644 index 0000000..2870eaf --- /dev/null +++ b/modules/render/Makefile.am @@ -0,0 +1,52 @@ +lib_LTLIBRARIES = libxcam_render.la + +XCAM_RENDER_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(LIBOSG_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + $(NULL) + +XCAM_RENDER_LIBS = \ + -losgGA \ + -losgDB \ + -losgUtil \ + -losgFX \ + -losgText \ + -losgViewer \ + -losg \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL) + +xcam_render_sources = \ + render_osg_camera_manipulator.cpp \ + render_osg_model.cpp \ + render_osg_viewer.cpp \ + $(NULL) + +libxcam_render_la_SOURCES = \ + $(xcam_render_sources) \ + $(NULL) + +libxcam_render_la_CXXFLAGS = \ + $(XCAM_RENDER_CXXFLAGS) \ + $(NULL) + +libxcam_render_la_LIBADD = \ + $(XCAM_RENDER_LIBS) \ + $(NULL) + +libxcam_render_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ + $(NULL) + +libxcam_renderincludedir = $(includedir)/xcam/render + +nobase_libxcam_renderinclude_HEADERS = \ + render_osg_camera_manipulator.h \ + render_osg_model.h \ + render_osg_viewer.h \ + render_osg_shader.h \ + $(NULL) + +libxcam_render_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/render/render_osg_camera_manipulator.cpp b/modules/render/render_osg_camera_manipulator.cpp new file mode 100644 index 0000000..ec59fb9 --- /dev/null +++ b/modules/render/render_osg_camera_manipulator.cpp @@ -0,0 +1,172 @@ +/* + * render_osg_camera_manipulator.cpp - supports 3D interactive manipulators + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#include "render_osg_camera_manipulator.h" + +namespace XCam { + +RenderOsgCameraManipulator::RenderOsgCameraManipulator () + : osgGA::StandardManipulator::StandardManipulator () + , mAngle (osg::PI) + , mLookAtOffset (0.0f) + , mMaxLookAtOffset (osg::PI_4) + , mLength (4.0f) + , mWidth (3.0f) + , mHeight (1.6f) + , mMaxHeight (4.0f) + , mMinHeight (0.6) + , mEyePosScale (1.0f) + , mUp (osg::Vec3d(0.0f, 0.0f, 1.0f)) +{ + setAllowThrow (false); + setAutoComputeHomePosition (false); +} + +RenderOsgCameraManipulator::~RenderOsgCameraManipulator () +{ +} + +osg::Matrixd +RenderOsgCameraManipulator::getInverseMatrix () const +{ + osg::Vec3d eyePos; + getEyePosition (eyePos); + osg::Vec3d lookAtPos; + getLookAtPosition (lookAtPos); + return osg::Matrixd::lookAt (eyePos, lookAtPos, mUp); +} + +osg::Matrixd +RenderOsgCameraManipulator::getMatrix () const +{ + osg::Matrixd matrix = getInverseMatrix (); + return osg::Matrixd::inverse (matrix); +} + +void +RenderOsgCameraManipulator::home (double /*currentTime*/) +{ + mAngle = osg::PI; + mLookAtOffset = 0.0f; + mEyePosScale = 1.0f; +} + +void +RenderOsgCameraManipulator::rotate (float deltaAngle) +{ + if (deltaAngle > 0.) { + if (mLookAtOffset < mMaxLookAtOffset) { + mLookAtOffset = std::min (mLookAtOffset + deltaAngle, mMaxLookAtOffset); + } else { + mAngle += deltaAngle; + } + } else { + if (mLookAtOffset > -mMaxLookAtOffset) { + mLookAtOffset = std::max (mLookAtOffset + deltaAngle, -mMaxLookAtOffset); + } else { + mAngle += deltaAngle; + } + } + if (mAngle > 2 * osg::PI) { + mAngle -= 2 * osg::PI; + } else if (mAngle < 0.0f) { + mAngle += 2 * osg::PI; + } +} + +void +RenderOsgCameraManipulator::modifyHeight (float delta) +{ + if (delta > 0.0) { + mHeight = std::min (mHeight + delta, mMaxHeight); + } else { + mHeight = std::max (mHeight + delta, mMinHeight); + } +} + +void +RenderOsgCameraManipulator::getEyePosition (osg::Vec3d &eyePos) const +{ + float indentFactor = 1.0f - (0.1f * ((mHeight - mMinHeight) / (mMaxHeight - mMinHeight))); + eyePos[0] = cos (mAngle) * mLength * indentFactor; + eyePos[1] = sin (mAngle) * mWidth * indentFactor; + eyePos[2] = mHeight; + eyePos *= mEyePosScale; +} + +void +RenderOsgCameraManipulator::getLookAtPosition (osg::Vec3d &lookAtPos) const +{ + float lookAtAngle = mAngle + mLookAtOffset; + lookAtPos[0] = cos (lookAtAngle) * mLength * 0.5f; + lookAtPos[1] = sin (lookAtAngle) * mWidth * 0.5f; + lookAtPos[2] = mHeight * 0.25f; +} + +bool +RenderOsgCameraManipulator::handleKeyDown (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) +{ + (void)us; + bool eventHandled = false; + int key = ea.getKey (); + if (key == osgGA::GUIEventAdapter::KEY_Space) { + home (ea.getTime ()); + + eventHandled = true; + } else if (key == osgGA::GUIEventAdapter::KEY_Left) { + rotate (-0.1); + eventHandled = true; + } else if (key == osgGA::GUIEventAdapter::KEY_Right) { + rotate (0.1); + eventHandled = true; + } + + return eventHandled; +} + +bool +RenderOsgCameraManipulator::handleMouseWheel (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) +{ + (void)us; + bool eventHandled = false; + osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion(); + + if (sm == osgGA::GUIEventAdapter::SCROLL_DOWN || sm == osgGA::GUIEventAdapter::SCROLL_RIGHT) { + rotate (0.1); + eventHandled = true; + } else if (sm == osgGA::GUIEventAdapter::SCROLL_UP || sm == osgGA::GUIEventAdapter::SCROLL_LEFT) { + rotate (-0.1); + eventHandled = true; + } + + return eventHandled; +} + +bool +RenderOsgCameraManipulator::performMovementLeftMouseButton (const double eventTimeDelta, const double dx, const double dy) +{ + (void)eventTimeDelta; + + rotate (-2.0 * dx); + modifyHeight (-dy); + return true; +} + +} // namespace XCam diff --git a/modules/render/render_osg_camera_manipulator.h b/modules/render/render_osg_camera_manipulator.h new file mode 100644 index 0000000..0653039 --- /dev/null +++ b/modules/render/render_osg_camera_manipulator.h @@ -0,0 +1,123 @@ +/* + * render_osg_camera_manipulator.h - supports 3D interactive manipulators + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_CAMERA_MANIPULATOR_H +#define XCAM_OSG_CAMERA_MANIPULATOR_H + +#include <osgGA/StandardManipulator> + +namespace XCam { + +class RenderOsgCameraManipulator + : public osgGA::StandardManipulator +{ +public: + + explicit RenderOsgCameraManipulator (); + + virtual ~RenderOsgCameraManipulator (); + + virtual void setByMatrix (const osg::Matrixd &matrix) + { + (void)matrix; + } + + virtual void setByInverseMatrix (const osg::Matrixd &matrix) + { + (void)matrix; + } + + virtual osg::Matrixd getMatrix () const; + + virtual osg::Matrixd getInverseMatrix () const; + + virtual void home (double currentTime); + + virtual void setTransformation (const osg::Vec3d &eye, const osg::Quat &rotation) + { + (void)eye; + (void)rotation; + } + + virtual void setTransformation (const osg::Vec3d &eye, const osg::Vec3d ¢er, const osg::Vec3d &up) + { + (void)eye; + (void)center; + (void)up; + } + + virtual void getTransformation (osg::Vec3d &eye, osg::Quat &rotation) const + { + (void)eye; + (void)rotation; + } + + virtual void getTransformation (osg::Vec3d &eye, osg::Vec3d ¢er, osg::Vec3d &up) const + { + (void)eye; + (void)center; + (void)up; + } + + void setInitialValues (float angle, float length, float width, float height) + { + mAngle = angle; + mLength = length; + mWidth = width; + mHeight = height; + mMinHeight = height / 2.0f; + + mUp = osg::Vec3d(0.0f, 0.0f, 1.0f); + } + +private: + RenderOsgCameraManipulator (RenderOsgCameraManipulator const &other); + + RenderOsgCameraManipulator &operator= (RenderOsgCameraManipulator const &other); + + virtual bool handleKeyDown (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us); + + virtual bool handleMouseWheel (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us); + + virtual bool performMovementLeftMouseButton (const double eventTimeDelta, const double dx, const double dy); + + void rotate (float deltaAngle); + + void modifyHeight (float delta); + + void getEyePosition (osg::Vec3d &eye) const; + + void getLookAtPosition (osg::Vec3d ¢er) const; + + float mAngle; + float mLookAtOffset; + float mMaxLookAtOffset; + float mLength; + float mWidth; + float mHeight; + float mMaxHeight; + float mMinHeight; + float mEyePosScale; + osg::Vec3d mUp; +}; + +} // namespace XCam + +#endif // XCAM_OSG_CAMERA_MANIPULATOR_H diff --git a/modules/render/render_osg_model.cpp b/modules/render/render_osg_model.cpp new file mode 100644 index 0000000..4062fed --- /dev/null +++ b/modules/render/render_osg_model.cpp @@ -0,0 +1,342 @@ +/* + * render_osg_model.cpp - represents renderable things by model + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#include "render_osg_model.h" + +#include <iostream> +#include <string> + +#include <osg/MatrixTransform> +#include <osg/Texture2D> +#include <osgDB/ReadFile> + +namespace XCam { + +RenderOsgModel::RenderOsgModel (const char *name, uint32_t width, uint32_t height) + : _name (NULL) + , _model (NULL) + , _geode (NULL) + , _program (NULL) + , _texture (NULL) +{ + XCAM_LOG_DEBUG ("RenderOsgModel width(%d), height(%d) ", width, height); + XCAM_ASSERT (name); + if (name) + _name = strndup (name, XCAM_MAX_STR_SIZE); + + _model = new osg::Group (); + _geode = new osg::Geode (); + + _texture = create_texture (width, height); + if (_texture.get ()) { + add_texture (_texture); + } +} + +RenderOsgModel::RenderOsgModel (const char *name, bool from_file) + : _name (NULL) + , _model (NULL) + , _geode (NULL) + , _program (NULL) + , _texture (NULL) +{ + XCAM_LOG_DEBUG ("RenderOsgModel model name (%s) ", name); + XCAM_ASSERT (name); + if (name) + _name = strndup (name, XCAM_MAX_STR_SIZE); + + _model = new osg::Group (); + _geode = new osg::Geode (); + + if (from_file && NULL != _geode.get ()) { + osg::ref_ptr<osg::Node> node = create_model_from_file (name); + _geode->addChild (node); + } +} + +RenderOsgModel::~RenderOsgModel () +{ + if (_name) + xcam_free (_name); +} + +osg::Node* +RenderOsgModel::create_model_from_file (const char *name) +{ + XCAM_LOG_DEBUG ("Invailide node name %s", name); + if (name == NULL) { + return NULL; + } + + osg::ref_ptr<osg::Node> node = osgDB::readNodeFile (name); + if (NULL == node.get ()) { + XCAM_LOG_ERROR ("Read node file FAILD!!! node name %s", name); + } + + return node.release(); +} + +void +RenderOsgModel::append_model (SmartPtr<RenderOsgModel> &child_model) +{ + osg::ref_ptr<osg::Group> model = get_model (); + + if (NULL == model.get () || NULL == child_model.ptr ()) { + XCAM_LOG_ERROR ("Append child model ERROR!! NULL model !!"); + return; + } + + model->addChild (child_model->get_model ()); +} + +void +RenderOsgModel::append_geode (SmartPtr<RenderOsgModel> &child_model) +{ + osg::ref_ptr<osg::Group> model = get_model (); + + if (NULL == model.get () || NULL == child_model.ptr ()) { + XCAM_LOG_ERROR ("Append child geode ERROR!! NULL model !!"); + return; + } + + model->addChild (child_model->get_geode ()); +} + +XCamReturn +RenderOsgModel::setup_shader_program ( + const char *name, + osg::Shader::Type type, + const char *source_text) +{ + XCAM_LOG_DEBUG ("setup shader program name(%s), type(%d)", name, type); + XCamReturn result = XCAM_RETURN_NO_ERROR; + + if (NULL == _program.get ()) { + _program = new osg::Program (); + _program->setName (name); + } + + _program->addShader (new osg::Shader (type, source_text)); + + _model->getOrCreateStateSet ()->setAttributeAndModes (_program, osg::StateAttribute::ON); + _model->getOrCreateStateSet ()->setMode (GL_DEPTH_TEST, osg::StateAttribute::ON); + + return result; +} + +XCamReturn +RenderOsgModel::setup_vertex_model ( + BowlModel::VertexMap &vertices, + BowlModel::PointMap &points, + BowlModel::IndexVector &indices, + float a, + float b, + float c) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::ref_ptr<osg::Group> model = get_model (); + osg::ref_ptr<osg::Geode> geode = get_geode (); + osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry (); + + geode->addDrawable (geometry); + geometry->setUseVertexBufferObjects (true); + + osg::ref_ptr<osg::Vec3Array> vertex_array = new osg::Vec3Array (); + osg::ref_ptr<osg::Vec2Array> tex_coord_array = new osg::Vec2Array (); + osg::ref_ptr<osg::DrawElementsUInt> index_array = new osg::DrawElementsUInt (GL_TRIANGLE_STRIP, 0); + + osg::ref_ptr<osg::Vec3Array> normal_array = new osg::Vec3Array (); + osg::ref_ptr<osg::Vec4Array> color_array = new osg::Vec4Array (); + + normal_array->push_back (osg::Vec3 (0, -1, 0)); + geometry->setNormalArray (normal_array); + geometry->setNormalBinding (osg::Geometry::BIND_OVERALL); + + color_array->push_back (osg::Vec4 (1.0, 0.0, 0.0, 1.0)); + geometry->setColorArray (color_array); + geometry->setColorBinding (osg::Geometry::BIND_OVERALL); + + for (uint32_t idx = 0; idx < vertices.size (); idx++) { + vertex_array->push_back ( + osg::Vec3f (vertices[idx].x * a, + vertices[idx].y * b, + vertices[idx].z * c)); + } + + for (uint32_t idx = 0; idx < points.size (); idx++) { + tex_coord_array->push_back (osg::Vec2f (points[idx].x, points[idx].y)); + } + + for (uint32_t idx = 0; idx < indices.size (); idx++) { + index_array->push_back (indices[idx]); + } + + geometry->setVertexArray (vertex_array.get ()); + + if (points.size () > 0) { + geometry->setTexCoordArray (0, tex_coord_array.get ()); + } + + if (indices.size () > 0) { + geometry->addPrimitiveSet (index_array.get ()); + } else { + geometry->addPrimitiveSet (new osg::DrawArrays (GL_TRIANGLE_FAN, 0, 4)); + } + + model->addChild (geode); + + return result; +} + +XCamReturn +RenderOsgModel::setup_model_matrix ( + float translation_x, + float translation_y, + float translation_z, + float rotation_x, + float rotation_y, + float rotation_z, + float rotation_degrees) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::ref_ptr<osg::Group> model = get_model (); + osg::ref_ptr<osg::Geode> geode = get_geode (); + + const osg::Vec3f axis(rotation_x, rotation_y, rotation_z); + osg::ref_ptr<osg::MatrixTransform> mat = new osg::MatrixTransform (); + mat->setMatrix (osg::Matrix::scale (osg::Vec3 (1.0, 1.0, 1.0)) * + osg::Matrix::rotate ((rotation_degrees / 180.f) * osg::PI_2, axis) * + osg::Matrix::translate (osg::Vec3 (translation_x, translation_y, translation_z))); + + mat->addChild (geode); + model->addChild (mat); + + return result; +} + +XCamReturn +RenderOsgModel::update_texture (SmartPtr<VideoBuffer> &buffer) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + XCAM_LOG_DEBUG ("RenderOsgModel::update_texture "); + + if (NULL == _texture.get ()) { + return XCAM_RETURN_ERROR_PARAM; + } + + { + SmartLock locker (_mutex); + + VideoBufferInfo info = buffer->get_video_info (); + uint32_t image_width = info.width; + uint32_t image_height = info.height; + + osg::ref_ptr<osg::Image> image_y = new osg::Image (); + osg::ref_ptr<osg::Image> image_uv = new osg::Image (); + + uint8_t* image_buffer = buffer->map (); + if (NULL == image_buffer) { + XCAM_LOG_ERROR ("buffer map return NULL!!"); + result = XCAM_RETURN_ERROR_MEM; + } else { + uint8_t* src_y = image_buffer; + uint8_t* src_uv = image_buffer + image_width * image_height; + + image_y->setImage (image_width, image_height, 1, + GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, + src_y, osg::Image::NO_DELETE); + + image_uv->setImage (image_width / 2, image_height / 2, 1, + GL_LUMINANCE, GL_RG, GL_UNSIGNED_BYTE, + src_uv, osg::Image::NO_DELETE); + + _texture->_texture_y->setImage (image_y); + _texture->_texture_uv->setImage (image_uv); + } + //buffer->unmap (); + } + + return result; +} + +NV12Texture* +RenderOsgModel::create_texture (uint32_t width, uint32_t height) +{ + osg::ref_ptr<NV12Texture> nv12 = new NV12Texture (width, height); + + nv12->_texture_y = new osg::Texture2D (); + nv12->_texture_y->setImage (new osg::Image ()); + + nv12->_texture_y->setInternalFormat (GL_LUMINANCE); + nv12->_texture_y->setResizeNonPowerOfTwoHint (false); + nv12->_texture_y->setNumMipmapLevels (0); + nv12->_texture_y->setFilter (osg::Texture::MIN_FILTER, osg::Texture::NEAREST); + nv12->_texture_y->setFilter (osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + nv12->_texture_y->setWrap (osg::Texture::WRAP_S, osg::Texture::CLAMP); + nv12->_texture_y->setWrap (osg::Texture::WRAP_T, osg::Texture::CLAMP); + + nv12->_texture_y->setTextureWidth (width); + nv12->_texture_y->setTextureHeight (height); + + nv12->_texture_uv = new osg::Texture2D (); + nv12->_texture_uv->setImage (new osg::Image ()); + + nv12->_texture_uv->setInternalFormat (GL_RG); + nv12->_texture_uv->setResizeNonPowerOfTwoHint (false); + nv12->_texture_uv->setNumMipmapLevels (0); + nv12->_texture_uv->setFilter (osg::Texture::MIN_FILTER, osg::Texture::NEAREST); + nv12->_texture_uv->setFilter (osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + nv12->_texture_uv->setWrap (osg::Texture::WRAP_S, osg::Texture::CLAMP); + nv12->_texture_uv->setWrap (osg::Texture::WRAP_T, osg::Texture::CLAMP); + + nv12->_texture_uv->setTextureWidth (width / 2); + nv12->_texture_uv->setTextureHeight (height / 2); + + return nv12.release (); +} + +XCamReturn +RenderOsgModel::add_texture (osg::ref_ptr<NV12Texture> &texture) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::ref_ptr<osg::Group> model = get_model (); + + if (NULL == model.get () || NULL == _texture.get ()) { + return XCAM_RETURN_ERROR_PARAM; + } + + model->getOrCreateStateSet()->setTextureAttribute(0, texture->_texture_y.get ()); + texture->_uniform_y = new osg::Uniform (osg::Uniform::SAMPLER_2D, "textureY"); + texture->_uniform_y->set (0); + model->getOrCreateStateSet ()->addUniform (texture->_uniform_y.get ()); + + model->getOrCreateStateSet ()->setTextureAttribute (1, texture->_texture_uv.get ()); + texture->_uniform_uv = new osg::Uniform (osg::Uniform::SAMPLER_2D, "textureUV"); + texture->_uniform_uv->set (1); + model->getOrCreateStateSet ()->addUniform (texture->_uniform_uv.get ()); + + return result; +} + +} // namespace XCam diff --git a/modules/render/render_osg_model.h b/modules/render/render_osg_model.h new file mode 100644 index 0000000..eaf6302 --- /dev/null +++ b/modules/render/render_osg_model.h @@ -0,0 +1,125 @@ +/* + * render_osg_model.h - represents renderable things by object + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_RENDER_MODEL_H +#define XCAM_OSG_RENDER_MODEL_H + +#include <osg/Texture2D> +#include <osg/Group> + +#include <interface/data_types.h> +#include <interface/stitcher.h> +#include <xcam_mutex.h> + +namespace XCam { + +class NV12Texture : public osg::Referenced +{ +public: + explicit NV12Texture (uint32_t width, uint32_t height) + { + _image_width = width; + _image_height = height; + } + +public: + uint32_t _image_width; + uint32_t _image_height; + + osg::ref_ptr<osg::Texture2D> _texture_y; + osg::ref_ptr<osg::Texture2D> _texture_uv; + + osg::ref_ptr<osg::Uniform> _uniform_y; + osg::ref_ptr<osg::Uniform> _uniform_uv; +}; + +class RenderOsgModel { +public: + + explicit RenderOsgModel (const char *name, uint32_t width, uint32_t height); + explicit RenderOsgModel (const char *name, bool from_file = true); + + virtual ~RenderOsgModel (); + + const char *get_name () const { + return _name; + } + + osg::Node* create_model_from_file (const char *name); + + osg::Group* get_model () const { + return _model; + } + + void append_model (SmartPtr<RenderOsgModel> &model); + + void append_geode (SmartPtr<RenderOsgModel> &model); + + + osg::Geode* get_geode () const { + return _geode; + } + + XCamReturn setup_shader_program ( + const char *name, + osg::Shader::Type type, + const char *source_text); + + XCamReturn setup_vertex_model ( + BowlModel::VertexMap &vertices, + BowlModel::PointMap &points, + BowlModel::IndexVector &indices, + float a = 1.0f, + float b = 1.0f, + float c = 1.0f); + + XCamReturn setup_model_matrix ( + float translation_x, + float translation_y, + float translation_z, + float rotation_x, + float rotation_y, + float rotation_z, + float rotation_degrees); + + XCamReturn update_texture (SmartPtr<VideoBuffer> &buffer); + +private: + + XCAM_DEAD_COPY (RenderOsgModel); + + NV12Texture* create_texture (uint32_t width, uint32_t height); + XCamReturn add_texture (osg::ref_ptr<NV12Texture> &texture); + +private: + + char *_name; + + osg::ref_ptr<osg::Group> _model; + osg::ref_ptr<osg::Geode> _geode; + osg::ref_ptr<osg::Program> _program; + osg::ref_ptr<NV12Texture> _texture; + + Mutex _mutex; +}; + +} // namespace XCam + +#endif // XCAM_OSG_RENDER_MODEL_H diff --git a/modules/render/render_osg_shader.h b/modules/render/render_osg_shader.h new file mode 100644 index 0000000..b2dd52e --- /dev/null +++ b/modules/render/render_osg_shader.h @@ -0,0 +1,93 @@ +/* + * render_osg_shader.h - common gl shaders + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_SHADER_H +#define XCAM_OSG_SHADER_H + +namespace XCam { + +static const char VtxShaderProjectNV12Texture[] = "" + "precision highp float; \n" + "attribute vec4 osg_Vertex; \n" + "attribute vec2 osg_MultiTexCoord0; \n" + "attribute vec4 osg_Color; \n" + "uniform mat4 osg_ModelViewProjectionMatrix; \n" + "uniform mat4 osg_ModelViewMatrix; \n" + "uniform mat4 osg_ViewMatrixInverse; \n" + "varying vec2 texcoord; \n" + "varying vec4 color; \n" + "void main(void) \n" + "{ \n" + " texcoord = osg_MultiTexCoord0; \n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n" + " color = osg_Color; \n" + "} \n"; + +static const char FrgShaderProjectNV12Texture[] = "" + "precision highp float; \n" + "uniform sampler2D textureY; \n" + "uniform sampler2D textureUV; \n" + "varying vec2 texcoord; \n" + "varying vec4 color; \n" + "vec4 getRGBColorNV12(sampler2D u_textureY, sampler2D u_textureUV, vec2 tex) \n" + "{ \n" + " vec4 resultcolor = vec4 (0.0, 0.0, 0.0, 1.0); \n" + " float y, u, v; \n" + " y = texture2D(u_textureY, vec2(tex.s, tex.t)).r; \n" + " vec2 colorUV = texture2D(u_textureUV, vec2(tex.s, tex.t)).rg; \n" + " u = colorUV.x-0.5; \n" + " v = colorUV.y-0.5; \n" + " y = 1.1643*(y-0.0625); \n" + " resultcolor.r = (y+1.5958*(v)); \n" + " resultcolor.g = (y-0.39173*(u)-0.81290*(v)); \n" + " resultcolor.b = (y+2.017*(u)); \n" + " resultcolor.a = 1.0; \n" + " return resultcolor; \n" + "} \n" + "void main() \n" + "{ \n" + " vec4 textureColor = getRGBColorNV12(textureY, textureUV, texcoord); \n" + " gl_FragColor = textureColor; \n" + "} \n"; + +const char VtxShaderSimpleTexture[] = "" + "precision highp float; \n" + "attribute vec4 osg_Vertex; \n" + "attribute vec4 osg_Color; \n" + "uniform mat4 osg_ModelViewProjectionMatrix; \n" + "varying vec4 color; \n" + "void main(void) \n" + "{ \n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n" + " color = osg_Color; \n" + "} \n"; + +const char FrgShaderSimpleTexture[] = "" + "precision highp float; \n" + "varying vec4 color; \n" + "void main() \n" + "{ \n" + " gl_FragColor = color; \n" + "} \n"; + + +} // namespace XCam + +#endif // XCAM_OSG_SHADER_H diff --git a/modules/render/render_osg_viewer.cpp b/modules/render/render_osg_viewer.cpp new file mode 100644 index 0000000..ff0f394 --- /dev/null +++ b/modules/render/render_osg_viewer.cpp @@ -0,0 +1,137 @@ +/* + * render_osg_viewer.cpp - renders a single view on to a single scene + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#include "render_osg_viewer.h" +#include "render_osg_model.h" +#include "render_osg_camera_manipulator.h" + +#include <string> + +namespace XCam { + +RenderOsgViewer::RenderOsgViewer () + : Thread ("RenderOsgViewerThread") + , _viewer (NULL) + , _model_groups (NULL) + , _initialized (false) +{ + _viewer = new osgViewer::Viewer (); + + if (!_initialized) { + initialize (); + } +} + +RenderOsgViewer::~RenderOsgViewer () +{ + _viewer->setDone (true); +} + +XCamReturn +RenderOsgViewer::initialize () +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); + uint32_t win_width = 1920; + uint32_t win_height = 1080; + if (wsi) { + wsi->getScreenResolution (osg::GraphicsContext::ScreenIdentifier (0), win_width, win_height); + } + + _viewer->setThreadingModel (osgViewer::Viewer::SingleThreaded); + + _viewer->setLightingMode (osg::View::SKY_LIGHT); + _viewer->getLight()->setAmbient (osg::Vec4f(0.f, 0.f, 0.f, 1.f)); + _viewer->getLight()->setDiffuse (osg::Vec4d(0.4f, 0.4f, 0.4f, 1.f)); + _viewer->getLight()->setSpecular (osg::Vec4d(0.5f, 0.5f, 0.5f, 1.f)); + + osg::ref_ptr<osgViewer::StatsHandler> stats_handler = new osgViewer::StatsHandler (); + _viewer->addEventHandler (stats_handler); + + _viewer->setUpViewInWindow (0, 0, win_width, win_height); + + osg::ref_ptr<RenderOsgCameraManipulator> vp_manipulator = new RenderOsgCameraManipulator (); + vp_manipulator->setInitialValues (osg::PI, 6.0f, 4.0f, 2.6f); + _viewer->setCameraManipulator (vp_manipulator); + _viewer->getCamera ()->setClearMask (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + _viewer->getCamera ()->setComputeNearFarMode (osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); + _viewer->getCamera ()->setClearColor (osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); + _viewer->getCamera ()->setViewport (0, 0, win_width, win_height); + + _initialized = true; + + return result; +} + +void +RenderOsgViewer::start_render () +{ + Thread::start (); +} + +void +RenderOsgViewer::stop_render () +{ + Thread::stop (); +} + +bool +RenderOsgViewer::loop () +{ + if (!_viewer->done ()) + { + _viewer->frame (); + } + + return true; +} + +void +RenderOsgViewer::set_camera_manipulator (osg::ref_ptr<osgGA::StandardManipulator> &manipulator) +{ + _viewer->setCameraManipulator (manipulator); +} + +void +RenderOsgViewer::add_model (SmartPtr<RenderOsgModel> &model) +{ + if (!model.ptr ()) { + return; + } + + if (!_model_groups.ptr ()) { + _model_groups = model; + } else { + _model_groups->append_model (model); + } +} + +void +RenderOsgViewer::validate_model_groups () +{ + if (!_model_groups.ptr ()) { + return; + } + _viewer->setSceneData (_model_groups->get_model ()); +} + +} // namespace XCam + diff --git a/modules/render/render_osg_viewer.h b/modules/render/render_osg_viewer.h new file mode 100644 index 0000000..335c562 --- /dev/null +++ b/modules/render/render_osg_viewer.h @@ -0,0 +1,73 @@ +/* + * render_osg_viewer.h - renders a single view on to a single scene + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_RENDER_VIEWER_H +#define XCAM_OSG_RENDER_VIEWER_H + +#include <osgViewer/Viewer> +#include <osgViewer/ViewerEventHandlers> +#include <osgGA/StandardManipulator> + +#include <interface/data_types.h> +#include <interface/stitcher.h> +#include <xcam_mutex.h> +#include <xcam_thread.h> + +namespace XCam { + +class RenderOsgModel; + +class RenderOsgViewer + : public Thread +{ +public: + + explicit RenderOsgViewer (); + + virtual ~RenderOsgViewer (); + + osgViewer::Viewer *get_viewer () { + return _viewer; + } + + void set_camera_manipulator (osg::ref_ptr<osgGA::StandardManipulator> &manipulator); + + void add_model (SmartPtr<RenderOsgModel> &model); + void validate_model_groups (); + + void start_render (); + void stop_render (); + +protected: + virtual bool loop (); + +private: + XCAM_DEAD_COPY (RenderOsgViewer); + XCamReturn initialize (); + +private: + osg::ref_ptr<osgViewer::Viewer> _viewer; + SmartPtr<RenderOsgModel> _model_groups; + bool _initialized; +}; + +} // namespace XCam + +#endif // XCAM_OSG_RENDER_VIEWER_H diff --git a/modules/soft/Makefile.am b/modules/soft/Makefile.am index b1cd92b..83b2721 100644 --- a/modules/soft/Makefile.am +++ b/modules/soft/Makefile.am @@ -1,75 +1,63 @@ lib_LTLIBRARIES = libxcam_soft.la -XCAMSOFT_CXXFLAGS = \ - $(LIBCL_CFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/modules \ +XCAMSOFT_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ $(NULL) -XCAMSOFT_LIBS = - -xcam_soft_sources = \ - soft_handler.cpp \ - soft_video_buf_allocator.cpp \ - soft_worker.cpp \ - soft_blender_tasks_priv.cpp \ - soft_blender.cpp \ - soft_geo_mapper.cpp \ - soft_geo_tasks_priv.cpp \ - soft_copy_task.cpp \ - soft_stitcher.cpp \ - $(NULL) +XCAMSOFT_LIBS = \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL) if HAVE_OPENCV -XCAMSOFT_CXXFLAGS += $(OPENCV_CFLAGS) - -XCAMSOFT_LIBS += $(OPENCV_LIBS) +XCAMSOFT_LIBS += $(top_builddir)/modules/ocv/libxcam_ocv.la +endif -xcam_soft_sources += \ - cv_capi_feature_match.cpp \ +xcam_soft_sources = \ + soft_handler.cpp \ + soft_video_buf_allocator.cpp \ + soft_worker.cpp \ + soft_blender_tasks_priv.cpp \ + soft_blender.cpp \ + soft_geo_mapper.cpp \ + soft_geo_tasks_priv.cpp \ + soft_copy_task.cpp \ + soft_stitcher.cpp \ $(NULL) -endif - -libxcam_soft_la_SOURCES = \ - $(xcam_soft_sources) \ +libxcam_soft_la_SOURCES = \ + $(xcam_soft_sources) \ $(NULL) -libxcam_soft_la_CXXFLAGS = \ - $(XCAMSOFT_CXXFLAGS) \ - $(XCAM_CXXFLAGS) \ +libxcam_soft_la_CXXFLAGS = \ + $(XCAMSOFT_CXXFLAGS) \ $(NULL) -libxcam_soft_la_LIBADD = \ - $(top_builddir)/xcore/libxcam_core.la \ - $(XCAMSOFT_LIBS) \ +libxcam_soft_la_LIBADD = \ + $(XCAMSOFT_LIBS) \ $(NULL) -libxcam_soft_la_LDFLAGS = \ - $(XCAM_LT_LDFLAGS) \ - $(PTHREAD_LDFLAGS) \ +libxcam_soft_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ $(NULL) libxcam_softincludedir = $(includedir)/xcam/soft -nobase_libxcam_softinclude_HEADERS = \ - soft_handler.h \ - soft_video_buf_allocator.h \ - soft_worker.h \ - soft_image.h \ - soft_blender.h \ - soft_geo_mapper.h \ - soft_copy_task.h \ - soft_stitcher.h \ +nobase_libxcam_softinclude_HEADERS = \ + soft_handler.h \ + soft_video_buf_allocator.h \ + soft_worker.h \ + soft_image.h \ + soft_blender.h \ + soft_geo_mapper.h \ + soft_copy_task.h \ + soft_stitcher.h \ $(NULL) -noinst_HEADERS = \ - soft_blender_tasks_priv.h \ - soft_geo_tasks_priv.h \ +noinst_HEADERS = \ + soft_blender_tasks_priv.h \ + soft_geo_tasks_priv.h \ $(NULL) -if HAVE_OPENCV -noinst_HEADERS += cv_capi_feature_match.h -endif - libxcam_soft_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/soft/cv_capi_feature_match.h b/modules/soft/cv_capi_feature_match.h deleted file mode 100644 index 67a9d4f..0000000 --- a/modules/soft/cv_capi_feature_match.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * cv_capi_feature_match.h - optical flow feature match - * - * Copyright (c) 2016-2017 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: Wind Yuan <feng.yuan@intel.com> - * Author: Yinhang Liu <yinhangx.liu@intel.com> - * Author: Zong Wei <wei.zong@intel.com> - */ - -#ifndef CV_CAPI_FEATURE_MATCH_H -#define CV_CAPI_FEATURE_MATCH_H - -#include <xcam_std.h> -#include <video_buffer.h> -#include <interface/feature_match.h> - -#ifdef ANDROID -#include <cv.h> -#else -#include <opencv2/opencv.hpp> -#endif - -namespace XCam { - -class CVCapiFeatureMatch - : public FeatureMatch -{ -public: - explicit CVCapiFeatureMatch (); - - void optical_flow_feature_match ( - const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, - Rect &left_img_crop, Rect &right_img_crop, int dst_width); - - void set_ocl (bool use_ocl) { - XCAM_UNUSED (use_ocl); - } - bool is_ocl_path () { - return false; - } - -protected: - bool get_crop_image (const SmartPtr<VideoBuffer> &buffer, const Rect &crop_rect, - std::vector<char> &crop_image, CvMat &img); - - void add_detected_data (CvArr* image, std::vector<CvPoint2D32f> &corners); - void get_valid_offsets (std::vector<CvPoint2D32f> &corner0, std::vector<CvPoint2D32f> &corner1, - std::vector<char> &status, std::vector<float> &error, - std::vector<float> &offsets, float &sum, int &count, - CvArr* out_image, CvSize &img0_size); - - void calc_of_match (CvArr* image0, CvArr* image1, - std::vector<CvPoint2D32f> &corner0, std::vector<CvPoint2D32f> &corner1, - std::vector<char> &status, std::vector<float> &error, - int &last_count, float &last_mean_offset, float &out_x_offset); - - void detect_and_match (CvArr* img_left, CvArr* img_right, Rect &crop_left, Rect &crop_right, - int &valid_count, float &mean_offset, float &x_offset, int dst_width); - -private: - XCAM_DEAD_COPY (CVCapiFeatureMatch); - - std::vector<char> _left_crop_image; - std::vector<char> _right_crop_image; -}; - -} - -#endif // CV_CAPI_FEATURE_MATCH_H diff --git a/modules/soft/soft_blender.cpp b/modules/soft/soft_blender.cpp index 7e0c678..056ad37 100644 --- a/modules/soft/soft_blender.cpp +++ b/modules/soft/soft_blender.cpp @@ -83,9 +83,11 @@ private: public: BlenderPrivConfig (SoftBlender *blender, uint32_t level) - : pyr_levels (level) + : pyr_levels (level - 1) , _blender (blender) - {} + { + XCAM_ASSERT (level >= 2 && level <= XCAM_SOFT_PYRAMID_MAX_LEVEL); + } XCamReturn init_first_masks (uint32_t width, uint32_t height); XCamReturn scale_down_masks (uint32_t level, uint32_t width, uint32_t height); @@ -171,8 +173,10 @@ SoftBlender::SoftBlender (const char *name) : SoftHandler (name) , Blender (SOFT_BLENDER_ALIGNMENT_X, SOFT_BLENDER_ALIGNMENT_Y) { - _priv_config = new SoftBlenderPriv::BlenderPrivConfig (this, XCAM_SOFT_PYRAMID_DEFAULT_LEVEL); - XCAM_ASSERT (_priv_config.ptr ()); + SmartPtr<SoftBlenderPriv::BlenderPrivConfig> config = + new SoftBlenderPriv::BlenderPrivConfig (this, XCAM_SOFT_PYRAMID_DEFAULT_LEVEL); + XCAM_ASSERT (config.ptr ()); + _priv_config = config; } SoftBlender::~SoftBlender () @@ -682,7 +686,9 @@ SoftBlender::configure_resource (const SmartPtr<Parameters> ¶m) XCAM_ASSERT (merge_size.width % SOFT_BLENDER_ALIGNMENT_X == 0); overlap_info.init (in0_info.format, merge_size.width, merge_size.height); - _priv_config->first_lap_pool = new SoftVideoBufAllocator (overlap_info); + SmartPtr<BufferPool> first_lap_pool = new SoftVideoBufAllocator (overlap_info); + XCAM_ASSERT (first_lap_pool.ptr ()); + _priv_config->first_lap_pool = first_lap_pool; XCAM_FAIL_RETURN ( ERROR, _priv_config->first_lap_pool->reserve (LAP_POOL_SIZE), XCAM_RETURN_ERROR_MEM, "blender:%s reserve lap buffer pool(w:%d,h:%d) failed", @@ -703,8 +709,9 @@ SoftBlender::configure_resource (const SmartPtr<Parameters> ¶m) merge_size.height = XCAM_ALIGN_UP ((merge_size.height + 1) / 2, SOFT_BLENDER_ALIGNMENT_Y); overlap_info.init (in0_info.format, merge_size.width, merge_size.height); - _priv_config->pyr_layer[i].overlap_pool = new SoftVideoBufAllocator (overlap_info); - XCAM_ASSERT (_priv_config->pyr_layer[i].overlap_pool.ptr ()); + SmartPtr<BufferPool> pool = new SoftVideoBufAllocator (overlap_info); + XCAM_ASSERT (pool.ptr ()); + _priv_config->pyr_layer[i].overlap_pool = pool; XCAM_FAIL_RETURN ( ERROR, _priv_config->pyr_layer[i].overlap_pool->reserve (OVERLAP_POOL_SIZE), XCAM_RETURN_ERROR_MEM, "blender:%s reserve buffer pool(w:%d,h:%d) failed", diff --git a/modules/soft/soft_blender.h b/modules/soft/soft_blender.h index b83511b..f6466f9 100644 --- a/modules/soft/soft_blender.h +++ b/modules/soft/soft_blender.h @@ -26,7 +26,7 @@ #include <soft/soft_handler.h> #define XCAM_SOFT_PYRAMID_MAX_LEVEL 4 -#define XCAM_SOFT_PYRAMID_DEFAULT_LEVEL 3 +#define XCAM_SOFT_PYRAMID_DEFAULT_LEVEL 2 namespace XCam { diff --git a/modules/soft/soft_blender_tasks_priv.h b/modules/soft/soft_blender_tasks_priv.h index a2f2ed8..b754df3 100644 --- a/modules/soft/soft_blender_tasks_priv.h +++ b/modules/soft/soft_blender_tasks_priv.h @@ -66,7 +66,7 @@ protected: out[4] += in[4] * coef; out[5] += in[5] * coef; out[6] += in[6] * coef; - out[7] += in[7] * coef; + //out[7] += in[7] * coef; } template<typename T> diff --git a/modules/soft/soft_geo_mapper.cpp b/modules/soft/soft_geo_mapper.cpp index 478b025..5dac5b7 100644 --- a/modules/soft/soft_geo_mapper.cpp +++ b/modules/soft/soft_geo_mapper.cpp @@ -27,6 +27,8 @@ namespace XCam { DECLARE_WORK_CALLBACK (CbGeoMapTask, SoftGeoMapper, remap_task_done); +DECLARE_WORK_CALLBACK (CbGeoMapDualConstTask, SoftDualConstGeoMapper, remap_task_done); +DECLARE_WORK_CALLBACK (CbGeoMapDualCurveTask, SoftDualCurveGeoMapper, remap_task_done); SoftGeoMapper::SoftGeoMapper (const char *name) : SoftHandler (name) @@ -60,6 +62,7 @@ SoftGeoMapper::set_lookup_table (const PointFloat2 *data, uint32_t width, uint32 ret[j].y = line [j].y; } } + return true; } @@ -73,6 +76,7 @@ SoftGeoMapper::remap ( if (xcam_ret_is_ok (ret) && !out_buf.ptr ()) { out_buf = param->out_buf; } + return ret; } @@ -87,16 +91,9 @@ SoftGeoMapper::configure_resource (const SmartPtr<Parameters> ¶m) const VideoBufferInfo &in_info = param->in_buf->get_video_info (); XCAM_FAIL_RETURN ( ERROR, in_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM, - "SoftGeoMapper(:%s) only support format(NV12) but input format is %s", + "SoftGeoMapper(%s) only support format(NV12) but input format is %s", XCAM_STR(get_name ()), xcam_fourcc_to_string (in_info.format)); - Float2 factors; - get_factors (factors.x, factors.y); - if (XCAM_DOUBLE_EQUAL_AROUND (factors.x, 0.0f) || - XCAM_DOUBLE_EQUAL_AROUND (factors.y, 0.0f)) { - auto_calculate_factors (_lookup_table->get_width (), _lookup_table->get_height ()); - } - uint32_t width, height; get_output_size (width, height); VideoBufferInfo out_info; @@ -106,13 +103,51 @@ SoftGeoMapper::configure_resource (const SmartPtr<Parameters> ¶m) XCAM_ALIGN_UP (height, XCAM_GEO_MAP_ALIGNMENT_Y)); set_out_video_info (out_info); + init_factors (); + XCAM_ASSERT (!_map_task.ptr ()); - _map_task = new XCamSoftTasks::GeoMapTask (new CbGeoMapTask(this)); - XCAM_ASSERT (_map_task.ptr ()); + _map_task = create_remap_task (); return XCAM_RETURN_NO_ERROR; } +void +SoftGeoMapper::set_work_size ( + uint32_t thread_x, uint32_t thread_y, + uint32_t luma_width, uint32_t luma_height) +{ + WorkSize work_unit = _map_task->get_work_uint (); + WorkSize global_size ( + xcam_ceil (luma_width, work_unit.value[0]) / work_unit.value[0], + xcam_ceil (luma_height, work_unit.value[1]) / work_unit.value[1]); + WorkSize local_size ( + xcam_ceil(global_size.value[0], thread_x) / thread_x , + xcam_ceil(global_size.value[1], thread_y) / thread_y); + + _map_task->set_local_size (local_size); + _map_task->set_global_size (global_size); +} + +bool +SoftGeoMapper::init_factors () +{ + Float2 factors; + get_factors (factors.x, factors.y); + if (!XCAM_DOUBLE_EQUAL_AROUND (factors.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factors.y, 0.0f)) + return true; + + return auto_calculate_factors (_lookup_table->get_width (), _lookup_table->get_height ()); +} + +SmartPtr<XCamSoftTasks::GeoMapTask> +SoftGeoMapper::create_remap_task () +{ + SmartPtr<XCamSoftTasks::GeoMapTask> map_task = new XCamSoftTasks::GeoMapTask (new CbGeoMapTask (this)); + XCAM_ASSERT (map_task.ptr ()); + + return map_task; +} + XCamReturn SoftGeoMapper::start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m) { @@ -131,17 +166,7 @@ SoftGeoMapper::start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m args->lookup_table = _lookup_table; args->factors = factors; - uint32_t thread_x = 2, thread_y = 2; - WorkSize work_unit = _map_task->get_work_uint (); - WorkSize global_size ( - xcam_ceil (args->out_luma->get_width (), work_unit.value[0]) / work_unit.value[0], - xcam_ceil (args->out_luma->get_height (), work_unit.value[1]) / work_unit.value[1]); - WorkSize local_size ( - xcam_ceil(global_size.value[0], thread_x) / thread_x , - xcam_ceil(global_size.value[1], thread_y) / thread_y); - - _map_task->set_local_size (local_size); - _map_task->set_global_size (global_size); + set_work_size (2, 2, args->out_luma->get_width (), args->out_luma->get_height ()); param->in_buf.release (); return _map_task->work (args); @@ -157,7 +182,7 @@ SoftGeoMapper::start_work (const SmartPtr<ImageHandler::Parameters> ¶m) ret = start_remap_task (param); XCAM_FAIL_RETURN ( ERROR, xcam_ret_is_ok (ret), ret, - "geo_mapper:%s start_work failed on idx0", XCAM_STR (get_name ())); + "SoftGeoMapper(%s) start_work failed on idx0", XCAM_STR (get_name ())); param->in_buf.release (); @@ -180,10 +205,11 @@ SoftGeoMapper::remap_task_done ( { XCAM_UNUSED (worker); XCAM_ASSERT (worker.ptr () == _map_task.ptr ()); + SmartPtr<XCamSoftTasks::GeoMapTask::Args> args = base.dynamic_cast_ptr<XCamSoftTasks::GeoMapTask::Args> (); XCAM_ASSERT (args.ptr ()); - const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); if (!check_work_continue (param, error)) return; @@ -194,6 +220,7 @@ SmartPtr<SoftHandler> create_soft_geo_mapper () { SmartPtr<SoftHandler> mapper = new SoftGeoMapper (); XCAM_ASSERT (mapper.ptr ()); + return mapper; } @@ -204,4 +231,216 @@ GeoMapper::create_soft_geo_mapper () return handler.dynamic_cast_ptr<GeoMapper> (); } +SoftDualConstGeoMapper::SoftDualConstGeoMapper (const char *name) + : SoftGeoMapper (name) + , _left_factor_x (0.0f) + , _left_factor_y (0.0f) + , _right_factor_x (0.0f) + , _right_factor_y (0.0f) +{ +} + +SoftDualConstGeoMapper::~SoftDualConstGeoMapper () +{ +} + +bool +SoftDualConstGeoMapper::set_left_factors (float x, float y) +{ + XCAM_FAIL_RETURN ( + ERROR, !XCAM_DOUBLE_EQUAL_AROUND (x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (y, 0.0f), false, + "SoftGeoMapper(%s) set factors failed. (x:%.3f, h:%.3f)", XCAM_STR(get_name ()), x, y); + _left_factor_x = x; + _left_factor_y = y; + + return true; +} + +bool +SoftDualConstGeoMapper::set_right_factors (float x, float y) +{ + XCAM_FAIL_RETURN ( + ERROR, !XCAM_DOUBLE_EQUAL_AROUND (x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (y, 0.0f), false, + "SoftGeoMapper(%s) set factors failed. (x:%.3f, h:%.3f)", XCAM_STR(get_name ()), x, y); + _right_factor_x = x; + _right_factor_y = y; + + return true; +} + +bool +SoftDualConstGeoMapper::auto_calculate_factors (uint32_t lut_w, uint32_t lut_h) +{ + XCAM_FAIL_RETURN ( + ERROR, lut_w > 1 && lut_w > 1, false, + "SoftGeoMapper(%s) auto calculate factors failed. lookuptable size need > 1. but set with (w:%d, h:%d)", + XCAM_STR(get_name ()), lut_w, lut_h); + + uint32_t width, height; + get_output_size (width, height); + XCAM_FAIL_RETURN ( + ERROR, width > 1 && height > 1, false, + "SoftGeoMapper(%s) auto calculate factors failed. output size was not set. (w:%d, h:%d)", + XCAM_STR(get_name ()), width, height); + + _left_factor_x = (width - 1.0f) / (lut_w - 1.0f); + _left_factor_y = (height - 1.0f) / (lut_h - 1.0f); + + _right_factor_x = _left_factor_x; + _right_factor_y = _left_factor_y; + + return true; +} + +bool +SoftDualConstGeoMapper::init_factors () +{ + Float2 left_factors, right_factors; + get_left_factors (left_factors.x, left_factors.y); + get_right_factors (right_factors.x, right_factors.y); + if (!XCAM_DOUBLE_EQUAL_AROUND (left_factors.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (left_factors.y, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (right_factors.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (right_factors.y, 0.0f)) + return true; + + SmartPtr<Float2Image> lookup_table = get_lookup_table (); + XCAM_ASSERT (lookup_table.ptr ()); + + return auto_calculate_factors (lookup_table->get_width (), lookup_table->get_height ()); +} + +SmartPtr<XCamSoftTasks::GeoMapTask> +SoftDualConstGeoMapper::create_remap_task () +{ + SmartPtr<XCamSoftTasks::GeoMapTask> map_task = + new XCamSoftTasks::GeoMapDualConstTask (new CbGeoMapDualConstTask (this)); + XCAM_ASSERT (map_task.ptr ()); + + return map_task; +} + +XCamReturn +SoftDualConstGeoMapper::prepare_arguments ( + const SmartPtr<Worker::Arguments> &base, + const SmartPtr<ImageHandler::Parameters> ¶m) +{ + SmartPtr<Float2Image> lookup_table = get_lookup_table (); + XCAM_ASSERT (lookup_table.ptr ()); + + SmartPtr<VideoBuffer> in_buf = param->in_buf, out_buf = param->out_buf; + SmartPtr<XCamSoftTasks::GeoMapDualConstTask::Args> args = + base.dynamic_cast_ptr<XCamSoftTasks::GeoMapDualConstTask::Args> (); + XCAM_ASSERT (args.ptr ()); + + Float2 factors; + get_left_factors (factors.x, factors.y); + args->left_factor = factors; + get_right_factors (factors.x, factors.y); + args->right_factor = factors; + args->in_luma = new UcharImage (in_buf, 0); + args->in_uv = new Uchar2Image (in_buf, 1); + args->out_luma = new UcharImage (out_buf, 0); + args->out_uv = new Uchar2Image (out_buf, 1); + args->lookup_table = lookup_table; + + set_work_size (2, 2, args->out_luma->get_width (), args->out_luma->get_height ()); + + param->in_buf.release (); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +SoftDualConstGeoMapper::start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + SmartPtr<XCamSoftTasks::GeoMapTask> map_task = get_map_task (); + XCAM_ASSERT (map_task.ptr ()); + + SmartPtr<XCamSoftTasks::GeoMapDualConstTask::Args> args = + new XCamSoftTasks::GeoMapDualConstTask::Args (param); + XCAM_ASSERT (args.ptr ()); + + prepare_arguments (args, param); + + return map_task->work (args); +} + +void +SoftDualConstGeoMapper::remap_task_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_ASSERT (worker.ptr () == get_map_task().ptr ()); + + SmartPtr<XCamSoftTasks::GeoMapDualConstTask::Args> args = + base.dynamic_cast_ptr<XCamSoftTasks::GeoMapDualConstTask::Args> (); + XCAM_ASSERT (args.ptr ()); + + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + if (!check_work_continue (param, error)) + return; + + work_well_done (param, error); +} + +SoftDualCurveGeoMapper::SoftDualCurveGeoMapper (const char *name) + : SoftDualConstGeoMapper (name) + , _scaled_height (0.0f) +{ +} + +SoftDualCurveGeoMapper::~SoftDualCurveGeoMapper () +{ +} + +SmartPtr<XCamSoftTasks::GeoMapTask> +SoftDualCurveGeoMapper::create_remap_task () +{ + SmartPtr<XCamSoftTasks::GeoMapDualCurveTask> map_task = + new XCamSoftTasks::GeoMapDualCurveTask (new CbGeoMapDualCurveTask (this)); + XCAM_ASSERT (map_task.ptr ()); + + map_task->set_scaled_height (_scaled_height); + + float factor_x, factor_y; + get_left_factors (factor_x, factor_y); + map_task->set_left_std_factor (factor_x, factor_y); + + get_right_factors (factor_x, factor_y); + map_task->set_right_std_factor (factor_x, factor_y); + + return map_task; +} + +XCamReturn +SoftDualCurveGeoMapper::start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + SmartPtr<XCamSoftTasks::GeoMapTask> map_task = get_map_task (); + XCAM_ASSERT (map_task.ptr ()); + + SmartPtr<XCamSoftTasks::GeoMapDualCurveTask::Args> args = + new XCamSoftTasks::GeoMapDualCurveTask::Args (param); + XCAM_ASSERT (args.ptr ()); + + prepare_arguments (args, param); + + return map_task->work (args); +} + +void +SoftDualCurveGeoMapper::remap_task_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (worker); + XCAM_ASSERT (worker.ptr () == get_map_task().ptr ()); + + SmartPtr<XCamSoftTasks::GeoMapDualCurveTask::Args> args = + base.dynamic_cast_ptr<XCamSoftTasks::GeoMapDualCurveTask::Args> (); + XCAM_ASSERT (args.ptr ()); + + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + if (!check_work_continue (param, error)) + return; + + work_well_done (param, error); +} + } diff --git a/modules/soft/soft_geo_mapper.h b/modules/soft/soft_geo_mapper.h index c0370d3..ef88f9f 100644 --- a/modules/soft/soft_geo_mapper.h +++ b/modules/soft/soft_geo_mapper.h @@ -30,13 +30,15 @@ namespace XCam { namespace XCamSoftTasks { class GeoMapTask; +class GeoMapDualConstTask; +class GeoMapDualCurveTask; }; class SoftGeoMapper : public SoftHandler, public GeoMapper { public: - SoftGeoMapper (const char *name = "SoftGeoMap"); + SoftGeoMapper (const char *name = "SoftGeoMapper"); ~SoftGeoMapper (); bool set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height); @@ -57,8 +59,18 @@ protected: XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); XCamReturn start_work (const SmartPtr<Parameters> ¶m); -private: - XCamReturn start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m); + void set_work_size (uint32_t thread_x, uint32_t thread_y, uint32_t luma_width, uint32_t luma_height); + SmartPtr<XCamSoftTasks::GeoMapTask> &get_map_task () { + return _map_task; + } + SmartPtr<Float2Image> &get_lookup_table () { + return _lookup_table; + } + +protected: + virtual bool init_factors (); + virtual SmartPtr<XCamSoftTasks::GeoMapTask> create_remap_task (); + virtual XCamReturn start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m); private: SmartPtr<XCamSoftTasks::GeoMapTask> _map_task; @@ -66,6 +78,64 @@ private: }; extern SmartPtr<SoftHandler> create_soft_geo_mapper (); -} +class SoftDualConstGeoMapper + : public SoftGeoMapper +{ +public: + SoftDualConstGeoMapper (const char *name = "SoftDualConstGeoMapper"); + ~SoftDualConstGeoMapper (); + + bool set_left_factors (float x, float y); + void get_left_factors (float &x, float &y) { + x = _left_factor_x; + y = _left_factor_y; + } + bool set_right_factors (float x, float y); + void get_right_factors (float &x, float &y) { + x = _right_factor_x; + y = _right_factor_y; + } + + virtual void remap_task_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &args, const XCamReturn error); + +protected: + XCamReturn prepare_arguments (const SmartPtr<Worker::Arguments> &args, + const SmartPtr<ImageHandler::Parameters> ¶m); + virtual bool auto_calculate_factors (uint32_t lut_w, uint32_t lut_h); + +protected: + virtual bool init_factors (); + virtual SmartPtr<XCamSoftTasks::GeoMapTask> create_remap_task (); + virtual XCamReturn start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m); + +private: + float _left_factor_x, _left_factor_y; + float _right_factor_x, _right_factor_y; +}; + +class SoftDualCurveGeoMapper + : public SoftDualConstGeoMapper +{ +public: + SoftDualCurveGeoMapper (const char *name = "SoftDualCurveGeoMapper"); + ~SoftDualCurveGeoMapper (); + + void set_scaled_height (float scaled_height) { + _scaled_height = scaled_height; + } + + virtual void remap_task_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &args, const XCamReturn error); + +private: + virtual SmartPtr<XCamSoftTasks::GeoMapTask> create_remap_task (); + virtual XCamReturn start_remap_task (const SmartPtr<ImageHandler::Parameters> ¶m); + +private: + float _scaled_height; +}; + +} #endif //XCAM_SOFT_GEO_MAP_H diff --git a/modules/soft/soft_geo_tasks_priv.cpp b/modules/soft/soft_geo_tasks_priv.cpp index 8079352..59e8845 100644 --- a/modules/soft/soft_geo_tasks_priv.cpp +++ b/modules/soft/soft_geo_tasks_priv.cpp @@ -24,6 +24,100 @@ namespace XCam { namespace XCamSoftTasks { +enum BoundState { + BoundInternal = 0, + BoundCritical, + BoundExternal +}; + +inline void check_bound (const uint32_t &img_w, const uint32_t &img_h, Float2 *in_pos, + const uint32_t &max_idx, BoundState &bound) +{ + if (in_pos[0].x >= 0.0f && in_pos[max_idx].x >= 0.0f && in_pos[0].x < img_w && in_pos[max_idx].x < img_w && + in_pos[0].y >= 0.0f && in_pos[max_idx].y >= 0.0f && in_pos[0].y < img_h && in_pos[max_idx].y < img_h) + bound = BoundInternal; + else if ((in_pos[0].x < 0.0f && in_pos[max_idx].x < 0.0f) || (in_pos[0].x >= img_w && in_pos[max_idx].x >= img_w) || + (in_pos[0].y < 0.0f && in_pos[max_idx].y < 0.0f) || (in_pos[0].y >= img_h && in_pos[max_idx].y >= img_h)) + bound = BoundExternal; + else + bound = BoundCritical; +} + +template <typename TypeT> +inline void calc_critical_pixels (const uint32_t &img_w, const uint32_t &img_h, Float2 *in_pos, + const uint32_t &max_idx, const TypeT &zero_byte, TypeT *luma) +{ + for (uint32_t idx = 0; idx < max_idx; ++idx) { + if (in_pos[idx].x < 0.0f || in_pos[idx].x >= img_w || in_pos[idx].y < 0.0f || in_pos[idx].y >= img_h) + luma[idx] = zero_byte; + } +} + +static void map_image ( + const UcharImage *in_luma, const Uchar2Image *in_uv, + UcharImage *out_luma, Uchar2Image *out_uv, const Float2Image *lut, + const uint32_t &luma_w, const uint32_t &luma_h, const uint32_t &uv_w, const uint32_t &uv_h, + const uint32_t &x_idx, const uint32_t &y_idx, const uint32_t &out_x, const uint32_t &out_y, + const Float2 &first, const Float2 &step, const Uchar *zero_luma_byte, const Uchar2 *zero_uv_byte) +{ + Float2 lut_pos[8] = { + first, Float2(first.x + step.x, first.y), + Float2(first.x + step.x * 2, first.y), Float2(first.x + step.x * 3, first.y), + Float2(first.x + step.x * 4, first.y), Float2(first.x + step.x * 5, first.y), + Float2(first.x + step.x * 6, first.y), Float2(first.x + step.x * 7, first.y) + }; + + //1st-line luma + Float2 in_pos[8]; + float luma_value[8]; + Uchar luma_uc[8]; + BoundState bound = BoundInternal; + lut->read_interpolate_array<Float2, 8> (lut_pos, in_pos); + check_bound (luma_w, luma_h, in_pos, 7, bound); + if (bound == BoundExternal) + out_luma->write_array_no_check<8> (out_x, out_y, zero_luma_byte); + else { + in_luma->read_interpolate_array<float, 8> (in_pos, luma_value); + convert_to_uchar_N<float, 8> (luma_value, luma_uc); + if (bound == BoundCritical) + calc_critical_pixels (luma_w, luma_h, in_pos, 8, zero_luma_byte[0], luma_uc); + out_luma->write_array_no_check<8> (out_x, out_y, luma_uc); + } + + //4x1 UV + Float2 uv_value[4]; + Uchar2 uv_uc[4]; + in_pos[0] /= 2.0f; + in_pos[1] = in_pos[2] / 2.0f; + in_pos[2] = in_pos[4] / 2.0f; + in_pos[3] = in_pos[6] / 2.0f; + check_bound (uv_w, uv_h, in_pos, 3, bound); + if (bound == BoundExternal) + out_uv->write_array_no_check<4> (x_idx * 4, y_idx, zero_uv_byte); + else { + in_uv->read_interpolate_array<Float2, 4> (in_pos, uv_value); + convert_to_uchar2_N<Float2, 4> (uv_value, uv_uc); + if (bound == BoundCritical) + calc_critical_pixels (uv_w, uv_h, in_pos, 4, zero_uv_byte[0], uv_uc); + out_uv->write_array_no_check<4> (x_idx * 4, y_idx, uv_uc); + } + + //2nd-line luma + lut_pos[0].y = lut_pos[1].y = lut_pos[2].y = lut_pos[3].y = lut_pos[4].y = lut_pos[5].y = + lut_pos[6].y = lut_pos[7].y = first.y + step.y; + lut->read_interpolate_array<Float2, 8> (lut_pos, in_pos); + check_bound (luma_w, luma_h, in_pos, 7, bound); + if (bound == BoundExternal) + out_luma->write_array_no_check<8> (out_x, out_y + 1, zero_luma_byte); + else { + in_luma->read_interpolate_array<float, 8> (in_pos, luma_value); + convert_to_uchar_N<float, 8> (luma_value, luma_uc); + if (bound == BoundCritical) + calc_critical_pixels (luma_w, luma_h, in_pos, 8, zero_luma_byte[0], luma_uc); + out_luma->write_array_no_check<8> (out_x, out_y + 1, luma_uc); + } +} + XCamReturn GeoMapTask::work_range (const SmartPtr<Arguments> &base, const WorkRange &range) { @@ -31,6 +125,7 @@ GeoMapTask::work_range (const SmartPtr<Arguments> &base, const WorkRange &range) static const Uchar2 zero_uv_byte[4] = {{128, 128}, {128, 128}, {128, 128}, {128, 128}}; SmartPtr<GeoMapTask::Args> args = base.dynamic_cast_ptr<GeoMapTask::Args> (); XCAM_ASSERT (args.ptr ()); + UcharImage *in_luma = args->in_luma.ptr (), *out_luma = args->out_luma.ptr (); Uchar2Image *in_uv = args->in_uv.ptr (), *out_uv = args->out_uv.ptr (); Float2Image *lut = args->lookup_table.ptr (); @@ -39,78 +134,246 @@ GeoMapTask::work_range (const SmartPtr<Arguments> &base, const WorkRange &range) XCAM_ASSERT (lut); Float2 factors = args->factors; - XCAM_ASSERT ( - !XCAM_DOUBLE_EQUAL_AROUND (factors.x, 0.0f) && - !XCAM_DOUBLE_EQUAL_AROUND (factors.y, 0.0f)); + XCAM_ASSERT (!XCAM_DOUBLE_EQUAL_AROUND (factors.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factors.y, 0.0f)); + + Float2 step = Float2(1.0f, 1.0f) / factors; Float2 out_center ((out_luma->get_width () - 1.0f ) / 2.0f, (out_luma->get_height () - 1.0f ) / 2.0f); Float2 lut_center ((lut->get_width () - 1.0f) / 2.0f, (lut->get_height () - 1.0f) / 2.0f); - float x_step = 1.0f / factors.x; - float y_step = 1.0f / factors.y; -#undef OUT_BOUND -#define OUT_BOUND(image, first, last) \ - (in_pos[first].x >= image->get_width ()) || \ - (in_pos[first].y >= image->get_height ()) || \ - (in_pos[last].x <= 0.0f) || (in_pos[last].y <= 0.0f) + uint32_t luma_w = in_luma->get_width (); + uint32_t luma_h = in_luma->get_height (); + uint32_t uv_w = in_uv->get_width (); + uint32_t uv_h = in_uv->get_height (); for (uint32_t y = range.pos[1]; y < range.pos[1] + range.pos_len[1]; ++y) for (uint32_t x = range.pos[0]; x < range.pos[0] + range.pos_len[0]; ++x) { - // calculate 8x2 luma, center aligned - Float2 in_pos[8]; - float luma_value[8]; - Uchar luma_uc[8]; uint32_t out_x = x * 8, out_y = y * 2; - //1st-line luma + // calculate 8x2 luma, center aligned Float2 out_pos (out_x, out_y); out_pos -= out_center; Float2 first = out_pos / factors; first += lut_center; - Float2 lut_pos[8] = { - first, Float2(first.x + x_step, first.y), - Float2(first.x + x_step * 2, first.y), Float2(first.x + x_step * 3, first.y), - Float2(first.x + x_step * 4, first.y), Float2(first.x + x_step * 5, first.y), - Float2(first.x + x_step * 6, first.y), Float2(first.x + x_step * 7, first.y) - }; - lut->read_interpolate_array<Float2, 8> (lut_pos, in_pos); - in_luma->read_interpolate_array<float, 8> (in_pos, luma_value); - convert_to_uchar_N<float, 8> (luma_value, luma_uc); - if (OUT_BOUND (in_luma, 0, 7)) - out_luma->write_array_no_check<8> (out_x, out_y, zero_luma_byte); - else - out_luma->write_array_no_check<8> (out_x, out_y, luma_uc); - - //4x1 UV - Float2 uv_value[4]; - Uchar2 uv_uc[4]; - in_pos[0] /= 2.0f; - in_pos[1] = in_pos[2] / 2.0f; - in_pos[2] = in_pos[4] / 2.0f; - in_pos[3] = in_pos[6] / 2.0f; - in_uv->read_interpolate_array<Float2, 4> (in_pos, uv_value); - convert_to_uchar2_N<Float2, 4> (uv_value, uv_uc); - if (OUT_BOUND (in_uv, 0, 3)) - out_uv->write_array_no_check<4> (x * 4, y, zero_uv_byte); - else - out_uv->write_array_no_check<4> (x * 4, y, uv_uc); - - //2nd-line luma - lut_pos[0].y = lut_pos[1].y = lut_pos[2].y = lut_pos[3].y = lut_pos[4].y = lut_pos[5].y = - lut_pos[6].y = lut_pos[7].y = first.y + y_step; - lut->read_interpolate_array<Float2, 8> (lut_pos, in_pos); - in_luma->read_interpolate_array<float, 8> (in_pos, luma_value); - convert_to_uchar_N<float, 8> (luma_value, luma_uc); - if (OUT_BOUND (in_luma, 0, 7)) - out_luma->write_array_no_check<8> (out_x, out_y + 1, zero_luma_byte); - else - out_luma->write_array_no_check<8> (out_x, out_y + 1, luma_uc); + + map_image (in_luma, in_uv, out_luma, out_uv, lut, luma_w, luma_h, uv_w, uv_h, + x, y, out_x, out_y, first, step, zero_luma_byte, zero_uv_byte); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +GeoMapDualConstTask::work_range (const SmartPtr<Arguments> &base, const WorkRange &range) +{ + static const Uchar zero_luma_byte[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + static const Uchar2 zero_uv_byte[4] = {{128, 128}, {128, 128}, {128, 128}, {128, 128}}; + SmartPtr<GeoMapDualConstTask::Args> args = base.dynamic_cast_ptr<GeoMapDualConstTask::Args> (); + XCAM_ASSERT (args.ptr ()); + + UcharImage *in_luma = args->in_luma.ptr (), *out_luma = args->out_luma.ptr (); + Uchar2Image *in_uv = args->in_uv.ptr (), *out_uv = args->out_uv.ptr (); + Float2Image *lut = args->lookup_table.ptr (); + XCAM_ASSERT (in_luma && in_uv); + XCAM_ASSERT (out_luma && out_uv); + XCAM_ASSERT (lut); + + Float2 left_factor = args->left_factor; + Float2 right_factor = args->right_factor; + XCAM_ASSERT ( + !XCAM_DOUBLE_EQUAL_AROUND (left_factor.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (left_factor.y, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (right_factor.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (right_factor.y, 0.0f)); + + Float2 left_step = Float2(1.0f, 1.0f) / left_factor; + Float2 right_step = Float2(1.0f, 1.0f) / right_factor; + + Float2 out_center ((out_luma->get_width () - 1.0f ) / 2.0f, (out_luma->get_height () - 1.0f ) / 2.0f); + Float2 lut_center ((lut->get_width () - 1.0f) / 2.0f, (lut->get_height () - 1.0f) / 2.0f); + + uint32_t luma_w = in_luma->get_width (); + uint32_t luma_h = in_luma->get_height (); + uint32_t uv_w = in_uv->get_width (); + uint32_t uv_h = in_uv->get_height (); + + for (uint32_t y = range.pos[1]; y < range.pos[1] + range.pos_len[1]; ++y) + for (uint32_t x = range.pos[0]; x < range.pos[0] + range.pos_len[0]; ++x) + { + uint32_t out_x = x * 8, out_y = y * 2; + Float2 &factor = (out_x + 4 < out_center.x) ? left_factor : right_factor; + Float2 &step = (out_x + 4 < out_center.x) ? left_step : right_step; + + // calculate 8x2 luma, center aligned + Float2 out_pos (out_x, out_y); + out_pos -= out_center; + Float2 first = out_pos / factor; + first += lut_center; + + map_image (in_luma, in_uv, out_luma, out_uv, lut, luma_w, luma_h, uv_w, uv_h, + x, y, out_x, out_y, first, step, zero_luma_byte, zero_uv_byte); } + return XCAM_RETURN_NO_ERROR; } +GeoMapDualCurveTask::GeoMapDualCurveTask (const SmartPtr<Worker::Callback> &cb) + : GeoMapDualConstTask (cb) + , _scaled_height (0.0f) + , _left_std_factor (0.0f, 0.0f) + , _right_std_factor (0.0f, 0.0f) + , _left_factors (NULL) + , _right_factors (NULL) + , _left_steps (NULL) + , _right_steps (NULL) +{ + set_work_uint (8, 2); } +GeoMapDualCurveTask::~GeoMapDualCurveTask () { + if (_left_factors) { + delete [] _left_factors; + _left_factors = NULL; + } + if (_right_factors) { + delete [] _right_factors; + _right_factors = NULL; + } + if (_left_steps) { + delete [] _left_steps; + _left_steps = NULL; + } + if (_right_steps) { + delete [] _right_steps; + _right_steps = NULL; + } } +void +GeoMapDualCurveTask::set_left_std_factor (float x, float y) { + XCAM_ASSERT (!XCAM_DOUBLE_EQUAL_AROUND (x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (y, 0.0f)); + + _left_std_factor.x = x; + _left_std_factor.y = y; +} + +void +GeoMapDualCurveTask::set_right_std_factor (float x, float y) { + XCAM_ASSERT (!XCAM_DOUBLE_EQUAL_AROUND (x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (y, 0.0f)); + + _right_std_factor.x = x; + _right_std_factor.y = y; +} + +static void calc_cur_row_factor ( + const uint32_t &y, const uint32_t &ym, + const Float2 &std_factor, const float &scaled_height, + const Float2 &factor, Float2 &cur_row_factor) +{ + float a, b, c; + a = (std_factor.x - factor.x) / ((scaled_height - ym) * (scaled_height - ym)); + b = -2 * a * ym; + c = std_factor.x - a * scaled_height * scaled_height - b * scaled_height; + cur_row_factor.x = (y >= scaled_height) ? std_factor.x : ((y < ym) ? factor.x : (a * y * y + b * y + c)); + + cur_row_factor.y = factor.y; +} + +void +GeoMapDualCurveTask::set_factors (SmartPtr<GeoMapDualCurveTask::Args> args, uint32_t size) { + if (_left_factors == NULL) { + _left_factors = new Float2[size]; + XCAM_ASSERT (_left_factors); + } + if (_right_factors == NULL) { + _right_factors = new Float2[size]; + XCAM_ASSERT (_right_factors); + } + + float ym = _scaled_height * 0.5f; + for (uint32_t y = 0; y < size; ++y) { + calc_cur_row_factor (y, ym, _left_std_factor, _scaled_height, args->left_factor, _left_factors[y]); + calc_cur_row_factor (y, ym, _right_std_factor, _scaled_height, args->right_factor, _right_factors[y]); + } +} + +bool +GeoMapDualCurveTask::set_steps (uint32_t size) { + if (_left_steps == NULL) { + _left_steps = new Float2[size]; + XCAM_ASSERT (_left_steps); + } + if (_right_steps == NULL) { + _right_steps = new Float2[size]; + XCAM_ASSERT (_right_steps); + } + + for (uint32_t y = 0; y < size; ++y) { + XCAM_FAIL_RETURN ( + ERROR, + !XCAM_DOUBLE_EQUAL_AROUND (_left_factors[y].x, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (_left_factors[y].y, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (_right_factors[y].x, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (_right_factors[y].y, 0.0f), + false, + "GeoMapDualCurveTask invalid factor(row:%d): left_factor(x:%f, y:%f) right_factor(x:%f, y:%f)", + y, _left_factors[y].x, _left_factors[y].y, _right_factors[y].x, _right_factors[y].y); + + _left_steps[y] = Float2(1.0f, 1.0f) / _left_factors[y]; + _right_steps[y] = Float2(1.0f, 1.0f) / _right_factors[y]; + } + + return true; +} + +XCamReturn +GeoMapDualCurveTask::work_range (const SmartPtr<Arguments> &base, const WorkRange &range) +{ + static const Uchar zero_luma_byte[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + static const Uchar2 zero_uv_byte[4] = {{128, 128}, {128, 128}, {128, 128}, {128, 128}}; + SmartPtr<GeoMapDualCurveTask::Args> args = base.dynamic_cast_ptr<GeoMapDualCurveTask::Args> (); + XCAM_ASSERT (args.ptr ()); + XCAM_ASSERT ( + !XCAM_DOUBLE_EQUAL_AROUND (args->left_factor.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (args->left_factor.y, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (args->right_factor.x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (args->right_factor.y, 0.0f)); + + UcharImage *in_luma = args->in_luma.ptr (), *out_luma = args->out_luma.ptr (); + Uchar2Image *in_uv = args->in_uv.ptr (), *out_uv = args->out_uv.ptr (); + Float2Image *lut = args->lookup_table.ptr (); + XCAM_ASSERT (in_luma && in_uv); + XCAM_ASSERT (out_luma && out_uv); + XCAM_ASSERT (lut); + + set_factors (args, out_luma->get_height ()); + set_steps (out_luma->get_height ()); + + Float2 out_center ((out_luma->get_width () - 1.0f ) / 2.0f, (out_luma->get_height () - 1.0f ) / 2.0f); + Float2 lut_center ((lut->get_width () - 1.0f) / 2.0f, (lut->get_height () - 1.0f) / 2.0f); + + uint32_t luma_w = in_luma->get_width (); + uint32_t luma_h = in_luma->get_height (); + uint32_t uv_w = in_uv->get_width (); + uint32_t uv_h = in_uv->get_height (); + + for (uint32_t y = range.pos[1]; y < range.pos[1] + range.pos_len[1]; ++y) + for (uint32_t x = range.pos[0]; x < range.pos[0] + range.pos_len[0]; ++x) + { + uint32_t out_x = x * 8, out_y = y * 2; + Float2 &factor = (out_x + 4 < out_center.x) ? _left_factors[out_y] : _right_factors[out_y]; + Float2 &step = (out_x + 4 < out_center.x) ? _left_steps[out_y] : _right_steps[out_y]; + + // calculate 8x2 luma, center aligned + Float2 out_pos (out_x, out_y); + out_pos -= out_center; + Float2 first = out_pos / factor; + first += lut_center; + + map_image (in_luma, in_uv, out_luma, out_uv, lut, luma_w, luma_h, uv_w, uv_h, + x, y, out_x, out_y, first, step, zero_luma_byte, zero_uv_byte); + } + + return XCAM_RETURN_NO_ERROR; +} + +} + +} diff --git a/modules/soft/soft_geo_tasks_priv.h b/modules/soft/soft_geo_tasks_priv.h index 36514b2..e1dc4d3 100644 --- a/modules/soft/soft_geo_tasks_priv.h +++ b/modules/soft/soft_geo_tasks_priv.h @@ -18,6 +18,9 @@ * Author: Wind Yuan <feng.yuan@intel.com> */ +#ifndef XCAM_SOFT_GEO_TASKS_PRIV_H +#define XCAM_SOFT_GEO_TASKS_PRIV_H + #include <xcam_std.h> #include <soft/soft_worker.h> #include <soft/soft_image.h> @@ -54,6 +57,73 @@ private: virtual XCamReturn work_range (const SmartPtr<Arguments> &args, const WorkRange &range); }; +class GeoMapDualConstTask + : public GeoMapTask +{ +public: + struct Args : GeoMapTask::Args { + Float2 left_factor; + Float2 right_factor; + + Args ( + const SmartPtr<ImageHandler::Parameters> ¶m) + : GeoMapTask::Args (param) + {} + }; + +public: + explicit GeoMapDualConstTask (const SmartPtr<Worker::Callback> &cb) + : GeoMapTask (cb) + { + set_work_uint (8, 2); + } + +private: + virtual XCamReturn work_range (const SmartPtr<Arguments> &args, const WorkRange &range); +}; + +class GeoMapDualCurveTask + : public GeoMapDualConstTask +{ +public: + struct Args : GeoMapDualConstTask::Args { + Args ( + const SmartPtr<ImageHandler::Parameters> ¶m) + : GeoMapDualConstTask::Args (param) + {} + }; + +public: + explicit GeoMapDualCurveTask (const SmartPtr<Worker::Callback> &cb); + ~GeoMapDualCurveTask (); + + void set_scaled_height (float scaled_height) { + XCAM_ASSERT (!XCAM_DOUBLE_EQUAL_AROUND (scaled_height, 0.0f)); + _scaled_height = scaled_height; + } + + void set_left_std_factor (float x, float y); + void set_right_std_factor (float x, float y); + +private: + void set_factors (SmartPtr<GeoMapDualCurveTask::Args> args, uint32_t size); + bool set_steps (uint32_t size); + + virtual XCamReturn work_range (const SmartPtr<Arguments> &args, const WorkRange &range); + + XCAM_DEAD_COPY (GeoMapDualCurveTask); + +private: + float _scaled_height; + Float2 _left_std_factor; + Float2 _right_std_factor; + Float2 *_left_factors; + Float2 *_right_factors; + Float2 *_left_steps; + Float2 *_right_steps; +}; + } } +#endif // XCAM_SOFT_GEO_TASKS_PRIV_H diff --git a/modules/soft/soft_handler.cpp b/modules/soft/soft_handler.cpp index 6a81472..984fa66 100644 --- a/modules/soft/soft_handler.cpp +++ b/modules/soft/soft_handler.cpp @@ -82,8 +82,6 @@ SyncMeta::is_error () const SoftHandler::SoftHandler (const char* name) : ImageHandler (name) - , _need_configure (true) - , _enable_allocator (true) , _wip_buf_count (0) { } @@ -99,47 +97,29 @@ SoftHandler::set_threads (const SmartPtr<ThreadPool> &pool) return true; } -bool -SoftHandler::set_out_video_info (const VideoBufferInfo &info) +SmartPtr<BufferPool> +SoftHandler::create_allocator () { - XCAM_ASSERT (info.width && info.height && info.format); - _out_video_info = info; - return true; -} - -bool -SoftHandler::enable_allocator (bool enable) -{ - _enable_allocator = enable; - return true; + return new SoftVideoBufAllocator; } XCamReturn -SoftHandler::confirm_configured () +SoftHandler::configure_rest () { XCamReturn ret = XCAM_RETURN_NO_ERROR; XCAM_ASSERT (_need_configure); - if (_enable_allocator) { - XCAM_FAIL_RETURN ( - ERROR, _out_video_info.is_valid (), XCAM_RETURN_ERROR_PARAM, - "soft_hander(%s) configure resource failed before reserver buffer since out video info was not set", - XCAM_STR (get_name ())); - - set_allocator (new SoftVideoBufAllocator); - ret = reserve_buffers (_out_video_info, DEFAULT_SOFT_BUF_COUNT); - XCAM_FAIL_RETURN ( - ERROR, ret == XCAM_RETURN_NO_ERROR, ret, - "soft_hander(%s) configure resource failed in reserving buffers", XCAM_STR (get_name ())); - } + ret = ImageHandler::configure_rest (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "soft_hander(%s) configure reset failed on ImageHandler::configure_rest", XCAM_STR (get_name ())); if (_threads.ptr () && !_threads->is_running ()) { ret = _threads->start (); XCAM_FAIL_RETURN ( - ERROR, ret == XCAM_RETURN_NO_ERROR, ret, - "soft_hander(%s) configure resource failed when starting threads", XCAM_STR (get_name ())); + ERROR, xcam_ret_is_ok (ret), ret, + "soft_hander(%s) configure reset failed when starting threads", XCAM_STR (get_name ())); } - _need_configure = false; return ret; } @@ -148,7 +128,6 @@ XCamReturn SoftHandler::execute_buffer (const SmartPtr<ImageHandler::Parameters> ¶m, bool sync) { XCamReturn ret = XCAM_RETURN_NO_ERROR; - SmartPtr<SyncMeta> sync_meta; XCAM_FAIL_RETURN ( ERROR, param.ptr (), XCAM_RETURN_ERROR_PARAM, @@ -161,10 +140,12 @@ SoftHandler::execute_buffer (const SmartPtr<ImageHandler::Parameters> ¶m, bo WARNING, xcam_ret_is_ok (ret), ret, "soft_hander(%s) configure resource failed", XCAM_STR (get_name ())); - ret = confirm_configured (); + ret = configure_rest (); XCAM_FAIL_RETURN ( WARNING, xcam_ret_is_ok (ret), ret, "soft_hander(%s) confirm configure failed", XCAM_STR (get_name ())); + + _need_configure = false; } if (!param->out_buf.ptr () && _enable_allocator) { @@ -176,7 +157,7 @@ SoftHandler::execute_buffer (const SmartPtr<ImageHandler::Parameters> ¶m, bo } XCAM_ASSERT (!param->find_meta<SyncMeta> ().ptr ()); - sync_meta = new SyncMeta (); + SmartPtr<SyncMeta> sync_meta = new SyncMeta (); XCAM_ASSERT (sync_meta.ptr ()); param->add_meta (sync_meta); diff --git a/modules/soft/soft_handler.h b/modules/soft/soft_handler.h index e2041bf..460762a 100644 --- a/modules/soft/soft_handler.h +++ b/modules/soft/soft_handler.h @@ -57,8 +57,6 @@ public: ~SoftHandler (); bool set_threads (const SmartPtr<ThreadPool> &pool); - bool set_out_video_info (const VideoBufferInfo &info); - bool enable_allocator (bool enable); // derive from ImageHandler virtual XCamReturn execute_buffer (const SmartPtr<Parameters> ¶m, bool sync); @@ -66,8 +64,10 @@ public: virtual XCamReturn terminate (); protected: - virtual XCamReturn configure_resource (const SmartPtr<Parameters> ¶m) = 0; - virtual XCamReturn start_work (const SmartPtr<Parameters> ¶m) = 0; + // derived from ImageHandler + virtual SmartPtr<BufferPool> create_allocator (); + virtual XCamReturn configure_rest (); + //virtual SmartPtr<Worker::Arguments> get_first_worker_args (const SmartPtr<SoftWorker> &worker, SmartPtr<Parameters> ¶ms) = 0; virtual void work_well_done (const SmartPtr<ImageHandler::Parameters> ¶m, XCamReturn err); virtual void work_broken (const SmartPtr<ImageHandler::Parameters> ¶m, XCamReturn err); @@ -76,7 +76,6 @@ protected: bool check_work_continue (const SmartPtr<ImageHandler::Parameters> ¶m, XCamReturn err); private: - XCamReturn confirm_configured (); void param_ended (SmartPtr<ImageHandler::Parameters> param, XCamReturn err); static bool is_param_error (const SmartPtr<ImageHandler::Parameters> ¶m); @@ -85,10 +84,7 @@ private: private: SmartPtr<ThreadPool> _threads; - VideoBufferInfo _out_video_info; SmartPtr<SyncMeta> _cur_sync; - bool _need_configure; - bool _enable_allocator; SafeList<Parameters> _params; mutable std::atomic<int32_t> _wip_buf_count; }; diff --git a/modules/soft/soft_stitcher.cpp b/modules/soft/soft_stitcher.cpp index 42f0c93..f5189e1 100644 --- a/modules/soft/soft_stitcher.cpp +++ b/modules/soft/soft_stitcher.cpp @@ -31,7 +31,7 @@ #define ENABLE_FEATURE_MATCH HAVE_OPENCV #if ENABLE_FEATURE_MATCH -#include "cv_capi_feature_match.h" +#include "ocv/cv_capi_feature_match.h" #ifndef ANDROID #include <opencv2/core/ocl.hpp> #endif @@ -181,18 +181,24 @@ public: XCamReturn stop (); XCamReturn fisheye_dewarp_to_table (); - XCamReturn feature_match ( - const SmartPtr<VideoBuffer> &left_buf, - const SmartPtr<VideoBuffer> &right_buf, - const uint32_t idx); + XCamReturn start_feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, const uint32_t idx); bool get_and_reset_feature_match_factors (uint32_t idx, Factor &left, Factor &right); private: + SmartPtr<SoftGeoMapper> create_geo_mapper (const Stitcher::RoundViewSlice &view_slice); + XCamReturn init_fisheye (uint32_t idx); bool init_dewarp_factors (uint32_t idx); XCamReturn create_copier (Stitcher::CopyArea area); + void calc_factors ( + const uint32_t &idx, const Factor &last_left_factor, const Factor &last_right_factor, + Factor &cur_left, Factor &cur_right); + + void init_feature_match (uint32_t idx); + private: FisheyeDewarp _fisheye [XCAM_STITCH_MAX_CAMERAS]; Overlap _overlaps [XCAM_STITCH_MAX_CAMERAS]; @@ -205,6 +211,21 @@ private: SoftStitcher *_stitcher; }; + +void +StitcherImpl::calc_factors ( + const uint32_t &idx, const Factor &last_left_factor, const Factor &last_right_factor, + Factor &cur_left, Factor &cur_right) +{ + Factor match_left_factor, match_right_factor; + get_and_reset_feature_match_factors (idx, match_left_factor, match_right_factor); + + cur_left.x = last_left_factor.x * match_left_factor.x; + cur_left.y = last_left_factor.y * match_left_factor.y; + cur_right.x = last_right_factor.x * match_right_factor.x; + cur_right.y = last_right_factor.y * match_right_factor.y; +} + bool StitcherImpl::init_dewarp_factors (uint32_t idx) { @@ -212,26 +233,38 @@ StitcherImpl::init_dewarp_factors (uint32_t idx) ERROR, _fisheye[idx].dewarp.ptr (), false, "FisheyeDewarp dewarp handler empty"); - Factor match_left_factor, match_right_factor; - get_and_reset_feature_match_factors (idx, match_left_factor, match_right_factor); + Factor last_left_factor, last_right_factor, cur_left, cur_right; + if (_stitcher->get_scale_mode () == ScaleSingleConst) { + Factor unify_factor; + _fisheye[idx].dewarp->get_factors (unify_factor.x, unify_factor.y); + if (XCAM_DOUBLE_EQUAL_AROUND (unify_factor.x, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (unify_factor.y, 0.0f)) { // not started. + return true; + } + last_left_factor = last_right_factor = unify_factor; - Factor unify_factor, last_left_factor, last_right_factor; - _fisheye[idx].dewarp->get_factors (unify_factor.x, unify_factor.y); - last_left_factor = last_right_factor = unify_factor; - if (XCAM_DOUBLE_EQUAL_AROUND (unify_factor.x, 0.0f) || - XCAM_DOUBLE_EQUAL_AROUND (unify_factor.y, 0.0f)) { // not started. - return true; - } + calc_factors (idx, last_left_factor, last_right_factor, cur_left, cur_right); + unify_factor.x = (cur_left.x + cur_right.x) / 2.0f; + unify_factor.y = (cur_left.y + cur_right.y) / 2.0f; - Factor cur_left, cur_right; - cur_left.x = last_left_factor.x * match_left_factor.x; - cur_left.y = last_left_factor.y * match_left_factor.y; - cur_right.x = last_right_factor.x * match_right_factor.x; - cur_right.y = last_right_factor.y * match_right_factor.y; + _fisheye[idx].dewarp->set_factors (unify_factor.x, unify_factor.y); + } else { + SmartPtr<SoftDualConstGeoMapper> dewarp = _fisheye[idx].dewarp.dynamic_cast_ptr<SoftDualConstGeoMapper> (); + XCAM_ASSERT (dewarp.ptr ()); + dewarp->get_left_factors (last_left_factor.x, last_left_factor.y); + dewarp->get_right_factors (last_right_factor.x, last_right_factor.y); + if (XCAM_DOUBLE_EQUAL_AROUND (last_left_factor.x, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (last_left_factor.y, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (last_right_factor.y, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (last_right_factor.y, 0.0f)) { // not started. + return true; + } + + calc_factors (idx, last_left_factor, last_right_factor, cur_left, cur_right); - unify_factor.x = (cur_left.x + cur_right.x) / 2.0f; - unify_factor.y = (cur_left.y + cur_right.y) / 2.0f; - _fisheye[idx].dewarp->set_factors (unify_factor.x, unify_factor.y); + dewarp->set_left_factors (cur_left.x, cur_left.y); + dewarp->set_right_factors (cur_right.x, cur_right.y); + } return true; } @@ -280,26 +313,49 @@ StitcherImpl::get_and_reset_feature_match_factors (uint32_t idx, Factor &left, F return true; } +SmartPtr<SoftGeoMapper> +StitcherImpl::create_geo_mapper (const Stitcher::RoundViewSlice &view_slice) +{ + SmartPtr<SoftGeoMapper> dewarp; + if (_stitcher->get_scale_mode () == ScaleSingleConst) + dewarp = new SoftGeoMapper ("sitcher_remapper"); + else if (_stitcher->get_scale_mode () == ScaleDualConst) + dewarp = new SoftDualConstGeoMapper ("sitcher_dualconst_remapper"); + else { + SmartPtr<SoftDualCurveGeoMapper> geomap = new SoftDualCurveGeoMapper ("sitcher_dualcurve_remapper"); + XCAM_ASSERT (geomap.ptr ()); + + BowlDataConfig bowl = _stitcher->get_bowl_config (); + float scaled_height = (bowl.wall_height + bowl.ground_length / 2.0f) / + (bowl.wall_height + bowl.ground_length) * view_slice.height; + + geomap->set_scaled_height (scaled_height); + dewarp = geomap; + } + + XCAM_ASSERT (dewarp.ptr ()); + return dewarp; +} + XCamReturn StitcherImpl::init_fisheye (uint32_t idx) { FisheyeDewarp &fisheye = _fisheye[idx]; + Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (idx); + SmartPtr<ImageHandler::Callback> dewarp_cb = new CbGeoMap (_stitcher); - fisheye.dewarp = new SoftGeoMapper ("sitcher_remapper"); - XCAM_ASSERT (fisheye.dewarp.ptr ()); + fisheye.dewarp = create_geo_mapper (view_slice);; fisheye.dewarp->set_callback (dewarp_cb); - Stitcher::RoundViewSlice view_slice = - _stitcher->get_round_view_slice (idx); - VideoBufferInfo buf_info; buf_info.init ( V4L2_PIX_FMT_NV12, view_slice.width, view_slice.height, XCAM_ALIGN_UP (view_slice.width, SOFT_STITCHER_ALIGNMENT_X), XCAM_ALIGN_UP (view_slice.height, SOFT_STITCHER_ALIGNMENT_Y)); - fisheye.buf_pool = new SoftVideoBufAllocator (buf_info); - XCAM_ASSERT (fisheye.buf_pool.ptr ()); + SmartPtr<BufferPool> pool = new SoftVideoBufAllocator (buf_info); + XCAM_ASSERT (pool.ptr ()); + fisheye.buf_pool = pool; XCAM_FAIL_RETURN ( ERROR, fisheye.buf_pool->reserve (2), XCAM_RETURN_ERROR_MEM, "stitcher:%s reserve dewarp buffer pool(w:%d,h:%d) failed", @@ -329,6 +385,61 @@ StitcherImpl::create_copier (Stitcher::CopyArea area) return XCAM_RETURN_NO_ERROR; } +void +StitcherImpl::init_feature_match (uint32_t idx) +{ +#if ENABLE_FEATURE_MATCH + +#ifndef ANDROID + FeatureMatchMode fm_mode = _stitcher->get_fm_mode (); + if (fm_mode == FMNone) + return ; + else if (fm_mode == FMDefault) + _overlaps[idx].matcher = FeatureMatch::create_default_feature_match (); + else if (fm_mode == FMCluster) + _overlaps[idx].matcher = FeatureMatch::create_cluster_feature_match (); + else if (fm_mode == FMCapi) + _overlaps[idx].matcher = FeatureMatch::create_capi_feature_match (); + else { + XCAM_LOG_ERROR ("unsupported FeatureMatchMode: %d", fm_mode); + XCAM_ASSERT (false); + } +#else + _overlaps[idx].matcher = new CVCapiFeatureMatch; +#endif + XCAM_ASSERT (_overlaps[idx].matcher.ptr ()); + + FMConfig config; + config.sitch_min_width = 136; + config.min_corners = 4; + config.offset_factor = 0.8f; + config.delta_mean_offset = 120.0f; + config.recur_offset_error = 8.0f; + config.max_adjusted_offset = 24.0f; + config.max_valid_offset_y = 20.0f; + config.max_track_error = 28.0f; +#ifdef ANDROID + config.max_track_error = 3600.0f; +#endif + _overlaps[idx].matcher->set_config (config); + _overlaps[idx].matcher->set_fm_index (idx); + + const BowlDataConfig bowl = _stitcher->get_bowl_config (); + const Stitcher::ImageOverlapInfo &info = _stitcher->get_overlap (idx); + Rect left_ovlap = info.left; + Rect right_ovlap = info.right; + + left_ovlap.pos_y = 0; + left_ovlap.height = int32_t (bowl.wall_height / (bowl.wall_height + bowl.ground_length) * left_ovlap.height); + right_ovlap.pos_y = 0; + right_ovlap.height = left_ovlap.height; + _overlaps[idx].matcher->set_crop_rect (left_ovlap, right_ovlap); +#else + XCAM_LOG_ERROR ("FeatureMatch unsupported"); + XCAM_ASSERT (false); +#endif +} + XCamReturn StitcherImpl::init_config (uint32_t count) { @@ -342,23 +453,7 @@ StitcherImpl::init_config (uint32_t count) "stitcher:%s init fisheye failed, idx:%d.", XCAM_STR (_stitcher->get_name ()), i); #if ENABLE_FEATURE_MATCH - _overlaps[i].matcher = new CVCapiFeatureMatch; - - CVFMConfig config; - config.sitch_min_width = 136; - config.min_corners = 4; - config.offset_factor = 0.8f; - config.delta_mean_offset = 120.0f; - config.recur_offset_error = 8.0f; - config.max_adjusted_offset = 24.0f; - config.max_valid_offset_y = 20.0f; -#ifndef ANDROID - config.max_track_error = 28.0f; -#else - config.max_track_error = 3600.0f; -#endif - _overlaps[i].matcher->set_config (config); - _overlaps[i].matcher->set_fm_index (i); + init_feature_match (i); #endif _overlaps[i].blender = create_soft_blender ().dynamic_cast_ptr<SoftBlender>(); @@ -436,7 +531,7 @@ StitcherImpl::fisheye_dewarp_to_table () _fisheye[i].dewarp->set_output_size (view_slice.width, view_slice.height); if (bowl.angle_end < bowl.angle_start) bowl.angle_start -= 360.0f; - XCAM_LOG_INFO ( + XCAM_LOG_DEBUG ( "soft-stitcher:%s camera(idx:%d) info (angle start:%.2f, range:%.2f), bowl info (angle start%.2f, end:%.2f)", XCAM_STR (_stitcher->get_name ()), i, view_slice.hori_angle_start, view_slice.hori_angle_range, @@ -493,24 +588,37 @@ Overlap::find_blender_param_in_map ( } XCamReturn -StitcherImpl::feature_match ( +StitcherImpl::start_single_blender ( + const uint32_t idx, + const SmartPtr<BlenderParam> ¶m) +{ + SmartPtr<SoftBlender> blender = _overlaps[idx].blender; + const Stitcher::ImageOverlapInfo &overlap_info = _stitcher->get_overlap (idx); + uint32_t out_width, out_height; + _stitcher->get_output_size (out_width, out_height); + + blender->set_output_size (out_width, out_height); + blender->set_merge_window (overlap_info.out_area); + blender->set_input_valid_area (overlap_info.left, 0); + blender->set_input_valid_area (overlap_info.right, 1); + blender->set_input_merge_area (overlap_info.left, 0); + blender->set_input_merge_area (overlap_info.right, 1); + return blender->execute_buffer (param, false); +} + +XCamReturn +StitcherImpl::start_feature_match ( const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, const uint32_t idx) { - const Stitcher::ImageOverlapInfo overlap_info = _stitcher->get_overlap (idx); - Rect left_ovlap = overlap_info.left; - Rect right_ovlap = overlap_info.right; - const VideoBufferInfo left_buf_info = left_buf->get_video_info (); +#if ENABLE_FEATURE_MATCH + _overlaps[idx].matcher->reset_offsets (); + _overlaps[idx].matcher->feature_match (left_buf, right_buf); - left_ovlap.pos_y = left_ovlap.height / 5; - left_ovlap.height = left_ovlap.height / 2; - right_ovlap.pos_y = right_ovlap.height / 5; - right_ovlap.height = right_ovlap.height / 2; + Rect left_ovlap, right_ovlap; + _overlaps[idx].matcher->get_crop_rect (left_ovlap, right_ovlap); - _overlaps[idx].matcher->reset_offsets (); - _overlaps[idx].matcher->optical_flow_feature_match ( - left_buf, right_buf, left_ovlap, right_ovlap, left_buf_info.width); float left_offsetx = _overlaps[idx].matcher->get_current_left_offset_x (); Factor left_factor, right_factor; @@ -520,7 +628,7 @@ StitcherImpl::feature_match ( float range = feature_center_x - center_x; XCAM_ASSERT (range > 1.0f); right_factor.x = (range + left_offsetx / 2.0f) / range; - right_factor.y = 1.0; + right_factor.y = 1.0f; XCAM_ASSERT (right_factor.x > 0.0f && right_factor.x < 2.0f); uint32_t right_idx = (idx + 1) % _stitcher->get_camera_num (); @@ -529,7 +637,7 @@ StitcherImpl::feature_match ( range = center_x - feature_center_x; XCAM_ASSERT (range > 1.0f); left_factor.x = (range + left_offsetx / 2.0f) / range; - left_factor.y = 1.0; + left_factor.y = 1.0f; XCAM_ASSERT (left_factor.x > 0.0f && left_factor.x < 2.0f); { @@ -539,25 +647,10 @@ StitcherImpl::feature_match ( } return XCAM_RETURN_NO_ERROR; -} - -XCamReturn -StitcherImpl::start_single_blender ( - const uint32_t idx, - const SmartPtr<BlenderParam> ¶m) -{ - SmartPtr<SoftBlender> blender = _overlaps[idx].blender; - const Stitcher::ImageOverlapInfo &overlap_info = _stitcher->get_overlap (idx); - uint32_t out_width, out_height; - _stitcher->get_output_size (out_width, out_height); - - blender->set_output_size (out_width, out_height); - blender->set_merge_window (overlap_info.out_area); - blender->set_input_valid_area (overlap_info.left, 0); - blender->set_input_valid_area (overlap_info.right, 1); - blender->set_input_merge_area (overlap_info.left, 0); - blender->set_input_merge_area (overlap_info.right, 1); - return blender->execute_buffer (param, false); +#else + XCAM_LOG_ERROR ("FeatureMatch unsupported"); + return XCAM_RETURN_ERROR_PARAM; +#endif } XCamReturn @@ -606,20 +699,23 @@ StitcherImpl::start_overlap_tasks ( #if ENABLE_FEATURE_MATCH //start feature match - if (cur_param.ptr ()) { - ret = feature_match (cur_param->in_buf, cur_param->in1_buf, idx); - XCAM_FAIL_RETURN ( - ERROR, xcam_ret_is_ok (ret), ret, - "soft-stitcher:%s feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), idx); - } + if (_stitcher->get_fm_mode ()) { + if (cur_param.ptr ()) { + ret = start_feature_match (cur_param->in_buf, cur_param->in1_buf, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "soft-stitcher:%s feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), idx); + } - if (prev_param.ptr ()) { - ret = feature_match (prev_param->in_buf, prev_param->in1_buf, pre_idx); - XCAM_FAIL_RETURN ( - ERROR, xcam_ret_is_ok (ret), ret, - "soft-stitcher:%s feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), pre_idx); + if (prev_param.ptr ()) { + ret = start_feature_match (prev_param->in_buf, prev_param->in1_buf, pre_idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "soft-stitcher:%s feature-match overlap idx:%d failed", XCAM_STR (_stitcher->get_name ()), pre_idx); + } } #endif + return XCAM_RETURN_NO_ERROR; } @@ -718,8 +814,10 @@ SoftStitcher::SoftStitcher (const char *name) : SoftHandler (name) , Stitcher (SOFT_STITCHER_ALIGNMENT_X, SOFT_STITCHER_ALIGNMENT_Y) { - _impl = new SoftSitcherPriv::StitcherImpl (this); - XCAM_ASSERT (_impl.ptr ()); + SmartPtr<SoftSitcherPriv::StitcherImpl> impl = new SoftSitcherPriv::StitcherImpl (this); + XCAM_ASSERT (impl.ptr ()); + _impl = impl; + #if ENABLE_FEATURE_MATCH #ifndef ANDROID cv::ocl::setUseOpenCL (false); @@ -801,7 +899,7 @@ SoftStitcher::dewarp_done ( if (!check_work_continue (param, error)) return; - XCAM_LOG_INFO ("soft-stitcher:%s camera(idx:%d) dewarp done", XCAM_STR (get_name ()), dewarp_param->idx); + XCAM_LOG_DEBUG ("soft-stitcher:%s camera(idx:%d) dewarp done", XCAM_STR (get_name ()), dewarp_param->idx); stitcher_dump_buf (dewarp_param->out_buf, dewarp_param->idx, "stitcher-dewarp"); //start both blender and feature match @@ -834,7 +932,7 @@ SoftStitcher::blender_done ( } stitcher_dump_buf (blender_param->out_buf, blender_param->idx, "stitcher-blend"); - XCAM_LOG_INFO ("blender:(%s) overlap:%d done", XCAM_STR (handler->get_name ()), blender_param->idx); + XCAM_LOG_DEBUG ("blender:(%s) overlap:%d done", XCAM_STR (handler->get_name ()), blender_param->idx); if (_impl->dec_task_count (param) == 0) { work_well_done (param, error); @@ -859,7 +957,7 @@ SoftStitcher::copy_task_done ( _impl->remove_task_count (param); return; } - XCAM_LOG_INFO ("soft-stitcher:%s camera(idx:%d) copy done", XCAM_STR (get_name ()), args->idx); + XCAM_LOG_DEBUG ("soft-stitcher:%s camera(idx:%d) copy done", XCAM_STR (get_name ()), args->idx); if (_impl->dec_task_count (param) == 0) { work_well_done (param, error); diff --git a/modules/soft/soft_worker.cpp b/modules/soft/soft_worker.cpp index 3a76345..9688155 100644 --- a/modules/soft/soft_worker.cpp +++ b/modules/soft/soft_worker.cpp @@ -103,8 +103,6 @@ WorkItem::done (XCamReturn err) SoftWorker::SoftWorker (const char *name, const SmartPtr<Callback> &cb) : Worker (name, cb) - , _global (1, 1, 1) - , _local (1, 1, 1) , _work_unit (1, 1, 1) { } @@ -136,30 +134,6 @@ SoftWorker::set_threads (const SmartPtr<ThreadPool> &threads) return true; } -bool -SoftWorker::set_global_size (const WorkSize &size) -{ - XCAM_FAIL_RETURN ( - ERROR, size.value[0] && size.value[1] && size.value[2], false, - "SoftWorker(%s) set global size(x:%d, y:%d, z:%d) failed.", - XCAM_STR (get_name ()), size.value[0], size.value[1], size.value[2]); - - _global = size; - return true; -} - -bool -SoftWorker::set_local_size (const WorkSize &size) -{ - XCAM_FAIL_RETURN ( - ERROR, size.value[0] && size.value[1] && size.value[2], false, - "SoftWorker(%s) set local size(x:%d, y:%d, z:%d) failed.", - XCAM_STR (get_name ()), size.value[0], size.value[1], size.value[2]); - - _local = size; - return true; -} - XCamReturn SoftWorker::stop () { @@ -172,14 +146,17 @@ SoftWorker::work (const SmartPtr<Worker::Arguments> &args) { XCamReturn ret = XCAM_RETURN_NO_ERROR; - XCAM_ASSERT (_local.value[0] * _local.value[1] * _local.value[2]); - XCAM_ASSERT (_global.value[0] * _global.value[1] * _global.value[2]); + const WorkSize &global = get_global_size (); + const WorkSize &local = get_local_size (); + + XCAM_ASSERT (local.value[0] && local.value[1] && local.value[2]); + XCAM_ASSERT (global.value[0] && global.value[1] && global.value[2]); WorkSize items; uint32_t max_items = 1; - for (uint32_t i = 0; i < SOFT_MAX_DIM; ++i) { - items.value[i] = xcam_ceil (_global.value[i], _local.value[i]) / _local.value[i]; + for (uint32_t i = 0; i < WORK_MAX_DIM; ++i) { + items.value[i] = xcam_ceil (global.value[i], local.value[i]) / local.value[i]; max_items *= items.value[i]; } @@ -196,8 +173,10 @@ SoftWorker::work (const SmartPtr<Worker::Arguments> &args) if (!_threads.ptr ()) { char thr_name [XCAM_MAX_STR_SIZE]; snprintf (thr_name, XCAM_MAX_STR_SIZE, "%s-thrs", XCAM_STR(get_name ())); - _threads = new ThreadPool (thr_name); - XCAM_ASSERT (_threads.ptr ()); + + SmartPtr<ThreadPool> threads = new ThreadPool (thr_name); + XCAM_ASSERT (threads.ptr ()); + _threads = threads; _threads->set_threads (max_items, max_items + 1); //extra thread to process all_items_done ret = _threads->start (); XCAM_FAIL_RETURN ( @@ -236,13 +215,16 @@ WorkRange SoftWorker::get_range (const WorkSize &item) { WorkRange range; - for (uint32_t i = 0; i < SOFT_MAX_DIM; ++i) { - range.pos[i] = item.value[i] * _local.value[i]; - XCAM_ASSERT (range.pos[i] < _global.value[i]); - if (range.pos[i] + _local.value[i] > _global.value[i]) - range.pos_len[i] = _global.value[i] - range.pos[i]; + const WorkSize &global = get_global_size (); + const WorkSize &local = get_local_size (); + + for (uint32_t i = 0; i < WORK_MAX_DIM; ++i) { + range.pos[i] = item.value[i] * local.value[i]; + XCAM_ASSERT (range.pos[i] < global.value[i]); + if (range.pos[i] + local.value[i] > global.value[i]) + range.pos_len[i] = global.value[i] - range.pos[i]; else - range.pos_len[i] = _local.value[i]; + range.pos_len[i] = local.value[i]; } return range; } diff --git a/modules/soft/soft_worker.h b/modules/soft/soft_worker.h index a851893..e734328 100644 --- a/modules/soft/soft_worker.h +++ b/modules/soft/soft_worker.h @@ -24,15 +24,13 @@ #include <xcam_std.h> #include <worker.h> -#define SOFT_MAX_DIM 3 - namespace XCam { class ThreadPool; struct WorkRange { - uint32_t pos[SOFT_MAX_DIM]; - uint32_t pos_len[SOFT_MAX_DIM]; + uint32_t pos[WORK_MAX_DIM]; + uint32_t pos_len[WORK_MAX_DIM]; WorkRange () { xcam_mem_clear (pos); @@ -40,15 +38,6 @@ struct WorkRange { } }; -struct WorkSize { - uint32_t value[SOFT_MAX_DIM]; - WorkSize (uint32_t x = 1, uint32_t y = 1, uint32_t z = 1) { - value[0] = x; - value[1] = y; - value[2] = z; - } -}; - //multi-thread worker class SoftWorker : public Worker @@ -65,14 +54,6 @@ public: } bool set_threads (const SmartPtr<ThreadPool> &threads); - bool set_global_size (const WorkSize &size); - const WorkSize &get_global_size () const { - return _global; - } - bool set_local_size (const WorkSize &size); - const WorkSize &get_local_size () const { - return _local; - } // derived from Worker virtual XCamReturn work (const SmartPtr<Arguments> &args); @@ -91,8 +72,6 @@ private: private: SmartPtr<ThreadPool> _threads; - WorkSize _global; - WorkSize _local; WorkSize _work_unit; }; diff --git a/modules/vulkan/Makefile.am b/modules/vulkan/Makefile.am new file mode 100644 index 0000000..22763f0 --- /dev/null +++ b/modules/vulkan/Makefile.am @@ -0,0 +1,76 @@ +lib_LTLIBRARIES = libxcam_vulkan.la + +XCAM_VK_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(LIBVULKAN_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + -I$(top_builddir)/shaders/spv \ + $(NULL) + +XCAM_VK_LIBS = \ + $(LIBVULKAN_LIBS) \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL) + +if HAVE_OPENCV +XCAM_VK_LIBS += $(top_builddir)/modules/ocv/libxcam_ocv.la +endif + +xcam_vulkan_sources = \ + vk_cmdbuf.cpp \ + vk_descriptor.cpp \ + vk_device.cpp \ + vk_handler.cpp \ + vk_instance.cpp \ + vk_memory.cpp \ + vk_pipeline.cpp \ + vk_shader.cpp \ + vk_sync.cpp \ + vk_video_buf_allocator.cpp \ + vk_worker.cpp \ + vulkan_common.cpp \ + vk_copy_handler.cpp \ + vk_geomap_handler.cpp \ + vk_blender.cpp \ + vk_stitcher.cpp \ + $(NULL) + +libxcam_vulkan_la_SOURCES = \ + $(xcam_vulkan_sources) \ + $(NULL) + +libxcam_vulkan_la_CXXFLAGS = \ + $(XCAM_VK_CXXFLAGS) \ + $(NULL) + +libxcam_vulkan_la_LIBADD = \ + $(XCAM_VK_LIBS) \ + $(NULL) + +libxcam_vulkan_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ + $(NULL) + +libxcam_vulkanincludedir = $(includedir)/xcam/vulkan + +nobase_libxcam_vulkaninclude_HEADERS = \ + vk_cmdbuf.h \ + vk_descriptor.h \ + vk_device.h \ + vk_handler.h \ + vk_instance.h \ + vk_memory.h \ + vk_pipeline.h \ + vk_shader.h \ + vk_sync.h \ + vk_video_buf_allocator.h \ + vk_worker.h \ + vulkan_common.h \ + vk_copy_handler.h \ + vk_geomap_handler.h \ + vk_blender.h \ + vk_stitcher.h \ + $(NULL) + +libxcam_vulkan_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/vulkan/vk_blender.cpp b/modules/vulkan/vk_blender.cpp new file mode 100644 index 0000000..f880649 --- /dev/null +++ b/modules/vulkan/vk_blender.cpp @@ -0,0 +1,1537 @@ +/* + * vk_blender.cpp - vulkan blender implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "xcam_utils.h" + +#include "vk_device.h" +#include "vk_worker.h" +#include "vk_blender.h" +#include "vk_video_buf_allocator.h" + +#define DUMP_BUFFER 0 + +#define GAUSS_RADIUS 2 +#define GAUSS_DIAMETER ((GAUSS_RADIUS)*2+1) + +const float gauss_coeffs[GAUSS_DIAMETER] = {0.152f, 0.222f, 0.252f, 0.222f, 0.152f}; + +#define GS_SHADER_BINDING_COUNT 4 +#define LAP_SHADER_BINDING_COUNT 6 +#define BLEND_SHADER_BINDING_COUNT 7 +#define RECONSTRUCT_SHADER_BINDING_COUNT 9 + +#define CHECK_RET(ret, format, ...) \ + if (!xcam_ret_is_ok (ret)) { \ + XCAM_LOG_ERROR (format, ## __VA_ARGS__); \ + } + +#define DECLARE_VK_PUSH_CONST(PushConstClass, PushConstsProp) \ + class PushConstClass : public VKConstRange::VKPushConstArg { \ + private: PushConstsProp _prop; \ + public: \ + PushConstClass (const PushConstsProp &prop) : _prop (prop) {} \ + bool get_const_data (VkPushConstantRange &range, void *& ptr) { \ + range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; \ + range.offset = 0; \ + range.size = sizeof (_prop); \ + ptr = &_prop; \ + return true; } \ + } + +namespace XCam { + +#if DUMP_BUFFER +static void +dump_vkbuf_with_perfix (const SmartPtr<VKBuffer> &buf, const char *perfix_name) +{ + XCAM_ASSERT (buf.ptr ()); + XCAM_ASSERT (perfix_name); + + const VKBufInfo &info = buf->get_buf_info (); + char file_name[XCAM_VK_NAME_LENGTH]; + snprintf ( + file_name, XCAM_VK_NAME_LENGTH, "%s-%dx%d.%s", + perfix_name, info.width, info.height, xcam_fourcc_to_string (info.format)); + + FILE *fp = fopen (file_name, "wb"); + if (!fp) { + XCAM_LOG_ERROR ( "vk-blend open file(%s) failed", file_name); + } + + uint8_t *ptr = (uint8_t *)buf->map (); + for (uint32_t i = 0; i < info.height * 3 / 2; ++i) { + uint8_t *start = ptr + info.aligned_width * i; + fwrite (start, info.width, 1, fp); + } + buf->unmap (); + fclose (fp); +} +#define dump_vkbuf dump_vkbuf_with_perfix + +static void +dump_level_vkbuf (const SmartPtr<VKBuffer> &buf, const char *name, uint32_t level, uint32_t idx) +{ + char file_name[XCAM_VK_NAME_LENGTH]; + snprintf (file_name, XCAM_VK_NAME_LENGTH, "%s-L%d-Idx%d", name, level, idx); + + dump_vkbuf_with_perfix (buf, file_name); +} +#endif + +namespace VKBlenderPriv { + +enum ShaderID { + ShaderGaussScalePyr = 0, + ShaderLapTransPyr, + ShaderBlendPyr, + ShaderReconstructPyr +}; + +static const VKShaderInfo shaders_info[] = { + VKShaderInfo ( + "main", + std::vector<uint32_t> { +#include "shader_gauss_scale_pyr.comp.spv" + }), + VKShaderInfo ( + "main", + std::vector<uint32_t> { +#include "shader_lap_trans_pyr.comp.spv" + }), + VKShaderInfo ( + "main", + std::vector<uint32_t> { +#include "shader_blend_pyr.comp.spv" + }), + VKShaderInfo ( + "main", + std::vector<uint32_t> { +#include "shader_reconstruct_pyr.comp.spv" + }) +}; + +struct GaussScalePushConstsProp { + uint in_img_width; + uint in_img_height; + uint in_offset_x; + uint out_img_width; + uint out_img_height; + uint merge_width; + + GaussScalePushConstsProp () + : in_img_width (0) + , in_img_height (0) + , in_offset_x (0) + , out_img_width (0) + , out_img_height (0) + , merge_width (0) + {} +}; + +struct LapPushConstsProp { + uint in_img_width; + uint in_img_height; + uint in_offset_x; + uint gaussscale_img_width; + uint gaussscale_img_height; + uint merge_width; + + LapPushConstsProp () + : in_img_width (0) + , in_img_height (0) + , in_offset_x (0) + , gaussscale_img_width (0) + , gaussscale_img_height (0) + , merge_width (0) + {} +}; + +struct BlendPushConstsProp { + uint in_img_width; + + BlendPushConstsProp () + : in_img_width (0) + {} +}; + +struct ReconstructPushConstsProp { + uint lap_img_width; + uint lap_img_height; + uint out_img_width; + uint out_offset_x; + uint prev_blend_img_width; + uint prev_blend_img_height; + + ReconstructPushConstsProp () + : lap_img_width (0) + , lap_img_height (0) + , out_img_width (0) + , out_offset_x (0) + , prev_blend_img_width (0) + , prev_blend_img_height (0) + {} +}; + +DECLARE_VK_PUSH_CONST (VKGaussScalePushConst, GaussScalePushConstsProp); +DECLARE_VK_PUSH_CONST (VKLapPushConst, LapPushConstsProp); +DECLARE_VK_PUSH_CONST (VKBlendPushConst, BlendPushConstsProp); +DECLARE_VK_PUSH_CONST (VKReconstructPushConst, ReconstructPushConstsProp); + +DECLARE_WORK_CALLBACK (CbGaussScalePyr, VKBlender, gauss_scale_done); +DECLARE_WORK_CALLBACK (CbLapTransPyr, VKBlender, lap_trans_done); +DECLARE_WORK_CALLBACK (CbBlendPyr, VKBlender, blend_done); +DECLARE_WORK_CALLBACK (CbReconstructPyr, VKBlender, reconstruct_done); + +class BlendArgs + : public VKWorker::VKArguments +{ +public: + BlendArgs (uint32_t lv, VKBlender::BufIdx i = VKBlender::BufIdx0); + + uint32_t get_level () { + return _level; + } + VKBlender::BufIdx get_idx () { + return _idx; + } + +private: + uint32_t _level; + VKBlender::BufIdx _idx; +}; + +struct PyrLayer { + uint32_t blend_width; + uint32_t blend_height; + + SmartPtr<VKBlender::Sync> lap_sync[VKBlender::BufIdxMax]; + SmartPtr<VKBlender::Sync> blend_sync; + SmartPtr<VKBlender::Sync> reconstruct_sync; + + SmartPtr<VKBuffer> gs_buf[VKBlender::BufIdxMax]; + SmartPtr<VKBuffer> lap_buf[VKBlender::BufIdxMax]; + SmartPtr<VKBuffer> mask; + SmartPtr<VKBuffer> blend_buf; + SmartPtr<VKBuffer> reconstruct_buf; + + VKDescriptor::SetBindInfoArray gs_bindings[VKBlender::BufIdxMax]; + VKDescriptor::SetBindInfoArray lap_bindings[VKBlender::BufIdxMax]; + VKDescriptor::SetBindInfoArray blend_bindings; + VKDescriptor::SetBindInfoArray reconstruct_bindings; + + SmartPtr<VKConstRange::VKPushConstArg> gs_consts[VKBlender::BufIdxMax]; + SmartPtr<VKConstRange::VKPushConstArg> lap_consts[VKBlender::BufIdxMax]; + SmartPtr<VKConstRange::VKPushConstArg> blend_consts; + SmartPtr<VKConstRange::VKPushConstArg> reconstruct_consts; + + WorkSize gs_global_size[VKBlender::BufIdxMax]; + WorkSize lap_global_size[VKBlender::BufIdxMax]; + WorkSize blend_global_size; + WorkSize reconstruct_global_size; + + VKWorker *gauss_scale[VKBlender::BufIdxMax]; + VKWorker *lap_trans[VKBlender::BufIdxMax]; + VKWorker *blend; + VKWorker *reconstruct; + + PyrLayer (); +}; + +typedef std::map<ShaderID, SmartPtr<VKWorker>> VKWorkers; + +class BlenderImpl { +public: + PyrLayer pyr_layer[XCAM_VK_MAX_LEVEL]; + uint32_t pyr_layers_num; + +private: + VKBlender *_blender; + VKWorkers _workers; + +public: + BlenderImpl (VKBlender *blender, uint32_t layers_num) + : pyr_layers_num (layers_num) + , _blender (blender) + { + XCAM_ASSERT (layers_num >= 2 && layers_num <= XCAM_VK_MAX_LEVEL); + } + + XCamReturn start_gauss_scale (uint32_t level, VKBlender::BufIdx idx); + XCamReturn start_lap_trans (uint32_t level, VKBlender::BufIdx idx); + XCamReturn start_top_blend (); + XCamReturn start_reconstruct (uint32_t level); + XCamReturn stop (); + + void init_syncs (); + XCamReturn init_layers_bufs (const SmartPtr<ImageHandler::Parameters> &base); + XCamReturn bind_io_bufs_to_layer0 ( + SmartPtr<VideoBuffer> &input0, SmartPtr<VideoBuffer> &input1, SmartPtr<VideoBuffer> &output); + XCamReturn bind_io_vkbufs_to_desc (); + XCamReturn fix_parameters (); + XCamReturn create_workers (const SmartPtr<VKBlender> &blender); + XCamReturn redirect_workers (); + +private: + XCamReturn start_lap_tran (uint32_t level, VKBlender::BufIdx idx); + + XCamReturn layer0_allocate_bufs (SmartPtr<VKDevice> dev); + XCamReturn layer0_init_mask (SmartPtr<VKDevice> dev); + + XCamReturn layerx_allocate_bufs (SmartPtr<VKDevice> dev, uint32_t level); + XCamReturn allocate_vk_bufs (SmartPtr<VKDevice> dev, uint32_t level); + XCamReturn scale_down_mask (SmartPtr<VKDevice> dev, uint32_t level); + + XCamReturn fix_gs_params (uint32_t level, VKBlender::BufIdx idx); + XCamReturn fix_lap_trans_params (uint32_t level, VKBlender::BufIdx idx); + XCamReturn fix_blend_params (); + XCamReturn fix_reconstruct_params (uint32_t level); +}; + +BlendArgs::BlendArgs (uint32_t lv, VKBlender::BufIdx i) + : _level (lv) + , _idx (i) +{ + XCAM_ASSERT (lv < XCAM_VK_DEFAULT_LEVEL); + XCAM_ASSERT (i < VKBlender::BufIdxMax); +} + +PyrLayer::PyrLayer () + : blend_width (0) + , blend_height (0) +{ +} + +void +BlenderImpl::init_syncs () +{ + for (uint32_t i = 0; i < pyr_layers_num - 1; ++i) { + PyrLayer &layer = pyr_layer[i]; + + layer.lap_sync[VKBlender::BufIdx0] = new VKBlender::Sync (2); + XCAM_ASSERT (layer.lap_sync[VKBlender::BufIdx0].ptr ()); + layer.lap_sync[VKBlender::BufIdx1] = new VKBlender::Sync (2); + XCAM_ASSERT (layer.lap_sync[VKBlender::BufIdx1].ptr ()); + + layer.reconstruct_sync = new VKBlender::Sync (3); + XCAM_ASSERT (layer.reconstruct_sync.ptr ()); + } + + pyr_layer[pyr_layers_num - 1].blend_sync = new VKBlender::Sync (2); + XCAM_ASSERT (pyr_layer[pyr_layers_num - 1].blend_sync.ptr ()); +} + +XCamReturn +BlenderImpl::bind_io_bufs_to_layer0 ( + SmartPtr<VideoBuffer> &input0, SmartPtr<VideoBuffer> &input1, SmartPtr<VideoBuffer> &output) +{ + XCAM_ASSERT (input0.ptr () && input1.ptr ()); + + SmartPtr<VKVideoBuffer> in0_vk = input0.dynamic_cast_ptr<VKVideoBuffer> (); + SmartPtr<VKVideoBuffer> in1_vk = input1.dynamic_cast_ptr<VKVideoBuffer> (); + + PyrLayer &layer0 = pyr_layer[0]; + layer0.gs_buf[VKBlender::BufIdx0] = in0_vk->get_vk_buf (); + layer0.gs_buf[VKBlender::BufIdx1] = in1_vk->get_vk_buf (); + XCAM_ASSERT (layer0.gs_buf[VKBlender::BufIdx0].ptr () && layer0.gs_buf[VKBlender::BufIdx1].ptr ()); + + if (!output.ptr ()) + return XCAM_RETURN_NO_ERROR; + + SmartPtr<VKVideoBuffer> out_vk = output.dynamic_cast_ptr<VKVideoBuffer> (); + XCAM_ASSERT (out_vk.ptr ()); + + layer0.reconstruct_buf = out_vk->get_vk_buf (); + XCAM_ASSERT (layer0.reconstruct_buf.ptr ()); + layer0.blend_buf = layer0.reconstruct_buf; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::bind_io_vkbufs_to_desc () +{ + PyrLayer &layer0 = pyr_layer[0]; + PyrLayer &layer1 = pyr_layer[1]; + XCAM_ASSERT (layer0.gs_buf[VKBlender::BufIdx0].ptr () && layer0.gs_buf[VKBlender::BufIdx1].ptr ()); + XCAM_ASSERT (layer0.reconstruct_buf.ptr ()); + + VKDescriptor::SetBindInfoArray &gs_bindings0 = layer1.gs_bindings[VKBlender::BufIdx0]; + VKDescriptor::SetBindInfoArray &gs_bindings1 = layer1.gs_bindings[VKBlender::BufIdx1]; + gs_bindings0[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneYIdx); + gs_bindings0[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneUVIdx); + gs_bindings1[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneYIdx); + gs_bindings1[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneUVIdx); + + VKDescriptor::SetBindInfoArray &lap_bindings0 = layer0.lap_bindings[VKBlender::BufIdx0]; + VKDescriptor::SetBindInfoArray &lap_bindings1 = layer0.lap_bindings[VKBlender::BufIdx1]; + lap_bindings0[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneYIdx); + lap_bindings0[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx0], NV12PlaneUVIdx); + lap_bindings1[0].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneYIdx); + lap_bindings1[1].desc = VKBufDesc (layer0.gs_buf[VKBlender::BufIdx1], NV12PlaneUVIdx); + + layer0.reconstruct_bindings[4].desc = VKBufDesc (layer0.reconstruct_buf, NV12PlaneYIdx); + layer0.reconstruct_bindings[5].desc = VKBufDesc (layer0.reconstruct_buf, NV12PlaneUVIdx); + + return XCAM_RETURN_NO_ERROR; +} + +static void +convert_to_vkinfo (const VideoBufferInfo &info, VKBufInfo &vk_info) +{ + vk_info.format = info.format; + vk_info.width = info.width; + vk_info.height = info.height; + vk_info.aligned_width = info.aligned_width; + vk_info.aligned_height = info.aligned_height; + vk_info.size = info.size; + vk_info.strides[0] = info.strides[0]; + vk_info.strides[1] = info.strides[1]; + vk_info.offsets[0] = info.offsets[0]; + vk_info.offsets[1] = info.offsets[1]; + vk_info.slice_size[0] = info.strides[0] * info.aligned_height; + vk_info.slice_size[1] = info.size - info.offsets[1]; +} + +XCamReturn +BlenderImpl::layer0_allocate_bufs (SmartPtr<VKDevice> dev) +{ + if (pyr_layers_num == 1) + return XCAM_RETURN_NO_ERROR; + + PyrLayer &layer0 = pyr_layer[0]; + XCAM_FAIL_RETURN ( + ERROR, layer0.blend_width && layer0.blend_height, XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid blend size:%dx%d", layer0.blend_width, layer0.blend_height); + + VideoBufferInfo info; + info.init ( + V4L2_PIX_FMT_NV12, layer0.blend_width, layer0.blend_height, + XCAM_ALIGN_UP (layer0.blend_width, VK_BLENDER_ALIGN_X), + XCAM_ALIGN_UP (layer0.blend_height, VK_BLENDER_ALIGN_X)); + + VKBufInfo vk_info; + convert_to_vkinfo (info, vk_info); + + for (int idx = 0; idx < VKBlender::BufIdxMax; ++idx) { + layer0.lap_buf[idx] = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size); + XCAM_ASSERT (layer0.lap_buf[idx].ptr ()); + layer0.lap_buf[idx]->set_buf_info (vk_info); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::allocate_vk_bufs (SmartPtr<VKDevice> dev, uint32_t level) +{ + XCAM_ASSERT (level >= 1 && level < pyr_layers_num); + + PyrLayer &layer = pyr_layer[level]; + VideoBufferInfo info; + info.init ( + V4L2_PIX_FMT_NV12, layer.blend_width, layer.blend_height, + XCAM_ALIGN_UP (layer.blend_width, VK_BLENDER_ALIGN_X), + XCAM_ALIGN_UP (layer.blend_height, VK_BLENDER_ALIGN_X)); + + VKBufInfo vk_info; + convert_to_vkinfo (info, vk_info); + + bool top_layer = (level == pyr_layers_num - 1); + for (int idx = 0; idx < VKBlender::BufIdxMax; ++idx) { + layer.gs_buf[idx] = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size); + XCAM_ASSERT (layer.gs_buf[idx].ptr ()); + layer.gs_buf[idx]->set_buf_info (vk_info); + + if (top_layer) + continue; + + layer.lap_buf[idx] = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size); + XCAM_ASSERT (layer.lap_buf[idx].ptr ()); + layer.lap_buf[idx]->set_buf_info (vk_info); + } + + layer.reconstruct_buf = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, vk_info.size); + XCAM_ASSERT (layer.reconstruct_buf.ptr ()); + layer.reconstruct_buf->set_buf_info (vk_info); + + if (top_layer) + layer.blend_buf = layer.reconstruct_buf; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::layer0_init_mask (SmartPtr<VKDevice> dev) +{ + PyrLayer &layer = pyr_layer[0]; + XCAM_ASSERT (layer.blend_width && ((layer.blend_width % VK_BLENDER_ALIGN_X) == 0)); + + uint32_t buf_size = layer.blend_width * sizeof (uint8_t); + SmartPtr<VKBuffer> buf = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, buf_size); + XCAM_ASSERT (buf.ptr ()); + + VKBufInfo info; + info.width = layer.blend_width; + info.height = 1; + info.size = buf_size; + buf->set_buf_info (info); + + std::vector<float> gauss_table; + uint32_t quater = info.width / 4; + + get_gauss_table (quater, (quater + 1) / 4.0f, gauss_table, false); + for (uint32_t i = 0; i < gauss_table.size (); ++i) { + float value = ((i < quater) ? (128.0f * (2.0f - gauss_table[i])) : (128.0f * gauss_table[i])); + value = XCAM_CLAMP (value, 0.0f, 255.0f); + gauss_table[i] = value; + } + + uint8_t *mask_ptr = (uint8_t *) buf->map (buf_size, 0); + XCAM_FAIL_RETURN (ERROR, mask_ptr, XCAM_RETURN_ERROR_PARAM, "vk-blend map range failed"); + + uint32_t gauss_start_pos = (info.width - gauss_table.size ()) / 2; + uint32_t idx = 0; + for (idx = 0; idx < gauss_start_pos; ++idx) { + mask_ptr[idx] = 255; + } + for (uint32_t i = 0; i < gauss_table.size (); ++idx, ++i) { + mask_ptr[idx] = (uint8_t) gauss_table[i]; + } + for (; idx < info.width; ++idx) { + mask_ptr[idx] = 0; + } + buf->unmap (); + + layer.mask = buf; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::scale_down_mask (SmartPtr<VKDevice> dev, uint32_t level) +{ + XCAM_ASSERT (level >= 1 && level < pyr_layers_num); + + PyrLayer &layer = pyr_layer[level]; + PyrLayer &prev_layer = pyr_layer[level - 1]; + + XCAM_ASSERT (prev_layer.mask.ptr ()); + XCAM_ASSERT (layer.blend_width && ((layer.blend_width % VK_BLENDER_ALIGN_X) == 0)); + + uint32_t buf_size = layer.blend_width * sizeof (uint8_t); + SmartPtr<VKBuffer> buf = VKBuffer::create_buffer (dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, buf_size); + XCAM_ASSERT (buf.ptr ()); + + VKBufInfo info; + info.width = layer.blend_width; + info.height = 1; + info.size = buf_size; + buf->set_buf_info (info); + + const VKBufInfo prev_info = prev_layer.mask->get_buf_info (); + uint8_t *prev_ptr = (uint8_t *) prev_layer.mask->map (prev_info.size, 0); + XCAM_FAIL_RETURN (ERROR, prev_ptr, XCAM_RETURN_ERROR_PARAM, "vk-blend map range failed"); + + uint8_t *cur_ptr = (uint8_t *) buf->map (info.size, 0); + XCAM_FAIL_RETURN (ERROR, cur_ptr, XCAM_RETURN_ERROR_PARAM, "vk-blend map range failed"); + + for (uint32_t i = 0; i < info.width; ++i) { + int prev_start = i * 2 - 2; + float sum = 0.0f; + + for (int j = 0; j < GAUSS_DIAMETER; ++j) { + int prev_idx = XCAM_CLAMP (prev_start + j, 0, (int)prev_info.width); + sum += prev_ptr[prev_idx] * gauss_coeffs[j]; + } + + cur_ptr[i] = XCAM_CLAMP (sum, 0.0f, 255.0f); + } + + buf->unmap (); + prev_layer.mask->unmap (); + + layer.mask = buf; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::layerx_allocate_bufs (SmartPtr<VKDevice> dev, uint32_t level) +{ + XCAM_ASSERT (level >= 1 && level < pyr_layers_num); + + PyrLayer &layer = pyr_layer[level]; + PyrLayer &prev_layer = pyr_layer[level - 1]; + XCAM_FAIL_RETURN ( + ERROR, prev_layer.blend_width && prev_layer.blend_height, XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid blend size:%dx%d", prev_layer.blend_width, prev_layer.blend_height); + + layer.blend_width = XCAM_ALIGN_UP ((prev_layer.blend_width + 1) / 2, VK_BLENDER_ALIGN_X); + layer.blend_height = XCAM_ALIGN_UP ((prev_layer.blend_height + 1) / 2, VK_BLENDER_ALIGN_Y); + + XCamReturn ret = allocate_vk_bufs (dev, level); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend build vk buffers failed, level:%d", level); + + ret = scale_down_mask (dev, level); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend scale down mask failed, level:%d", level); + + return ret; +} + +static XCamReturn +check_desc ( + const VideoBufferInfo &in0_info, const VideoBufferInfo &in1_info, + const Rect &merge0_area, const Rect &merge1_area) +{ + XCAM_FAIL_RETURN ( + ERROR, + in0_info.width && in0_info.height && in1_info.width && + in0_info.height == in1_info.height, + XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid buffer size: in0:%dx%d in1:%dx%d out:%dx%d", + in0_info.width, in0_info.height, in1_info.width, in1_info.height); + + XCAM_FAIL_RETURN ( + ERROR, + merge0_area.width && merge0_area.width == merge1_area.width && + merge0_area.pos_y == 0 && merge1_area.pos_y == 0 && + merge0_area.height == merge1_area.height && merge0_area.height == (int32_t)in0_info.height, + XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid merge area: merge0(%d, %d, %d, %d) merge1(%d, %d, %d, %d)", + merge0_area.pos_x, merge0_area.pos_y, merge0_area.width, merge0_area.height, + merge1_area.pos_x, merge1_area.pos_y, merge1_area.width, merge1_area.height); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::init_layers_bufs (const SmartPtr<ImageHandler::Parameters> &base) +{ + XCAM_ASSERT (base.ptr ()); + SmartPtr<VKBlender::BlenderParam> param = base.dynamic_cast_ptr<VKBlender::BlenderParam> (); + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->in1_buf.ptr ()); + + const VideoBufferInfo &in0_info = param->in_buf->get_video_info (); + const VideoBufferInfo &in1_info = param->in1_buf->get_video_info (); + const Rect merge0_area = _blender->get_input_merge_area (VKBlender::BufIdx0); + const Rect merge1_area = _blender->get_input_merge_area (VKBlender::BufIdx1); + + XCamReturn ret = check_desc (in0_info, in1_info, merge0_area, merge1_area); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend check desc failed"); + + PyrLayer &layer0 = pyr_layer[0]; + layer0.blend_width = XCAM_ALIGN_UP (merge0_area.width, VK_BLENDER_ALIGN_X); + layer0.blend_height = XCAM_ALIGN_UP (merge0_area.height, VK_BLENDER_ALIGN_Y); + + SmartPtr<VKDevice> dev = _blender->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + + ret = bind_io_bufs_to_layer0 (param->in_buf, param->in1_buf, param->out_buf); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend bind bufs to layer0 failed"); + ret = layer0_allocate_bufs (dev); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend layer0 build buffers failed"); + ret = layer0_init_mask (dev); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend layer0 init mask failed"); + + for (uint32_t level = 1; level < pyr_layers_num; ++level) { + layerx_allocate_bufs (dev, level); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-blend build buffers failed, level:%d", level); + } + + return XCAM_RETURN_NO_ERROR; +} + +static SmartPtr<VKWorker> +create_gauss_scale_pyr_shader (const SmartPtr<VKBlender> &blender) +{ + SmartPtr<VKDevice> dev = blender->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + + GaussScalePushConstsProp prop; + VKConstRange::VKPushConstArgs push_consts; + push_consts.push_back (new VKGaussScalePushConst (prop)); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < GS_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + SmartPtr<VKWorker> worker = new VKWorker (dev, "VKGaussScaleShader", new CbGaussScalePyr (blender)); + XCAM_ASSERT (worker.ptr ()); + + XCamReturn ret = worker->build (shaders_info[ShaderGaussScalePyr], binding_layout, push_consts); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKGaussScaleShader failed"); + + return worker; +} + +static SmartPtr<VKWorker> +create_lap_trans_pyr_shader (const SmartPtr<VKBlender> &blender) +{ + SmartPtr<VKDevice> dev = blender->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + + LapPushConstsProp prop; + VKConstRange::VKPushConstArgs push_consts; + push_consts.push_back (new VKLapPushConst (prop)); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < LAP_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + SmartPtr<VKWorker> worker = new VKWorker (dev, "VKLapTransShader", new CbLapTransPyr (blender)); + XCAM_ASSERT (worker.ptr ()); + + XCamReturn ret = worker->build (shaders_info[ShaderLapTransPyr], binding_layout, push_consts); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKLapTransShader failed"); + + return worker; +} + +static SmartPtr<VKWorker> +create_blend_pyr_shader (const SmartPtr<VKBlender> &blender) +{ + SmartPtr<VKDevice> dev = blender->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + + BlendPushConstsProp prop; + VKConstRange::VKPushConstArgs push_consts; + push_consts.push_back (new VKBlendPushConst (prop)); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < BLEND_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + SmartPtr<VKWorker> worker = new VKWorker (dev, "VKBlendPyrShader", new CbBlendPyr (blender)); + XCAM_ASSERT (worker.ptr ()); + + XCamReturn ret = worker->build (shaders_info[ShaderBlendPyr], binding_layout, push_consts); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKBlendPyrShader failed"); + + return worker; +} + +static SmartPtr<VKWorker> +create_reconstruct_pyr_shader (const SmartPtr<VKBlender> &blender) +{ + SmartPtr<VKDevice> dev = blender->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + + ReconstructPushConstsProp prop; + VKConstRange::VKPushConstArgs push_consts; + push_consts.push_back (new VKReconstructPushConst (prop)); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < RECONSTRUCT_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + SmartPtr<VKWorker> worker = new VKWorker (dev, "VKReconstructShader", new CbReconstructPyr (blender)); + XCAM_ASSERT (worker.ptr ()); + + XCamReturn ret = worker->build (shaders_info[ShaderReconstructPyr], binding_layout, push_consts); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), NULL, "vk-blend build VKReconstructShader failed"); + + return worker; +} + +XCamReturn +BlenderImpl::create_workers (const SmartPtr<VKBlender> &blender) +{ + XCAM_ASSERT (blender.ptr ()); + + VKWorkers::iterator i = _workers.find (ShaderGaussScalePyr); + if (i == _workers.end ()) { + SmartPtr<VKWorker> gauss_scale = create_gauss_scale_pyr_shader (blender); + XCAM_ASSERT (gauss_scale.ptr ()); + _workers.insert (std::make_pair (ShaderGaussScalePyr, gauss_scale)); + } + + i = _workers.find (ShaderLapTransPyr); + if (i == _workers.end ()) { + SmartPtr<VKWorker> lap_trans = create_lap_trans_pyr_shader (blender); + XCAM_ASSERT (lap_trans.ptr ()); + _workers.insert (std::make_pair (ShaderLapTransPyr, lap_trans)); + } + + i = _workers.find (ShaderBlendPyr); + if (i == _workers.end ()) { + SmartPtr<VKWorker> blend = create_blend_pyr_shader (blender); + XCAM_ASSERT (blend.ptr ()); + _workers.insert (std::make_pair (ShaderBlendPyr, blend)); + } + + i = _workers.find (ShaderReconstructPyr); + if (i == _workers.end ()) { + SmartPtr<VKWorker> reconstruct = create_reconstruct_pyr_shader (blender); + XCAM_ASSERT (reconstruct.ptr ()); + _workers.insert (std::make_pair (ShaderReconstructPyr, reconstruct)); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::redirect_workers () +{ + VKWorkers::iterator i = _workers.find (ShaderGaussScalePyr); + XCAM_ASSERT (i != _workers.end ()); + SmartPtr<VKWorker> gauss_scale = i->second; + + i = _workers.find (ShaderLapTransPyr); + XCAM_ASSERT (i != _workers.end ()); + SmartPtr<VKWorker> lap_trans = i->second; + + i = _workers.find (ShaderBlendPyr); + XCAM_ASSERT (i != _workers.end ()); + SmartPtr<VKWorker> top_blend = i->second; + + i = _workers.find (ShaderReconstructPyr); + XCAM_ASSERT (i != _workers.end ()); + SmartPtr<VKWorker> reconstruct = i->second; + + XCAM_ASSERT (gauss_scale.ptr () && lap_trans.ptr () && reconstruct.ptr () && top_blend.ptr ()); + for (uint32_t i = 0; i < pyr_layers_num - 1; ++i) { + PyrLayer &layer_next = pyr_layer[i + 1]; + layer_next.gauss_scale[VKBlender::BufIdx0] = gauss_scale.ptr (); + layer_next.gauss_scale[VKBlender::BufIdx1] = gauss_scale.ptr (); + + PyrLayer &layer = pyr_layer[i]; + layer.lap_trans[VKBlender::BufIdx0] = lap_trans.ptr (); + layer.lap_trans[VKBlender::BufIdx1] = lap_trans.ptr (); + layer.reconstruct = reconstruct.ptr (); + } + + PyrLayer &top_layer = pyr_layer[pyr_layers_num - 1]; + top_layer.blend = top_blend.ptr (); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::fix_parameters () +{ + for (uint32_t i = 0; i < pyr_layers_num - 1; ++i) { + fix_gs_params (i + 1, VKBlender::BufIdx0); + fix_gs_params (i + 1, VKBlender::BufIdx1); + + fix_lap_trans_params (i, VKBlender::BufIdx0); + fix_lap_trans_params (i, VKBlender::BufIdx1); + + fix_reconstruct_params (i); + } + + fix_blend_params (); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::fix_gs_params (uint32_t level, VKBlender::BufIdx idx) +{ + XCAM_ASSERT (level >= 1); + + uint32_t level_in = level - 1; + PyrLayer &layer_in = pyr_layer[level_in]; + PyrLayer &layer_out = pyr_layer[level]; + XCAM_ASSERT (layer_out.gs_buf[idx].ptr () && (layer_in.gs_buf[idx].ptr () || level == 1)); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < GS_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + VKDescriptor::SetBindInfoArray bindings (GS_SHADER_BINDING_COUNT); + bindings[0].layout = binding_layout[0]; + bindings[1].layout = binding_layout[1]; + if (layer_in.gs_buf[idx].ptr ()) { + bindings[0].desc = VKBufDesc (layer_in.gs_buf[idx], NV12PlaneYIdx); + bindings[1].desc = VKBufDesc (layer_in.gs_buf[idx], NV12PlaneUVIdx); + } + bindings[2].layout = binding_layout[2]; + bindings[2].desc = VKBufDesc (layer_out.gs_buf[idx], NV12PlaneYIdx); + bindings[3].layout = binding_layout[3]; + bindings[3].desc = VKBufDesc (layer_out.gs_buf[idx], NV12PlaneUVIdx); + layer_out.gs_bindings[idx] = bindings; + + const VKBufInfo in_info = layer_in.gs_buf[idx]->get_buf_info (); + const VKBufInfo out_info = layer_out.gs_buf[idx]->get_buf_info (); + + size_t unit_bytes = sizeof (uint32_t); + GaussScalePushConstsProp prop; + prop.in_img_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes; + prop.in_img_height = in_info.height; + prop.out_img_width = XCAM_ALIGN_UP (out_info.width, unit_bytes) / unit_bytes; + prop.out_img_height = out_info.height; + if (level == 1) { + const Rect area = _blender->get_input_merge_area (idx); + prop.in_offset_x = XCAM_ALIGN_UP (area.pos_x, unit_bytes) / unit_bytes; + prop.merge_width = XCAM_ALIGN_UP (area.width, unit_bytes) / unit_bytes; + } else { + prop.in_offset_x = 0; + prop.merge_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes; + } + layer_out.gs_consts[idx] = new VKGaussScalePushConst (prop); + + layer_out.gs_global_size[idx] = WorkSize ( + XCAM_ALIGN_UP (prop.out_img_width, 8) / 8, + XCAM_ALIGN_UP (out_info.height, 16) / 16); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::fix_lap_trans_params (uint32_t level, VKBlender::BufIdx idx) +{ + XCAM_ASSERT (level < pyr_layers_num - 1); + + PyrLayer &layer = pyr_layer[level]; + PyrLayer &layer_next = pyr_layer[level + 1]; + XCAM_ASSERT ((layer.gs_buf[idx].ptr () || level == 0) && layer_next.gs_buf[idx].ptr ()); + XCAM_ASSERT (layer.lap_buf[idx].ptr ()); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < LAP_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + VKDescriptor::SetBindInfoArray bindings (LAP_SHADER_BINDING_COUNT); + bindings[0].layout = binding_layout[0]; + bindings[1].layout = binding_layout[1]; + if (layer.gs_buf[idx].ptr ()) { + bindings[0].desc = VKBufDesc (layer.gs_buf[idx], NV12PlaneYIdx); + bindings[1].desc = VKBufDesc (layer.gs_buf[idx], NV12PlaneUVIdx); + } + bindings[2].layout = binding_layout[2]; + bindings[2].desc = VKBufDesc (layer_next.gs_buf[idx], NV12PlaneYIdx); + bindings[3].layout = binding_layout[3]; + bindings[3].desc = VKBufDesc (layer_next.gs_buf[idx], NV12PlaneUVIdx); + bindings[4].layout = binding_layout[4]; + bindings[4].desc = VKBufDesc (layer.lap_buf[idx], NV12PlaneYIdx); + bindings[5].layout = binding_layout[5]; + bindings[5].desc = VKBufDesc (layer.lap_buf[idx], NV12PlaneUVIdx); + layer.lap_bindings[idx] = bindings; + + const VKBufInfo in_info = layer.gs_buf[idx]->get_buf_info (); + const VKBufInfo gs_info = layer_next.gs_buf[idx]->get_buf_info (); + + size_t unit_bytes = sizeof (uint32_t) * 2; + LapPushConstsProp prop; + prop.in_img_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes; + prop.in_img_height = in_info.height; + prop.gaussscale_img_width = XCAM_ALIGN_UP (gs_info.width, sizeof (uint32_t)) / sizeof (uint32_t); + prop.gaussscale_img_height = gs_info.height; + if (level == 0) { + const Rect area = _blender->get_input_merge_area (idx); + prop.in_offset_x = XCAM_ALIGN_UP (area.pos_x, unit_bytes) / unit_bytes; + prop.merge_width = XCAM_ALIGN_UP (area.width, unit_bytes) / unit_bytes; + } else { + prop.in_offset_x = 0; + prop.merge_width = XCAM_ALIGN_UP (in_info.width, unit_bytes) / unit_bytes; + } + layer.lap_consts[idx] = new VKLapPushConst (prop); + + layer.lap_global_size[idx] = WorkSize ( + XCAM_ALIGN_UP (prop.merge_width, 8) / 8, + XCAM_ALIGN_UP (in_info.height, 32) / 32); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::fix_blend_params () +{ + PyrLayer &top_layer = pyr_layer[pyr_layers_num - 1]; + XCAM_ASSERT (top_layer.gs_buf[VKBlender::BufIdx0].ptr () && top_layer.gs_buf[VKBlender::BufIdx1].ptr ()); + XCAM_ASSERT (top_layer.mask.ptr ()); + XCAM_ASSERT (top_layer.blend_buf.ptr ()); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < BLEND_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + VKDescriptor::SetBindInfoArray bindings (BLEND_SHADER_BINDING_COUNT); + bindings[0].layout = binding_layout[0]; + bindings[0].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx0], NV12PlaneYIdx); + bindings[1].layout = binding_layout[1]; + bindings[1].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx0], NV12PlaneUVIdx); + bindings[2].layout = binding_layout[2]; + bindings[2].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx1], NV12PlaneYIdx); + bindings[3].layout = binding_layout[3]; + bindings[3].desc = VKBufDesc (top_layer.gs_buf[VKBlender::BufIdx1], NV12PlaneUVIdx); + bindings[4].layout = binding_layout[4]; + bindings[4].desc = VKBufDesc (top_layer.blend_buf, NV12PlaneYIdx); + bindings[5].layout = binding_layout[5]; + bindings[5].desc = VKBufDesc (top_layer.blend_buf, NV12PlaneUVIdx); + bindings[6].layout = binding_layout[6]; + bindings[6].desc = VKBufDesc (top_layer.mask); + top_layer.blend_bindings = bindings; + + const VKBufInfo in0_info = top_layer.gs_buf[VKBlender::BufIdx0]->get_buf_info (); + size_t unit_bytes = sizeof (uint32_t) * 2; + BlendPushConstsProp prop; + prop.in_img_width = XCAM_ALIGN_UP (in0_info.width, unit_bytes) / unit_bytes; + top_layer.blend_consts = new VKBlendPushConst (prop); + + top_layer.blend_global_size = WorkSize ( + XCAM_ALIGN_UP (prop.in_img_width, 8) / 8, + XCAM_ALIGN_UP (in0_info.height, 16) / 16); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::fix_reconstruct_params (uint32_t level) +{ + XCAM_ASSERT (level < pyr_layers_num - 1); + + PyrLayer &layer = pyr_layer[level]; + PyrLayer &prev_layer = pyr_layer[level + 1]; + + XCAM_ASSERT (layer.lap_buf[VKBlender::BufIdx0].ptr ()); + XCAM_ASSERT (layer.lap_buf[VKBlender::BufIdx1].ptr ()); + XCAM_ASSERT (prev_layer.reconstruct_buf.ptr () && (layer.reconstruct_buf.ptr () || level == 0)); + XCAM_ASSERT (layer.mask.ptr ()); + + VKDescriptor::BindingArray binding_layout; + binding_layout.clear (); + for (int i = 0; i < RECONSTRUCT_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + binding_layout.push_back (binding); + } + + VKDescriptor::SetBindInfoArray bindings (RECONSTRUCT_SHADER_BINDING_COUNT); + bindings[0].layout = binding_layout[0]; + bindings[0].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx0], NV12PlaneYIdx); + bindings[1].layout = binding_layout[1]; + bindings[1].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx0], NV12PlaneUVIdx); + bindings[2].layout = binding_layout[2]; + bindings[2].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx1], NV12PlaneYIdx); + bindings[3].layout = binding_layout[3]; + bindings[3].desc = VKBufDesc (layer.lap_buf[VKBlender::BufIdx1], NV12PlaneUVIdx); + bindings[4].layout = binding_layout[4]; + bindings[5].layout = binding_layout[5]; + if (layer.reconstruct_buf.ptr ()) { + bindings[4].desc = VKBufDesc (layer.reconstruct_buf, NV12PlaneYIdx); + bindings[5].desc = VKBufDesc (layer.reconstruct_buf, NV12PlaneUVIdx); + } + bindings[6].layout = binding_layout[6]; + bindings[6].desc = VKBufDesc (prev_layer.reconstruct_buf, NV12PlaneYIdx); + bindings[7].layout = binding_layout[7]; + bindings[7].desc = VKBufDesc (prev_layer.reconstruct_buf, NV12PlaneUVIdx); + bindings[8].layout = binding_layout[8]; + bindings[8].desc = VKBufDesc (layer.mask); + layer.reconstruct_bindings = bindings; + + const VKBufInfo lap0_info = layer.lap_buf[VKBlender::BufIdx0]->get_buf_info (); + const VKBufInfo prev_recons_info = prev_layer.reconstruct_buf->get_buf_info (); + + size_t unit_bytes = sizeof (uint32_t) * 2; + ReconstructPushConstsProp prop; + prop.lap_img_width = XCAM_ALIGN_UP (lap0_info.width, unit_bytes) / unit_bytes; + prop.lap_img_height = lap0_info.height; + prop.prev_blend_img_width = XCAM_ALIGN_UP (prev_recons_info.width, sizeof (uint32_t)) / sizeof (uint32_t); + prop.prev_blend_img_height = prev_recons_info.height; + if (level == 0) { + const VideoBufferInfo info = _blender->get_out_video_info (); + prop.out_img_width = XCAM_ALIGN_UP (info.width, unit_bytes) / unit_bytes; + + const Rect area = _blender->get_merge_window (); + prop.out_offset_x = XCAM_ALIGN_UP (area.pos_x, unit_bytes) / unit_bytes; + } else { + const VKBufInfo info = layer.reconstruct_buf->get_buf_info (); + prop.out_img_width = XCAM_ALIGN_UP (info.width, unit_bytes) / unit_bytes; + prop.out_offset_x = 0; + } + layer.reconstruct_consts = new VKReconstructPushConst (prop); + + layer.reconstruct_global_size = WorkSize ( + XCAM_ALIGN_UP (prop.lap_img_width, 8) / 8, + XCAM_ALIGN_UP (lap0_info.height, 32) / 32); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::start_gauss_scale (uint32_t level, VKBlender::BufIdx idx) +{ + XCAM_ASSERT (level >= 1 && level < pyr_layers_num); + + PyrLayer &layer = pyr_layer[level]; + layer.gauss_scale[idx]->set_global_size (layer.gs_global_size[idx]); + + SmartPtr<BlendArgs> args = new BlendArgs (level, idx); + args->set_bindings (layer.gs_bindings[idx]); + args->add_push_const (layer.gs_consts[idx]); + + return layer.gauss_scale[idx]->work (args); +} + +XCamReturn +BlenderImpl::start_lap_tran (uint32_t level, VKBlender::BufIdx idx) +{ + PyrLayer &layer = pyr_layer[level]; + + SmartPtr<VKBlender::Sync> &sync = layer.lap_sync[idx]; + if (!sync->is_synced ()) + return XCAM_RETURN_NO_ERROR; + sync->reset (); + + layer.lap_trans[idx]->set_global_size (layer.lap_global_size[idx]); + + SmartPtr<BlendArgs> args = new BlendArgs (level, idx); + args->set_bindings (layer.lap_bindings[idx]); + args->add_push_const (layer.lap_consts[idx]); + + return layer.lap_trans[idx]->work (args); +} + +XCamReturn +BlenderImpl::start_lap_trans (uint32_t level, VKBlender::BufIdx idx) +{ + XCAM_ASSERT (level >= 1 && level < pyr_layers_num); + + uint32_t pre_level = level - 1; + pyr_layer[pre_level].lap_sync[idx]->increment (); + + XCamReturn ret = start_lap_tran (pre_level, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-blend start lap tran failed, level:%d idx:%d", pre_level, idx); + + if (level == pyr_layers_num - 1) + return XCAM_RETURN_NO_ERROR; + pyr_layer[level].lap_sync[idx]->increment (); + + ret = start_lap_tran (level, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-blend start lap tran failed, level:%d idx:%d", level, idx); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +BlenderImpl::start_top_blend () +{ + uint32_t level = pyr_layers_num - 1; + PyrLayer &layer = pyr_layer[level]; + + SmartPtr<VKBlender::Sync> &sync = layer.blend_sync; + if (!sync->is_synced ()) + return XCAM_RETURN_NO_ERROR; + sync->reset (); + + SmartPtr<VKWorker::VKArguments> args = new VKWorker::VKArguments; + args->set_bindings (layer.blend_bindings); + args->add_push_const (layer.blend_consts); + + layer.blend->set_global_size (layer.blend_global_size); + + return layer.blend->work (args); +} + +XCamReturn +BlenderImpl::start_reconstruct (uint32_t level) +{ + XCAM_ASSERT (level < pyr_layers_num - 1); + PyrLayer &layer = pyr_layer[level]; + + SmartPtr<VKBlender::Sync> &sync = layer.reconstruct_sync; + if (!sync->is_synced ()) + return XCAM_RETURN_NO_ERROR; + sync->reset (); + + SmartPtr<BlendArgs> args = new BlendArgs (level); + args->set_bindings (layer.reconstruct_bindings); + args->add_push_const (layer.reconstruct_consts); + + layer.reconstruct->set_global_size (layer.reconstruct_global_size); + + return layer.reconstruct->work (args); +} + +XCamReturn +BlenderImpl::stop () +{ + for (uint32_t lv = 0; lv < pyr_layers_num; ++lv) { + pyr_layer[lv].gs_buf[VKBlender::BufIdx0].release (); + pyr_layer[lv].gs_buf[VKBlender::BufIdx1].release (); + pyr_layer[lv].lap_buf[VKBlender::BufIdx0].release (); + pyr_layer[lv].lap_buf[VKBlender::BufIdx1].release (); + pyr_layer[lv].reconstruct_buf.release (); + pyr_layer[lv].blend_buf.release (); + + pyr_layer[lv].gs_consts[VKBlender::BufIdx0].release (); + pyr_layer[lv].gs_consts[VKBlender::BufIdx1].release (); + pyr_layer[lv].lap_consts[VKBlender::BufIdx0].release (); + pyr_layer[lv].lap_consts[VKBlender::BufIdx1].release (); + pyr_layer[lv].reconstruct_consts.release (); + pyr_layer[lv].blend_consts.release (); + } + + return XCAM_RETURN_NO_ERROR; +} + +} + +VKBlender::VKBlender (const SmartPtr<VKDevice> dev, const char *name) + : VKHandler (dev, name) + , Blender (VK_BLENDER_ALIGN_X, VK_BLENDER_ALIGN_Y) +{ + SmartPtr<VKBlenderPriv::BlenderImpl> impl = + new VKBlenderPriv::BlenderImpl (this, XCAM_VK_DEFAULT_LEVEL); + XCAM_ASSERT (impl.ptr ()); + + _impl = impl; +} + +VKBlender::~VKBlender () +{ +} + +XCamReturn +VKBlender::blend ( + const SmartPtr<VideoBuffer> &in0, const SmartPtr<VideoBuffer> &in1, SmartPtr<VideoBuffer> &out_buf) +{ + XCAM_ASSERT (in0.ptr () && in1.ptr ()); + + SmartPtr<BlenderParam> param = new BlenderParam (in0, in1, out_buf); + XCAM_ASSERT (param.ptr ()); + + XCamReturn ret = execute_buffer (param, true); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend execute buffer failed"); + + finish (); + if (!out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +static XCamReturn +check_merge_area (const SmartPtr<VKBlender> &blender) +{ + Rect in0_area, in1_area, out_area; + + in0_area = blender->get_input_merge_area (VKBlender::BufIdx0); + XCAM_FAIL_RETURN ( + ERROR, + in0_area.pos_y == 0 && in0_area.width && in0_area.height && + in0_area.pos_x % VK_BLENDER_ALIGN_X == 0 && + in0_area.width % VK_BLENDER_ALIGN_X == 0 && + in0_area.height % VK_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid input0 merge area, pos_x:%d, pos_y:%d, width:%d, height:%d", + in0_area.pos_x, in0_area.pos_y, in0_area.width, in0_area.height); + + in1_area = blender->get_input_merge_area (VKBlender::BufIdx1); + XCAM_FAIL_RETURN ( + ERROR, + in1_area.pos_y == 0 && in1_area.width && in1_area.height && + in1_area.pos_x % VK_BLENDER_ALIGN_X == 0 && + in1_area.width % VK_BLENDER_ALIGN_X == 0 && + in1_area.height % VK_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid input1 merge area, pos_x:%d, pos_y:%d, width:%d, height:%d", + in1_area.pos_x, in1_area.pos_y, in1_area.width, in1_area.height); + + out_area = blender->get_merge_window (); + XCAM_FAIL_RETURN ( + ERROR, + out_area.pos_y == 0 && out_area.width && out_area.height && + out_area.pos_x % VK_BLENDER_ALIGN_X == 0 && + out_area.width % VK_BLENDER_ALIGN_X == 0 && + out_area.height % VK_BLENDER_ALIGN_Y == 0, + XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid output merge area, pos_x:%d, pos_y:%d, width:%d, height:%d", + out_area.pos_x, out_area.pos_y, out_area.width, out_area.height); + + XCAM_FAIL_RETURN ( + ERROR, + in0_area.width == in1_area.width && in0_area.height == in1_area.height && + in0_area.width == out_area.width && in0_area.height == out_area.height, + XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid input or output overlap area, input0:%dx%d, input1:%dx%d, output:%dx%d", + in0_area.width, in0_area.height, in1_area.width, in1_area.height, out_area.width, out_area.height); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKBlender::set_output_info (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + const VideoBufferInfo &in0_info = param->in_buf->get_video_info (); + XCAM_FAIL_RETURN ( + ERROR, in0_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM, + "vk-blend only support NV12 format, but input format is %s", + xcam_fourcc_to_string (in0_info.format)); + + uint32_t out_width, out_height; + get_output_size (out_width, out_height); + XCAM_FAIL_RETURN ( + ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM, + "vk-blend invalid output size:%dx%d", out_width, out_height); + + VideoBufferInfo out_info; + out_info.init ( + in0_info.format, out_width, out_height, + XCAM_ALIGN_UP (out_width, VK_BLENDER_ALIGN_X), + XCAM_ALIGN_UP (out_height, VK_BLENDER_ALIGN_Y)); + set_out_video_info (out_info); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKBlender::configure_resource (const SmartPtr<Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr ()); + XCAM_ASSERT (_impl->pyr_layers_num <= XCAM_VK_MAX_LEVEL); + + SmartPtr<BlenderParam> blend_param = param.dynamic_cast_ptr<BlenderParam> (); + XCAM_ASSERT (blend_param.ptr () && blend_param->in_buf.ptr () && blend_param->in1_buf.ptr ()); + + XCamReturn ret = set_output_info (param); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend set output video info failed"); + + ret = check_merge_area (this); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend check merge area failed"); + + _impl->init_syncs (); + + ret = _impl->init_layers_bufs (param); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend init buffers failed"); + + ret = _impl->fix_parameters (); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend fix parameters failed"); + + ret = _impl->create_workers (this); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend create workers failed"); + + ret = _impl->redirect_workers (); + XCAM_FAIL_RETURN (ERROR, xcam_ret_is_ok (ret), ret, "vk-blend redirect workers failed"); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKBlender::start_work (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + SmartPtr<VKBlender::BlenderParam> blend_param = param.dynamic_cast_ptr<BlenderParam> (); + XCAM_ASSERT (blend_param.ptr ()); + XCAM_ASSERT (blend_param->in_buf.ptr () && blend_param->in1_buf.ptr () && blend_param->out_buf.ptr ()); + +#if DUMP_BUFFER + SmartPtr<VKVideoBuffer> in0_vk = blend_param->in_buf.dynamic_cast_ptr<VKVideoBuffer> (); + SmartPtr<VKVideoBuffer> in1_vk = blend_param->in1_buf.dynamic_cast_ptr<VKVideoBuffer> (); + XCAM_ASSERT (in0_vk.ptr () && in1_vk.ptr ()); + dump_level_vkbuf (in0_vk->get_vk_buf (), "blend-in", 0, VKBlender::BufIdx0); + dump_level_vkbuf (in1_vk->get_vk_buf (), "blend-in", 0, VKBlender::BufIdx1); +#endif + + _impl->bind_io_bufs_to_layer0 (blend_param->in_buf, blend_param->in1_buf, blend_param->out_buf); + _impl->bind_io_vkbufs_to_desc (); + + _impl->pyr_layer[0].lap_sync[BufIdx0]->increment (); + _impl->pyr_layer[0].lap_sync[BufIdx1]->increment (); + + XCamReturn ret = XCAM_RETURN_NO_ERROR; + ret = _impl->start_gauss_scale (1, BufIdx0); + CHECK_RET (ret, "vk-blend start gauss scale failed, level:1 index:0\n"); + + ret = _impl->start_gauss_scale (1, BufIdx1); + CHECK_RET (ret, "vk-blend start gauss scale failed, level:1 index:1\n"); + + execute_done (param, ret); + + return ret; +} + +void +VKBlender::gauss_scale_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + if (!xcam_ret_is_ok (error)) { + XCAM_LOG_ERROR ("vk-blend gauss scale failed"); + return ; + } + + SmartPtr<VKBlenderPriv::BlendArgs> args = base.dynamic_cast_ptr<VKBlenderPriv::BlendArgs> (); + XCAM_ASSERT (args.ptr ()); + uint32_t level = args->get_level (); + uint32_t next_level = level + 1; + BufIdx idx = args->get_idx (); + + SmartPtr<VKWorker> gs_worker = worker.dynamic_cast_ptr<VKWorker> (); + XCAM_ASSERT (gs_worker.ptr ()); + gs_worker->wait_fence (); + +#if DUMP_BUFFER + dump_level_vkbuf (_impl->pyr_layer[level].gs_buf[idx], "gauss-scale", level, idx); +#endif + + XCamReturn ret = _impl->start_lap_trans (level, idx); + CHECK_RET (ret, "vk-blend execute laplace transformation failed, level:%d idx:%d", level, idx); + + if (next_level == _impl->pyr_layers_num) { + _impl->pyr_layer[level].blend_sync->increment (); + + ret = _impl->start_top_blend (); + CHECK_RET (ret, "vk-blend execute top blend failed, level:%d idx:%d", level, idx); + } else { + ret = _impl->start_gauss_scale (next_level, idx); + CHECK_RET (ret, "vk-blend execute gauss scale failed, level:%d idx:%d", next_level, idx); + } +} + +void +VKBlender::lap_trans_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (base); + if (!xcam_ret_is_ok (error)) { + XCAM_LOG_ERROR ("vk-blend laplace transformation failed"); + return ; + } + + SmartPtr<VKBlenderPriv::BlendArgs> args = base.dynamic_cast_ptr<VKBlenderPriv::BlendArgs> (); + XCAM_ASSERT (args.ptr ()); + uint32_t level = args->get_level (); + + SmartPtr<VKWorker> laptrans_worker = worker.dynamic_cast_ptr<VKWorker> (); + XCAM_ASSERT (laptrans_worker.ptr ()); + laptrans_worker->wait_fence (); + +#if DUMP_BUFFER + BufIdx idx = args->get_idx (); + dump_level_vkbuf (_impl->pyr_layer[level].lap_buf[idx], "lap", level, idx); +#endif + + _impl->pyr_layer[level].reconstruct_sync->increment (); + + XCamReturn ret = _impl->start_reconstruct (level); + CHECK_RET (ret, "vk-blend execute reconstruct failed, level:%d", level); +} + +void +VKBlender::blend_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (base); + if (!xcam_ret_is_ok (error)) { + XCAM_LOG_ERROR ("vk-blend blend failed"); + return ; + } + + SmartPtr<VKWorker> blend_worker = worker.dynamic_cast_ptr<VKWorker> (); + XCAM_ASSERT (blend_worker.ptr ()); + blend_worker->wait_fence (); + +#if DUMP_BUFFER + dump_vkbuf (_impl->pyr_layer[_impl->pyr_layers_num - 1].blend_buf, "blend-top"); +#endif + + uint32_t pre_level = _impl->pyr_layers_num - 2; + _impl->pyr_layer[pre_level].reconstruct_sync->increment (); + + XCamReturn ret = _impl->start_reconstruct (pre_level); + CHECK_RET (ret, "vk-blend execute reconstruct failed, level:%d", pre_level); +} + +void +VKBlender::reconstruct_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + XCAM_UNUSED (base); + if (!xcam_ret_is_ok (error)) { + XCAM_LOG_ERROR ("vk-blend reconstruct failed"); + return ; + } + + SmartPtr<VKBlenderPriv::BlendArgs> args = base.dynamic_cast_ptr<VKBlenderPriv::BlendArgs> (); + XCAM_ASSERT (args.ptr ()); + uint32_t level = args->get_level (); + + SmartPtr<VKWorker> reconstruct_worker = worker.dynamic_cast_ptr<VKWorker> (); + XCAM_ASSERT (reconstruct_worker.ptr ()); + reconstruct_worker->wait_fence (); + +#if DUMP_BUFFER + BufIdx idx = args->get_idx (); + dump_level_vkbuf (_impl->pyr_layer[level].reconstruct_buf, "reconstruct", level, idx); +#endif + + if (level == 0) { + return; + } + + uint32_t pre_level = level - 1; + _impl->pyr_layer[pre_level].reconstruct_sync->increment (); + + XCamReturn ret = _impl->start_reconstruct (pre_level); + CHECK_RET (ret, "vk-blend execute reconstruct failed, level:%d", pre_level); +} + +SmartPtr<VKHandler> +create_vk_blender (const SmartPtr<VKDevice> &dev) +{ + SmartPtr<VKBlender> blender = new VKBlender (dev); + XCAM_ASSERT (blender.ptr ()); + + return blender; +} + +SmartPtr<Blender> +Blender::create_vk_blender (const SmartPtr<VKDevice> &dev) +{ + SmartPtr<VKHandler> handler = XCam::create_vk_blender (dev); + return handler.dynamic_cast_ptr<Blender> (); +} + +} diff --git a/modules/vulkan/vk_blender.h b/modules/vulkan/vk_blender.h new file mode 100644 index 0000000..223b48f --- /dev/null +++ b/modules/vulkan/vk_blender.h @@ -0,0 +1,120 @@ +/* + * vk_blender.h - vulkan blender class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_VK_BLENDER_H +#define XCAM_VK_BLENDER_H + +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_handler.h> +#include <interface/blender.h> + +#define VK_BLENDER_ALIGN_X 8 +#define VK_BLENDER_ALIGN_Y 4 + +#define XCAM_VK_MAX_LEVEL 4 +#define XCAM_VK_DEFAULT_LEVEL 2 + +namespace XCam { + +namespace VKBlenderPriv { +class BlenderImpl; +} + +class VKBlender + : public VKHandler, public Blender +{ + friend class VKBlenderPriv::BlenderImpl; + friend SmartPtr<VKHandler> create_vk_blender (const SmartPtr<VKDevice> &dev); + +public: + struct BlenderParam : ImageHandler::Parameters { + SmartPtr<VideoBuffer> in1_buf; + + BlenderParam ( + const SmartPtr<VideoBuffer> &in0, + const SmartPtr<VideoBuffer> &in1, + const SmartPtr<VideoBuffer> &out) + : Parameters (in0, out) + , in1_buf (in1) + {} + }; + + class Sync + { + public: + Sync (uint32_t threshold) + : _count (0), _threshold (threshold) + {} + + void increment () { + ++_count; + } + void reset () { + _count = 0; + } + bool is_synced () { + return (_threshold == _count); + } + + private: + uint32_t _count; + const uint32_t _threshold; + }; + + enum BufIdx { + BufIdx0 = 0, + BufIdx1, + BufIdxMax + }; + +public: + ~VKBlender (); + + void gauss_scale_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + void lap_trans_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + void blend_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + void reconstruct_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + +protected: + explicit VKBlender (const SmartPtr<VKDevice> dev, const char *name = "VKBlender"); + + // derived from Blender interface + XCamReturn blend ( + const SmartPtr<VideoBuffer> &in0, const SmartPtr<VideoBuffer> &in1, SmartPtr<VideoBuffer> &out); + + // derived from VKHandler + XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + XCamReturn start_work (const SmartPtr<Parameters> ¶m); + + XCamReturn set_output_info (const SmartPtr<ImageHandler::Parameters> ¶m); + +private: + SmartPtr<VKBlenderPriv::BlenderImpl> _impl; +}; + +extern SmartPtr<VKHandler> create_vk_blender (const SmartPtr<VKDevice> &dev); + +} + +#endif // XCAM_VK_BLENDER_H diff --git a/modules/vulkan/vk_cmdbuf.cpp b/modules/vulkan/vk_cmdbuf.cpp new file mode 100644 index 0000000..1bc33be --- /dev/null +++ b/modules/vulkan/vk_cmdbuf.cpp @@ -0,0 +1,172 @@ +/* + * vk_cmdbuf.cpp - Vulkan command buffer + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_cmdbuf.h" +#include "vulkan_common.h" +#include "vk_pipeline.h" + +namespace XCam { + +VKCmdBuf::Pool::Pool (const SmartPtr<VKDevice> dev, VkCommandPool id) + : _pool_id (id) + , _dev (dev) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id)); +} + +VKCmdBuf::Pool::~Pool () +{ + if (XCAM_IS_VALID_VK_ID (_pool_id)) + _dev->destroy_cmd_pool (_pool_id); +} + +SmartPtr<VKCmdBuf> +VKCmdBuf::Pool::allocate_buffer () +{ + //VkCommandBufferAllocateInfo info {}; + VkCommandBuffer cmd_buf_id = _dev->allocate_cmd_buffer (_pool_id); + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (cmd_buf_id), NULL, + "VKCmdBuf allocate cmd buffer failed"); + return new VKCmdBuf (this, cmd_buf_id); +} + +void +VKCmdBuf::Pool::free_buffer (VkCommandBuffer buf_id) +{ + XCAM_ASSERT (_dev.ptr ()); + _dev->free_cmd_buffer (_pool_id, buf_id); +} + +SmartPtr<VKCmdBuf::Pool> +VKCmdBuf::create_pool (const SmartPtr<VKDevice> dev, VkFlags queue_flag) +{ + VkCommandPool pool_id = dev->create_cmd_pool (queue_flag); + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (pool_id), NULL, + "VKCmdBuf create_pool failed"); + SmartPtr<VKCmdBuf::Pool> pool = new VKCmdBuf::Pool (dev, pool_id); + return pool; +} + +SmartPtr<VKCmdBuf> +VKCmdBuf::create_command_buffer ( + const SmartPtr<VKDevice> dev, + const SmartPtr<VKCmdBuf::Pool> pool) +{ + XCAM_FAIL_RETURN ( + ERROR, dev.ptr (), NULL, + "VKCmdBuf create command buffer failed"); + + SmartPtr<VKCmdBuf::Pool> cmdbuf_pool = pool; + if (!pool.ptr()) { + cmdbuf_pool = create_pool (dev, VK_QUEUE_COMPUTE_BIT); + } + + XCAM_FAIL_RETURN ( + ERROR, cmdbuf_pool.ptr (), NULL, + "VKCmdBuf create command pool failed"); + + return cmdbuf_pool->allocate_buffer (); +} + +VKCmdBuf::VKCmdBuf (const SmartPtr<VKCmdBuf::Pool> pool, VkCommandBuffer buf_id) + : _cmd_buf_id (buf_id) + , _pool (pool) +{ +} + +VKCmdBuf::~VKCmdBuf () +{ + if (_pool.ptr () && XCAM_IS_VALID_VK_ID (_cmd_buf_id)) + _pool->free_buffer (_cmd_buf_id); +} + +VKCmdBuf::DispatchParam::DispatchParam (const SmartPtr<VKPipeline> &p, uint32_t x, uint32_t y, uint32_t z) + : _group_size (x, y, z) + , _pipeline (p) +{ +} + +VKCmdBuf::DispatchParam::~DispatchParam () +{ +} + +bool +VKCmdBuf::DispatchParam::update_push_consts (VKConstRange::VKPushConstArgs & push_consts) +{ + _push_consts = push_consts; + return true; +} + +XCamReturn +VKCmdBuf::DispatchParam::fill_cmd_buf (VKCmdBuf &buf) +{ + XCamReturn ret = _pipeline->bind_by (buf); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), + ret, "VKCmdBuf DispatchParam fill command buffer failed when binding pipeline"); + + for (size_t i = 0; i < _push_consts.size (); ++i) { + XCAM_RETURN_CHECK ( + ERROR, _pipeline->push_consts_by (buf, _push_consts[i]), + "VKCmdBuf DispatchParam fill command buffer failed when push consts (:%d)", i); + } + return buf.dispatch (_group_size); +} + +XCamReturn +VKCmdBuf::record (const SmartPtr<DispatchParam> param) +{ + VkCommandBufferBeginInfo buf_begin_info = {}; + buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + buf_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + buf_begin_info.pInheritanceInfo = NULL; + + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_cmd_buf_id)); + XCAM_VK_CHECK_RETURN ( + ERROR, vkBeginCommandBuffer (_cmd_buf_id, &buf_begin_info), + XCAM_RETURN_ERROR_VULKAN, "VKCmdBuf begin command buffer failed"); + + XCamReturn ret = param->fill_cmd_buf (*this); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), + ret, "VKCmdBuf dispatch params failed"); + + XCAM_VK_CHECK_RETURN ( + ERROR, vkEndCommandBuffer (_cmd_buf_id), + XCAM_RETURN_ERROR_VULKAN, "VKCmdBuf begin command buffer failed"); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKCmdBuf::dispatch (const GroupSize &group) +{ + XCAM_FAIL_RETURN ( + ERROR, group.x * group.y * group.z > 0, + XCAM_RETURN_ERROR_VULKAN, "VKCmdBuf dispatch params failed"); + + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_cmd_buf_id)); + vkCmdDispatch (_cmd_buf_id, group.x, group.y, group.z); + return XCAM_RETURN_NO_ERROR; +} + +} diff --git a/modules/vulkan/vk_cmdbuf.h b/modules/vulkan/vk_cmdbuf.h new file mode 100644 index 0000000..458bea3 --- /dev/null +++ b/modules/vulkan/vk_cmdbuf.h @@ -0,0 +1,106 @@ +/* + * vk_cmdbuf.h - Vulkan command buffer + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_CMD_BUF_H +#define XCAM_VK_CMD_BUF_H + +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_descriptor.h> +#include <vulkan/vk_device.h> + +namespace XCam { + +class VKCmdBuf +{ +public: + struct GroupSize { + uint32_t x; + uint32_t y; + uint32_t z; + GroupSize (uint32_t x_, uint32_t y_, uint32_t z_) + : x (x_) + , y (y_) + , z (z_) + {} + }; + + class DispatchParam { + friend class VKCmdBuf; + public: + DispatchParam (const SmartPtr<VKPipeline> &p, uint32_t x, uint32_t y = 1, uint32_t z = 1); + virtual ~DispatchParam (); + bool update_push_consts (VKConstRange::VKPushConstArgs & push_consts); + protected: + virtual XCamReturn fill_cmd_buf (VKCmdBuf &buf); + XCAM_DEAD_COPY (DispatchParam); + + protected: + GroupSize _group_size; + const SmartPtr<VKPipeline> _pipeline; + VKConstRange::VKPushConstArgs _push_consts; + }; + + class Pool + : public RefObj + { + friend class VKCmdBuf; + public: + ~Pool (); + SmartPtr<VKCmdBuf> allocate_buffer (); + void free_buffer (VkCommandBuffer buf_id); + + private: + explicit Pool (const SmartPtr<VKDevice> dev, VkCommandPool id); + XCAM_DEAD_COPY (Pool); + private: + VkCommandPool _pool_id; + SmartPtr<VKDevice> _dev; + }; + +public: + static SmartPtr<VKCmdBuf> + create_command_buffer (const SmartPtr<VKDevice> dev, const SmartPtr<Pool> pool = NULL); + static SmartPtr<Pool> create_pool (const SmartPtr<VKDevice> dev, VkFlags queue_flag); + virtual ~VKCmdBuf (); + + VkCommandBuffer get_cmd_buf_id () const { + return _cmd_buf_id; + } + + XCamReturn record (const SmartPtr<DispatchParam> param); + + // for fill_cmd_buf + XCamReturn dispatch (const GroupSize &group); + +protected: + explicit VKCmdBuf (const SmartPtr<Pool> pool, VkCommandBuffer buf_id); + +private: + XCAM_DEAD_COPY (VKCmdBuf); + +protected: + VkCommandBuffer _cmd_buf_id; + + SmartPtr<Pool> _pool; +}; + +} + +#endif //XCAM_VK_CMD_BUF_H diff --git a/modules/vulkan/vk_copy_handler.cpp b/modules/vulkan/vk_copy_handler.cpp new file mode 100644 index 0000000..4a89446 --- /dev/null +++ b/modules/vulkan/vk_copy_handler.cpp @@ -0,0 +1,270 @@ +/* + * vk_copy_handler.cpp - vulkan copy 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include <vulkan/vulkan_std.h> +#include "vk_copy_handler.h" +#include "vk_video_buf_allocator.h" +#include "vk_shader.h" +#include "vk_memory.h" +#include "vk_worker.h" +#include "vk_device.h" + +#define COPY_SHADER_BINDING_COUNT 2 +#define INVALID_INDEX (uint32_t)(-1) + +namespace XCam { + +namespace { + +DECLARE_WORK_CALLBACK (CbCopyShader, VKCopyHandler, copy_done); + +class CopyArgs + : public VKWorker::VKArguments +{ +public: + explicit CopyArgs (const SmartPtr<ImageHandler::Parameters> ¶m) + : _param (param) + { + XCAM_ASSERT (param.ptr ()); + } + const SmartPtr<ImageHandler::Parameters> &get_param () const { + return _param; + } + +private: + SmartPtr<ImageHandler::Parameters> _param; +}; + +class VKCopyPushConst + : public VKConstRange::VKPushConstArg +{ +public: + VKCopyPushConst (const VKCopyHandler::PushConstsProp &prop) + : _prop (prop) + {} + + bool get_const_data (VkPushConstantRange &range, void *& ptr) { + range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + range.offset = 0; + range.size = sizeof (_prop); + ptr = &_prop; + return true; + } + +private: + VKCopyHandler::PushConstsProp _prop; +}; + +}; + +static const VKShaderInfo copy_shader_info ( + "main", +std::vector<uint32_t> { +#include "shader_copy.comp.spv" +}); + +#if 0 +VKCopyArguments::VKCopyArguments (const SmartPtr<VKBuffer> in, SmartPtr<VKBuffer> out) + : _in_buf (in) + , _out_buf (out) +{ + XCAM_ASSERT (in.ptr()); + XCAM_ASSERT (out.ptr()); +} + +XCamReturn +VKCopyArguments::prepare_bindings (VKDescriptor::SetBindInfoArray &binding_array) +{ + XCAM_FAIL_RETURN ( + ERROR, _in_buf.ptr () && _out_buf.ptr (), XCAM_RETURN_ERROR_PARAM, + "VKCopyArguments input or output buffer is empty."); + + binding_array.resize (2); + binding_array[0].layout = new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0); + binding_array[0].desc = VKBufDesc (_in_buf); + + binding_array[0].layout = new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1); + binding_array[0].desc = VKBufDesc (_out_buf); + return XCAM_RETURN_NO_ERROR; +} +#endif + +VKCopyHandler::PushConstsProp::PushConstsProp () + : in_img_width (0) + , in_x_offset (0) + , out_img_width (0) + , out_x_offset (0) + , copy_width (0) +{ +} + +VKCopyHandler::VKCopyHandler (const SmartPtr<VKDevice> &dev, const char* name) + : VKHandler (dev, name) + , _index (INVALID_INDEX) +{ +} + +bool +VKCopyHandler::set_copy_area (uint32_t idx, const Rect &in_area, const Rect &out_area) +{ + XCAM_FAIL_RETURN ( + ERROR, + idx != INVALID_INDEX && + in_area.width && in_area.height && + in_area.width == out_area.width && in_area.height == out_area.height, + false, + "VKCopyHandler(%s): set copy area(idx:%d) failed, input size:%dx%d output size:%dx%d", + XCAM_STR (get_name ()), idx, in_area.width, in_area.height, out_area.width, out_area.height); + + _index = idx; + _in_area = in_area; + _out_area = out_area; + + XCAM_LOG_DEBUG ("VKCopyHandler: copy area(idx:%d) input area(%d, %d, %d, %d) output area(%d, %d, %d, %d)", + idx, + in_area.pos_x, in_area.pos_y, in_area.width, in_area.height, + out_area.pos_x, out_area.pos_y, out_area.width, out_area.height); + + return true; +} + +#define UNIT_BYTES (4*sizeof(uint32_t)) + +XCamReturn +VKCopyHandler::configure_resource (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + XCAM_ASSERT (param.ptr ()); + XCAM_ASSERT (!_worker.ptr ()); + + XCAM_FAIL_RETURN ( + ERROR, param->in_buf.ptr (), XCAM_RETURN_ERROR_VULKAN, + "VKCopyHandler(%s) param.in_buf is empty.", XCAM_STR (get_name ())); + XCAM_FAIL_RETURN ( + ERROR, _index != INVALID_INDEX, XCAM_RETURN_ERROR_PARAM, + "VKCopyHandler(%s) invalid copy area, need set copy area first", XCAM_STR (get_name ())); + + VideoBufferInfo in_info = param->in_buf->get_video_info (); + VideoBufferInfo out_info; + if (param->out_buf.ptr ()) + out_info = param->out_buf->get_video_info (); + else + out_info = get_out_video_info (); + XCAM_FAIL_RETURN ( + ERROR, out_info.is_valid (), XCAM_RETURN_ERROR_PARAM, + "VKCopyHandler(%s) invalid out info.", XCAM_STR (get_name ())); + + _image_prop.in_img_width = in_info.aligned_width / UNIT_BYTES; + _image_prop.in_x_offset = _in_area.pos_x / UNIT_BYTES; + _image_prop.out_img_width = out_info.aligned_width / UNIT_BYTES; + _image_prop.out_x_offset = _out_area.pos_x / UNIT_BYTES; + _image_prop.copy_width = _in_area.width / UNIT_BYTES; + WorkSize global_size ( + XCAM_ALIGN_UP (_image_prop.copy_width, 8 ) / 8, + XCAM_ALIGN_UP (_in_area.height * 3 / 2, 8 ) / 8); + + _binding_layout.clear (); + for (int i = 0; i < COPY_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + _binding_layout.push_back (binding); + } + + if (!_worker.ptr ()) { + _worker = new VKWorker(get_vk_device(), "CbCopyShader", new CbCopyShader (this)); + XCAM_ASSERT (_worker.ptr()); + + _worker->set_global_size (global_size); + + VKConstRange::VKPushConstArgs push_consts; + push_consts.push_back (new VKCopyPushConst (_image_prop)); + ret = _worker->build (copy_shader_info, _binding_layout, push_consts); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_VULKAN, + "VKCopyHandler(%s) build copy shader failed.", XCAM_STR (get_name ())); + } + + return ret; +} + +XCamReturn +VKCopyHandler::start_work (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (_binding_layout.size () == COPY_SHADER_BINDING_COUNT); + SmartPtr<VKVideoBuffer> in_vk = param->in_buf.dynamic_cast_ptr<VKVideoBuffer> (); + SmartPtr<VKVideoBuffer> out_vk = param->out_buf.dynamic_cast_ptr<VKVideoBuffer> (); + + XCAM_FAIL_RETURN ( + ERROR, in_vk.ptr () && out_vk.ptr(), XCAM_RETURN_ERROR_VULKAN, + "VKCopyHandler(%s) param.in_buf or param.out_buf is not vk buf.", XCAM_STR (get_name ())); + + VKDescriptor::SetBindInfoArray bindings (_binding_layout.size ()); + bindings[0].layout = _binding_layout[0]; + bindings[0].desc = VKBufDesc (in_vk->get_vk_buf ()); + bindings[1].layout = _binding_layout[1]; + bindings[1].desc = VKBufDesc (out_vk->get_vk_buf ()); + + SmartPtr<CopyArgs> args = new CopyArgs (param); + args->set_bindings (bindings); + args->add_push_const (new VKCopyPushConst (_image_prop)); + return _worker->work (args); +} + +void +VKCopyHandler::copy_done ( + const SmartPtr<Worker> &worker, + const SmartPtr<Worker::Arguments> &base, + const XCamReturn error) +{ + if (!xcam_ret_is_ok (error)) { + XCAM_LOG_ERROR ("VKCopyHandler(%s) copy failed.", XCAM_STR (get_name ())); + } + + SmartPtr<VKWorker> vk_worker = worker.dynamic_cast_ptr<VKWorker> (); + XCAM_ASSERT (vk_worker.ptr ()); + vk_worker->wait_fence (); + + SmartPtr<CopyArgs> args = base.dynamic_cast_ptr<CopyArgs> (); + XCAM_ASSERT (args.ptr ()); + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); +} + +XCamReturn +VKCopyHandler::copy (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf) +{ + SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in_buf, out_buf); + XCAM_ASSERT (param.ptr ()); + + XCamReturn ret = execute_buffer (param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "VKCopyHandler(%s) copy failed", XCAM_STR (get_name ())); + + if (!out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +}; diff --git a/modules/vulkan/vk_copy_handler.h b/modules/vulkan/vk_copy_handler.h new file mode 100644 index 0000000..8c71bae --- /dev/null +++ b/modules/vulkan/vk_copy_handler.h @@ -0,0 +1,90 @@ +/* + * vk_copy_handler.h - vulkan copy 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_COPY_HANDLER_H +#define XCAM_VK_COPY_HANDLER_H + +#include <xcam_utils.h> +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_worker.h> +#include <vulkan/vk_handler.h> +#include <vulkan/vk_descriptor.h> + +namespace XCam { + +#if 0 +class VKCopyArguments + : public VKWorker::VKArguments +{ +public: + explicit VKCopyArguments (const SmartPtr<VKBuffer> in, SmartPtr<VKBuffer> out); + +private: + virtual XCamReturn prepare_bindings (VKDescriptor::SetBindInfoArray &binding_array); +private: + SmartPtr<VKBuffer> _in_buf; + SmartPtr<VKBuffer> _out_buf; +}; +#endif + +class VKCopyHandler + : public VKHandler +{ +public: + struct PushConstsProp { + uint in_img_width; + uint in_x_offset; + uint out_img_width; + uint out_x_offset; + uint copy_width; + + PushConstsProp (); + }; + +public: + explicit VKCopyHandler (const SmartPtr<VKDevice> &dev, const char* name = "vk-copy-handler"); + + bool set_copy_area (uint32_t idx, const Rect &in_area, const Rect &out_area); + uint32_t get_index () { + return _index; + } + + XCamReturn copy (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf); + void copy_done ( + const SmartPtr<Worker> &worker, + const SmartPtr<Worker::Arguments> &base, + const XCamReturn error); + +private: + virtual XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + virtual XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + SmartPtr<VKWorker> _worker; + PushConstsProp _image_prop; + VKDescriptor::BindingArray _binding_layout; + + uint32_t _index; + Rect _in_area; + Rect _out_area; +}; + +} +#endif //XCAM_VK_COPY_HANDLER_H diff --git a/modules/vulkan/vk_descriptor.cpp b/modules/vulkan/vk_descriptor.cpp new file mode 100644 index 0000000..888d3d6 --- /dev/null +++ b/modules/vulkan/vk_descriptor.cpp @@ -0,0 +1,220 @@ +/* + * vk_descriptor.cpp - Vulkan descriptor + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_descriptor.h" +#include "vk_device.h" + +namespace XCam { + +namespace VKDescriptor { + +SetLayoutBinding::SetLayoutBinding ( + VkDescriptorType type, VkShaderStageFlags stage, uint32_t idx, uint32_t count) +{ + xcam_mem_clear (_binding); + _binding.binding = idx; + _binding.descriptorType = type; + _binding.descriptorCount = count; + _binding.stageFlags = stage; + _binding.pImmutableSamplers = NULL; +} + +SetLayoutBinding::~SetLayoutBinding () +{ +} + +VkBindingArray +get_vk_layoutbindings (const BindingArray &array) +{ + VkBindingArray ret; + ret.reserve (array.size ()); + for (size_t i = 0; i < array.size (); ++i) { + ret.push_back(array[i]->get_vk_binding ()); + } + return ret; +} + +Pool::Pool (const SmartPtr<VKDevice> dev) + : _pool_id (VK_NULL_HANDLE) + , _set_size (0) + , _dev (dev) +{} + +Pool::~Pool () +{ + if (XCAM_IS_VALID_VK_ID (_pool_id)) { + _dev->destroy_desc_pool (_pool_id); + } +} + +void +Pool::add_binding (const SmartPtr<SetLayoutBinding> &bind) +{ + VkDescriptorSetLayoutBinding vk_binding = bind->get_vk_binding (); + Pool::TypeTable::iterator i = _types.find (vk_binding.descriptorType); + if (i == _types.end ()) + _types.insert (i, Pool::TypeTable::value_type (vk_binding.descriptorType, vk_binding.descriptorCount)); + else + i->second += vk_binding.descriptorCount; +} + +bool +Pool::add_set_bindings (const BindingArray &binds) +{ + XCAM_FAIL_RETURN ( + ERROR, !XCAM_IS_VALID_VK_ID (_pool_id), false, + "vk desriptor pool was inited, cannot add new binding."); + + for (BindingArray::const_iterator i = binds.begin (); i != binds.end (); ++i) { + add_binding (*i); + } + ++_set_size; + + return true; +} + +XCamReturn +Pool::create () +{ + XCAM_FAIL_RETURN ( + ERROR, !_types.empty (), XCAM_RETURN_ERROR_PARAM, + "vk desriptor pool cannot create since no types added."); + + XCAM_FAIL_RETURN ( + ERROR, _dev.ptr (), XCAM_RETURN_ERROR_PARAM, + "vk desriptor pool cannot create, device is null"); + + std::vector<VkDescriptorPoolSize> pool_sizes; + pool_sizes.reserve (_types.size ()); + for (Pool::TypeTable::iterator i = _types.begin (); i != _types.end(); ++i) { + VkDescriptorPoolSize new_size = {}; + new_size.type = i->first; + new_size.descriptorCount = i->second; + pool_sizes.push_back (new_size); + } + + XCAM_ASSERT (_set_size); + VkDescriptorPoolCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + create_info.maxSets = _set_size; + create_info.poolSizeCount = pool_sizes.size (); + create_info.pPoolSizes = pool_sizes.data (); + + _pool_id = _dev->create_desc_pool (create_info); + + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (_pool_id), XCAM_RETURN_ERROR_VULKAN, + "vk desriptor pool create pool_id failed"); + + return XCAM_RETURN_NO_ERROR; +} + +SmartPtr<Set> +Pool::allocate_set (const SetBindInfoArray &bind_array, VkDescriptorSetLayout layout) +{ + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (_pool_id), NULL, + "vk desriptor pool allocate set failed, pool was not ready"); + +#if 0 + XCAM_FAIL_RETURN ( + ERROR, bind_array.size () == bufs.size (), NULL, + "vk desriptor pool allocate set failed, bindings and bufs sizes are not matched"); +#endif + + XCAM_FAIL_RETURN ( + ERROR, _set_size > 0, NULL, + "vk desriptor pool allocate set failed, bindings and bufs sizes are not matched"); + + //TODO remove binds types from _types + + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = _pool_id; + alloc_info.pSetLayouts = &layout; + alloc_info.descriptorSetCount = 1; + + VkDescriptorSet desc_set_id = _dev->allocate_desc_set (alloc_info); + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (desc_set_id) > 0, NULL, + "vk desriptor pool allocate set failed"); + SmartPtr<Set> new_set = new Set (desc_set_id, this); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (new_set->update_set (bind_array)), NULL, + "vk descriptor pool update set failed"); + + --_set_size; + return new_set; +} + +void +Pool::destroy_desc_set (VkDescriptorSet set_id) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_pool_id)); + if (xcam_ret_is_ok (_dev->free_desc_set (set_id, _pool_id))) + ++_set_size; +} + +Set::Set (VkDescriptorSet set_id, const SmartPtr<Pool> pool) + : _set_id (set_id) + , _pool (pool) +{ +} + +Set::~Set () +{ + if (XCAM_IS_VALID_VK_ID (_set_id)) { + _pool->destroy_desc_set (_set_id); + } +} + +XCamReturn +Set::update_set (const SetBindInfoArray &bind_array) +{ + std::vector<VkWriteDescriptorSet> write_desc_info (bind_array.size ()); + for (uint32_t i = 0; i < bind_array.size (); ++i) { + const SetBindInfo &bind_info = bind_array[i]; + SmartPtr<SetLayoutBinding> bind = bind_info.layout; + XCAM_ASSERT (bind.ptr () && bind_info.desc.buf.ptr ()); + + VkWriteDescriptorSet &info = write_desc_info[i]; + xcam_mem_clear (info); + info.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + info.dstSet = _set_id; + info.dstBinding = bind->get_index (); + info.descriptorCount = 1; + info.descriptorType = bind->get_desc_type(); + info.pBufferInfo = &bind_info.desc.desc_info; + } + SmartPtr<VKDevice> dev = _pool->get_device (); + XCAM_ASSERT (dev.ptr ()); + XCamReturn ret = dev->update_desc_set (write_desc_info); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk descriptor pool update set failed"); + + _bind_array = bind_array; + return ret; +} + +} + +} diff --git a/modules/vulkan/vk_descriptor.h b/modules/vulkan/vk_descriptor.h new file mode 100644 index 0000000..63eff6a --- /dev/null +++ b/modules/vulkan/vk_descriptor.h @@ -0,0 +1,163 @@ +/* + * vk_descriptor.h - Vulkan descriptor + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_DESCRIPTOR_H +#define XCAM_VK_DESCRIPTOR_H + +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_memory.h> +#include <map> + +namespace XCam { + +class VKDevice; + +namespace VKDescriptor { + +class SetLayoutBinding +{ +public: + virtual ~SetLayoutBinding (); + const VkDescriptorSetLayoutBinding &get_vk_binding () const { + return _binding; + } + VkDescriptorType get_desc_type () const { + return _binding.descriptorType; + } + uint32_t get_index () const { + return _binding.binding; + } + +protected: + explicit SetLayoutBinding ( + VkDescriptorType type, VkShaderStageFlags stage, uint32_t idx, uint32_t count); + +private: + XCAM_DEAD_COPY (SetLayoutBinding); +protected: + VkDescriptorSetLayoutBinding _binding; +}; + +template <VkShaderStageFlags stage> +class LayoutBinding + : public SetLayoutBinding +{ +public: + explicit LayoutBinding (VkDescriptorType type, uint32_t idx) + : SetLayoutBinding (type, stage, idx, 1) + {} +}; + +typedef LayoutBinding<VK_SHADER_STAGE_COMPUTE_BIT> ComputeLayoutBinding; +typedef LayoutBinding<VK_SHADER_STAGE_VERTEX_BIT> VetexLayoutBinding; +typedef LayoutBinding<VK_SHADER_STAGE_FRAGMENT_BIT> FragmentLayoutBinding; + +typedef std::vector<SmartPtr<SetLayoutBinding>> BindingArray; + +typedef std::vector<VkDescriptorSetLayoutBinding> VkBindingArray; + +VkBindingArray get_vk_layoutbindings (const BindingArray &array); + +struct SetBindInfo { + SmartPtr<SetLayoutBinding> layout; + VKBufDesc desc; +}; + +typedef std::vector<SetBindInfo> SetBindInfoArray; + +class Pool; +class Set { +public: + explicit Set (VkDescriptorSet set_id, const SmartPtr<Pool> pool); + ~Set (); + XCamReturn update_set (const SetBindInfoArray &bind_array); + VkDescriptorSet get_set_id () const { + return _set_id; + } + +private: + XCAM_DEAD_COPY (Set); + + VkDescriptorSet _set_id; + SetBindInfoArray _bind_array; + SmartPtr<Pool> _pool; +}; + +class Pool + : public RefObj +{ + friend class Set; +public: + explicit Pool (const SmartPtr<VKDevice> dev); + ~Pool (); + bool add_set_bindings (const BindingArray &binds); + XCamReturn create (); + const SmartPtr<VKDevice> &get_device() const { + return _dev; + } + + SmartPtr<Set> allocate_set ( + const SetBindInfoArray &bind_array, VkDescriptorSetLayout layout); + +private: + XCAM_DEAD_COPY (Pool); + void add_binding (const SmartPtr<SetLayoutBinding> &bind); + void destroy_desc_set (VkDescriptorSet set_id); + +private: + typedef std::map<VkDescriptorType, uint32_t> TypeTable; + + VkDescriptorPool _pool_id; + uint32_t _set_size; + TypeTable _types; + const SmartPtr<VKDevice> _dev; +}; + +} + +namespace VKConstRange { + +class VKPushConstArg { +public: + virtual ~VKPushConstArg () {} + virtual bool get_const_data (VkPushConstantRange &range, void *& ptr) = 0; +}; + +typedef std::vector<SmartPtr<VKPushConstArg>> VKPushConstArgs; + +typedef std::vector<VkPushConstantRange> VKConstantArray; + +template <VkShaderStageFlags stage> +VkPushConstantRange +get_constants (uint32_t size, uint32_t offset) +{ + VkPushConstantRange range = {}; + range.stageFlags = stage; + range.offset = offset; + range.size = size; + return range; +} + +#define get_compute_consts get_constants<VK_SHADER_STAGE_COMPUTE_BIT> +} + +} + +#endif //XCAM_VK_DESCRIPTOR_H diff --git a/modules/vulkan/vk_device.cpp b/modules/vulkan/vk_device.cpp new file mode 100644 index 0000000..bf5e68e --- /dev/null +++ b/modules/vulkan/vk_device.cpp @@ -0,0 +1,471 @@ +/* + * vk_device.cpp - vulkan device + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vulkan_common.h" +#include "vk_device.h" +#include "vk_shader.h" +#include "vk_instance.h" +#include "vk_sync.h" +#include "vk_cmdbuf.h" +#include "file_handle.h" + +namespace XCam { + +SmartPtr<VKDevice> VKDevice::_default_dev; +Mutex VKDevice::_default_mutex; + +VKDevice::~VKDevice () +{ + if (_dev_id) + vkDestroyDevice (_dev_id, _allocator.ptr ()); +} + +VKDevice::VKDevice (VkDevice id, const SmartPtr<VKInstance> &instance) + : _dev_id (id) + , _instance (instance) +{ + XCAM_ASSERT (instance.ptr ()); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id)); + _allocator = instance->get_allocator (); +} + +SmartPtr<VKDevice> +VKDevice::default_device () +{ + SmartLock lock (_default_mutex); + if (!_default_dev.ptr()) { + _default_dev = create_device (); + } + XCAM_FAIL_RETURN ( + ERROR, _default_dev.ptr (), NULL, + "VKDevice prepare default device failed."); + return _default_dev; +} + +SmartPtr<VKDevice> +VKDevice::create_device () +{ + SmartPtr<VKInstance> instance = VKInstance::get_instance (); + XCAM_FAIL_RETURN ( + ERROR, instance.ptr (), NULL, + "vk create device failed"); + + VkPhysicalDevice phy_dev = instance->get_physical_dev (); + uint32_t compute_idx = instance->get_compute_queue_family_idx (); + SmartPtr<VkAllocationCallbacks> allocator = instance->get_allocator (); + + float priority = 1.0f; //TODO, queue priority change? + VkDeviceQueueCreateInfo dev_queue_info = {}; + dev_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + dev_queue_info.queueFamilyIndex = compute_idx; // default use compute idx + dev_queue_info.queueCount = 1; + dev_queue_info.pQueuePriorities = &priority; + + VkDeviceCreateInfo dev_create_info = {}; + dev_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + //TODO, add graphics queue info + dev_create_info.queueCreateInfoCount = 1; + dev_create_info.pQueueCreateInfos = &dev_queue_info; + + VkDevice dev_id = 0; + XCAM_VK_CHECK_RETURN ( + ERROR, + vkCreateDevice (phy_dev, &dev_create_info, allocator.ptr (), &dev_id), + NULL, "create vk device failed"); + + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (dev_id)); + SmartPtr<VKDevice> device = new VKDevice (dev_id, instance); + XCAM_ASSERT (device.ptr ()); + + XCamReturn ret = device->prepare_compute_queue (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), NULL, + "VKDevice prepare compute queue failed."); + + return device; +} + +XCamReturn +VKDevice::prepare_compute_queue () +{ + uint32_t compute_idx = _instance->get_compute_queue_family_idx (); + vkGetDeviceQueue (_dev_id, compute_idx, 0, &_compute_queue); + return XCAM_RETURN_NO_ERROR; +} + +SmartPtr<VKShader> +VKDevice::create_shader (const char *file_name) +{ + FileHandle file (file_name, "rb"); + XCAM_FAIL_RETURN ( + ERROR, file.is_valid (), NULL, + "VKDevice load shader failed when opend shader file:%s.", + XCAM_STR (file_name)); + + size_t file_size; + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (file.get_file_size (file_size)) || file_size == 0, NULL, + "VKDevice load shader failed when read shader file:%s.", + XCAM_STR (file_name)); + std::vector<uint32_t> content (XCAM_ALIGN_UP (file_size, 4) / 4, 0); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (file.read_file ((void *)content.data (), file_size)), NULL, + "VKDevice load shader failed when read shader file:%s.", + XCAM_STR (file_name)); + file.close (); + + SmartPtr<VKShader> shader = create_shader (content); + if (shader.ptr ()) + shader->set_name (file_name); + return shader; +} + +SmartPtr<VKShader> +VKDevice::create_shader (const std::vector<uint32_t> &binary) +{ + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (_dev_id), NULL, + "VKDevice load shader failed with error of null device ready."); + XCAM_FAIL_RETURN ( + ERROR, binary.size () > 5, NULL, + "VKDevice load shader failed since binary is corrupt."); + + VkShaderModule shader_id; + VkShaderModuleCreateInfo module_create_info = {}; + module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + module_create_info.pNext = NULL; + module_create_info.codeSize = binary.size() * sizeof (binary[0]); + module_create_info.pCode = binary.data(); + module_create_info.flags = 0; + + XCAM_VK_CHECK_RETURN ( + ERROR, vkCreateShaderModule (_dev_id, &module_create_info, NULL, &shader_id), + NULL, "VKDevice create shader module failed."); + + XCAM_IS_VALID_VK_ID (shader_id); + return new VKShader (this, shader_id); +} + +void +VKDevice::destroy_shader_id (VkShaderModule shader) +{ + if (XCAM_IS_VALID_VK_ID(_dev_id) && XCAM_IS_VALID_VK_ID (shader)) + vkDestroyShaderModule (_dev_id, shader, _allocator.ptr()); +} + +VkDeviceMemory +VKDevice::allocate_mem_id (VkDeviceSize size, VkMemoryPropertyFlags memory_prop) +{ + VkDeviceMemory mem_id; + VkMemoryAllocateInfo mem_alloc_info = {}; + mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc_info.allocationSize = size; + mem_alloc_info.memoryTypeIndex = _instance->get_mem_type_index (memory_prop); + + XCAM_FAIL_RETURN ( + ERROR, mem_alloc_info.memoryTypeIndex != (uint32_t)(-1), VK_NULL_HANDLE, + "VKDevice create mem id failed, can NOT find memory type:0x%08x.", (uint32_t)memory_prop); + + XCAM_VK_CHECK_RETURN ( + ERROR, vkAllocateMemory (_dev_id, &mem_alloc_info, _allocator.ptr (), &mem_id), + VK_NULL_HANDLE, "create vk buffer failed in allocating memory"); + return mem_id; +} + +void +VKDevice::free_mem_id (VkDeviceMemory mem) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (mem)); + + vkFreeMemory (_dev_id, mem, _allocator.ptr ()); +} + +XCamReturn +VKDevice::map_mem (VkDeviceMemory mem, VkDeviceSize size, VkDeviceSize offset, void *&ptr) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (mem)); + XCAM_VK_CHECK_RETURN ( + ERROR, vkMapMemory (_dev_id, mem, offset, size, 0, &ptr), XCAM_RETURN_ERROR_VULKAN, + "vk device map mem failed. size:%lld", size); + return XCAM_RETURN_NO_ERROR; +} + +void +VKDevice::unmap_mem (VkDeviceMemory mem) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (mem)); + vkUnmapMemory (_dev_id, mem); +} + +VkBuffer +VKDevice::create_buf_id (VkBufferUsageFlags usage, uint32_t size) +{ + VkBufferCreateInfo buf_create_info = {}; + buf_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buf_create_info.size = size; + buf_create_info.usage = usage; + buf_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VkBuffer buf_id; + XCAM_VK_CHECK_RETURN ( + ERROR, vkCreateBuffer (_dev_id, &buf_create_info, _allocator.ptr (), &buf_id), + VK_NULL_HANDLE, "create vk buffer failed"); + + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf_id)); + return buf_id; +} + +void +VKDevice::destroy_buf_id (VkBuffer buf) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf)); + + vkDestroyBuffer (_dev_id, buf, _allocator.ptr ()); +} + +XCamReturn +VKDevice::bind_buffer (VkBuffer buf, VkDeviceMemory mem, VkDeviceSize offset) +{ + XCAM_VK_CHECK_RETURN ( + ERROR, vkBindBufferMemory (_dev_id, buf, mem, offset), + XCAM_RETURN_ERROR_VULKAN, "vkdevice bind buffer to mem failed"); + + return XCAM_RETURN_NO_ERROR; +} + +VkDescriptorPool +VKDevice::create_desc_pool (const VkDescriptorPoolCreateInfo &info) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + + VkDescriptorPool pool_id; + XCAM_VK_CHECK_RETURN ( + ERROR, + vkCreateDescriptorPool (_dev_id, &info, _allocator.ptr (), &pool_id), + VK_NULL_HANDLE, + "vkdevice create desriptor pool failed"); + return pool_id; +} + +void +VKDevice::destroy_desc_pool (VkDescriptorPool pool) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool)); + vkDestroyDescriptorPool (_dev_id, pool, _allocator.ptr ()); +} + +VkDescriptorSet +VKDevice::allocate_desc_set (const VkDescriptorSetAllocateInfo &info) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + + VkDescriptorSet set_id; + XCAM_VK_CHECK_RETURN ( + ERROR, + vkAllocateDescriptorSets (_dev_id, &info, &set_id), + VK_NULL_HANDLE, + "vkdevice create desriptor set failed"); + return set_id; + +} + +XCamReturn +VKDevice::free_desc_set (VkDescriptorSet set, VkDescriptorPool pool) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (set)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool)); + + XCAM_VK_CHECK_RETURN ( + ERROR, + vkFreeDescriptorSets (_dev_id, pool, 1, &set), + XCAM_RETURN_ERROR_VULKAN, + "vkdevice free desriptor set from pool failed"); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKDevice::update_desc_set (const std::vector<VkWriteDescriptorSet> &sets) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + vkUpdateDescriptorSets (_dev_id, sets.size (), sets.data (), 0, NULL); + + return XCAM_RETURN_NO_ERROR; +} + +VkCommandPool +VKDevice::create_cmd_pool (VkFlags queue_flag) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (_instance.ptr ()); + VkCommandPool pool_id = VK_NULL_HANDLE; + + VkCommandPoolCreateInfo create_pool_info = {}; + create_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + create_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + + if (queue_flag == VK_QUEUE_COMPUTE_BIT) + create_pool_info.queueFamilyIndex = _instance->get_compute_queue_family_idx (); + else if (queue_flag == VK_QUEUE_GRAPHICS_BIT) + create_pool_info.queueFamilyIndex = _instance->get_graphics_queue_family_idx (); + else { + XCAM_LOG_WARNING ("VKDevice create command pool failed, queue_flag(%d) not supported.", queue_flag); + return VK_NULL_HANDLE; + } + + XCAM_VK_CHECK_RETURN ( + ERROR, vkCreateCommandPool (_dev_id, &create_pool_info, _allocator.ptr (), &pool_id), + VK_NULL_HANDLE, "VKDevice create command pool failed."); + return pool_id; +} + +void +VKDevice::destroy_cmd_pool (VkCommandPool pool) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool)); + vkDestroyCommandPool (_dev_id, pool, _allocator.ptr ()); +} + +VkCommandBuffer +VKDevice::allocate_cmd_buffer (VkCommandPool pool) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool)); + + VkCommandBufferAllocateInfo allocate_info = {}; + allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocate_info.commandPool = pool; + allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocate_info.commandBufferCount = 1; + + VkCommandBuffer buf_id = VK_NULL_HANDLE; + + XCAM_VK_CHECK_RETURN ( + ERROR, vkAllocateCommandBuffers (_dev_id, &allocate_info, &buf_id), + VK_NULL_HANDLE, "VKDevice create command buffers failed."); + return buf_id; +} + +void +VKDevice::free_cmd_buffer (VkCommandPool pool, VkCommandBuffer buf) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pool)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf)); + + vkFreeCommandBuffers (_dev_id, pool, 1, &buf); +} + +SmartPtr<VKFence> +VKDevice::create_fence (VkFenceCreateFlags flags) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = flags; + + VkFence fence_id = VK_NULL_HANDLE; + XCAM_VK_CHECK_RETURN ( + ERROR, vkCreateFence (_dev_id, &fence_info, _allocator.ptr (), &fence_id), + NULL, "VKDevice create fence failed."); + return new VKFence (this, fence_id); +} + +void +VKDevice::destroy_fence (VkFence fence) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (fence)); + + vkDestroyFence (_dev_id, fence, _allocator.ptr ()); +} + +XCamReturn +VKDevice::reset_fence (VkFence fence) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (fence)); + + XCAM_VK_CHECK_RETURN ( + ERROR, vkResetFences (_dev_id, 1, &fence), + XCAM_RETURN_ERROR_VULKAN, "VKDevice reset fence failed."); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKDevice::wait_for_fence (VkFence fence, uint64_t timeout) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_dev_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (fence)); + + VkResult ret = vkWaitForFences (_dev_id, 1, &fence, VK_TRUE, timeout); + if (ret == VK_TIMEOUT) { + XCAM_LOG_DEBUG ("VKDevice wait for fence timeout"); + return XCAM_RETURN_ERROR_TIMEOUT; + } + + XCAM_FAIL_RETURN ( + ERROR, ret == VK_SUCCESS, + XCAM_RETURN_ERROR_VULKAN, "VKDevice wait for fence failed."); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKDevice::compute_queue_submit (const SmartPtr<VKCmdBuf> cmd_buf, const SmartPtr<VKFence> fence) +{ + XCAM_FAIL_RETURN ( + ERROR, cmd_buf.ptr (), + XCAM_RETURN_ERROR_PARAM, "VKDevice compute queue submit failed, cmd_buf is empty."); + + VkCommandBuffer buf_id = cmd_buf->get_cmd_buf_id (); + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &buf_id; + + VkFence fence_id = VK_NULL_HANDLE; + if (fence.ptr ()) + fence_id = fence->get_fence_id (); + XCAM_VK_CHECK_RETURN ( + ERROR, vkQueueSubmit (_compute_queue, 1, &submit_info, fence_id), + XCAM_RETURN_ERROR_VULKAN, "VKDevice compute queue submit failed."); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKDevice::compute_queue_wait_idle () +{ + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (_compute_queue), + XCAM_RETURN_ERROR_PARAM, "VKDevice compute queue wait idle failed, queue_id is null"); + + XCAM_VK_CHECK_RETURN ( + ERROR, vkQueueWaitIdle (_compute_queue), + XCAM_RETURN_ERROR_VULKAN, "VKDevice compute queue wait idle failed"); + + return XCAM_RETURN_NO_ERROR; +} + +} diff --git a/modules/vulkan/vk_device.h b/modules/vulkan/vk_device.h new file mode 100644 index 0000000..27a07a1 --- /dev/null +++ b/modules/vulkan/vk_device.h @@ -0,0 +1,120 @@ +/* + * vk_device.h - vulkan device + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_DEVICE_H +#define XCAM_VK_DEVICE_H + +#include <vulkan/vulkan_std.h> +#include <xcam_mutex.h> + +namespace XCam { + +class VKPipeline; +class VKShader; +class VKFence; +class VKCmdBuf; +class VKInstance; +class VKMemory; +class VKBuffer; + +namespace VKDescriptor { +class Pool; +class Set; +}; + +class VKDevice + : public RefObj +{ + friend class VKFence; + friend class VKShader; + friend class VKPipeline; + friend class VKCmdBuf; + friend class VKDescriptor::Pool; + friend class VKDescriptor::Set; + friend class VKMemory; + friend class VKBuffer; +public: + ~VKDevice (); + static SmartPtr<VKDevice> default_device (); + static SmartPtr<VKDevice> create_device (); + + VkDevice get_dev_id () const { + return _dev_id; + } + SmartPtr<VkAllocationCallbacks> + get_allocation_cb () const { + return _allocator; + } + + SmartPtr<VKShader> create_shader (const char *file_name); + SmartPtr<VKShader> create_shader (const std::vector<uint32_t> &binary); + //SmartPtr<VKPipeline> create_pipeline (const SmartPtr<VKShader> shader); + SmartPtr<VKFence> create_fence (VkFenceCreateFlags flags = VK_FENCE_CREATE_SIGNALED_BIT); + XCamReturn compute_queue_submit (const SmartPtr<VKCmdBuf> cmd_buf, const SmartPtr<VKFence> fence); + XCamReturn compute_queue_wait_idle (); + +protected: + void destroy_shader_id (VkShaderModule shader); + VkDeviceMemory allocate_mem_id (VkDeviceSize size, VkMemoryPropertyFlags memory_prop); + void free_mem_id (VkDeviceMemory mem); + XCamReturn map_mem (VkDeviceMemory mem, VkDeviceSize size, VkDeviceSize offset, void *&ptr); + void unmap_mem (VkDeviceMemory mem); + VkBuffer create_buf_id (VkBufferUsageFlags usage, uint32_t size); + void destroy_buf_id (VkBuffer buf); + XCamReturn bind_buffer (VkBuffer buf, VkDeviceMemory mem, VkDeviceSize offset = 0); + + VkDescriptorPool create_desc_pool (const VkDescriptorPoolCreateInfo &info); + void destroy_desc_pool (VkDescriptorPool pool); + + VkDescriptorSet allocate_desc_set (const VkDescriptorSetAllocateInfo &info); + XCamReturn free_desc_set (VkDescriptorSet set, VkDescriptorPool pool); + + XCamReturn update_desc_set (const std::vector<VkWriteDescriptorSet> &sets); + VkCommandPool create_cmd_pool (VkFlags queue_flag = VK_QUEUE_COMPUTE_BIT); + void destroy_cmd_pool (VkCommandPool pool); + + VkCommandBuffer allocate_cmd_buffer (VkCommandPool pool); + void free_cmd_buffer (VkCommandPool pool, VkCommandBuffer buf); + + void destroy_fence (VkFence fence); + XCamReturn reset_fence (VkFence fence); + XCamReturn wait_for_fence (VkFence fence, uint64_t timeout); + +protected: + explicit VKDevice (VkDevice id, const SmartPtr<VKInstance> &instance); + XCamReturn prepare_compute_queue (); + //SmartPtr<VKLayout> create_desc_set_layout (); + +private: + XCAM_DEAD_COPY (VKDevice); + +private: + static SmartPtr<VKDevice> _default_dev; + static Mutex _default_mutex; + + VkDevice _dev_id; + VkQueue _compute_queue; + SmartPtr<VkAllocationCallbacks> _allocator; + SmartPtr<VKInstance> _instance; +}; + +} + +#endif //XCAM_VK_DEVICE_H diff --git a/modules/vulkan/vk_geomap_handler.cpp b/modules/vulkan/vk_geomap_handler.cpp new file mode 100644 index 0000000..4b65a44 --- /dev/null +++ b/modules/vulkan/vk_geomap_handler.cpp @@ -0,0 +1,314 @@ +/* + * vk_geomap_handler.cpp - vulkan geometry map handler implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "vk_geomap_handler.h" +#include "vk_video_buf_allocator.h" +#include "vk_device.h" + +#define GEOMAP_SHADER_BINDING_COUNT 5 + +#define XCAM_VK_GEOMAP_ALIGN_X 4 +#define XCAM_VK_GEOMAP_ALIGN_Y 2 + +namespace XCam { + +namespace { + +DECLARE_WORK_CALLBACK (CbGeoMapShader, VKGeoMapHandler, geomap_done); + +class GeoMapArgs + : public VKWorker::VKArguments +{ +public: + explicit GeoMapArgs (const SmartPtr<ImageHandler::Parameters> ¶m) + : _param (param) + { + XCAM_ASSERT (param.ptr ()); + } + const SmartPtr<ImageHandler::Parameters> &get_param () const { + return _param; + } + +private: + SmartPtr<ImageHandler::Parameters> _param; +}; + +class VKGeoMapPushConst + : public VKConstRange::VKPushConstArg +{ +public: + VKGeoMapPushConst (const VKGeoMapHandler::PushConstsProp &prop) + : _prop (prop) + {} + + bool get_const_data (VkPushConstantRange &range, void *& ptr) { + range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + range.offset = 0; + range.size = sizeof (_prop); + ptr = &_prop; + return true; + } + +private: + VKGeoMapHandler::PushConstsProp _prop; +}; + +static const VKShaderInfo geomap_shader_info ( + "main", +std::vector<uint32_t> { +#include "shader_geomap.comp.spv" +}); + +} + +VKGeoMapHandler::PushConstsProp::PushConstsProp () + : in_img_width (0) + , in_img_height (0) + , out_img_width (0) + , out_img_height (0) + , lut_width (0) + , lut_height (0) +{ + xcam_mem_clear (lut_step); + xcam_mem_clear (lut_std_step); +} + +VKGeoMapHandler::VKGeoMapHandler (const SmartPtr<VKDevice> &dev, const char* name) + : VKHandler (dev, name) +{ +} + +bool +VKGeoMapHandler::set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height) +{ + XCAM_FAIL_RETURN ( + ERROR, data && width && height, false, + "VKGeoMapHandler(%s) set look up table failed, data ptr:%p, width:%d, height:%d", + XCAM_STR (get_name ()), data, width, height); + XCAM_ASSERT (!_lut_buf.ptr ()); + + _lut_width = width; + _lut_height = height; + + uint32_t lut_size = width * height * 2 * sizeof (float); + SmartPtr<VKBuffer> buf = VKBuffer::create_buffer ( + get_vk_device (), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, lut_size); + XCAM_ASSERT (buf.ptr ()); + + float *ptr = (float *) buf->map (lut_size, 0); + XCAM_FAIL_RETURN (ERROR, ptr, false, "VKGeoMapHandler(%s) map range failed", XCAM_STR (get_name ())); + for (uint32_t i = 0; i < height; ++i) { + float *ret = &ptr[i * width * 2]; + const PointFloat2 *line = &data[i * width]; + + for (uint32_t j = 0; j < width; ++j) { + ret[j * 2] = line[j].x; + ret[j * 2 + 1] = line[j].y; + } + } + buf->unmap (); + _lut_buf = buf; + + return true; +} + +bool +VKGeoMapHandler::init_factors () +{ + XCAM_ASSERT (_lut_width && _lut_height); + + float factor_x, factor_y; + get_factors (factor_x, factor_y); + + if (!XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) && !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f)) + return true; + + return auto_calculate_factors (_lut_width, _lut_height); +} + +#define UNIT_BYTES (sizeof (uint32_t)) + +XCamReturn +VKGeoMapHandler::configure_resource (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (param.ptr () && param->in_buf.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, _lut_buf.ptr (), XCAM_RETURN_ERROR_PARAM, + "VKGeoMapHandler(%s) configure resource failed, look up table is empty", XCAM_STR (get_name ())); + + const VideoBufferInfo &in_info = param->in_buf->get_video_info (); + XCAM_FAIL_RETURN ( + ERROR, in_info.format == V4L2_PIX_FMT_NV12, XCAM_RETURN_ERROR_PARAM, + "VKGeoMapHandler(%s) only support NV12 format, but input format is %s", + XCAM_STR (get_name ()), xcam_fourcc_to_string (in_info.format)); + + uint32_t out_width, out_height; + get_output_size (out_width, out_height); + VideoBufferInfo out_info; + out_info.init ( + in_info.format, out_width, out_height, + XCAM_ALIGN_UP (out_width, XCAM_VK_GEOMAP_ALIGN_X), + XCAM_ALIGN_UP (out_height, XCAM_VK_GEOMAP_ALIGN_Y)); + set_out_video_info (out_info); + + init_factors (); + + float factor_x, factor_y; + get_factors (factor_x, factor_y); + XCAM_FAIL_RETURN ( + ERROR, + !XCAM_DOUBLE_EQUAL_AROUND (factor_x, 0.0f) && + !XCAM_DOUBLE_EQUAL_AROUND (factor_y, 0.0f), + XCAM_RETURN_ERROR_PARAM, + "VKGeoMapHandler(%s) invalid standard factors: x:%f, y:%f", + XCAM_STR (get_name ()), factor_x, factor_y); + + _image_prop.in_img_width = in_info.aligned_width / UNIT_BYTES; + _image_prop.in_img_height = in_info.aligned_height; + _image_prop.out_img_width = out_info.aligned_width / UNIT_BYTES; + _image_prop.out_img_height = out_info.aligned_height; + _image_prop.lut_width = _lut_width; + _image_prop.lut_height = _lut_height; + _image_prop.lut_std_step[0] = 1.0f / factor_x; + _image_prop.lut_std_step[1] = 1.0f / factor_y; + + WorkSize global_size ( + XCAM_ALIGN_UP (_image_prop.out_img_width, 8) / 8, + XCAM_ALIGN_UP (_image_prop.out_img_height, 16) / 16); + + _binding_layout.clear (); + for (int i = 0; i < GEOMAP_SHADER_BINDING_COUNT; ++i) { + SmartPtr<VKDescriptor::SetLayoutBinding> binding = + new VKDescriptor::ComputeLayoutBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, i); + _binding_layout.push_back (binding); + } + + XCamReturn ret = XCAM_RETURN_NO_ERROR; + if (!_worker.ptr ()) { + _worker = new VKWorker (get_vk_device(), "CbGeoMapShader", new CbGeoMapShader (this)); + XCAM_ASSERT (_worker.ptr ()); + + _worker->set_global_size (global_size); + + VKConstRange::VKPushConstArgs push_consts; + push_consts.push_back (new VKGeoMapPushConst (_image_prop)); + ret = _worker->build (geomap_shader_info, _binding_layout, push_consts); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_VULKAN, + "VKGeoMapHandler(%s) build geomap shader failed.", XCAM_STR (get_name ())); + } + + return ret; +} + +XCamReturn +VKGeoMapHandler::start_work (const SmartPtr<ImageHandler::Parameters> ¶m) +{ + XCAM_ASSERT (_lut_buf.ptr ()); + XCAM_ASSERT (param.ptr () && param->in_buf.ptr () && param->out_buf.ptr ()); + XCAM_ASSERT (_binding_layout.size () == GEOMAP_SHADER_BINDING_COUNT); + + SmartPtr<VKVideoBuffer> in_vk = param->in_buf.dynamic_cast_ptr<VKVideoBuffer> (); + SmartPtr<VKVideoBuffer> out_vk = param->out_buf.dynamic_cast_ptr<VKVideoBuffer> (); + XCAM_FAIL_RETURN ( + ERROR, in_vk.ptr () && out_vk.ptr(), XCAM_RETURN_ERROR_VULKAN, + "VKGeoMapHandler(%s) param.in_buf or param.out_buf is not vk buffer", XCAM_STR (get_name ())); + + VKDescriptor::SetBindInfoArray bindings (_binding_layout.size ()); + bindings[0].layout = _binding_layout[0]; + bindings[0].desc = VKBufDesc (in_vk->get_vk_buf (), NV12PlaneYIdx); + bindings[1].layout = _binding_layout[1]; + bindings[1].desc = VKBufDesc (in_vk->get_vk_buf (), NV12PlaneUVIdx); + bindings[2].layout = _binding_layout[2]; + bindings[2].desc = VKBufDesc (out_vk->get_vk_buf (), NV12PlaneYIdx); + bindings[3].layout = _binding_layout[3]; + bindings[3].desc = VKBufDesc (out_vk->get_vk_buf (), NV12PlaneUVIdx); + bindings[4].layout = _binding_layout[4]; + bindings[4].desc = VKBufDesc (_lut_buf); + + float factor_x, factor_y; + get_factors (factor_x, factor_y); + _image_prop.lut_step[0] = 1.0f / factor_x; + _image_prop.lut_step[1] = 1.0f / factor_y; + _image_prop.lut_step[2] = _image_prop.lut_step[0]; + _image_prop.lut_step[3] = _image_prop.lut_step[1]; + + SmartPtr<GeoMapArgs> args = new GeoMapArgs (param); + XCAM_ASSERT (args.ptr ()); + args->set_bindings (bindings); + args->add_push_const (new VKGeoMapPushConst (_image_prop)); + + return _worker->work (args); +} + +void +VKGeoMapHandler::geomap_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error) +{ + if (!xcam_ret_is_ok (error)) { + XCAM_LOG_ERROR ("VKGeoMapHandler(%s) geometry map failed.", XCAM_STR (get_name ())); + } + + SmartPtr<VKWorker> vk_worker = worker.dynamic_cast_ptr<VKWorker> (); + XCAM_ASSERT (vk_worker.ptr ()); + vk_worker->wait_fence (); + + SmartPtr<GeoMapArgs> args = base.dynamic_cast_ptr<GeoMapArgs> (); + XCAM_ASSERT (args.ptr ()); + const SmartPtr<ImageHandler::Parameters> param = args->get_param (); + XCAM_ASSERT (param.ptr ()); + + execute_done (param, error); +} + +XCamReturn +VKGeoMapHandler::remap (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf) +{ + SmartPtr<ImageHandler::Parameters> param = new ImageHandler::Parameters (in_buf, out_buf); + XCAM_ASSERT (param.ptr ()); + + XCamReturn ret = execute_buffer (param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "VKGeoMapHandler(%s) remap failed", XCAM_STR (get_name ())); + + if (!out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +SmartPtr<VKHandler> create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name) +{ + SmartPtr<VKHandler> mapper = new VKGeoMapHandler (dev, name); + XCAM_ASSERT (mapper.ptr ()); + + return mapper; +} + +SmartPtr<GeoMapper> +GeoMapper::create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name) +{ + SmartPtr<VKHandler> handler = XCam::create_vk_geo_mapper (dev, name); + return handler.dynamic_cast_ptr<GeoMapper> (); +} + +}; diff --git a/modules/vulkan/vk_geomap_handler.h b/modules/vulkan/vk_geomap_handler.h new file mode 100644 index 0000000..bf8d4d3 --- /dev/null +++ b/modules/vulkan/vk_geomap_handler.h @@ -0,0 +1,78 @@ +/* + * vk_geomap_handler.h - vulkan geometry map handler class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_VK_GEOMAP_HANDLER_H +#define XCAM_VK_GEOMAP_HANDLER_H + +#include <xcam_utils.h> +#include <interface/geo_mapper.h> +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_worker.h> +#include <vulkan/vk_handler.h> + +namespace XCam { + +class VKGeoMapHandler + : public VKHandler, public GeoMapper +{ +public: + struct PushConstsProp { + uint in_img_width; + uint in_img_height; + uint out_img_width; + uint out_img_height; + uint lut_width; + uint lut_height; + float lut_step[4]; + float lut_std_step[2]; + + PushConstsProp (); + }; + +public: + explicit VKGeoMapHandler (const SmartPtr<VKDevice> &dev, const char* name = "vk-geomap-handler"); + + bool set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height); + + XCamReturn remap (const SmartPtr<VideoBuffer> &in_buf, SmartPtr<VideoBuffer> &out_buf); + void geomap_done ( + const SmartPtr<Worker> &worker, const SmartPtr<Worker::Arguments> &base, const XCamReturn error); + +private: + virtual XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + virtual XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + virtual bool init_factors (); + +private: + SmartPtr<VKWorker> _worker; + PushConstsProp _image_prop; + VKDescriptor::BindingArray _binding_layout; + + SmartPtr<VKBuffer> _lut_buf; + uint32_t _lut_width; + uint32_t _lut_height; +}; + +extern SmartPtr<VKHandler> create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name); + +} +#endif // XCAM_VK_GEOMAP_HANDLER_H diff --git a/modules/vulkan/vk_handler.cpp b/modules/vulkan/vk_handler.cpp new file mode 100644 index 0000000..6aa1a83 --- /dev/null +++ b/modules/vulkan/vk_handler.cpp @@ -0,0 +1,60 @@ +/* + * vk_handler.cpp - vulkan image handler class + * + * Copyright (c) 2017 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_handler.h" +#include "vk_device.h" +#include "vk_video_buf_allocator.h" + +namespace XCam { + +VKHandler::VKHandler (const SmartPtr<VKDevice> &dev, const char* name) + : ImageHandler (name) + , _device (dev) +{ +} + +VKHandler::~VKHandler () +{ +} + + +XCamReturn +VKHandler::finish () +{ + if (_device.ptr ()) + _device->compute_queue_wait_idle (); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKHandler::terminate () +{ + finish (); + return ImageHandler::terminate (); +} + +SmartPtr<BufferPool> +VKHandler::create_allocator () +{ + return new VKVideoBufAllocator (_device); +} + +} diff --git a/modules/vulkan/vk_handler.h b/modules/vulkan/vk_handler.h new file mode 100644 index 0000000..3d80fa0 --- /dev/null +++ b/modules/vulkan/vk_handler.h @@ -0,0 +1,57 @@ +/* + * vk_handler.h - vulkan image handler class + * + * Copyright (c) 2017 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_HANDLER_H +#define XCAM_VK_HANDLER_H + +#include <vulkan/vulkan_std.h> +#include <image_handler.h> + +namespace XCam { + +class VKDevice; + +class VKHandler + : public ImageHandler +{ +public: + explicit VKHandler (const SmartPtr<VKDevice> &dev, const char* name = "vk-handler"); + ~VKHandler (); + const SmartPtr<VKDevice> &get_vk_device () const { + return _device; + } + + // derive from ImageHandler + virtual XCamReturn finish (); + virtual XCamReturn terminate (); + +protected: + SmartPtr<BufferPool> create_allocator (); + +private: + XCAM_DEAD_COPY (VKHandler); + +protected: + SmartPtr<VKDevice> _device; +}; + +} + +#endif //XCAM_VK_HANDLER_H diff --git a/modules/vulkan/vk_instance.cpp b/modules/vulkan/vk_instance.cpp new file mode 100644 index 0000000..81b3e6d --- /dev/null +++ b/modules/vulkan/vk_instance.cpp @@ -0,0 +1,230 @@ +/* + * vk_instance.cpp - vulkan instance + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_instance.h" +#include "vulkan_common.h" + +#define APP_NAME "xcam" +#define ENGINE_NAME "xcam" + +#define XCAM_INVALID_VK_QUEUE_IDX UINT32_MAX + +namespace XCam { + +extern void vk_init_error_string (); + +SmartPtr<VKInstance> VKInstance::_instance; +Mutex VKInstance::_instance_mutex; + +VKInstance::~VKInstance () +{ + if (XCAM_IS_VALID_VK_ID (_instance_id)) + vkDestroyInstance (_instance_id, _allocator.ptr ()); +} + +VKInstance::VKInstance (VkInstance id, VkAllocationCallbacks *allocator) + : _instance_id (id) + , _allocator (allocator) + , _physical_device (NULL) + , _compute_queue_family_idx (XCAM_INVALID_VK_QUEUE_IDX) + , _graphics_queue_family_idx (XCAM_INVALID_VK_QUEUE_IDX) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id)); + xcam_mem_clear (_device_properties); + xcam_mem_clear (_dev_mem_properties); +} + +SmartPtr<VKInstance> +VKInstance::get_instance () +{ + SmartLock locker (_instance_mutex); + if (!_instance.ptr ()) { + vk_init_error_string (); + _instance = create_instance (); + } + return _instance; +} + +SmartPtr<VKInstance> +VKInstance::create_instance () +{ + VkApplicationInfo app_info = {}; + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app_info.pApplicationName = APP_NAME; + app_info.applicationVersion = 0; + app_info.pEngineName = ENGINE_NAME; + app_info.engineVersion = xcam_version (); + app_info.apiVersion = VK_API_VERSION_1_0; + + VkInstance id; + VkInstanceCreateInfo inst_create_info = {}; + inst_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + inst_create_info.pApplicationInfo = &app_info; + inst_create_info.enabledExtensionCount = 0; // TODO, add extensions + XCAM_VK_CHECK_RETURN( + ERROR, vkCreateInstance (&inst_create_info, NULL, &id), + NULL, "create vk instance failed"); + + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id)); + SmartPtr<VKInstance> vk_instance = new VKInstance (id, NULL); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (vk_instance->query_physical_info ()), NULL, + "vk instance query physical info failed"); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (vk_instance->query_queue_info ()), NULL, + "vk instance query queue info failed"); + + return vk_instance; +} + +static const char *s_device_types[] = { + "OTHER_DEVICE", + "INTEGRATED_GPU", + "DISCRETE_GPU", + "VIRTUAL_GPU", + "CPU_TYPE", +}; + +static const char* +device_type_to_str(VkPhysicalDeviceType type) +{ + size_t number = sizeof (s_device_types) / sizeof (s_device_types[0]); + assert (number == 5); + if ((size_t)type < number) + return s_device_types [type]; + return "UNKNOWN_TYPE"; +} + +XCamReturn +VKInstance::query_physical_info () +{ +#define MAX_DEV_NUM 256 + VkPhysicalDevice devs[MAX_DEV_NUM]; + uint32_t dev_num = 0; + XCAM_VK_CHECK_RETURN ( + ERROR, vkEnumeratePhysicalDevices (_instance_id, &dev_num, NULL), + XCAM_RETURN_ERROR_VULKAN, "enum vk physical devices failed"); + XCAM_FAIL_RETURN ( + ERROR, dev_num, XCAM_RETURN_ERROR_VULKAN, + "There is NO vk physical devices"); + + dev_num = XCAM_MIN (dev_num, MAX_DEV_NUM); + vkEnumeratePhysicalDevices (_instance_id, &dev_num, devs); + + VkPhysicalDevice gpu_dev[VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE] = {}; + + VkPhysicalDeviceProperties dev_prop; + for (uint32_t i = 0; i < dev_num; ++i) { + vkGetPhysicalDeviceProperties (devs[i], &dev_prop); + + if (dev_prop.deviceType < VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE || + dev_prop.deviceType > VK_PHYSICAL_DEVICE_TYPE_END_RANGE) { + continue; + } + if (gpu_dev[dev_prop.deviceType]) { + XCAM_LOG_WARNING ( + "double vk physical dev, type:%d, name:%s", + dev_prop.deviceType, dev_prop.deviceName); + continue; + } + gpu_dev[dev_prop.deviceType] = devs[i]; +#if 0 + printf ("found vk physical dev_id:%d, name:%s, type:%d, API:%d\n", + dev_prop.deviceID, dev_prop.deviceName, + device_type_to_str (dev_prop.deviceType), dev_prop.apiVersion); +#endif + } + + if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU]) + _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU]; + else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU]) + _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU]; + else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU]) + _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU]; + else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_CPU]) { + _physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_CPU]; + XCAM_LOG_WARNING ("vk device select physical CPU, performance may slow down"); + } else { + XCAM_LOG_ERROR ("did NOT find available vk physical device"); + return XCAM_RETURN_ERROR_VULKAN; + } + + vkGetPhysicalDeviceProperties (_physical_device, &dev_prop); + XCAM_LOG_INFO ("choose vk physical dev properties dev_id:%d, name:%s, type:%s, API:%d\n", + dev_prop.deviceID, dev_prop.deviceName, + device_type_to_str (dev_prop.deviceType), dev_prop.apiVersion); + _device_properties = dev_prop; + vkGetPhysicalDeviceMemoryProperties (_physical_device, &_dev_mem_properties); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKInstance::query_queue_info () +{ + XCAM_ASSERT (_physical_device); + // get queue family porperties + uint32_t queue_count = 0; +#define MAX_QUEUE_FAMILY_NUM 256 + VkQueueFamilyProperties queue_family[MAX_QUEUE_FAMILY_NUM]; + + vkGetPhysicalDeviceQueueFamilyProperties ( + _physical_device, &queue_count, NULL); + XCAM_FAIL_RETURN ( + ERROR, queue_count, XCAM_RETURN_ERROR_VULKAN, + "There is NO vk physical devices"); + + if (queue_count > MAX_QUEUE_FAMILY_NUM) + queue_count = MAX_QUEUE_FAMILY_NUM; + + vkGetPhysicalDeviceQueueFamilyProperties ( + _physical_device, &queue_count, queue_family); + + for (uint32_t i = 0; i < queue_count; ++i) { + if (queue_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) { + _compute_queue_family_idx = i; + } + if (queue_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + _graphics_queue_family_idx = i; + } + } + + XCAM_FAIL_RETURN ( + ERROR, + _compute_queue_family_idx != XCAM_INVALID_VK_QUEUE_IDX && + _graphics_queue_family_idx != XCAM_INVALID_VK_QUEUE_IDX, + XCAM_RETURN_ERROR_VULKAN, + "There is NO vk compute/graphics queue family"); + + return XCAM_RETURN_NO_ERROR; +} + +uint32_t +VKInstance::get_mem_type_index (VkMemoryPropertyFlags prop) const +{ + for (uint32_t i = 0; i < _dev_mem_properties.memoryTypeCount; ++i) { + if (((uint32_t)(_dev_mem_properties.memoryTypes[i].propertyFlags) & prop) == prop) + return i; + } + return (uint32_t)(-1); +} + +} diff --git a/modules/vulkan/vk_instance.h b/modules/vulkan/vk_instance.h new file mode 100644 index 0000000..b4b51d4 --- /dev/null +++ b/modules/vulkan/vk_instance.h @@ -0,0 +1,77 @@ +/* + * vk_instance.h - vulkan instance + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_INSTANCE_H +#define XCAM_VK_INSTANCE_H + +#include <vulkan/vulkan_std.h> +#include <xcam_mutex.h> + +namespace XCam { + +class VKInstance +{ +public: + ~VKInstance (); + static SmartPtr<VKInstance> get_instance (); + + VkInstance get_id () const { + return _instance_id; + } + VkPhysicalDevice get_physical_dev () const { + return _physical_device; + } + uint32_t get_compute_queue_family_idx () const { + return _compute_queue_family_idx; + } + uint32_t get_graphics_queue_family_idx () const { + return _graphics_queue_family_idx; + } + uint32_t get_mem_type_index (VkMemoryPropertyFlags prop) const; + + SmartPtr<VkAllocationCallbacks> get_allocator () const { + return _allocator; + } + +private: + explicit VKInstance (VkInstance id, VkAllocationCallbacks *allocator); + static SmartPtr<VKInstance> create_instance (); + XCamReturn query_physical_info (); + XCamReturn query_queue_info (); + +private: + XCAM_DEAD_COPY (VKInstance); + +private: + static SmartPtr<VKInstance> _instance; + static Mutex _instance_mutex; + + VkInstance _instance_id; + SmartPtr<VkAllocationCallbacks> _allocator; + VkPhysicalDevice _physical_device; + VkPhysicalDeviceProperties _device_properties; + VkPhysicalDeviceMemoryProperties _dev_mem_properties; + uint32_t _compute_queue_family_idx; + uint32_t _graphics_queue_family_idx; +}; + +} + +#endif //XCAM_VK_INSTANCE_H diff --git a/modules/vulkan/vk_memory.cpp b/modules/vulkan/vk_memory.cpp new file mode 100644 index 0000000..09af690 --- /dev/null +++ b/modules/vulkan/vk_memory.cpp @@ -0,0 +1,182 @@ +/* + * vk_memory.cpp - Vulkan memory + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_memory.h" +#include "vk_device.h" + +namespace XCam { + +VKBufInfo::VKBufInfo () + : format (V4L2_PIX_FMT_NV12) + , width (0) + , height (0) + , aligned_width (0) + , aligned_height (0) + , size (0) +{ + xcam_mem_clear (strides); + xcam_mem_clear (offsets); + xcam_mem_clear (slice_size); +} + +VKMemory::VKMemory ( + const SmartPtr<VKDevice> dev, + VkDeviceMemory id, + uint32_t size, + VkMemoryPropertyFlags mem_prop) + : _dev (dev) + , _mem_id (id) + , _mem_prop (mem_prop) + , _size (size) + , _mapped_ptr (NULL) +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id)); +} + +VKMemory::~VKMemory () +{ + if (XCAM_IS_VALID_VK_ID (_mem_id) && _dev.ptr ()) { + _dev->free_mem_id (_mem_id); + } +} + +void * +VKMemory::map (VkDeviceSize size, VkDeviceSize offset) +{ + if (_mapped_ptr) + return _mapped_ptr; + + XCAM_FAIL_RETURN ( + ERROR, + xcam_ret_is_ok (_dev->map_mem (_mem_id, size, offset, _mapped_ptr)), NULL, + "VK memory map failed"); + + return _mapped_ptr; +} + +void +VKMemory::unmap () +{ + if (_mapped_ptr) { + _dev->unmap_mem (_mem_id); + _mapped_ptr = NULL; + } +} + +VKBuffer::VKBuffer ( + const SmartPtr<VKDevice> dev, + VkBuffer buf_id, + VkDeviceMemory mem_id, + uint32_t size, + VkBufferUsageFlags usage, + VkMemoryPropertyFlags prop) + : VKMemory (dev, mem_id, size, prop) + , _buffer_id (buf_id) + , _usage_flags (usage) + , _prop_flags (prop) +{ +} + +VKBuffer::~VKBuffer () +{ + if (XCAM_IS_VALID_VK_ID (_buffer_id) && _dev.ptr ()) { + _dev->destroy_buf_id (_buffer_id); + } +} + +XCamReturn +VKBuffer::bind () +{ + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_buffer_id)); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_mem_id)); + + return _dev->bind_buffer (_buffer_id, _mem_id, 0); +} + +SmartPtr<VKBuffer> +VKBuffer::create_buffer ( + const SmartPtr<VKDevice> dev, + VkBufferUsageFlags usage, + uint32_t size, void *data, + VkMemoryPropertyFlags mem_prop) +{ + XCAM_FAIL_RETURN ( + ERROR, dev.ptr () && size, NULL, + "vk create buffer failed because of dev or size errors"); + + VkBuffer buf_id = dev->create_buf_id (usage, size); + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (buf_id), NULL, + "vk create buffer failed"); + + VkDevice dev_id = dev->get_dev_id (); + VkMemoryRequirements mem_reqs; + vkGetBufferMemoryRequirements (dev_id, buf_id, &mem_reqs); + VkDeviceMemory mem_id = dev->allocate_mem_id (mem_reqs.size, mem_prop); + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (mem_id), NULL, + "vk create buffer failed in mem allocation"); + + // size == mem_reqs.size or size? + SmartPtr<VKBuffer> buf = new VKBuffer (dev, buf_id, mem_id, size, usage, mem_prop); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (buf->bind ()), NULL, + "vk create bufer failed when bind with memory"); + if (!data) + return buf; + + void *ptr = buf->map (); + XCAM_FAIL_RETURN ( + ERROR, ptr, NULL, + "vk create bufer failed when map the buf"); + memcpy (ptr, data, size); + buf->unmap (); + + return buf; + +} + +VKBufDesc::VKBufDesc () +{ + xcam_mem_clear (desc_info); +} + +VKBufDesc::VKBufDesc (const SmartPtr<VKBuffer> &buffer, NV12PlaneIdx plane) + : buf (buffer) +{ + xcam_mem_clear (desc_info); + const VKBufInfo info = buffer->get_buf_info (); + + desc_info.buffer = buffer->get_buf_id (); + desc_info.offset = info.offsets[plane]; + desc_info.range = info.slice_size[plane]; +} + +VKBufDesc::VKBufDesc (const SmartPtr<VKBuffer> &buffer, uint32_t offset, size_t size) + : buf (buffer) +{ + xcam_mem_clear (desc_info); + desc_info.buffer = buffer->get_buf_id (); + desc_info.offset = offset; + desc_info.range = size; +} + +} diff --git a/modules/vulkan/vk_memory.h b/modules/vulkan/vk_memory.h new file mode 100644 index 0000000..3eba942 --- /dev/null +++ b/modules/vulkan/vk_memory.h @@ -0,0 +1,134 @@ +/* + * vk_memory.h - Vulkan memory + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_MEMORY_H +#define XCAM_VK_MEMORY_H + +#include <vulkan/vulkan_std.h> + +#define XCAM_VK_MAX_COMPONENTS 4 + +namespace XCam { + +struct VKBufInfo { + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t aligned_width; + uint32_t aligned_height; + uint32_t size; + uint32_t strides[XCAM_VK_MAX_COMPONENTS]; + uint32_t offsets[XCAM_VK_MAX_COMPONENTS]; + uint32_t slice_size[XCAM_VK_MAX_COMPONENTS]; + + VKBufInfo (); + bool operator == (const VKBufInfo &info) const; +}; + +class VKDevice; + +class VKMemory +{ +public: + virtual ~VKMemory (); + void *map (VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0); + void unmap (); + +protected: + explicit VKMemory ( + const SmartPtr<VKDevice> dev, VkDeviceMemory id, + uint32_t size, VkMemoryPropertyFlags mem_prop); + VkDeviceMemory get_mem_id () const { + return _mem_id; + } + +private: + XCAM_DEAD_COPY (VKMemory); + +protected: + const SmartPtr<VKDevice> _dev; + VkDeviceMemory _mem_id; + VkMemoryPropertyFlags _mem_prop; + uint32_t _size; + void *_mapped_ptr; +}; + +class VKBuffer + : public VKMemory +{ +public: + ~VKBuffer (); + + // usage can be VK_BUFFER_USAGE_STORAGE_BUFFER_BIT or VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + static SmartPtr<VKBuffer> + create_buffer ( + const SmartPtr<VKDevice> dev, + VkBufferUsageFlags usage, + uint32_t size, void *data = NULL, + VkMemoryPropertyFlags mem_prop = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + VkBuffer get_buf_id () const { + return _buffer_id; + } + VkBufferUsageFlags get_usage_flags () const { + return _usage_flags; + } + VkMemoryPropertyFlags get_mem_flags () const { + return _prop_flags; + } + + void set_buf_info (const VKBufInfo &info) { + _buf_info = info; + } + const VKBufInfo &get_buf_info () const { + return _buf_info; + } + +private: + explicit VKBuffer ( + const SmartPtr<VKDevice> dev, VkBuffer buf_id, + VkDeviceMemory mem_id, uint32_t size, + VkBufferUsageFlags usage, VkMemoryPropertyFlags prop); + XCamReturn bind (); + +private: + XCAM_DEAD_COPY (VKBuffer); + +private: + VkBuffer _buffer_id; + VkBufferUsageFlags _usage_flags; + VkMemoryPropertyFlags _prop_flags; + VKBufInfo _buf_info; +}; + +struct VKBufDesc { + SmartPtr<VKBuffer> buf; + VkDescriptorBufferInfo desc_info; + + VKBufDesc (); + VKBufDesc (const SmartPtr<VKBuffer> &buffer, NV12PlaneIdx plane); + VKBufDesc (const SmartPtr<VKBuffer> &buffer, uint32_t offset = 0, size_t size = VK_WHOLE_SIZE); +}; + +typedef std::vector<SmartPtr<VKBuffer>> VKBufferArray; + +} + +#endif //XCAM_VK_MEMORY_H diff --git a/modules/vulkan/vk_pipeline.cpp b/modules/vulkan/vk_pipeline.cpp new file mode 100644 index 0000000..5483582 --- /dev/null +++ b/modules/vulkan/vk_pipeline.cpp @@ -0,0 +1,293 @@ +/* + * vk_pipeline.cpp - Vulkan pipeline + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_pipeline.h" +#include "vulkan_common.h" +#include "vk_cmdbuf.h" + +namespace XCam { + +VKPipeline::VKPipeline ( + const SmartPtr<VKDevice> dev, + const ShaderVec &shaders, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKConstantArray &consts) + : _pipe_id (VK_NULL_HANDLE) + , _dev (dev) + , _shaders (shaders) + , _bindings (bindings) + , _push_consts (consts) +{ + _allocator = _dev->get_allocation_cb (); + xcam_mem_clear (_name); +} + +VKPipeline::~VKPipeline () +{ + if (!_dev.ptr ()) + return; + + VkDevice dev_id = _dev->get_dev_id (); + if (XCAM_IS_VALID_VK_ID (_pipe_id)) + vkDestroyPipeline (dev_id, _pipe_id, _allocator.ptr ()); +} + +void +VKPipeline::set_desc_pool (const SmartPtr<VKDescriptor::Pool> pool) +{ + _pool = pool; + + //TODO, check pool status and allocate set, need or not? +} + +VkDescriptorSetLayout +VKPipeline::create_desc_set_layout ( + const VKDescriptor::BindingArray &bindings) +{ + VKDescriptor::VkBindingArray array = VKDescriptor::get_vk_layoutbindings (bindings); + + VkDescriptorSetLayoutCreateInfo descriptor_layout = {}; + descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_layout.bindingCount = array.size (); + descriptor_layout.pBindings = array.data (); + + VkDescriptorSetLayout layout = NULL; + XCAM_VK_CHECK_RETURN ( + ERROR, + vkCreateDescriptorSetLayout ( + _dev->get_dev_id (), &descriptor_layout, _allocator.ptr (), &layout), + NULL, "VkPipeline create descriptor set layout failed"); + + return layout; +} + + +VkPipelineLayout +VKPipeline::create_pipeline_layout ( + VkDescriptorSetLayout desc_layout, + const VKConstRange::VKConstantArray &consts) +{ + VkPipelineLayoutCreateInfo pipe_layout_create_info = {}; + pipe_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipe_layout_create_info.flags = 0; + pipe_layout_create_info.setLayoutCount = 1; + pipe_layout_create_info.pSetLayouts = &desc_layout; + if (!consts.empty()) { + pipe_layout_create_info.pushConstantRangeCount = consts.size (); + pipe_layout_create_info.pPushConstantRanges = consts.data (); + } + + VkPipelineLayout layout = NULL; + XCAM_VK_CHECK_RETURN ( + ERROR, + vkCreatePipelineLayout ( + _dev->get_dev_id (), &pipe_layout_create_info, NULL, &layout), + NULL, "VkPipeline create descriptor set layout failed"); + + return layout; +} + +SmartPtr<VKPipeline> +VKPipeline::create_compute_pipeline ( + const SmartPtr<VKDevice> dev, + const SmartPtr<VKShader> shader, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKConstantArray &consts) +{ + XCAM_FAIL_RETURN ( + ERROR, dev.ptr () && shader.ptr (), NULL, + "VKDevice create pipeline with error of null device ready."); + + ShaderVec shaders = {shader}; + SmartPtr<VKPipeline> pipe = new VKComputePipeline (dev, shaders, bindings, consts); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (pipe->ensure_layouts ()), NULL, + "vk pipeline ensure layouts failed"); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (pipe->ensure_pipeline ()), NULL, + "vk pipeline ensure pipeline failed"); + + return pipe; +} + +VKComputePipeline::VKComputePipeline ( + const SmartPtr<VKDevice> dev, + const ShaderVec &shaders, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKConstantArray &consts) + : VKPipeline (dev, shaders, bindings, consts) + , _pipe_layout (VK_NULL_HANDLE) + , _desc_layout (VK_NULL_HANDLE) +{ +} + +VKComputePipeline::~VKComputePipeline () +{ + if (!_dev.ptr ()) + return; + + VkDevice dev_id = _dev->get_dev_id (); + if (XCAM_IS_VALID_VK_ID (_pipe_layout)) + vkDestroyPipelineLayout (dev_id, _pipe_layout, _allocator.ptr ()); + if (XCAM_IS_VALID_VK_ID (_desc_layout)) + vkDestroyDescriptorSetLayout (dev_id, _desc_layout, _allocator.ptr ()); +} + +XCamReturn +VKComputePipeline::ensure_layouts () +{ + if (!XCAM_IS_VALID_VK_ID (_desc_layout)) { + _desc_layout = create_desc_set_layout (_bindings); + } + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID(_desc_layout), XCAM_RETURN_ERROR_VULKAN, + "vk compute pipeline create desc layout failed"); + + if (!XCAM_IS_VALID_VK_ID (_pipe_layout)) { + _pipe_layout = create_pipeline_layout (_desc_layout, _push_consts); + } + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID(_pipe_layout), XCAM_RETURN_ERROR_VULKAN, + "vk compute pipeline create pipeline layout failed"); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKComputePipeline::ensure_pipeline () +{ + XCAM_FAIL_RETURN ( + ERROR, XCAM_IS_VALID_VK_ID (_desc_layout) && XCAM_IS_VALID_VK_ID (_pipe_layout), + XCAM_RETURN_ERROR_PARAM, + "vk compute ensure pipeline failed. need ensure desc_layout and pipe_layout first"); + + XCAM_FAIL_RETURN ( + ERROR, !_shaders.empty (), XCAM_RETURN_ERROR_PARAM, + "vk compute ensure pipeline failed, shader was empty"); + + VkComputePipelineCreateInfo pipeline_create_info = + get_compute_create_info (_shaders[0], _pipe_layout); + + VkPipeline pipe_id; + XCAM_VK_CHECK_RETURN ( + ERROR, vkCreateComputePipelines ( + _dev->get_dev_id (), 0, 1, &pipeline_create_info, 0, &pipe_id), + XCAM_RETURN_ERROR_VULKAN, "VK create compute pipeline failed."); + + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (pipe_id)); + _pipe_id = pipe_id; + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKComputePipeline::update_bindings (const VKDescriptor::SetBindInfoArray &bind_array) +{ + XCAM_FAIL_RETURN ( + ERROR, _pool.ptr () && XCAM_IS_VALID_VK_ID (_desc_layout), XCAM_RETURN_ERROR_PARAM, + "vk compute pipeline update bindins failed, pool was not set or desc_layout not ensured"); + + if (_desc_set.ptr ()) + _desc_set.release (); + + _desc_set = _pool->allocate_set (bind_array, _desc_layout); + XCAM_FAIL_RETURN ( + ERROR, _desc_set.ptr (), XCAM_RETURN_ERROR_UNKNOWN, + "vk compute pipeline update bindins failed to allocate desc_set or update bindings"); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKComputePipeline::bind_by (VKCmdBuf &cmd_buf) +{ + + VkCommandBuffer buf_id = cmd_buf.get_cmd_buf_id (); + VkPipeline pipe_id = get_pipeline_id (); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (buf_id)); + XCAM_FAIL_RETURN ( + ERROR, + XCAM_IS_VALID_VK_ID (pipe_id) && XCAM_IS_VALID_VK_ID (_pipe_layout) && _desc_set.ptr (), + XCAM_RETURN_ERROR_PARAM, + "vk compute pipeline bind command buffer failed, please check pipe_id, pipe_layout and desc_layout."); + + // // bind pipeline sets + vkCmdBindPipeline (buf_id, VK_PIPELINE_BIND_POINT_COMPUTE, pipe_id); + + // bind descriptor sets + VkDescriptorSet desc_set_id = _desc_set->get_set_id (); + vkCmdBindDescriptorSets ( + buf_id, VK_PIPELINE_BIND_POINT_COMPUTE, _pipe_layout, + 0, 1, &desc_set_id, 0, NULL); + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKComputePipeline::push_consts_by ( + VKCmdBuf &cmd_buf, const SmartPtr<VKConstRange::VKPushConstArg> &push_const) +{ + VkCommandBuffer cmd_buf_id = cmd_buf.get_cmd_buf_id (); + XCAM_FAIL_RETURN ( + ERROR, + XCAM_IS_VALID_VK_ID (cmd_buf_id) && XCAM_IS_VALID_VK_ID (_pipe_layout), + XCAM_RETURN_ERROR_PARAM, + "vk compute pipeline push_consts by cmdbuf failed, please check pipe_layout and cmd_buf_id."); + + XCAM_ASSERT (push_const.ptr ()); + VkPushConstantRange const_range; + xcam_mem_clear (const_range); + void *ptr = NULL; + push_const->get_const_data (const_range, ptr); + + XCAM_FAIL_RETURN ( + ERROR, + const_range.stageFlags == VK_SHADER_STAGE_COMPUTE_BIT, + XCAM_RETURN_ERROR_PARAM, + "vk compute pipeline push_consts by cmdbuf failed, please check pipe_layout and cmd_buf_id."); + + vkCmdPushConstants( + cmd_buf_id, _pipe_layout, VK_SHADER_STAGE_COMPUTE_BIT, const_range.offset, const_range.size, ptr); + return XCAM_RETURN_NO_ERROR; +} + +VkComputePipelineCreateInfo +VKComputePipeline::get_compute_create_info ( + const SmartPtr<VKShader> &shader, + VkPipelineLayout &layout) +{ + VkPipelineShaderStageCreateInfo shader_stage_create_info = {}; + shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stage_create_info.flags = 0; + shader_stage_create_info.stage = shader->get_shader_stage_flags (); + shader_stage_create_info.module = shader->get_shader_id (); + shader_stage_create_info.pName = shader->get_func_name (); + + VkComputePipelineCreateInfo pipeline_create_info = { }; + pipeline_create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipeline_create_info.pNext = NULL; + pipeline_create_info.flags = 0; + pipeline_create_info.stage = shader_stage_create_info; + pipeline_create_info.layout = layout; + + return pipeline_create_info; +} + +} diff --git a/modules/vulkan/vk_pipeline.h b/modules/vulkan/vk_pipeline.h new file mode 100644 index 0000000..cecb99b --- /dev/null +++ b/modules/vulkan/vk_pipeline.h @@ -0,0 +1,127 @@ +/* + * vk_pipeline.h - Vulkan pipeline + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_PIPELINE_H +#define XCAM_VK_PIPELINE_H + +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_descriptor.h> +#include <vulkan/vk_device.h> +#include <vulkan/vk_shader.h> + +namespace XCam { + +class VKPipeline +{ +public: + static SmartPtr<VKPipeline> + create_compute_pipeline ( + const SmartPtr<VKDevice> dev, + const SmartPtr<VKShader> shader, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKConstantArray &consts); + + virtual ~VKPipeline (); + + VkPipeline get_pipeline_id () const { + return _pipe_id; + } + const char *get_name () const { + return _name; + } + void set_desc_pool (const SmartPtr<VKDescriptor::Pool> pool); + //interface + virtual XCamReturn update_bindings (const VKDescriptor::SetBindInfoArray &bind_array) = 0; + + // inter-functions, called by VKCmdBuf + virtual XCamReturn bind_by (VKCmdBuf &cmd_buf) = 0; + virtual XCamReturn push_consts_by ( + VKCmdBuf &cmd_buf, const SmartPtr<VKConstRange::VKPushConstArg> &push_const) = 0; + +protected: + explicit VKPipeline ( + const SmartPtr<VKDevice> dev, + const ShaderVec &shaders, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKConstantArray &consts); + + VkDescriptorSetLayout create_desc_set_layout ( + const VKDescriptor::BindingArray &bindings); + + VkPipelineLayout create_pipeline_layout ( + VkDescriptorSetLayout desc_layout, + const VKConstRange::VKConstantArray &consts); + + // intra virtual functions + virtual XCamReturn ensure_layouts () = 0; + virtual XCamReturn ensure_pipeline () = 0; + +private: + XCAM_DEAD_COPY (VKPipeline); + +protected: + VkPipeline _pipe_id; + char _name [XCAM_VK_NAME_LENGTH]; + + SmartPtr<VKDevice> _dev; + SmartPtr<VkAllocationCallbacks> _allocator; + ShaderVec _shaders; + VKDescriptor::BindingArray _bindings; + VKConstRange::VKConstantArray _push_consts; + SmartPtr<VKDescriptor::Pool> _pool; +}; + +class VKComputePipeline + : public VKPipeline +{ + friend class VKPipeline; + +public: + static VkComputePipelineCreateInfo + get_compute_create_info (const SmartPtr<VKShader> &shader, VkPipelineLayout &layout); + + ~VKComputePipeline (); + + //inherit from VKPipeline + XCamReturn update_bindings (const VKDescriptor::SetBindInfoArray &bind_array); + +protected: + explicit VKComputePipeline ( + const SmartPtr<VKDevice> dev, + const ShaderVec &shaders, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKConstantArray &consts); + + //virtual functions from VKPipeline + XCamReturn ensure_layouts (); + XCamReturn ensure_pipeline (); + XCamReturn bind_by (VKCmdBuf &cmd_buf); + XCamReturn push_consts_by ( + VKCmdBuf &cmd_buf, const SmartPtr<VKConstRange::VKPushConstArg> &push_const); + +private: + VkPipelineLayout _pipe_layout; + VkDescriptorSetLayout _desc_layout; + SmartPtr<VKDescriptor::Set> _desc_set; +}; + +} + +#endif //XCAM_VK_PIPELINE_H diff --git a/modules/vulkan/vk_shader.cpp b/modules/vulkan/vk_shader.cpp new file mode 100644 index 0000000..96e0427 --- /dev/null +++ b/modules/vulkan/vk_shader.cpp @@ -0,0 +1,60 @@ +/* + * vk_shader.cpp - vulkan shader module + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_shader.h" +#include "vk_device.h" +#include "file_handle.h" + +namespace XCam { + +VKShader::VKShader (SmartPtr<VKDevice> dev, VkShaderModule id, const char *name) + : _device (dev) + , _shader_id (id) + , _shader_stage (VK_SHADER_STAGE_COMPUTE_BIT) +{ + XCAM_IS_VALID_VK_ID (id); + xcam_mem_clear (_name); + if (name) + strncpy (_name, name, XCAM_VK_NAME_LENGTH - 1); + strncpy (_func_name, "main", XCAM_VK_NAME_LENGTH - 1); +} + +VKShader::~VKShader () +{ + if (XCAM_IS_VALID_VK_ID (_shader_id)) + _device->destroy_shader_id (_shader_id); +} + +void +VKShader::set_func_name (const char *name) +{ + XCAM_ASSERT (name); + strncpy (_func_name, name, XCAM_VK_NAME_LENGTH - 1); +} + +void +VKShader::set_name (const char *name) +{ + XCAM_ASSERT (name); + strncpy (_name, name, XCAM_VK_NAME_LENGTH - 1); +} + + +} diff --git a/modules/vulkan/vk_shader.h b/modules/vulkan/vk_shader.h new file mode 100644 index 0000000..fd243bb --- /dev/null +++ b/modules/vulkan/vk_shader.h @@ -0,0 +1,71 @@ +/* + * vk_shader.h - Vulkan shader module + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_SHADER_H +#define XCAM_VK_SHADER_H + +#include <vulkan/vulkan_std.h> + +namespace XCam { + +class VKDevice; + +class VKShader +{ + friend class VKDevice; +public: + ~VKShader (); + + VkShaderModule get_shader_id () const { + return _shader_id; + } + VkShaderStageFlagBits get_shader_stage_flags () const { + return _shader_stage; + } + void set_func_name (const char *name); + void set_name (const char *name); + const char *get_func_name () const { + return _func_name; + } + const char *get_name () const { + return _name; + } + +private: + explicit VKShader (SmartPtr<VKDevice> dev, VkShaderModule id, const char *name = "null"); + +private: + XCAM_DEAD_COPY (VKShader); + +private: + //static ShaderTable _shader_cache; + //static Mutex _cache_mutex; + SmartPtr<VKDevice> _device; + VkShaderModule _shader_id; + VkShaderStageFlagBits _shader_stage; + char _func_name [XCAM_VK_NAME_LENGTH]; + char _name [XCAM_VK_NAME_LENGTH]; +}; + +typedef std::vector<SmartPtr<VKShader>> ShaderVec; + +} + +#endif //XCAM_VK_SHADER_H diff --git a/modules/vulkan/vk_stitcher.cpp b/modules/vulkan/vk_stitcher.cpp new file mode 100644 index 0000000..f074e48 --- /dev/null +++ b/modules/vulkan/vk_stitcher.cpp @@ -0,0 +1,824 @@ +/* + * vk_stitcher.cpp - Vulkan stitcher implementation + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "surview_fisheye_dewarp.h" +#include "vk_video_buf_allocator.h" +#include "vk_geomap_handler.h" +#include "vk_blender.h" +#include "vk_copy_handler.h" +#include "vk_stitcher.h" +#include "interface/feature_match.h" + +#define DUMP_BUFFER 0 + +#define GEOMAP_POOL_SIZE 1 + +#define VK_STITCHER_ALIGNMENT_X 16 +#define VK_STITCHER_ALIGNMENT_Y 4 + +#define MAP_FACTOR_X 16 +#define MAP_FACTOR_Y 16 + +#define CHECK_RET(ret, format, ...) \ + if (!xcam_ret_is_ok (ret)) { \ + XCAM_LOG_ERROR (format, ## __VA_ARGS__); \ + } + +namespace XCam { + +#if DUMP_BUFFER +static void +dump_buf (const SmartPtr<VideoBuffer> &buf, uint32_t idx, const char *prefix) +{ + XCAM_ASSERT (buf.ptr () && prefix); + + char name[256]; + snprintf (name, 256, "%s-%d", prefix, idx); + dump_buf_perfix_path (buf, name); +} +#endif + +namespace VKSitcherPriv { + +DECLARE_HANDLER_CALLBACK (CbGeoMap, VKStitcher, geomap_done); + +struct GeoMapParam + : ImageHandler::Parameters +{ + SmartPtr<VKStitcher::StitcherParam> stitch_param; + uint32_t idx; + + GeoMapParam (uint32_t i) + : idx (i) + {} +}; + +struct Factor { + float x, y; + + Factor () : x (1.0f), y (1.0f) {} + void reset () { + x = 1.0f; + y = 1.0f; + } +}; + +struct GeoMapFactors { + Factor left; + Factor right; +}; + +typedef std::vector<SmartPtr<VKCopyHandler>> Copiers; + +struct StitcherResource { + SmartPtr<VKBlender::Sync> blender_sync[XCAM_STITCH_MAX_CAMERAS]; + SmartPtr<BufferPool> mapper_pool[XCAM_STITCH_MAX_CAMERAS]; + + SmartPtr<GeoMapParam> mapper_param[XCAM_STITCH_MAX_CAMERAS]; + SmartPtr<VKBlender::BlenderParam> blender_param[XCAM_STITCH_MAX_CAMERAS]; + SmartPtr<ImageHandler::Parameters> copier_param[XCAM_STITCH_MAX_CAMERAS]; + + SmartPtr<VKGeoMapHandler> mapper[XCAM_STITCH_MAX_CAMERAS]; + SmartPtr<VKBlender> blender[XCAM_STITCH_MAX_CAMERAS]; + Copiers copiers; + + SmartPtr<FeatureMatch> matcher[XCAM_STITCH_MAX_CAMERAS]; + GeoMapFactors mapper_factors[XCAM_STITCH_MAX_CAMERAS]; + + StitcherResource (); +}; + +class StitcherImpl { + friend class XCam::VKStitcher; + +public: + StitcherImpl (VKStitcher *handler) + : _stitcher (handler) + {} + + XCamReturn init_resource (); + + XCamReturn start_geo_mappers (const SmartPtr<VKStitcher::StitcherParam> ¶m); + XCamReturn start_blenders (const SmartPtr<VKStitcher::StitcherParam> ¶m, uint32_t idx); + XCamReturn start_copier (const SmartPtr<VKStitcher::StitcherParam> ¶m, uint32_t idx); + XCamReturn start_feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, uint32_t idx); + + XCamReturn stop (); + +private: + SmartPtr<VKGeoMapHandler> create_geo_mapper ( + const SmartPtr<VKDevice> &dev, const Stitcher::RoundViewSlice &view_slice); + + XCamReturn init_geo_mappers (const SmartPtr<VKDevice> &dev); + XCamReturn init_blenders (const SmartPtr<VKDevice> &dev); + XCamReturn init_copiers (const SmartPtr<VKDevice> &dev); + void init_feature_matchers (); + + void calc_geomap_factors ( + uint32_t idx, const Factor &last_left_factor, const Factor &last_right_factor, + Factor &cur_left, Factor &cur_right); + bool update_geomap_factors (uint32_t idx); + XCamReturn create_geomap_pool (const SmartPtr<VKDevice> &dev, uint32_t idx); + XCamReturn set_geomap_table ( + const SmartPtr<VKGeoMapHandler> &mapper, const CameraInfo &cam_info, + const Stitcher::RoundViewSlice &view_slice, const BowlDataConfig &bowl); + XCamReturn generate_geomap_table (const SmartPtr<VKGeoMapHandler> &mapper, uint32_t idx); + + void update_blender_sync (uint32_t idx); + XCamReturn start_blender (const SmartPtr<VKStitcher::StitcherParam> ¶m, uint32_t idx); + +private: + StitcherResource _res; + VKStitcher *_stitcher; +}; + +StitcherResource::StitcherResource () +{ +} + +SmartPtr<VKGeoMapHandler> +StitcherImpl::create_geo_mapper ( + const SmartPtr<VKDevice> &dev, const Stitcher::RoundViewSlice &view_slice) +{ + XCAM_UNUSED (view_slice); + + SmartPtr<VKGeoMapHandler> mapper; + if (_stitcher->get_scale_mode () == ScaleSingleConst) { + mapper = new VKGeoMapHandler (dev, "sitcher_singleconst_remapper"); + } else { + XCAM_LOG_ERROR ( + "vk-stitcher(%s) unsupported scale mode:%d", + XCAM_STR (_stitcher->get_name ()), _stitcher->get_scale_mode ()); + } + XCAM_ASSERT (mapper.ptr ()); + + return mapper; +} + +void +StitcherImpl::update_blender_sync (uint32_t idx) +{ + uint32_t cam_num = _stitcher->get_camera_num (); + uint32_t pre_idx = (idx + cam_num - 1) % cam_num; + + _res.blender_sync[pre_idx]->increment (); + _res.blender_sync[idx]->increment (); +} + +void +StitcherImpl::calc_geomap_factors ( + uint32_t idx, const Factor &last_left_factor, const Factor &last_right_factor, + Factor &cur_left, Factor &cur_right) +{ + const Factor &fm_left_factor = _res.mapper_factors[idx].left; + const Factor &fm_right_factor = _res.mapper_factors[idx].right; + + cur_left.x = last_left_factor.x * fm_left_factor.x; + cur_left.y = last_left_factor.y * fm_left_factor.y; + cur_right.x = last_right_factor.x * fm_right_factor.x; + cur_right.y = last_right_factor.y * fm_right_factor.y; + + _res.mapper_factors[idx].left.reset (); + _res.mapper_factors[idx].right.reset (); +} + +bool +StitcherImpl::update_geomap_factors (uint32_t idx) +{ + SmartPtr<VKGeoMapHandler> &mapper = _res.mapper[idx]; + XCAM_FAIL_RETURN ( + ERROR, mapper.ptr (), false, + "vk-stitcher(%s) geomap handler is empty, idx:%d", XCAM_STR (_stitcher->get_name ()), idx); + + if (_stitcher->get_scale_mode () == ScaleSingleConst) { + Factor unify_factor, cur_left, cur_right; + + mapper->get_factors (unify_factor.x, unify_factor.y); + if (XCAM_DOUBLE_EQUAL_AROUND (unify_factor.x, 0.0f) || + XCAM_DOUBLE_EQUAL_AROUND (unify_factor.y, 0.0f)) { // not started. + return true; + } + + calc_geomap_factors (idx, unify_factor, unify_factor, cur_left, cur_right); + unify_factor.x = (cur_left.x + cur_right.x) / 2.0f; + unify_factor.y = (cur_left.y + cur_right.y) / 2.0f; + + mapper->set_factors (unify_factor.x, unify_factor.y); + } else { + XCAM_LOG_ERROR ( + "vk-stitcher(%s) unsupported scale mode:%d", + XCAM_STR (_stitcher->get_name ()), _stitcher->get_scale_mode ()); + return false; + } + + return true; +} + +XCamReturn +StitcherImpl::create_geomap_pool (const SmartPtr<VKDevice> &dev, uint32_t idx) +{ + uint32_t output_width, output_height; + _res.mapper[idx]->get_output_size (output_width, output_height); + + VideoBufferInfo out_info; + out_info.init ( + V4L2_PIX_FMT_NV12, output_width, output_height, + XCAM_ALIGN_UP (output_width, VK_STITCHER_ALIGNMENT_X), + XCAM_ALIGN_UP (output_height, VK_STITCHER_ALIGNMENT_Y)); + + SmartPtr<BufferPool> pool = create_vk_buffer_pool (dev); + XCAM_ASSERT (pool.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, pool->set_video_info (out_info) && pool->reserve (GEOMAP_POOL_SIZE), + XCAM_RETURN_ERROR_MEM, + "vk-stitcher(%s) create buffer pool failed, buffer size:%dx%d, idx:%d", + XCAM_STR (_stitcher->get_name ()), out_info.width, out_info.height, idx); + + _res.mapper_pool[idx] = pool; + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::set_geomap_table ( + const SmartPtr<VKGeoMapHandler> &mapper, const CameraInfo &cam_info, + const Stitcher::RoundViewSlice &view_slice, const BowlDataConfig &bowl) +{ + PolyFisheyeDewarp fd; + fd.set_intrinsic_param (cam_info.calibration.intrinsic); + fd.set_extrinsic_param (cam_info.calibration.extrinsic); + + uint32_t table_width, table_height; + table_width = view_slice.width / MAP_FACTOR_X; + table_height = view_slice.height / MAP_FACTOR_Y; + + SurViewFisheyeDewarp::MapTable map_table (table_width * table_height); + fd.fisheye_dewarp ( + map_table, table_width, table_height, + view_slice.width, view_slice.height, bowl); + + bool ret = mapper->set_lookup_table (map_table.data (), table_width, table_height); + XCAM_FAIL_RETURN ( + ERROR, ret, XCAM_RETURN_ERROR_UNKNOWN, + "vk-stitcher(%s) set geomap lookup table failed", XCAM_STR (_stitcher->get_name ())); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::generate_geomap_table ( + const SmartPtr<VKGeoMapHandler> &mapper, uint32_t idx) +{ + CameraInfo cam_info; + _stitcher->get_camera_info (idx, cam_info); + Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (idx); + + BowlDataConfig bowl = _stitcher->get_bowl_config (); + bowl.angle_start = view_slice.hori_angle_start; + bowl.angle_end = format_angle (view_slice.hori_angle_start + view_slice.hori_angle_range); + if (bowl.angle_end < bowl.angle_start) + bowl.angle_start -= 360.0f; + + XCAM_LOG_DEBUG ( + "vk-stitcher(%s) camera(idx:%d) info(angle start:%.2f, range:%.2f), bowl info(angle start:%.2f, end:%.2f)", + XCAM_STR (_stitcher->get_name ()), idx, + view_slice.hori_angle_start, view_slice.hori_angle_range, + bowl.angle_start, bowl.angle_end); + + XCamReturn ret = set_geomap_table (mapper, cam_info, view_slice, bowl); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) set geometry map table failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::init_geo_mappers (const SmartPtr<VKDevice> &dev) +{ + uint32_t cam_num = _stitcher->get_camera_num (); + SmartPtr<ImageHandler::Callback> cb = new CbGeoMap (_stitcher); + + for (uint32_t idx = 0; idx < cam_num; ++idx) { + Stitcher::RoundViewSlice view_slice = _stitcher->get_round_view_slice (idx); + + SmartPtr<VKGeoMapHandler> &mapper = _res.mapper[idx]; + mapper = create_geo_mapper (dev, view_slice); + mapper->set_callback (cb); + mapper->set_output_size (view_slice.width, view_slice.height); + + create_geomap_pool (dev, idx); + + SmartPtr<GeoMapParam> &mapper_param = _res.mapper_param[idx]; + mapper_param = new GeoMapParam (idx); + XCAM_ASSERT (mapper_param.ptr ()); + + mapper_param->out_buf = _res.mapper_pool[idx]->get_buffer (); + XCAM_ASSERT (mapper_param->out_buf.ptr ()); + + XCamReturn ret = generate_geomap_table (mapper, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) generate geomap table failed", XCAM_STR (_stitcher->get_name ())); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::init_blenders (const SmartPtr<VKDevice> &dev) +{ + uint32_t out_width, out_height; + _stitcher->get_output_size (out_width, out_height); + uint32_t cam_num = _stitcher->get_camera_num (); + + for (uint32_t idx = 0; idx < cam_num; ++idx) { + SmartPtr<VKBlender> &blender = _res.blender[idx]; + blender = create_vk_blender (dev).dynamic_cast_ptr<VKBlender> (); + XCAM_ASSERT (blender.ptr ()); + + const Stitcher::ImageOverlapInfo &overlap = _stitcher->get_overlap (idx); + blender->set_output_size (out_width, out_height); + blender->set_merge_window (overlap.out_area); + blender->set_input_valid_area (overlap.left, 0); + blender->set_input_valid_area (overlap.right, 1); + blender->set_input_merge_area (overlap.left, 0); + blender->set_input_merge_area (overlap.right, 1); + + SmartPtr<VKBlender::BlenderParam> &blender_param = _res.blender_param[idx]; + blender_param = new VKBlender::BlenderParam (NULL, NULL, NULL); + XCAM_ASSERT (blender_param.ptr ()); + + uint32_t next_idx = (idx + 1) % cam_num; + blender_param->in_buf = _res.mapper_param[idx]->out_buf; + blender_param->in1_buf = _res.mapper_param[next_idx]->out_buf; + XCAM_ASSERT (blender_param->in_buf.ptr () && blender_param->in1_buf.ptr ()); + + _res.blender_sync[idx] = new VKBlender::Sync (2); + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::init_copiers (const SmartPtr<VKDevice> &dev) +{ + uint32_t cam_num = _stitcher->get_camera_num (); + for (uint32_t idx = 0; idx < cam_num; ++idx) { + SmartPtr<ImageHandler::Parameters> &copier_param = _res.copier_param[idx]; + copier_param = new ImageHandler::Parameters (); + XCAM_ASSERT (copier_param.ptr ()); + + copier_param->in_buf = _res.mapper_param[idx]->out_buf; + XCAM_ASSERT (copier_param->in_buf.ptr ()); + } + + Stitcher::CopyAreaArray areas = _stitcher->get_copy_area (); + uint32_t size = areas.size (); + for (uint32_t idx = 0; idx < size; ++idx) { + XCAM_ASSERT (areas[idx].in_idx < size); + + SmartPtr<VKCopyHandler> copier = new VKCopyHandler (dev); + XCAM_ASSERT (copier.ptr ()); + copier->enable_allocator (false); + copier->set_copy_area (areas[idx].in_idx, areas[idx].in_area, areas[idx].out_area); + + _res.copiers.push_back (copier); + } + + return XCAM_RETURN_NO_ERROR; +} + +void +StitcherImpl::init_feature_matchers () +{ +#if HAVE_OPENCV + FeatureMatchMode fm_mode = _stitcher->get_fm_mode (); + if (fm_mode == FMNone) + return ; + + uint32_t cam_num = _stitcher->get_camera_num (); + for (uint32_t idx = 0; idx < cam_num; ++idx) { + SmartPtr<FeatureMatch> &matcher = _res.matcher[idx]; +#ifndef ANDROID + if (fm_mode == FMDefault) + matcher = FeatureMatch::create_default_feature_match (); + else if (fm_mode == FMCluster) + matcher = FeatureMatch::create_cluster_feature_match (); + else if (fm_mode == FMCapi) + matcher = FeatureMatch::create_capi_feature_match (); + else { + XCAM_LOG_ERROR ( + "vk-stitcher(%s) unsupported FeatureMatchMode: %d", + XCAM_STR (_stitcher->get_name ()), fm_mode); + } +#else + matcher = FeatureMatch::create_capi_feature_match (); +#endif + XCAM_ASSERT (matcher.ptr ()); + + FMConfig config; + config.sitch_min_width = 136; + config.min_corners = 4; + config.offset_factor = 0.8f; + config.delta_mean_offset = 120.0f; + config.recur_offset_error = 8.0f; + config.max_adjusted_offset = 24.0f; + config.max_valid_offset_y = 20.0f; + config.max_track_error = 28.0f; +#ifdef ANDROID + config.max_track_error = 3600.0f; +#endif + matcher->set_config (config); + matcher->set_fm_index (idx); + + const BowlDataConfig bowl = _stitcher->get_bowl_config (); + const Stitcher::ImageOverlapInfo &info = _stitcher->get_overlap (idx); + Rect left_ovlap = info.left; + Rect right_ovlap = info.right; + left_ovlap.pos_y = 0; + left_ovlap.height = int32_t (bowl.wall_height / (bowl.wall_height + bowl.ground_length) * left_ovlap.height); + right_ovlap.pos_y = 0; + right_ovlap.height = left_ovlap.height; + matcher->set_crop_rect (left_ovlap, right_ovlap); + } +#else + XCAM_LOG_ERROR ("vk-stitcher(%s) feature match is unsupported", XCAM_STR (_stitcher->get_name ())); + XCAM_ASSERT (false); +#endif +} + +XCamReturn +StitcherImpl::init_resource () +{ + const SmartPtr<VKDevice> &dev = _stitcher->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + + XCamReturn ret = init_geo_mappers (dev); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) init dewarps failed", XCAM_STR (_stitcher->get_name ())); + +#if HAVE_OPENCV + init_feature_matchers (); +#endif + + ret = init_blenders (dev); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) init blenders failed", XCAM_STR (_stitcher->get_name ())); + + ret = init_copiers (dev); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) init copiers failed", XCAM_STR (_stitcher->get_name ())); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_geo_mappers (const SmartPtr<VKStitcher::StitcherParam> ¶m) +{ + uint32_t cam_num = _stitcher->get_camera_num (); + + for (uint32_t idx = 0; idx < cam_num; ++idx) { + if (_stitcher->get_fm_mode ()) + update_geomap_factors (idx); + + SmartPtr<GeoMapParam> &mapper_param = _res.mapper_param[idx]; + mapper_param->in_buf = param->in_bufs[idx]; + mapper_param->stitch_param = param; + + XCamReturn ret = _res.mapper[idx]->execute_buffer (mapper_param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) execute geo mapper failed, idx:%d", + XCAM_STR (_stitcher->get_name ()), idx); + +#if DUMP_BUFFER + dump_buf (mapper_param->out_buf, idx, "stitcher-geomap"); +#endif + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, uint32_t idx) +{ +#if HAVE_OPENCV + _res.matcher[idx]->reset_offsets (); + _res.matcher[idx]->feature_match (left_buf, right_buf); + + Rect left_ovlap, right_ovlap; + _res.matcher[idx]->get_crop_rect (left_ovlap, right_ovlap); + float left_offsetx = _res.matcher[idx]->get_current_left_offset_x (); + + uint32_t left_idx = idx; + Factor left_factor, right_factor; + float center_x = (float) _stitcher->get_center (left_idx).slice_center_x; + float feature_center_x = (float)left_ovlap.pos_x + (left_ovlap.width / 2.0f); + float range = feature_center_x - center_x; + XCAM_ASSERT (range > 1.0f); + right_factor.x = (range + left_offsetx / 2.0f) / range; + right_factor.y = 1.0f; + XCAM_ASSERT (right_factor.x > 0.0f && right_factor.x < 2.0f); + + uint32_t right_idx = (idx + 1) % _stitcher->get_camera_num (); + center_x = (float) _stitcher->get_center (right_idx).slice_center_x; + feature_center_x = (float)right_ovlap.pos_x + (right_ovlap.width / 2.0f); + range = center_x - feature_center_x; + XCAM_ASSERT (range > 1.0f); + left_factor.x = (range + left_offsetx / 2.0f) / range; + left_factor.y = 1.0f; + XCAM_ASSERT (left_factor.x > 0.0f && left_factor.x < 2.0f); + + _res.mapper_factors[left_idx].right = right_factor; + _res.mapper_factors[right_idx].left = left_factor; + + return XCAM_RETURN_NO_ERROR; +#else + XCAM_LOG_ERROR ("vk-stitcher(%s) feature match is unsupported", XCAM_STR (_stitcher->get_name ())); + return XCAM_RETURN_ERROR_PARAM; +#endif +} + +XCamReturn +StitcherImpl::start_blender ( + const SmartPtr<VKStitcher::StitcherParam> ¶m, uint32_t idx) +{ + SmartPtr<VKBlender::Sync> &sync = _res.blender_sync[idx]; + if (!sync->is_synced ()) + return XCAM_RETURN_NO_ERROR; + sync->reset (); + + SmartPtr<VKBlender::BlenderParam> &blend_param = _res.blender_param[idx]; + blend_param->out_buf = param->out_buf; + + XCamReturn ret = _res.blender[idx]->execute_buffer (blend_param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) execute blender failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx); + +#if DUMP_BUFFER + dump_buf (param->out_buf, idx, "stitcher-blend"); +#endif + +#if HAVE_OPENCV + if (_stitcher->get_fm_mode ()) { + ret = start_feature_match (blend_param->in_buf, blend_param->in1_buf, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) start feature match failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx); + } +#endif + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_blenders (const SmartPtr<VKStitcher::StitcherParam> ¶m, uint32_t idx) +{ + uint32_t cam_num = _stitcher->get_camera_num (); + uint32_t pre_idx = (idx + cam_num - 1) % cam_num; + + XCamReturn ret = start_blender (param, pre_idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) start blender failed, idx:%d", XCAM_STR (_stitcher->get_name ()), pre_idx); + + ret = start_blender (param, idx); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) start blender failed, idx:%d", XCAM_STR (_stitcher->get_name ()), idx); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::start_copier ( + const SmartPtr<VKStitcher::StitcherParam> ¶m, uint32_t idx) +{ + uint32_t size = _stitcher->get_copy_area ().size (); + + for (uint32_t i = 0; i < size; ++i) { + if(_res.copiers[i]->get_index () != idx) + continue; + + SmartPtr<ImageHandler::Parameters> ©_param = _res.copier_param[idx]; + copy_param->out_buf = param->out_buf; + + XCamReturn ret = _res.copiers[i]->execute_buffer (copy_param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) execute copier failed, i:%d idx:%d", + XCAM_STR (_stitcher->get_name ()), i, idx); + +#if DUMP_BUFFER + dump_buf (copy_param->out_buf, i, "stitcher-copy"); +#endif + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +StitcherImpl::stop () +{ + uint32_t cam_num = _stitcher->get_camera_num (); + for (uint32_t i = 0; i < cam_num; ++i) { + if (_res.mapper[i].ptr ()) { + _res.mapper[i]->terminate (); + _res.mapper[i].release (); + } + if (_res.mapper_pool[i].ptr ()) { + _res.mapper_pool[i]->stop (); + } + + if (_res.blender[i].ptr ()) { + _res.blender[i]->terminate (); + _res.blender[i].release (); + } + } + + for (Copiers::iterator i = _res.copiers.begin (); i != _res.copiers.end (); ++i) { + SmartPtr<VKCopyHandler> &copier = *i; + if (copier.ptr ()) { + copier->terminate (); + copier.release (); + } + } + + return XCAM_RETURN_NO_ERROR; +} + +}; + +VKStitcher::VKStitcher (const SmartPtr<VKDevice> &dev, const char *name) + : VKHandler (dev, name) + , Stitcher (VK_STITCHER_ALIGNMENT_X, VK_STITCHER_ALIGNMENT_X) +{ + SmartPtr<VKSitcherPriv::StitcherImpl> impl = new VKSitcherPriv::StitcherImpl (this); + XCAM_ASSERT (impl.ptr ()); + _impl = impl; +} + +VKStitcher::~VKStitcher () +{ + _impl.release (); +} + +XCamReturn +VKStitcher::terminate () +{ + _impl->stop (); + return VKHandler::terminate (); +} + +XCamReturn +VKStitcher::stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf) +{ + XCAM_FAIL_RETURN ( + ERROR, !in_bufs.empty (), XCAM_RETURN_ERROR_PARAM, + "vk-stitcher(%s) input buffers is empty", XCAM_STR (get_name ())); + + SmartPtr<StitcherParam> param = new StitcherParam (); + XCAM_ASSERT (param.ptr ()); + + uint32_t buf_num = 0; + for (VideoBufferList::const_iterator iter = in_bufs.begin(); iter != in_bufs.end (); ++iter) { + XCAM_ASSERT ((*iter).ptr ()); + param->in_bufs[buf_num++] = *iter; + } + param->in_buf_num = buf_num; + param->out_buf = out_buf; + + XCamReturn ret = execute_buffer (param, false); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) execute buffer failed", XCAM_STR (get_name ())); + + finish (); + if (!out_buf.ptr ()) { + out_buf = param->out_buf; + } + + return ret; +} + +XCamReturn +VKStitcher::configure_resource (const SmartPtr<Parameters> ¶m) +{ + XCAM_UNUSED (param); + XCAM_ASSERT (_impl.ptr ()); + + XCamReturn ret = estimate_round_slices (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) estimate round view slices failed", XCAM_STR (get_name ())); + + ret = estimate_coarse_crops (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) estimate coarse crops failed", XCAM_STR (get_name ())); + + ret = mark_centers (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) mark centers failed", XCAM_STR (get_name ())); + + ret = estimate_overlap (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) estimake coarse overlap failed", XCAM_STR (get_name ())); + + ret = update_copy_areas (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) update copy areas failed", XCAM_STR (get_name ())); + + ret = _impl->init_resource (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk-stitcher(%s) initialize private config failed", XCAM_STR (get_name ())); + + VideoBufferInfo out_info; + uint32_t out_width, out_height; + get_output_size (out_width, out_height); + XCAM_FAIL_RETURN ( + ERROR, out_width && out_height, XCAM_RETURN_ERROR_PARAM, + "vk-stitcher(%s) output size was not set", XCAM_STR (get_name ())); + + out_info.init ( + V4L2_PIX_FMT_NV12, out_width, out_height, + XCAM_ALIGN_UP (out_width, VK_STITCHER_ALIGNMENT_X), + XCAM_ALIGN_UP (out_height, VK_STITCHER_ALIGNMENT_Y)); + set_out_video_info (out_info); + + return ret; +} + +XCamReturn +VKStitcher::start_work (const SmartPtr<Parameters> &base) +{ + XCAM_ASSERT (base.ptr ()); + + SmartPtr<StitcherParam> param = base.dynamic_cast_ptr<StitcherParam> (); + XCAM_ASSERT (param.ptr () && param->in_buf_num > 0); + + XCamReturn ret = _impl->start_geo_mappers (param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), XCAM_RETURN_ERROR_PARAM, + "vk_stitcher(%s) start geometry map failed", XCAM_STR (get_name ())); + + return ret; +} + +void +VKStitcher::geomap_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> &base, const XCamReturn error) +{ + XCAM_UNUSED (handler); + XCAM_UNUSED (error); + + SmartPtr<VKSitcherPriv::GeoMapParam> param = base.dynamic_cast_ptr<VKSitcherPriv::GeoMapParam> (); + XCAM_ASSERT (param.ptr ()); + SmartPtr<VKStitcher::StitcherParam> &stitch_param = param->stitch_param; + XCAM_ASSERT (stitch_param.ptr ()); + + _impl->update_blender_sync (param->idx); + + XCamReturn ret = _impl->start_blenders (stitch_param, param->idx); + CHECK_RET (ret, "vk-stitcher(%s) start blenders failed, idx:%d", XCAM_STR (get_name ()), param->idx); + + ret = _impl->start_copier (stitch_param, param->idx); + CHECK_RET (ret, "vk-stitcher(%s) start copier failed, idx:%d", XCAM_STR (get_name ()), param->idx); +} + +SmartPtr<Stitcher> +Stitcher::create_vk_stitcher (const SmartPtr<VKDevice> dev) +{ + return new VKStitcher (dev); +} + +} diff --git a/modules/vulkan/vk_stitcher.h b/modules/vulkan/vk_stitcher.h new file mode 100644 index 0000000..c59f013 --- /dev/null +++ b/modules/vulkan/vk_stitcher.h @@ -0,0 +1,80 @@ +/* + * vk_stitcher.h - Vulkan stitcher class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_VK_STITCHER_H +#define XCAM_VK_STITCHER_H + +#include <interface/stitcher.h> +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_handler.h> + +namespace XCam { + +namespace VKSitcherPriv { +class StitcherImpl; +class CbGeoMap; +}; + +class VKStitcher + : public VKHandler + , public Stitcher +{ + friend class VKSitcherPriv::StitcherImpl; + friend class VKSitcherPriv::CbGeoMap; + +public: + struct StitcherParam + : ImageHandler::Parameters + { + uint32_t in_buf_num; + SmartPtr<VideoBuffer> in_bufs[XCAM_STITCH_MAX_CAMERAS]; + + StitcherParam () + : Parameters (NULL, NULL) + , in_buf_num (0) + {} + }; + +public: + explicit VKStitcher (const SmartPtr<VKDevice> &dev, const char *name = "VKStitcher"); + ~VKStitcher (); + + // derived from VKHandler + virtual XCamReturn terminate (); + +protected: + // interface derive from Stitcher + XCamReturn stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf); + + // derived from VKHandler + XCamReturn configure_resource (const SmartPtr<Parameters> ¶m); + XCamReturn start_work (const SmartPtr<Parameters> ¶m); + +private: + void geomap_done ( + const SmartPtr<ImageHandler> &handler, + const SmartPtr<ImageHandler::Parameters> ¶m, const XCamReturn error); + +private: + SmartPtr<VKSitcherPriv::StitcherImpl> _impl; +}; + +} +#endif // XCAM_VK_STITCHER_H diff --git a/modules/vulkan/vk_sync.cpp b/modules/vulkan/vk_sync.cpp new file mode 100644 index 0000000..f5ea6c6 --- /dev/null +++ b/modules/vulkan/vk_sync.cpp @@ -0,0 +1,55 @@ +/* + * vk_sync.cpp - Vulkan sync + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_sync.h" +#include "vk_device.h" + +namespace XCam { + +VKFence::~VKFence () +{ + if (_dev.ptr () && XCAM_IS_VALID_VK_ID (_fence_id)) + _dev->destroy_fence (_fence_id); +} + +VKFence::VKFence (const SmartPtr<VKDevice> dev, VkFence id) + : _fence_id (id) + , _dev (dev) +{ +} + +XCamReturn +VKFence::reset () +{ + XCAM_ASSERT (_dev.ptr ()); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_fence_id)); + + return _dev->reset_fence (_fence_id); +} + +XCamReturn +VKFence::wait (uint64_t timeout) +{ + XCAM_ASSERT (_dev.ptr ()); + XCAM_ASSERT (XCAM_IS_VALID_VK_ID (_fence_id)); + return _dev->wait_for_fence (_fence_id, timeout); +} + +} diff --git a/modules/vulkan/vk_sync.h b/modules/vulkan/vk_sync.h new file mode 100644 index 0000000..e2a7d34 --- /dev/null +++ b/modules/vulkan/vk_sync.h @@ -0,0 +1,56 @@ +/* + * vk_sync.h - Vulkan sync + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_SYNC_H +#define XCAM_VK_SYNC_H + +#include <vulkan/vulkan_std.h> + +namespace XCam { + +class VKDevice; + +class VKFence +{ + friend class VKDevice; +public: + virtual ~VKFence (); + + XCamReturn reset (); + XCamReturn wait (uint64_t timeout = UINT64_MAX); + + VkFence get_fence_id () const { + return _fence_id; + } + +protected: + explicit VKFence (const SmartPtr<VKDevice> dev, VkFence id); + +private: + XCAM_DEAD_COPY (VKFence); + +protected: + VkFence _fence_id; + SmartPtr<VKDevice> _dev; +}; + +} + +#endif //XCAM_VK_SYNC_H diff --git a/modules/vulkan/vk_video_buf_allocator.cpp b/modules/vulkan/vk_video_buf_allocator.cpp new file mode 100644 index 0000000..c60476a --- /dev/null +++ b/modules/vulkan/vk_video_buf_allocator.cpp @@ -0,0 +1,164 @@ +/* + * vk_video_buf_allocator.cpp - vulkan video buffer allocator implementation + * + * Copyright (c) 2017 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_video_buf_allocator.h" +#include "vk_memory.h" +#include "vk_device.h" + +namespace XCam { + +class VKVideoData + : public BufferData +{ + friend class VKVideoBuffer; +public: + explicit VKVideoData (const SmartPtr<VKBuffer> vk_buf); + virtual ~VKVideoData (); + + //derive from BufferData + virtual uint8_t *map (); + virtual bool unmap (); + + bool is_valid (); + +private: + uint8_t *_mem_ptr; + SmartPtr<VKBuffer> _vk_buf; +}; + +VKVideoData::VKVideoData (const SmartPtr<VKBuffer> vk_buf) + : _mem_ptr (NULL) + , _vk_buf (vk_buf) +{ + XCAM_ASSERT (vk_buf.ptr ()); +} + +VKVideoData::~VKVideoData () +{ +} + +bool +VKVideoData::is_valid () +{ + return _vk_buf.ptr () && XCAM_IS_VALID_VK_ID (_vk_buf->get_buf_id ()); +} + +uint8_t * +VKVideoData::map () +{ + if (!_mem_ptr) { + _mem_ptr = (uint8_t *)_vk_buf->map (); + } + return _mem_ptr; +} + +bool +VKVideoData::unmap () +{ + if (!_mem_ptr) + return false; + + _mem_ptr = NULL; + _vk_buf->unmap (); + return true; +} + +VKVideoBufAllocator::VKVideoBufAllocator (const SmartPtr<VKDevice> dev) + : _dev (dev) +{ +} + +VKVideoBufAllocator::~VKVideoBufAllocator () +{ +} + +SmartPtr<BufferData> +VKVideoBufAllocator::allocate_data (const VideoBufferInfo &buffer_info) +{ + XCAM_FAIL_RETURN ( + ERROR, buffer_info.size, NULL, + "VKVideoBufAllocator allocate data failed. buf_size is zero"); + + SmartPtr<VKBuffer> vk_buf = + VKBuffer::create_buffer (_dev, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, buffer_info.size); + + XCAM_FAIL_RETURN ( + ERROR, vk_buf.ptr (), NULL, + "VKVideoBufAllocator create vk memory failed. buf_size :%d", buffer_info.size); + + VKBufInfo info; + info.format = buffer_info.format; + info.width = buffer_info.width; + info.height = buffer_info.height; + info.aligned_width = buffer_info.aligned_width; + info.aligned_height = buffer_info.aligned_height; + info.size = buffer_info.size; + info.strides[0] = buffer_info.strides[0]; + info.strides[1] = buffer_info.strides[1]; + info.offsets[0] = buffer_info.offsets[0]; + info.offsets[1] = buffer_info.offsets[1]; + info.slice_size[0] = buffer_info.strides[0] * buffer_info.aligned_height; + info.slice_size[1] = buffer_info.size - buffer_info.offsets[1]; + vk_buf->set_buf_info (info); + + SmartPtr<VKVideoData> data = new VKVideoData (vk_buf); + XCAM_FAIL_RETURN ( + ERROR, data.ptr () && data->is_valid (), NULL, + "VKVideoBufAllocator allocate data failed. buf_size:%d", buffer_info.size); + + return data; +} + +SmartPtr<BufferProxy> +VKVideoBufAllocator::create_buffer_from_data (SmartPtr<BufferData> &data) +{ + const VideoBufferInfo &info = get_video_info (); + + XCAM_ASSERT (data.ptr ()); + return new VKVideoBuffer (info, data); +} + +VKVideoBuffer::VKVideoBuffer (const VideoBufferInfo &info, const SmartPtr<BufferData> &data) + : BufferProxy (info, data) +{ +} + +SmartPtr<VKBuffer> +VKVideoBuffer::get_vk_buf () +{ + SmartPtr<BufferData> data = get_buffer_data (); + SmartPtr<VKVideoData> vk_data = data.dynamic_cast_ptr<VKVideoData> (); + XCAM_FAIL_RETURN ( + ERROR, vk_data.ptr () && vk_data->_vk_buf.ptr (), VK_NULL_HANDLE, + "VKVideoBuffer get buf_id failed, data is empty"); + + return vk_data->_vk_buf; +} + +SmartPtr<BufferPool> +create_vk_buffer_pool (const SmartPtr<VKDevice> &dev) +{ + XCAM_FAIL_RETURN ( + ERROR, dev.ptr () && XCAM_IS_VALID_VK_ID(dev->get_dev_id()), NULL, + "create_vk_buffer_pool failed since vk device is invalid"); + return new VKVideoBufAllocator (dev); +} + +} diff --git a/modules/vulkan/vk_video_buf_allocator.h b/modules/vulkan/vk_video_buf_allocator.h new file mode 100644 index 0000000..af56f94 --- /dev/null +++ b/modules/vulkan/vk_video_buf_allocator.h @@ -0,0 +1,58 @@ +/* + * vk_video_buf_allocator.h - vulkan video buffer allocator class + * + * Copyright (c) 2017 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_VIDEO_BUF_ALLOCATOR_H +#define XCAM_VK_VIDEO_BUF_ALLOCATOR_H + +#include <buffer_pool.h> + +namespace XCam { + +class VKDevice; +class VKBuffer; + +class VKVideoBufAllocator + : public BufferPool +{ +public: + explicit VKVideoBufAllocator (const SmartPtr<VKDevice> dev); + virtual ~VKVideoBufAllocator (); + +private: + //derive from BufferPool + virtual SmartPtr<BufferData> allocate_data (const VideoBufferInfo &buffer_info); + virtual SmartPtr<BufferProxy> create_buffer_from_data (SmartPtr<BufferData> &data); + +private: + SmartPtr<VKDevice> _dev; +}; + +class VKVideoBuffer + : public BufferProxy +{ +public: + explicit VKVideoBuffer (const VideoBufferInfo &info, const SmartPtr<BufferData> &data); + SmartPtr<VKBuffer> get_vk_buf (); +}; + +} + +#endif //XCAM_VK_VIDEO_BUF_ALLOCATOR_H + diff --git a/modules/vulkan/vk_worker.cpp b/modules/vulkan/vk_worker.cpp new file mode 100644 index 0000000..f40a81a --- /dev/null +++ b/modules/vulkan/vk_worker.cpp @@ -0,0 +1,218 @@ +/* + * vk_worker.cpp - vulkan worker class + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vk_worker.h" +#include "vk_sync.h" +#include "vk_pipeline.h" +#include "vk_cmdbuf.h" +#include "vk_device.h" +#include "vulkan_common.h" + +namespace XCam { + +XCamReturn +VKWorker::VKArguments::prepare_bindings ( + VKDescriptor::SetBindInfoArray &binding_array, + VKConstRange::VKPushConstArgs &push_consts) +{ + XCAM_ASSERT (_binding_bufs.size ()); + XCAM_FAIL_RETURN ( + ERROR, _binding_bufs.size (), XCAM_RETURN_ERROR_PARAM, + "VKArguments found bindings empty, please check settings or derive interface prepare_bindings"); + + binding_array = _binding_bufs; + push_consts = _push_consts; + return XCAM_RETURN_NO_ERROR; +} + +bool +VKWorker::VKArguments::set_bindings (const VKDescriptor::SetBindInfoArray &arr) +{ + _binding_bufs = arr; + return true; +} + +bool +VKWorker::VKArguments::add_binding (const VKDescriptor::SetBindInfo &info) +{ + _binding_bufs.push_back (info); + return true; +} + +bool +VKWorker::VKArguments::add_push_const (const SmartPtr<VKConstRange::VKPushConstArg> &push_const) +{ + _push_consts.push_back (push_const); + return true; +} + +VKWorker::VKWorker (SmartPtr<VKDevice> dev, const char *name, const SmartPtr<Callback> &cb) + : Worker (name, cb) + , _device (dev) +{ +} + +VKWorker::~VKWorker () +{ +} + +XCamReturn +VKWorker::build ( + const VKShaderInfo &info, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKPushConstArgs &consts) +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + XCAM_FAIL_RETURN ( + ERROR, _device.ptr (), XCAM_RETURN_ERROR_VULKAN, + "vk woker(%s) build failed since vk_device is null.", XCAM_STR (get_name ())); + + SmartPtr<VKShader> shader; + if (info.type == VKSahderInfoSpirVPath) { + const char *dir_env = std::getenv (XCAM_VK_SHADER_PATH); + std::string vk_dir (dir_env, (dir_env ? strlen (dir_env) : 0)); + if (vk_dir.empty () || !vk_dir.length()) + vk_dir = XCAM_DEFAULT_VK_SHADER_PATH; + std::string spirv_path = vk_dir + "/" + info.spirv_path; + shader = _device->create_shader (spirv_path.c_str ()); + } else if (info.type == VKSahderInfoSpirVBinary) { + shader = _device->create_shader (info.spirv_bin); + } + XCAM_FAIL_RETURN ( + ERROR, shader.ptr (), XCAM_RETURN_ERROR_VULKAN, + "vk woker(%s) build failed when creating shader.", XCAM_STR (get_name ())); + shader->set_func_name (info.func_name.c_str ()); + + _desc_pool = new VKDescriptor::Pool (_device); + XCAM_ASSERT (_desc_pool.ptr ()); + XCAM_FAIL_RETURN ( + ERROR, _desc_pool->add_set_bindings (bindings), XCAM_RETURN_ERROR_VULKAN, + "vk woker(%s) build failed to add bindings to desc_pool", XCAM_STR (get_name ())); + ret = _desc_pool->create (); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk woker(%s) build failed to craete bindings in desc_pool", XCAM_STR (get_name ())); + + VKConstRange::VKConstantArray const_array; + for (size_t i = 0; i < consts.size(); ++i) { + VkPushConstantRange data_const = {0, 0, 0}; + void *ptr = NULL; + consts[i]->get_const_data (data_const, ptr); + const_array.push_back (data_const); + } + _pipeline = VKPipeline::create_compute_pipeline (_device, shader, bindings, const_array); + XCAM_FAIL_RETURN ( + ERROR, _pipeline.ptr (), XCAM_RETURN_ERROR_VULKAN, + "vk woker(%s) build failed when creating pipelines.", XCAM_STR (get_name ())); + + _pipeline->set_desc_pool (_desc_pool); + + _cmdbuf = VKCmdBuf::create_command_buffer (_device); + XCAM_FAIL_RETURN ( + ERROR, _cmdbuf.ptr (), XCAM_RETURN_ERROR_VULKAN, + "vk woker(%s) build failed when creating command buffers.", XCAM_STR (get_name ())); + + _fence = _device->create_fence (VK_FENCE_CREATE_SIGNALED_BIT); + XCAM_FAIL_RETURN ( + ERROR, _fence.ptr (), XCAM_RETURN_ERROR_VULKAN, + "vk woker(%s) build failed when creating fence.", XCAM_STR (get_name ())); + return XCAM_RETURN_NO_ERROR; +} + +// derived from Worker +XCamReturn +VKWorker::work (const SmartPtr<Worker::Arguments> &args) +{ + SmartPtr<VKArguments> vk_args = args.dynamic_cast_ptr<VKArguments>(); + XCAM_FAIL_RETURN ( + ERROR, vk_args.ptr(), XCAM_RETURN_ERROR_PARAM, + "vk woker(%s) work argements error.", XCAM_STR (get_name ())); + + VKDescriptor::SetBindInfoArray binding_array; + VKConstRange::VKPushConstArgs push_consts; + XCamReturn ret = vk_args->prepare_bindings (binding_array, push_consts); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk woker(%s) prepare argements failed.", XCAM_STR (get_name ())); + + XCAM_FAIL_RETURN ( + ERROR, !binding_array.empty (), XCAM_RETURN_ERROR_PARAM, + "vk woker(%s) binding_array is empty.", XCAM_STR (get_name ())); + + ret = _pipeline->update_bindings (binding_array); + + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk woker(%s) update binding argements failed.", XCAM_STR (get_name ())); + + const WorkSize global = get_global_size (); + SmartPtr<VKCmdBuf::DispatchParam> dispatch = + new VKCmdBuf::DispatchParam (_pipeline, global.value[0], global.value[1], global.value[2]); + if (!push_consts.empty()) { + XCAM_FAIL_RETURN ( + ERROR, dispatch->update_push_consts (push_consts), XCAM_RETURN_ERROR_PARAM, + "vk woker(%s) update push-consts failed.", XCAM_STR (get_name ())); + } + + ret = _cmdbuf->record (dispatch); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk woker(%s) record cmdbuf failed.", XCAM_STR (get_name ())); + + ret = _device->compute_queue_submit (_cmdbuf, _fence); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "vk woker(%s) submit compute queue failed.", XCAM_STR (get_name ())); + + status_check (args, ret); + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKWorker::stop () +{ + if (_pipeline.ptr () && _device.ptr ()) { + if (_fence.ptr ()) { + _fence->wait (); + _fence->reset (); + } + _device->compute_queue_wait_idle (); + } + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +VKWorker::wait_fence () +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + if (_fence.ptr ()) { + ret = _fence->wait (); + if (!xcam_ret_is_ok (ret)) { + XCAM_LOG_ERROR ("vk woker(%s) wait fence failed.", XCAM_STR (get_name ())); + } + _fence->reset (); + } + + return ret; +} + +} diff --git a/modules/vulkan/vk_worker.h b/modules/vulkan/vk_worker.h new file mode 100644 index 0000000..c23bd4d --- /dev/null +++ b/modules/vulkan/vk_worker.h @@ -0,0 +1,112 @@ +/* + * vk_worker.h - vulkan worker class + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_WORKER_H +#define XCAM_VK_WORKER_H + +#include <vulkan/vulkan_std.h> +#include <vulkan/vk_descriptor.h> +#include <worker.h> +#include <string> + +namespace XCam { + +class VKPipeline; +class VKDevice; +class VKFence; +class VKCmdBuf; + +enum VKSahderInfoType { + VKSahderInfoSpirVBinary = 0, + VKSahderInfoSpirVPath = 1, +}; + +struct VKShaderInfo { + VKSahderInfoType type; + std::string func_name; + std::string spirv_path; + std::vector<uint32_t> spirv_bin; + + VKShaderInfo () {} + VKShaderInfo (const char *func, const char *path) + : type (VKSahderInfoSpirVPath) + , func_name (func) + , spirv_path (path) + {} + VKShaderInfo (const char *func, const std::vector<uint32_t> &binary) + : type (VKSahderInfoSpirVBinary) + , func_name (func) + , spirv_bin (binary) + {} +}; + +class VKWorker + : public Worker +{ +public: + class VKArguments: + public Worker::Arguments + { + friend class VKWorker; + public: + VKArguments () {} + VKArguments (VKDescriptor::SetBindInfoArray &arr) + : _binding_bufs (arr) + {} + bool set_bindings (const VKDescriptor::SetBindInfoArray &arr); + bool add_binding (const VKDescriptor::SetBindInfo &info); + bool add_push_const (const SmartPtr<VKConstRange::VKPushConstArg> &push_const); + + protected: + virtual XCamReturn prepare_bindings ( + VKDescriptor::SetBindInfoArray &binding_array, + VKConstRange::VKPushConstArgs &push_consts); + private: + VKDescriptor::SetBindInfoArray _binding_bufs; + VKConstRange::VKPushConstArgs _push_consts; + }; + +public: + explicit VKWorker (SmartPtr<VKDevice> dev, const char *name, const SmartPtr<Callback> &cb = NULL); + virtual ~VKWorker (); + + XCamReturn build ( + const VKShaderInfo &info, + const VKDescriptor::BindingArray &bindings, + const VKConstRange::VKPushConstArgs &consts); + + // derived from Worker + virtual XCamReturn work (const SmartPtr<Arguments> &args); + virtual XCamReturn stop (); + XCamReturn wait_fence (); + +private: + XCAM_DEAD_COPY (VKWorker); + +private: + SmartPtr<VKDevice> _device; + SmartPtr<VKDescriptor::Pool> _desc_pool; + SmartPtr<VKPipeline> _pipeline; + SmartPtr<VKFence> _fence; + SmartPtr<VKCmdBuf> _cmdbuf; +}; + +} +#endif //XCAM_VK_WORKER_H diff --git a/modules/vulkan/vulkan_common.cpp b/modules/vulkan/vulkan_common.cpp new file mode 100644 index 0000000..6e7ec66 --- /dev/null +++ b/modules/vulkan/vulkan_common.cpp @@ -0,0 +1,77 @@ +/* + * vulkan_common.cpp - vulkan common + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "vulkan_common.h" +#include <map> + +#define VK_STR_INSERT(ERR) \ + vk_errors.insert (VkErrorMap::value_type(VK_ ##ERR, #ERR)) + +namespace XCam { + +typedef std::map <uint32_t, const char*> VkErrorMap; + +static VkErrorMap vk_errors; + +void vk_init_error_string () +{ + if (!vk_errors.empty ()) + return; + + VK_STR_INSERT (SUCCESS); + VK_STR_INSERT (NOT_READY); + VK_STR_INSERT (TIMEOUT); + VK_STR_INSERT (EVENT_SET); + VK_STR_INSERT (EVENT_RESET); + VK_STR_INSERT (INCOMPLETE); + VK_STR_INSERT (ERROR_OUT_OF_HOST_MEMORY); + VK_STR_INSERT (ERROR_OUT_OF_DEVICE_MEMORY); + VK_STR_INSERT (ERROR_INITIALIZATION_FAILED); + VK_STR_INSERT (ERROR_DEVICE_LOST); + VK_STR_INSERT (ERROR_MEMORY_MAP_FAILED); + VK_STR_INSERT (ERROR_LAYER_NOT_PRESENT); + VK_STR_INSERT (ERROR_FEATURE_NOT_PRESENT); + VK_STR_INSERT (ERROR_INCOMPATIBLE_DRIVER); + VK_STR_INSERT (ERROR_TOO_MANY_OBJECTS); + VK_STR_INSERT (ERROR_FORMAT_NOT_SUPPORTED); + VK_STR_INSERT (ERROR_FRAGMENTED_POOL); +} + +const char* +vk_error_str(VkResult id) +{ + VkErrorMap::iterator i = vk_errors.find (id); + if (i == vk_errors.end ()) + return "VkUnKnown"; + return i->second; +} + +const std::string +xcam_default_shader_path () +{ + std::string home = "~"; + const char *env = std::getenv ("HOME"); + if (env) + home.assign (env, strlen (env)); + + return home + "/.xcam/vk"; +} + +} diff --git a/modules/vulkan/vulkan_common.h b/modules/vulkan/vulkan_common.h new file mode 100644 index 0000000..8093029 --- /dev/null +++ b/modules/vulkan/vulkan_common.h @@ -0,0 +1,33 @@ +/* + * vulkan_common.h - vulkan common + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_COMMON_H +#define XCAM_VK_COMMON_H + +#include <vulkan/vulkan_std.h> +#include <string> + +namespace XCam { + +const char* vk_error_str(VkResult id); +const std::string xcam_default_shader_path (); +} + +#endif diff --git a/modules/vulkan/vulkan_std.h b/modules/vulkan/vulkan_std.h new file mode 100644 index 0000000..952645e --- /dev/null +++ b/modules/vulkan/vulkan_std.h @@ -0,0 +1,43 @@ +/* + * vulkan_std.h - vulkan common + * + * 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: Wind Yuan <feng.yuan@intel.com> + */ + +#ifndef XCAM_VK_STD_H +#define XCAM_VK_STD_H + +#include <xcam_std.h> +#include <vulkan/vulkan.h> + +#define XCAM_VK_CHECK_RETURN(LEVEL, vk_exp, failed_value, format, ...) \ + do { \ + VkResult err = vk_exp; \ + XCAM_FAIL_RETURN (LEVEL, err == VK_SUCCESS, failed_value, \ + format ", vk_error(%d:%s)", ## __VA_ARGS__, \ + (int)err, vk_error_str(err)); \ + } while (0) + + +#define XCAM_VK_NAME_LENGTH 256 + +#define XCAM_IS_VALID_VK_ID(id) (VK_NULL_HANDLE != (id)) + +#define XCAM_VK_SHADER_PATH "XCAM_VK_SHADER_PATH" +#define XCAM_DEFAULT_VK_SHADER_PATH xcam_default_shader_path() + +#endif diff --git a/plugins/3a/Makefile.am b/plugins/3a/Makefile.am index 63c148a..4dbfcba 100644 --- a/plugins/3a/Makefile.am +++ b/plugins/3a/Makefile.am @@ -1,15 +1,5 @@ -if ENABLE_IA_AIQ -AIQ_DIR = aiq -else -AIQ_DIR = -endif - -if ENABLE_IA_AIQ if HAVE_LIBCL HYBRID_DIR = hybrid -else -HYBRID_DIR = -endif endif -SUBDIRS = $(AIQ_DIR) $(HYBRID_DIR) +SUBDIRS = aiq $(HYBRID_DIR) diff --git a/plugins/3a/aiq/Makefile.am b/plugins/3a/aiq/Makefile.am index c1ca926..b22febb 100644 --- a/plugins/3a/aiq/Makefile.am +++ b/plugins/3a/aiq/Makefile.am @@ -1,43 +1,44 @@ plugin_LTLIBRARIES = libxcam_3a_aiq.la -XCAMAIQ_CXXFLAGS = $(XCAM_CXXFLAGS) -XCAMAIQ_LIBS = \ +XCAM_AIQ_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules/isp \ + -I$(top_srcdir)/plugins/3a/aiq \ + $(NULL) + +XCAM_AIQ_LIBS = \ + $(top_builddir)/xcore/libxcam_core.la \ + $(top_builddir)/modules/isp/libxcam_isp.la \ $(NULL) if HAVE_LIBDRM -XCAMAIQ_CXXFLAGS += $(LIBDRM_CFLAGS) -XCAMAIQ_LIBS += $(LIBDRM_LIBS) +XCAM_AIQ_CXXFLAGS += $(LIBDRM_CFLAGS) +XCAM_AIQ_LIBS += $(LIBDRM_LIBS) endif if USE_LOCAL_ATOMISP -XCAMAIQ_CXXFLAGS += \ - -I$(top_srcdir)/ext/atomisp \ +XCAM_AIQ_CXXFLAGS += \ + -I$(top_srcdir)/ext/atomisp \ $(NULL) endif plugindir="$(libdir)/xcam/plugins/3a" libxcam_3a_aiq_la_SOURCES = \ - aiq_wrapper.cpp \ + aiq_wrapper.cpp \ $(NULL) libxcam_3a_aiq_la_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAMAIQ_CXXFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/modules/isp \ - -I$(top_srcdir)/plugins/3a/aiq \ + $(XCAM_AIQ_CXXFLAGS) \ $(NULL) libxcam_3a_aiq_la_LIBADD = \ - $(XCAMAIQ_LIBS) \ - $(top_builddir)/modules/isp/libxcam_isp.la \ - $(top_builddir)/xcore/libxcam_core.la \ + $(XCAM_AIQ_LIBS) \ $(NULL) libxcam_3a_aiq_la_LDFLAGS = \ - -module -avoid-version \ - $(top_builddir)/xcore/libxcam_core.la \ - $(PTHREAD_LDFLAGS) \ + -module -avoid-version \ $(NULL) libxcam_3a_aiq_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/plugins/3a/aiq/aiq_wrapper.cpp b/plugins/3a/aiq/aiq_wrapper.cpp index e6feb20..c09d9df 100644 --- a/plugins/3a/aiq/aiq_wrapper.cpp +++ b/plugins/3a/aiq/aiq_wrapper.cpp @@ -24,7 +24,7 @@ #include "x3a_statistics_queue.h" #include "aiq3a_utils.h" #include "x3a_result_factory.h" -#include "x3a_analyze_tuner.h" +#include "iq/x3a_analyze_tuner.h" #define DEFAULT_AIQ_CPF_FILE "/etc/atomisp/imx185.cpf" @@ -112,22 +112,22 @@ XCam3AAiqContext::setup_stats_pool (uint32_t bit_depth) VideoBufferInfo info; info.init (XCAM_PIX_FMT_SGRBG16, _video_width, _video_height); - _stats_pool = new X3aStatisticsQueue; - XCAM_ASSERT (_stats_pool.ptr ()); + SmartPtr<X3aStatisticsQueue> pool = new X3aStatisticsQueue; + XCAM_ASSERT (pool.ptr ()); - _stats_pool->set_bit_depth (bit_depth); + pool->set_bit_depth (bit_depth); XCAM_FAIL_RETURN ( WARNING, - _stats_pool->set_video_info (info), + pool->set_video_info (info), false, "3a stats set video info failed"); - - if (!_stats_pool->reserve (6)) { + if (!pool->reserve (6)) { XCAM_LOG_WARNING ("init_3a_stats_pool failed to reserve stats buffer."); return false; } + _stats_pool = pool; return true; } diff --git a/plugins/3a/hybrid/Makefile.am b/plugins/3a/hybrid/Makefile.am index df23f61..e09aa57 100644 --- a/plugins/3a/hybrid/Makefile.am +++ b/plugins/3a/hybrid/Makefile.am @@ -1,30 +1,31 @@ plugin_LTLIBRARIES = libxcam_3a_hybrid.la -XCAMSRC_CXXFLAGS = $(XCAM_CXXFLAGS) -XCAMSRC_LIBS = \ +XCAM_HYBRID_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/plugins/3a/hybrid \ + $(NULL) + +XCAM_HYBRID_LIBS = \ + $(top_builddir)/xcore/libxcam_core.la \ $(NULL) plugindir="$(libdir)/xcam/plugins/3a" libxcam_3a_hybrid_la_SOURCES = \ - sample.cpp \ + sample.cpp \ $(NULL) libxcam_3a_hybrid_la_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAMSRC_CXXFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/plugins/3a/hybrid \ + $(XCAM_HYBRID_CXXFLAGS) \ $(NULL) libxcam_3a_hybrid_la_LIBADD = \ - $(XCAMSRC_LIBS) \ - $(top_builddir)/xcore/libxcam_core.la \ + $(XCAM_HYBRID_LIBS) \ $(NULL) libxcam_3a_hybrid_la_LDFLAGS = \ - -module -avoid-version \ - $(top_builddir)/xcore/libxcam_core.la \ - $(PTHREAD_LDFLAGS) \ + -module -avoid-version \ $(NULL) libxcam_3a_hybrid_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/plugins/Makefile.am b/plugins/Makefile.am index e3e20f4..f46513e 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -1,13 +1,9 @@ if ENABLE_3ALIB X3ALIB_DIR = 3a -else -X3ALIB_DIR = endif if ENABLE_SMART_LIB SMARTLIB_DIR = smart -else -SMARTLIB_DIR = endif SUBDIRS = $(X3ALIB_DIR) $(SMARTLIB_DIR) diff --git a/plugins/smart/Makefile.am b/plugins/smart/Makefile.am index 49cf033..ef1348d 100644 --- a/plugins/smart/Makefile.am +++ b/plugins/smart/Makefile.am @@ -1,13 +1,11 @@ - if ENABLE_DVS if HAVE_LIBCL DVS_DIR = dvs -else -DVS_DIR = endif -else -DVS_DIR = endif -SUBDIRS = $(DVS_DIR) sample +if ENABLE_IA_AIQ +SAMPLE_DIR = sample +endif +SUBDIRS = $(DVS_DIR) $(SAMPLE_DIR)
\ No newline at end of file diff --git a/plugins/smart/dvs/Makefile.am b/plugins/smart/dvs/Makefile.am index 2675621..7b72a89 100644 --- a/plugins/smart/dvs/Makefile.am +++ b/plugins/smart/dvs/Makefile.am @@ -2,46 +2,41 @@ SUBDIRS = libdvs noinst_LTLIBRARIES = libxcam_plugin_dvs.la -XCAM_PLUGIN_DVS_CXXFLAGS = $(XCAM_CXXFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/modules \ - -I$(top_srcdir)/plugins/smart/dvs/libdvs \ - $(NULL) - -if HAVE_LIBDRM -XCAM_PLUGIN_DVS_CXXFLAGS += $(LIBDRM_CFLAGS) -endif +XCAM_PLUGIN_DVS_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + -I$(top_srcdir)/plugins/smart/dvs/libdvs \ + $(NULL) -XCAM_PLUGIN_DVS_LIBS = \ - $(top_builddir)/plugins/smart/dvs/libdvs/libxcam_dvs.a \ - $(NULL) +XCAM_PLUGIN_DVS_LIBS = \ + $(OPENCV_LIBS) \ + $(top_builddir)/xcore/libxcam_core.la \ + $(top_builddir)/modules/ocl/libxcam_ocl.la \ + $(top_builddir)/plugins/smart/dvs/libdvs/libxcam_dvs.a \ + $(NULL) if HAVE_LIBDRM +XCAM_PLUGIN_DVS_CXXFLAGS += $(LIBDRM_CFLAGS) XCAM_PLUGIN_DVS_LIBS += $(LIBDRM_LIBS) endif plugindir="$(libdir)/xcam/plugins/smart" -libxcam_plugin_dvs_la_SOURCES = \ - xcam_plugin_dvs.cpp \ - $(NULL) +libxcam_plugin_dvs_la_SOURCES = \ + xcam_plugin_dvs.cpp \ + $(NULL) -libxcam_plugin_dvs_la_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAM_PLUGIN_DVS_CXXFLAGS) \ - $(NULL) +libxcam_plugin_dvs_la_CXXFLAGS = \ + $(XCAM_PLUGIN_DVS_CXXFLAGS) \ + $(NULL) -libxcam_plugin_dvs_la_LIBADD = \ - $(XCAM_PLUGIN_DVS_LIBS) \ - $(top_builddir)/modules/ocl/libxcam_ocl.la \ - $(top_builddir)/xcore/libxcam_core.la \ - $(OPENCV_LIBS) \ +libxcam_plugin_dvs_la_LIBADD = \ + $(XCAM_PLUGIN_DVS_LIBS) \ $(NULL) -libxcam_plugin_dvs_la_LDFLAGS = \ - -module -avoid-version \ - $(top_builddir)/xcore/libxcam_core.la \ - $(PTHREAD_LDFLAGS) \ - $(OPENCV_LIBS) \ +libxcam_plugin_dvs_la_LDFLAGS = \ + -module -avoid-version \ $(NULL) libxcam_plugin_dvs_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/plugins/smart/dvs/libdvs/Makefile.am b/plugins/smart/dvs/libdvs/Makefile.am index 6fba743..8ffcb8c 100644 --- a/plugins/smart/dvs/libdvs/Makefile.am +++ b/plugins/smart/dvs/libdvs/Makefile.am @@ -1,45 +1,32 @@ -noinst_LIBRARIES = \ - libxcam_dvs.a \ - $(NULL) - -XCAM_DVS_LIB_CXXFLAGS = \ - $(XCAM_CXXFLAGS) \ - $(OPENCV_CFLAGS) \ - $(NULL) - -XCAM_DVS_LIBS = \ - $(OPENCV_LIBS) \ - $(NULL) +noinst_LIBRARIES = libxcam_dvs.a libxcam_dvs_a_SOURCES = \ - libdvs.cpp \ - stabilizer.cpp \ - $(NULL) - -libxcam_dvs_a_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAM_DVS_LIB_CXXFLAGS) \ - -I$(top_srcdir)/xcore \ - $(NULL) + libdvs.cpp \ + stabilizer.cpp \ + $(NULL) -libxcam_dvs_a_LIBADD = \ - $(top_builddir)/xcore/libxcam_core.la \ +libxcam_dvs_a_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(OPENCV_CFLAGS) \ + -I$(top_srcdir)/xcore \ $(NULL) -noinst_PROGRAMS = \ - test_image_stabilization \ +libxcam_dvs_a_LIBADD = \ + $(top_builddir)/xcore/libxcam_core.la \ $(NULL) +noinst_PROGRAMS = test_image_stabilization + test_image_stabilization_SOURCES = \ test-image-stabilization.cpp \ $(NULL) test_image_stabilization_CXXFLAGS = \ - $(XCAM_CXXFLAGS) \ + $(XCAM_CXXFLAGS) \ -I$(top_srcdir)/xcore \ $(NULL) test_image_stabilization_LDADD = \ - libxcam_dvs.a \ + libxcam_dvs.a \ $(OPENCV_LIBS) \ $(NULL) - diff --git a/plugins/smart/dvs/libdvs/stabilizer.cpp b/plugins/smart/dvs/libdvs/stabilizer.cpp index 1dd4f66..ba660f9 100644 --- a/plugins/smart/dvs/libdvs/stabilizer.cpp +++ b/plugins/smart/dvs/libdvs/stabilizer.cpp @@ -377,13 +377,23 @@ VideoStabilizer::setFrameSize(Size frameSize) Mat VideoStabilizer::nextFrame() { + Mat frame; + if (isTwoPass_) { Ptr<TwoPassVideoStabilizer> stab = stabilizer_.dynamicCast<TwoPassVideoStabilizer>(); - return stab->nextFrame(); + if(!stab.empty()) + frame = stab->nextFrame(); + else + CV_Error (Error::StsNullPtr, "VideoStabilizer: cast stabilizer failed"); } else { Ptr<OnePassVideoStabilizer> stab = stabilizer_.dynamicCast<OnePassVideoStabilizer>(); - return stab->nextFrame(); + if(!stab.empty()) + frame = stab->nextFrame(); + else + CV_Error (Error::StsNullPtr, "VideoStabilizer: cast stabilizer failed"); } + + return frame; } Mat @@ -393,10 +403,16 @@ VideoStabilizer::nextStabilizedMotion(DvsData* frame, int& stablizedPos) if (isTwoPass_) { Ptr<TwoPassVideoStabilizer> stab = stabilizer_.dynamicCast<TwoPassVideoStabilizer>(); - HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); + if(!stab.empty()) + HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); + else + CV_Error (Error::StsNullPtr, "VideoStabilizer: cast stabilizer failed"); } else { Ptr<OnePassVideoStabilizer> stab = stabilizer_.dynamicCast<OnePassVideoStabilizer>(); - HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); + if(!stab.empty()) + HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); + else + CV_Error (Error::StsNullPtr, "VideoStabilizer: cast stabilizer failed"); } return HMatrix; diff --git a/plugins/smart/dvs/libdvs/test-image-stabilization.cpp b/plugins/smart/dvs/libdvs/test-image-stabilization.cpp index 944ef12..c2549e5 100644 --- a/plugins/smart/dvs/libdvs/test-image-stabilization.cpp +++ b/plugins/smart/dvs/libdvs/test-image-stabilization.cpp @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) break; case 'e': usage (argv[0]); - return -1; + return 0; default: printf ("getopt_long return unknown value:%c \n", opt); usage (argv[0]); diff --git a/plugins/smart/dvs/xcam_plugin_dvs.cpp b/plugins/smart/dvs/xcam_plugin_dvs.cpp index d8e2365..c6f154a 100644 --- a/plugins/smart/dvs/xcam_plugin_dvs.cpp +++ b/plugins/smart/dvs/xcam_plugin_dvs.cpp @@ -136,7 +136,6 @@ XCamReturn dvs_analyze(XCamSmartAnalysisContext *context, XCamVideoBuffer *buffe DvsBuffer* dvs_buf = new DvsBuffer(buffer, frame); //set default config DvsConfig config; - memset(&config, 0, sizeof(DvsConfig)); config.use_ocl = true; config.frame_width = buffer->info.width; config.frame_height = buffer->info.height; @@ -158,6 +157,14 @@ XCamReturn dvs_analyze(XCamSmartAnalysisContext *context, XCamVideoBuffer *buffe XCAM_LOG_WARNING ("dvs_analyze not ready! "); } else { XCamDVSResult *dvs_result = (XCamDVSResult *)malloc(sizeof(XCamDVSResult)); + if (!dvs_result) { + XCAM_LOG_ERROR ("dvs_result: malloc failed!"); + results[0] = NULL; + *res_count = 0; + + return XCAM_RETURN_ERROR_MEM; + } + memset(dvs_result, 0, sizeof(XCamDVSResult)); dvs_result->head.type = XCAM_3A_RESULT_DVS; diff --git a/plugins/smart/sample/Makefile.am b/plugins/smart/sample/Makefile.am index 407d2dd3..2dc4b51 100644 --- a/plugins/smart/sample/Makefile.am +++ b/plugins/smart/sample/Makefile.am @@ -1,46 +1,38 @@ -noinst_LTLIBRARIES = \ - $(NULL) +noinst_LTLIBRARIES = libxcam_sample_smart.la -if ENABLE_IA_AIQ -noinst_LTLIBRARIES += \ - libxcam_sample_smart.la \ +XCAM_SAMPLE_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules/isp \ + -I$(top_srcdir)/plugins/smart \ $(NULL) -endif -XCAMSMART_CXXFLAGS = $(XCAM_CXXFLAGS) -XCAMSMART_LIBS = \ +XCAM_SAMPLE_LIBS = \ + $(top_builddir)/xcore/libxcam_core.la \ $(NULL) if USE_LOCAL_ATOMISP -XCAMSMART_CXXFLAGS += \ - -I$(top_srcdir)/ext/atomisp \ +XCAM_SAMPLE_CXXFLAGS += \ + -I$(top_srcdir)/ext/atomisp \ $(NULL) endif plugindir="$(libdir)/xcam/plugins/smart" -if ENABLE_IA_AIQ libxcam_sample_smart_la_SOURCES = \ - sample_smart_analysis.cpp \ + sample_smart_analysis.cpp \ $(NULL) libxcam_sample_smart_la_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAMSMART_CXXFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/modules/isp \ - -I$(top_srcdir)/plugins/smart \ + $(XCAM_SAMPLE_CXXFLAGS) \ $(NULL) libxcam_sample_smart_la_LIBADD = \ - $(XCAMSMART_LIBS) \ - $(top_builddir)/xcore/libxcam_core.la \ + $(XCAM_SAMPLE_LIBS) \ $(NULL) libxcam_sample_smart_la_LDFLAGS = \ - -module -avoid-version \ - $(top_builddir)/xcore/libxcam_core.la \ - $(PTHREAD_LDFLAGS) \ + -module -avoid-version \ $(NULL) -endif libxcam_sample_smart_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/plugins/smart/sample/sample_smart_analysis.cpp b/plugins/smart/sample/sample_smart_analysis.cpp index a144946..defcca4 100644 --- a/plugins/smart/sample/sample_smart_analysis.cpp +++ b/plugins/smart/sample/sample_smart_analysis.cpp @@ -228,10 +228,11 @@ SampleHandler::update_params (const XCamSmartAnalysisParam *params) XCamReturn SampleHandler::analyze (XCamVideoBuffer *buffer) { - XCAM_LOG_DEBUG ("Smart SampleHandler::analyze on ts:" XCAM_TIMESTAMP_FORMAT, XCAM_TIMESTAMP_ARGS (buffer->timestamp)); if (NULL == buffer) { return XCAM_RETURN_ERROR_PARAM; } + XCAM_LOG_DEBUG ("Smart SampleHandler::analyze on ts:" XCAM_TIMESTAMP_FORMAT, XCAM_TIMESTAMP_ARGS (buffer->timestamp)); + XCamReturn ret = XCAM_RETURN_NO_ERROR; XCAM_LOG_DEBUG ("format(0x%x), color_bits(%d)", buffer->info.format, buffer->info.color_bits); diff --git a/shaders/Makefile.am b/shaders/Makefile.am new file mode 100644 index 0000000..4e540d5 --- /dev/null +++ b/shaders/Makefile.am @@ -0,0 +1,9 @@ +if HAVE_LIBCL +CLX_DIR = clx +endif + +if HAVE_GLES +GLSLX_DIR = glslx +endif + +SUBDIRS = $(CLX_DIR) $(GLSLX_DIR) diff --git a/cl_kernel/kernel_3d_denoise.cl b/shaders/cl/kernel_3d_denoise.cl index c94c1d7..c94c1d7 100644 --- a/cl_kernel/kernel_3d_denoise.cl +++ b/shaders/cl/kernel_3d_denoise.cl diff --git a/cl_kernel/kernel_3d_denoise_slm.cl b/shaders/cl/kernel_3d_denoise_slm.cl index 55eef62..55eef62 100644 --- a/cl_kernel/kernel_3d_denoise_slm.cl +++ b/shaders/cl/kernel_3d_denoise_slm.cl diff --git a/cl_kernel/kernel_bayer_basic.cl b/shaders/cl/kernel_bayer_basic.cl index e6c19dd..e6c19dd 100644 --- a/cl_kernel/kernel_bayer_basic.cl +++ b/shaders/cl/kernel_bayer_basic.cl diff --git a/cl_kernel/kernel_bayer_pipe.cl b/shaders/cl/kernel_bayer_pipe.cl index 91dd362..91dd362 100644 --- a/cl_kernel/kernel_bayer_pipe.cl +++ b/shaders/cl/kernel_bayer_pipe.cl diff --git a/cl_kernel/kernel_bi_filter.cl b/shaders/cl/kernel_bi_filter.cl index 4023c12..4023c12 100644 --- a/cl_kernel/kernel_bi_filter.cl +++ b/shaders/cl/kernel_bi_filter.cl diff --git a/cl_kernel/kernel_csc.cl b/shaders/cl/kernel_csc.cl index 1a6739a..1a6739a 100644 --- a/cl_kernel/kernel_csc.cl +++ b/shaders/cl/kernel_csc.cl diff --git a/cl_kernel/kernel_defog_dcp.cl b/shaders/cl/kernel_defog_dcp.cl index 3903da6..3903da6 100644 --- a/cl_kernel/kernel_defog_dcp.cl +++ b/shaders/cl/kernel_defog_dcp.cl diff --git a/cl_kernel/kernel_demo.cl b/shaders/cl/kernel_demo.cl index 161e6e6..161e6e6 100644 --- a/cl_kernel/kernel_demo.cl +++ b/shaders/cl/kernel_demo.cl diff --git a/cl_kernel/kernel_fisheye.cl b/shaders/cl/kernel_fisheye.cl index 3b3f5b5..3b3f5b5 100644 --- a/cl_kernel/kernel_fisheye.cl +++ b/shaders/cl/kernel_fisheye.cl diff --git a/cl_kernel/kernel_gauss.cl b/shaders/cl/kernel_gauss.cl index 4e66d48..4e66d48 100644 --- a/cl_kernel/kernel_gauss.cl +++ b/shaders/cl/kernel_gauss.cl diff --git a/cl_kernel/kernel_gauss_lap_pyramid.cl b/shaders/cl/kernel_gauss_lap_pyramid.cl index b983b57..b983b57 100644 --- a/cl_kernel/kernel_gauss_lap_pyramid.cl +++ b/shaders/cl/kernel_gauss_lap_pyramid.cl diff --git a/cl_kernel/kernel_geo_map.cl b/shaders/cl/kernel_geo_map.cl index b696a40..40b191a 100644 --- a/cl_kernel/kernel_geo_map.cl +++ b/shaders/cl/kernel_geo_map.cl @@ -14,6 +14,10 @@ #define ENABLE_LSC 0 #endif +#ifndef ENABLE_SCALE +#define ENABLE_SCALE 0 +#endif + #define CONST_DATA_Y 0.0f #define CONST_DATA_UV (float2)(0.5f, 0.5f) @@ -66,6 +70,10 @@ __kernel void kernel_geo_map ( __read_only image2d_t input_y, __read_only image2d_t input_uv, __read_only image2d_t geo_table, float2 table_scale_size, +#if ENABLE_SCALE + float2 left_scale_factor, float2 right_scale_factor, + float stable_y_start, +#endif #if ENABLE_LSC __read_only image2d_t lsc_table, float2 gray_threshold, #endif @@ -79,11 +87,33 @@ kernel_geo_map ( bool out_of_bound[8]; float2 input_pos[8]; // map to [-0.5, 0.5) - float2 table_scale_step = 1.0f / table_scale_size; + float2 scale = 1.0f; + +#if ENABLE_SCALE + float a, b, c; + float y_m = stable_y_start * 0.5f; + + float2 scale_factor = (g_x * PIXEL_RES_STEP_X < out_size.x / 2.0f) ? left_scale_factor : right_scale_factor; + a = (1 - scale_factor.x) / ((stable_y_start - y_m) * (stable_y_start - y_m)); + b = -2 * a * y_m; + c = 1 - a * stable_y_start * stable_y_start - b * stable_y_start; + + scale.y = (g_y >= stable_y_start) ? 1.0f : ((right_scale_factor.y - left_scale_factor.y) / + (out_size.x - PIXEL_RES_STEP_X) * g_x * PIXEL_RES_STEP_X + left_scale_factor.y); + float y_scale = ((float)g_y - stable_y_start) * scale.y + stable_y_start; + scale.x = (y_scale >= stable_y_start) ? 1.0f : ((y_scale < y_m) ? scale_factor.x : (a * y_scale * y_scale + b * y_scale + c)); +#endif + + float2 table_scale_step = 1.0f / (table_scale_size * scale); float2 out_map_pos; sampler_t sampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR; +#if ENABLE_SCALE + out_map_pos.x = (g_x * PIXEL_RES_STEP_X - out_size.x / 2.0f) * table_scale_step.x + 0.5f; + out_map_pos.y = ((float)g_y - stable_y_start) * table_scale_step.y + stable_y_start / out_size.y; +#else out_map_pos = (convert_float2((int2)(g_x * PIXEL_RES_STEP_X, g_y)) - out_size / 2.0f) * table_scale_step + 0.5f; +#endif get_geo_mapped_y (input_y, geo_table, out_map_pos, table_scale_step.x, out_of_bound, input_pos, &output_data); @@ -100,7 +130,21 @@ kernel_geo_map ( output_data.s67 = out_of_bound[6] ? CONST_DATA_UV : read_imagef (input_uv, sampler, input_pos[6]).xy; write_imageui (output_uv, (int2)(g_x, g_y_uv), convert_uint4(as_ushort4(convert_uchar8(output_data * 255.0f)))); +#if ENABLE_SCALE + scale.y = (g_y + 1 >= stable_y_start) ? 1.0f : ((right_scale_factor.y - left_scale_factor.y) / + (out_size.x - PIXEL_RES_STEP_X) * g_x * PIXEL_RES_STEP_X + left_scale_factor.y); + y_scale = (g_y + 1 - stable_y_start) * scale.y + stable_y_start; + scale.x = (y_scale >= stable_y_start) ? 1.0f : + ((y_scale < y_m) ? scale_factor.x : (a * y_scale * y_scale + b * y_scale + c)); + + table_scale_step = 1.0f / (table_scale_size * scale); + + out_map_pos.x = (g_x * PIXEL_RES_STEP_X - out_size.x / 2.0f) * table_scale_step.x + 0.5f; + out_map_pos.y = ((float)g_y + 1 - stable_y_start) * table_scale_step.y + stable_y_start / out_size.y; +#else out_map_pos.y += table_scale_step.y; +#endif + get_geo_mapped_y (input_y, geo_table, out_map_pos, table_scale_step.x, out_of_bound, input_pos, &output_data); #if ENABLE_LSC diff --git a/cl_kernel/kernel_image_scaler.cl b/shaders/cl/kernel_image_scaler.cl index c6c1ca3..c6c1ca3 100644 --- a/cl_kernel/kernel_image_scaler.cl +++ b/shaders/cl/kernel_image_scaler.cl diff --git a/cl_kernel/kernel_image_warp.cl b/shaders/cl/kernel_image_warp.cl index 22acd39..22acd39 100644 --- a/cl_kernel/kernel_image_warp.cl +++ b/shaders/cl/kernel_image_warp.cl diff --git a/cl_kernel/kernel_min_filter.cl b/shaders/cl/kernel_min_filter.cl index 6a30f20..6a30f20 100644 --- a/cl_kernel/kernel_min_filter.cl +++ b/shaders/cl/kernel_min_filter.cl diff --git a/cl_kernel/kernel_newtonemapping.cl b/shaders/cl/kernel_newtonemapping.cl index c66bab4..c66bab4 100755 --- a/cl_kernel/kernel_newtonemapping.cl +++ b/shaders/cl/kernel_newtonemapping.cl diff --git a/cl_kernel/kernel_retinex.cl b/shaders/cl/kernel_retinex.cl index 9df3a58..9df3a58 100644 --- a/cl_kernel/kernel_retinex.cl +++ b/shaders/cl/kernel_retinex.cl diff --git a/cl_kernel/kernel_rgb_pipe.cl b/shaders/cl/kernel_rgb_pipe.cl index 277d9d4..277d9d4 100644 --- a/cl_kernel/kernel_rgb_pipe.cl +++ b/shaders/cl/kernel_rgb_pipe.cl diff --git a/cl_kernel/kernel_tnr.cl b/shaders/cl/kernel_tnr.cl index e5c1c36..e5c1c36 100644 --- a/cl_kernel/kernel_tnr.cl +++ b/shaders/cl/kernel_tnr.cl diff --git a/cl_kernel/kernel_tonemapping.cl b/shaders/cl/kernel_tonemapping.cl index 2f239ca..2f239ca 100644 --- a/cl_kernel/kernel_tonemapping.cl +++ b/shaders/cl/kernel_tonemapping.cl diff --git a/cl_kernel/kernel_wavelet_coeff.cl b/shaders/cl/kernel_wavelet_coeff.cl index 51c3b5f..51c3b5f 100644 --- a/cl_kernel/kernel_wavelet_coeff.cl +++ b/shaders/cl/kernel_wavelet_coeff.cl diff --git a/cl_kernel/kernel_wavelet_denoise.cl b/shaders/cl/kernel_wavelet_denoise.cl index b0353a1..b0353a1 100644 --- a/cl_kernel/kernel_wavelet_denoise.cl +++ b/shaders/cl/kernel_wavelet_denoise.cl diff --git a/cl_kernel/kernel_wavelet_haar.cl b/shaders/cl/kernel_wavelet_haar.cl index bdecd68..bdecd68 100644 --- a/cl_kernel/kernel_wavelet_haar.cl +++ b/shaders/cl/kernel_wavelet_haar.cl diff --git a/cl_kernel/kernel_wire_frame.cl b/shaders/cl/kernel_wire_frame.cl index 5862dd5..5862dd5 100644 --- a/cl_kernel/kernel_wire_frame.cl +++ b/shaders/cl/kernel_wire_frame.cl diff --git a/cl_kernel/kernel_yuv_pipe.cl b/shaders/cl/kernel_yuv_pipe.cl index 681fa62..681fa62 100644 --- a/cl_kernel/kernel_yuv_pipe.cl +++ b/shaders/cl/kernel_yuv_pipe.cl diff --git a/clx_kernel/.gitignore b/shaders/clx/.gitignore index 74cd98e..74cd98e 100644 --- a/clx_kernel/.gitignore +++ b/shaders/clx/.gitignore diff --git a/shaders/clx/Makefile.am b/shaders/clx/Makefile.am new file mode 100644 index 0000000..b122b1b --- /dev/null +++ b/shaders/clx/Makefile.am @@ -0,0 +1,39 @@ +clx_sources = \ + kernel_csc.clx \ + kernel_demo.clx \ + kernel_defog_dcp.clx \ + kernel_min_filter.clx \ + kernel_bi_filter.clx \ + kernel_tnr.clx \ + kernel_bayer_pipe.clx \ + kernel_bayer_basic.clx \ + kernel_fisheye.clx \ + kernel_rgb_pipe.clx \ + kernel_yuv_pipe.clx \ + kernel_tonemapping.clx \ + kernel_newtonemapping.clx \ + kernel_image_scaler.clx \ + kernel_retinex.clx \ + kernel_gauss.clx \ + kernel_gauss_lap_pyramid.clx \ + kernel_geo_map.clx \ + kernel_wavelet_denoise.clx \ + kernel_wavelet_haar.clx \ + kernel_wavelet_coeff.clx \ + kernel_wire_frame.clx \ + kernel_3d_denoise.clx \ + kernel_3d_denoise_slm.clx \ + kernel_image_warp.clx \ + $(NULL) + +add_quotation_marks_sh = \ + $(top_srcdir)/tools/add-quotation-marks.sh + +cl_dir = $(top_srcdir)/shaders/cl + +all-local: $(clx_sources) + +$(clx_sources): %.clx: $(cl_dir)/%.cl + @$(add_quotation_marks_sh) $< $@ + +CLEANFILES = $(clx_sources) diff --git a/shaders/glsl/shader_blend_pyr.comp.sl b/shaders/glsl/shader_blend_pyr.comp.sl new file mode 100644 index 0000000..dd1fb0f --- /dev/null +++ b/shaders/glsl/shader_blend_pyr.comp.sl @@ -0,0 +1,91 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer In0BufY { + uvec2 data[]; +} in0_buf_y; + +layout (binding = 1) readonly buffer In0BufUV { + uvec2 data[]; +} in0_buf_uv; + +layout (binding = 2) readonly buffer In1BufY { + uvec2 data[]; +} in1_buf_y; + +layout (binding = 3) readonly buffer In1BufUV { + uvec2 data[]; +} in1_buf_uv; + +layout (binding = 4) writeonly buffer OutBufY { + uvec2 data[]; +} out_buf_y; + +layout (binding = 5) writeonly buffer OutBufUV { + uvec2 data[]; +} out_buf_uv; + +layout (binding = 6) readonly buffer MaskBuf { + uvec2 data[]; +} mask_buf; + +uniform uint in_img_width; + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + g_id.x = clamp (g_id.x, 0u, in_img_width - 1u); + + uvec2 mask = mask_buf.data[g_id.x]; + vec4 mask0 = unpackUnorm4x8 (mask.x); + vec4 mask1 = unpackUnorm4x8 (mask.y); + + uint y_idx = g_id.y * 2u * in_img_width + g_id.x; + uvec2 in0_y = in0_buf_y.data[y_idx]; + vec4 in0_y0 = unpackUnorm4x8 (in0_y.x); + vec4 in0_y1 = unpackUnorm4x8 (in0_y.y); + + uvec2 in1_y = in1_buf_y.data[y_idx]; + vec4 in1_y0 = unpackUnorm4x8 (in1_y.x); + vec4 in1_y1 = unpackUnorm4x8 (in1_y.y); + + vec4 out_y0 = (in0_y0 - in1_y0) * mask0 + in1_y0; + vec4 out_y1 = (in0_y1 - in1_y1) * mask1 + in1_y1; + out_y0 = clamp (out_y0, 0.0f, 1.0f); + out_y1 = clamp (out_y1, 0.0f, 1.0f); + out_buf_y.data[y_idx] = uvec2 (packUnorm4x8 (out_y0), packUnorm4x8 (out_y1)); + + y_idx += in_img_width; + in0_y = in0_buf_y.data[y_idx]; + in0_y0 = unpackUnorm4x8 (in0_y.x); + in0_y1 = unpackUnorm4x8 (in0_y.y); + + in1_y = in1_buf_y.data[y_idx]; + in1_y0 = unpackUnorm4x8 (in1_y.x); + in1_y1 = unpackUnorm4x8 (in1_y.y); + + out_y0 = (in0_y0 - in1_y0) * mask0 + in1_y0; + out_y1 = (in0_y1 - in1_y1) * mask1 + in1_y1; + out_y0 = clamp (out_y0, 0.0f, 1.0f); + out_y1 = clamp (out_y1, 0.0f, 1.0f); + out_buf_y.data[y_idx] = uvec2 (packUnorm4x8 (out_y0), packUnorm4x8 (out_y1)); + + uint uv_idx = g_id.y * in_img_width + g_id.x; + uvec2 in0_uv = in0_buf_uv.data[uv_idx]; + vec4 in0_uv0 = unpackUnorm4x8 (in0_uv.x); + vec4 in0_uv1 = unpackUnorm4x8 (in0_uv.y); + + uvec2 in1_uv = in1_buf_uv.data[uv_idx]; + vec4 in1_uv0 = unpackUnorm4x8 (in1_uv.x); + vec4 in1_uv1 = unpackUnorm4x8 (in1_uv.y); + + mask0.yw = mask0.xz; + mask1.yw = mask1.xz; + vec4 out_uv0 = (in0_uv0 - in1_uv0) * mask0 + in1_uv0; + vec4 out_uv1 = (in0_uv1 - in1_uv1) * mask1 + in1_uv1; + + out_uv0 = clamp (out_uv0, 0.0f, 1.0f); + out_uv1 = clamp (out_uv1, 0.0f, 1.0f); + out_buf_uv.data[uv_idx] = uvec2 (packUnorm4x8 (out_uv0), packUnorm4x8 (out_uv1)); +} diff --git a/shaders/glsl/shader_copy.comp.sl b/shaders/glsl/shader_copy.comp.sl new file mode 100644 index 0000000..ced6c91 --- /dev/null +++ b/shaders/glsl/shader_copy.comp.sl @@ -0,0 +1,28 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBuf { + uvec4 data[]; +} in_buf; + +layout (binding = 1) writeonly buffer OutBuf { + uvec4 data[]; +} out_buf; + +uniform uint in_img_width; +uniform uint in_x_offset; + +uniform uint out_img_width; +uniform uint out_x_offset; + +uniform uint copy_width; + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + g_id.x = min (g_id.x, copy_width - 1u); + + out_buf.data[g_id.y * out_img_width + out_x_offset + g_id.x] = + in_buf.data[g_id.y * in_img_width + in_x_offset + g_id.x]; +} diff --git a/shaders/glsl/shader_gauss_scale_pyr.comp.sl b/shaders/glsl/shader_gauss_scale_pyr.comp.sl new file mode 100644 index 0000000..1fbdd8f --- /dev/null +++ b/shaders/glsl/shader_gauss_scale_pyr.comp.sl @@ -0,0 +1,174 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBufY { + uint data[]; +} in_buf_y; + +layout (binding = 1) readonly buffer InBufUV { + uint data[]; +} in_buf_uv; + +layout (binding = 2) writeonly buffer OutBufY { + uint data[]; +} out_buf_y; + +layout (binding = 3) writeonly buffer OutBufUV { + uint data[]; +} out_buf_uv; + +uniform uint in_img_width; +uniform uint in_img_height; +uniform uint in_offset_x; + +uniform uint out_img_width; + +uniform uint merge_width; + +const float coeffs[5] = float[] (0.152f, 0.222f, 0.252f, 0.222f, 0.152f); + +#define unpack_unorm(buf, pixel, idx) \ + { \ + pixel[0] = unpackUnorm4x8 (buf.data[idx]); \ + pixel[1] = unpackUnorm4x8 (buf.data[idx + 1u]); \ + pixel[2] = unpackUnorm4x8 (buf.data[idx + 2u]); \ + pixel[3] = unpackUnorm4x8 (buf.data[idx + 3u]); \ + } + +#define multiply_coeff(sum, pixel, idx) \ + { \ + sum[0] += pixel[0] * coeffs[idx]; \ + sum[1] += pixel[1] * coeffs[idx]; \ + sum[2] += pixel[2] * coeffs[idx]; \ + sum[3] += pixel[3] * coeffs[idx]; \ + } + +void gauss_scale_y (uvec2 y_id); +void gauss_scale_uv (uvec2 uv_id); + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + g_id.x = clamp (g_id.x, 0u, merge_width - 1u); + + uvec2 y_id = g_id * uvec2 (1u, 2u); + gauss_scale_y (y_id); + + gauss_scale_uv (g_id); +} + +void gauss_scale_y (uvec2 y_id) +{ + uvec2 in_id = y_id * 2u; + uvec2 gauss_start = in_id - uvec2 (1u, 2u); + gauss_start.y = clamp (gauss_start.y, 0u, in_img_height - 7u); + + vec4 sum0[4] = vec4[] (vec4 (0.0f), vec4 (0.0f), vec4 (0.0f), vec4 (0.0f)); + vec4 sum1[4] = vec4[] (vec4 (0.0f), vec4 (0.0f), vec4 (0.0f), vec4 (0.0f)); + + vec4 pixel_y[4]; + uint in_idx = (in_id.y == 0u) ? (in_id.x - 1u) : (gauss_start.y * in_img_width + gauss_start.x); + in_idx += in_offset_x; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 0u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + in_img_width); + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 1u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + in_img_width); + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 2u); + multiply_coeff (sum1, pixel_y, 0u); + + in_idx += in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 3u); + multiply_coeff (sum1, pixel_y, 1u); + + in_idx += in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 4u); + multiply_coeff (sum1, pixel_y, 2u); + + in_idx += in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum1, pixel_y, 3u); + + in_idx += in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum1, pixel_y, 4u); + + sum0[0] = (in_id.x == 0u) ? vec4 (sum0[1].x) : sum0[0]; + sum1[0] = (in_id.x == 0u) ? vec4 (sum1[1].x) : sum1[0]; + sum0[3] = (in_id.x == merge_width - 2u) ? vec4 (sum0[2].w) : sum0[3]; + sum1[3] = (in_id.x == merge_width - 2u) ? vec4 (sum1[2].w) : sum1[3]; + + vec4 out_data0 = + vec4 (sum0[0].z, sum0[1].x, sum0[1].z, sum0[2].x) * coeffs[0] + + vec4 (sum0[0].w, sum0[1].y, sum0[1].w, sum0[2].y) * coeffs[1] + + vec4 (sum0[1].x, sum0[1].z, sum0[2].x, sum0[2].z) * coeffs[2] + + vec4 (sum0[1].y, sum0[1].w, sum0[2].y, sum0[2].w) * coeffs[3] + + vec4 (sum0[1].z, sum0[2].x, sum0[2].z, sum0[3].x) * coeffs[4]; + + vec4 out_data1 = + vec4 (sum1[0].z, sum1[1].x, sum1[1].z, sum1[2].x) * coeffs[0] + + vec4 (sum1[0].w, sum1[1].y, sum1[1].w, sum1[2].y) * coeffs[1] + + vec4 (sum1[1].x, sum1[1].z, sum1[2].x, sum1[2].z) * coeffs[2] + + vec4 (sum1[1].y, sum1[1].w, sum1[2].y, sum1[2].w) * coeffs[3] + + vec4 (sum1[1].z, sum1[2].x, sum1[2].z, sum1[3].x) * coeffs[4]; + + out_data0 = clamp (out_data0, 0.0f, 1.0f); + out_data1 = clamp (out_data1, 0.0f, 1.0f); + + y_id.x = clamp (y_id.x, 0u, out_img_width - 1u); + uint out_idx = y_id.y * out_img_width + y_id.x; + out_buf_y.data[out_idx] = packUnorm4x8 (out_data0); + out_buf_y.data[out_idx + out_img_width] = packUnorm4x8 (out_data1); +} + +void gauss_scale_uv (uvec2 uv_id) +{ + uvec2 in_id = uv_id * 2u; + uvec2 gauss_start = in_id - uvec2 (1u, 2u); + gauss_start.y = clamp (gauss_start.y, 0u, in_img_height / 2u - 5u); + + vec4 sum[4] = vec4[] (vec4 (0.0f), vec4 (0.0f), vec4 (0.0f), vec4 (0.0f)); + uint in_idx = (in_id.y == 0u) ? (in_id.x - 1u) : (gauss_start.y * in_img_width + gauss_start.x); + in_idx += in_offset_x; + + vec4 pixel_uv[4]; + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 0u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + in_img_width); + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 1u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + in_img_width); + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 2u); + + in_idx += in_img_width; + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 3u); + + in_idx += in_img_width; + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 4u); + + sum[0] = (in_id.x == 0u) ? vec4 (sum[1]) : sum[0]; + sum[3] = (in_id.x == merge_width - 2u) ? vec4 (sum[2]) : sum[3]; + + vec4 out_data = + vec4 (sum[0].x, sum[0].y, sum[1].x, sum[1].y) * coeffs[0] + + vec4 (sum[0].z, sum[0].w, sum[1].z, sum[1].w) * coeffs[1] + + vec4 (sum[1].x, sum[1].y, sum[2].x, sum[2].y) * coeffs[2] + + vec4 (sum[1].z, sum[1].w, sum[2].z, sum[2].w) * coeffs[3] + + vec4 (sum[2].x, sum[2].y, sum[3].x, sum[3].y) * coeffs[4]; + + out_data = clamp (out_data, 0.0f, 1.0f); + uv_id.x = clamp (uv_id.x, 0u, out_img_width - 1u); + out_buf_uv.data[uv_id.y * out_img_width + uv_id.x] = packUnorm4x8 (out_data); +} diff --git a/shaders/glsl/shader_geomap.comp.sl b/shaders/glsl/shader_geomap.comp.sl new file mode 100644 index 0000000..d2b5b70 --- /dev/null +++ b/shaders/glsl/shader_geomap.comp.sl @@ -0,0 +1,238 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBufY { + uint data[]; +} in_buf_y; + +layout (binding = 1) readonly buffer InBufUV { + uint data[]; +} in_buf_uv; + +layout (binding = 2) writeonly buffer OutBufY { + uint data[]; +} out_buf_y; + +layout (binding = 3) writeonly buffer OutBufUV { + uint data[]; +} out_buf_uv; + +layout (binding = 4) readonly buffer GeoMapTable { + vec2 data[]; +} lut; + +uniform uint in_img_width; +uniform uint in_img_height; + +uniform uint out_img_width; +uniform uint out_img_height; + +uniform uint lut_width; +uniform uint lut_height; + +uniform vec4 lut_step; +uniform vec2 lut_std_step; + +#define UNIT_SIZE 4u + +#define unpack_unorm_y(index) \ + { \ + vec4 value = unpackUnorm4x8 (in_buf_y.data[index00[index]]); \ + out_y00[index] = value[x00_fract[index]]; \ + value = unpackUnorm4x8 (in_buf_y.data[index01[index]]); \ + out_y01[index] = value[x01_fract[index]]; \ + value = unpackUnorm4x8 (in_buf_y.data[index10[index]]); \ + out_y10[index] = value[x10_fract[index]]; \ + value = unpackUnorm4x8 (in_buf_y.data[index11[index]]); \ + out_y11[index] = value[x11_fract[index]]; \ + } + +void geomap_y (vec4 lut_x, vec4 lut_y, out vec4 in_img_x, out vec4 in_img_y, out bvec4 out_bound, out uint out_data); +void geomap_uv (vec2 in_uv_x, vec2 in_uv_y, bvec4 out_bound_uv, out uint out_data); + +void main () +{ + uint g_x = gl_GlobalInvocationID.x; + uint g_y = gl_GlobalInvocationID.y * 2u; + + vec2 cent = (vec2 (out_img_width, out_img_height) - 1.0f) / 2.0f; + vec2 step = g_x < uint (cent.x) ? lut_step.xy : lut_step.zw; + + vec2 start = (vec2 (g_x, g_y) - cent) * step + cent * lut_std_step; + vec4 lut_x = start.x * float (UNIT_SIZE) + vec4 (0.0f, step.x, step.x * 2.0f, step.x * 3.0f); + vec4 lut_y = start.yyyy; + lut_x = clamp (lut_x, 0.0f, float (lut_width) - 1.0f); + lut_y = clamp (lut_y, 0.0f, float (lut_height) - 1.0f - step.y); + + uint out_data; + vec4 in_img_x, in_img_y; + bvec4 out_bound; + geomap_y (lut_x, lut_y, in_img_x, in_img_y, out_bound, out_data); + out_buf_y.data[g_y * out_img_width + g_x] = out_data; + + bvec4 out_bound_uv = out_bound.xxzz; + if (all (out_bound_uv)) { + out_data = packUnorm4x8 (vec4 (0.5f)); + } else { + vec2 in_uv_x = in_img_x.xz; + vec2 in_uv_y = in_img_y.xz / 2.0f; + in_uv_y = clamp (in_uv_y, 0.0f, float (in_img_height / 2u - 1u)); + geomap_uv (in_uv_x, in_uv_y, out_bound_uv, out_data); + } + out_buf_uv.data[g_y / 2u * out_img_width + g_x] = out_data; + + lut_y += step.y; + geomap_y (lut_x, lut_y, in_img_x, in_img_y, out_bound, out_data); + out_buf_y.data[(g_y + 1u) * out_img_width + g_x] = out_data; +} + +void geomap_y (vec4 lut_x, vec4 lut_y, out vec4 in_img_x, out vec4 in_img_y, out bvec4 out_bound, out uint out_data) +{ + uvec4 x00 = uvec4 (lut_x); + uvec4 y00 = uvec4 (lut_y); + uvec4 x01 = x00 + 1u; + uvec4 y01 = y00; + uvec4 x10 = x00; + uvec4 y10 = y00 + 1u; + uvec4 x11 = x01; + uvec4 y11 = y10; + + vec4 fract_x = fract (lut_x); + vec4 fract_y = fract (lut_y); + vec4 weight00 = (1.0f - fract_x) * (1.0f - fract_y); + vec4 weight01 = fract_x * (1.0f - fract_y); + vec4 weight10 = (1.0f - fract_x) * fract_y; + vec4 weight11 = fract_x * fract_y; + + uvec4 index00 = y00 * lut_width + x00; + uvec4 index01 = y01 * lut_width + x01; + uvec4 index10 = y10 * lut_width + x10; + uvec4 index11 = y11 * lut_width + x11; + + vec4 in_img_x00, in_img_x01, in_img_x10, in_img_x11; + vec4 in_img_y00, in_img_y01, in_img_y10, in_img_y11; + for (uint i = 0u; i < UNIT_SIZE; ++i) { + vec2 value = lut.data[index00[i]]; + in_img_x00[i] = value.x; + in_img_y00[i] = value.y; + value = lut.data[index01[i]]; + in_img_x01[i] = value.x; + in_img_y01[i] = value.y; + value = lut.data[index10[i]]; + in_img_x10[i] = value.x; + in_img_y10[i] = value.y; + value = lut.data[index11[i]]; + in_img_x11[i] = value.x; + in_img_y11[i] = value.y; + } + in_img_x = in_img_x00 * weight00 + in_img_x01 * weight01 + in_img_x10 * weight10 + in_img_x11 * weight11; + in_img_y = in_img_y00 * weight00 + in_img_y01 * weight01 + in_img_y10 * weight10 + in_img_y11 * weight11; + + for (uint i = 0u; i < UNIT_SIZE; ++i) { + out_bound[i] = in_img_x[i] < 0.0f || in_img_x[i] > float (in_img_width * UNIT_SIZE - 1u) || + in_img_y[i] < 0.0f || in_img_y[i] > float (in_img_height - 1u); + } + if (all (out_bound)) { + out_data = 0u; + return; + } + + x00 = uvec4 (in_img_x); + y00 = uvec4 (in_img_y); + x01 = x00 + 1u; + y01 = y00; + x10 = x00; + y10 = y00 + 1u; + x11 = x01; + y11 = y10; + + fract_x = fract (in_img_x); + fract_y = fract (in_img_y); + weight00 = (1.0f - fract_x) * (1.0f - fract_y); + weight01 = fract_x * (1.0f - fract_y); + weight10 = (1.0f - fract_x) * fract_y; + weight11 = fract_x * fract_y; + + uvec4 x00_floor = x00 / UNIT_SIZE; + uvec4 x01_floor = x01 / UNIT_SIZE; + uvec4 x10_floor = x10 / UNIT_SIZE; + uvec4 x11_floor = x11 / UNIT_SIZE; + uvec4 x00_fract = x00 % UNIT_SIZE; + uvec4 x01_fract = x01 % UNIT_SIZE; + uvec4 x10_fract = x10 % UNIT_SIZE; + uvec4 x11_fract = x11 % UNIT_SIZE; + + index00 = y00 * in_img_width + x00_floor; + index01 = y01 * in_img_width + x01_floor; + index10 = y10 * in_img_width + x10_floor; + index11 = y11 * in_img_width + x11_floor; + + // pixel Y-value + vec4 out_y00, out_y01, out_y10, out_y11; + unpack_unorm_y (0); + unpack_unorm_y (1); + unpack_unorm_y (2); + unpack_unorm_y (3); + + vec4 inter_y = out_y00 * weight00 + out_y01 * weight01 + out_y10 * weight10 + out_y11 * weight11; + out_data = packUnorm4x8 (inter_y * vec4 (not (out_bound))); +} + +void geomap_uv (vec2 in_uv_x, vec2 in_uv_y, bvec4 out_bound_uv, out uint out_data) +{ + uvec2 x00 = uvec2 (in_uv_x); + uvec2 y00 = uvec2 (in_uv_y); + uvec2 x01 = x00 + 1u; + uvec2 y01 = y00; + uvec2 x10 = x00; + uvec2 y10 = y00 + 1u; + uvec2 x11 = x01; + uvec2 y11 = y10; + + vec2 fract_x = fract (in_uv_x); + vec2 fract_y = fract (in_uv_y); + vec2 weight00 = (1.0f - fract_x) * (1.0f - fract_y); + vec2 weight01 = fract_x * (1.0f - fract_y); + vec2 weight10 = (1.0f - fract_x) * fract_y; + vec2 weight11 = fract_x * fract_y; + + uvec2 x00_floor = x00 / UNIT_SIZE; + uvec2 x01_floor = x01 / UNIT_SIZE; + uvec2 x10_floor = x10 / UNIT_SIZE; + uvec2 x11_floor = x11 / UNIT_SIZE; + uvec2 x00_fract = (x00 % UNIT_SIZE) / 2u; + uvec2 x01_fract = (x01 % UNIT_SIZE) / 2u; + uvec2 x10_fract = (x10 % UNIT_SIZE) / 2u; + uvec2 x11_fract = (x11 % UNIT_SIZE) / 2u; + + uvec2 index00 = y00 * in_img_width + x00_floor; + uvec2 index01 = y01 * in_img_width + x01_floor; + uvec2 index10 = y10 * in_img_width + x10_floor; + uvec2 index11 = y11 * in_img_width + x11_floor; + + // pixel UV-value + vec4 out_uv00, out_uv01, out_uv10, out_uv11; + vec4 value = unpackUnorm4x8 (in_buf_uv.data[index00.x]); + out_uv00.xy = x00_fract.x == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index01.x]); + out_uv01.xy = x01_fract.x == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index10.x]); + out_uv10.xy = x10_fract.x == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index11.x]); + out_uv11.xy = x11_fract.x == 0u ? value.xy : value.zw; + + value = unpackUnorm4x8 (in_buf_uv.data[index00.y]); + out_uv00.zw = x00_fract.y == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index01.y]); + out_uv01.zw = x01_fract.y == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index10.y]); + out_uv10.zw = x10_fract.y == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index11.y]); + out_uv11.zw = x11_fract.y == 0u ? value.xy : value.zw; + + vec4 inter_uv = out_uv00 * weight00.xxyy + out_uv01 * weight01.xxyy + + out_uv10 * weight10.xxyy + out_uv11 * weight11.xxyy; + inter_uv = inter_uv * vec4 (not (out_bound_uv)) + vec4 (out_bound_uv) * 0.5f; + out_data = packUnorm4x8 (inter_uv); +} diff --git a/shaders/glsl/shader_lap_trans_pyr.comp.sl b/shaders/glsl/shader_lap_trans_pyr.comp.sl new file mode 100644 index 0000000..128a3a2 --- /dev/null +++ b/shaders/glsl/shader_lap_trans_pyr.comp.sl @@ -0,0 +1,162 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBufY { + uvec2 data[]; +} in_buf_y; + +layout (binding = 1) readonly buffer InBufUV { + uvec2 data[]; +} in_buf_uv; + +layout (binding = 2) readonly buffer GaussScaleBufY { + uint data[]; +} gaussscale_buf_y; + +layout (binding = 3) readonly buffer GaussScaleBufUV { + uint data[]; +} gaussscale_buf_uv; + +layout (binding = 4) writeonly buffer OutBufY { + uvec2 data[]; +} out_buf_y; + +layout (binding = 5) writeonly buffer OutBufUV { + uvec2 data[]; +} out_buf_uv; + +uniform uint in_img_width; +uniform uint in_img_height; +uniform uint in_offset_x; + +uniform uint gaussscale_img_width; +uniform uint gaussscale_img_height; + +uniform uint merge_width; + +// normalization of half gray level +const float norm_half_gl = 128.0f / 255.0f; + +void lap_trans_y (uvec2 y_id, uvec2 gs_id); +void lap_trans_uv (uvec2 uv_id, uvec2 gs_id); + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + + uvec2 y_id = uvec2 (g_id.x, g_id.y * 4u); + y_id.x = clamp (y_id.x, 0u, merge_width - 1u); + + uvec2 gs_id = uvec2 (g_id.x, g_id.y * 2u); + gs_id.x = clamp (gs_id.x, 0u, gaussscale_img_width - 1u); + lap_trans_y (y_id, gs_id); + + y_id.y += 2u; + gs_id.y += 1u; + lap_trans_y (y_id, gs_id); + + uvec2 uv_id = uvec2 (y_id.x, g_id.y * 2u); + gs_id.y = g_id.y; + lap_trans_uv (uv_id, gs_id); +} + +void lap_trans_y (uvec2 y_id, uvec2 gs_id) +{ + y_id.y = clamp (y_id.y, 0u, in_img_height - 1u); + gs_id.y = clamp (gs_id.y, 0u, gaussscale_img_height - 1u); + + uint y_idx = y_id.y * in_img_width + in_offset_x + y_id.x; + uvec2 in_pack = in_buf_y.data[y_idx]; + vec4 in0 = unpackUnorm4x8 (in_pack.x); + vec4 in1 = unpackUnorm4x8 (in_pack.y); + + uint gs_idx = gs_id.y * gaussscale_img_width + gs_id.x; + vec4 gs0 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx]); + vec4 gs1 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx + 1u]); + gs1 = (gs_id.x == gaussscale_img_width - 1u) ? gs0.wwww : gs1; + + vec4 inter = (gs0 + vec4 (gs0.yzw, gs1.x)) * 0.5f; + vec4 inter00 = vec4 (gs0.x, inter.x, gs0.y, inter.y); + vec4 inter01 = vec4 (gs0.z, inter.z, gs0.w, inter.w); + + vec4 lap0 = (in0 - inter00) * 0.5f + norm_half_gl; + vec4 lap1 = (in1 - inter01) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + uint out_idx = y_id.y * merge_width + y_id.x; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); + + y_idx = (y_id.y >= in_img_height - 1u) ? y_idx : y_idx + in_img_width; + in_pack = in_buf_y.data[y_idx]; + in0 = unpackUnorm4x8 (in_pack.x); + in1 = unpackUnorm4x8 (in_pack.y); + + gs_idx = (gs_id.y >= gaussscale_img_height - 1u) ? gs_idx : gs_idx + gaussscale_img_width; + gs0 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx]); + gs1 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx + 1u]); + gs1 = (gs_id.x == gaussscale_img_width - 1u) ? gs0.wwww : gs1; + + inter = (gs0 + vec4 (gs0.yzw, gs1.x)) * 0.5f; + vec4 inter10 = (inter00 + vec4 (gs0.x, inter.x, gs0.y, inter.y)) * 0.5f; + vec4 inter11 = (inter01 + vec4 (gs0.z, inter.z, gs0.w, inter.w)) * 0.5f; + + lap0 = (in0 - inter10) * 0.5f + norm_half_gl; + lap1 = (in1 - inter11) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + out_idx += merge_width; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); +} + +void lap_trans_uv (uvec2 uv_id, uvec2 gs_id) +{ + uv_id.y = clamp (uv_id.y, 0u, in_img_height / 2u - 1u); + gs_id.y = clamp (gs_id.y, 0u, gaussscale_img_height / 2u - 1u); + + uint uv_idx = uv_id.y * in_img_width + in_offset_x + uv_id.x; + uvec2 in_pack = in_buf_uv.data[uv_idx]; + vec4 in0 = unpackUnorm4x8 (in_pack.x); + vec4 in1 = unpackUnorm4x8 (in_pack.y); + + uint gs_idx = gs_id.y * gaussscale_img_width + gs_id.x; + vec4 gs0 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx]); + vec4 gs1 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx + 1u]); + gs1 = (gs_id.x == gaussscale_img_width - 1u) ? gs0.zwzw : gs1; + + vec4 inter = (gs0 + vec4 (gs0.zw, gs1.xy)) * 0.5f; + vec4 inter00 = vec4 (gs0.xy, inter.xy); + vec4 inter01 = vec4 (gs0.zw, inter.zw); + + vec4 lap0 = (in0 - inter00) * 0.5f + norm_half_gl; + vec4 lap1 = (in1 - inter01) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + uint out_idx = uv_id.y * merge_width + uv_id.x; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); + + uv_idx = (uv_id.y >= (in_img_height / 2u - 1u)) ? uv_idx : uv_idx + in_img_width; + in_pack = in_buf_uv.data[uv_idx]; + in0 = unpackUnorm4x8 (in_pack.x); + in1 = unpackUnorm4x8 (in_pack.y); + + gs_idx = (gs_id.y >= (gaussscale_img_height / 2u - 1u)) ? gs_idx : gs_idx + gaussscale_img_width; + gs0 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx]); + gs1 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx + 1u]); + gs1 = (gs_id.x == gaussscale_img_width - 1u) ? gs0.zwzw : gs1; + + inter = (gs0 + vec4 (gs0.zw, gs1.xy)) * 0.5f; + vec4 inter10 = (inter00 + vec4 (gs0.xy, inter.xy)) * 0.5f; + vec4 inter11 = (inter01 + vec4 (gs0.zw, inter.zw)) * 0.5f; + + lap0 = (in0 - inter10) * 0.5f + norm_half_gl; + lap1 = (in1 - inter11) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + out_idx += merge_width; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); +} diff --git a/shaders/glsl/shader_reconstruct_pyr.comp.sl b/shaders/glsl/shader_reconstruct_pyr.comp.sl new file mode 100644 index 0000000..d5537b9 --- /dev/null +++ b/shaders/glsl/shader_reconstruct_pyr.comp.sl @@ -0,0 +1,219 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer Lap0BufY { + uvec2 data[]; +} lap0_buf_y; + +layout (binding = 1) readonly buffer Lap0BufUV { + uvec2 data[]; +} lap0_buf_uv; + +layout (binding = 2) readonly buffer Lap1BufY { + uvec2 data[]; +} lap1_buf_y; + +layout (binding = 3) readonly buffer Lap1BufUV { + uvec2 data[]; +} lap1_buf_uv; + +layout (binding = 4) writeonly buffer OutBufY { + uvec2 data[]; +} out_buf_y; + +layout (binding = 5) writeonly buffer OutBufUV { + uvec2 data[]; +} out_buf_uv; + +layout (binding = 6) readonly buffer PrevBlendBufY { + uint data[]; +} prev_blend_y; + +layout (binding = 7) readonly buffer PrevBlendBufUV { + uint data[]; +} prev_blend_uv; + +layout (binding = 8) readonly buffer MaskBuf { + uvec2 data[]; +} mask_buf; + +uniform uint lap_img_width; +uniform uint lap_img_height; + +uniform uint out_img_width; +uniform uint out_offset_x; + +uniform uint prev_blend_img_width; +uniform uint prev_blend_img_height; + +// normalization of gray level +const float norm_gl = 256.0f / 255.0f; + +void reconstruct_y (uvec2 y_id, uvec2 blend_id); +void reconstruct_uv (uvec2 uv_id, uvec2 blend_id); + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + + uvec2 y_id = uvec2 (g_id.x, g_id.y * 4u); + y_id.x = clamp (y_id.x, 0u, lap_img_width - 1u); + + uvec2 blend_id = uvec2 (g_id.x, g_id.y * 2u); + blend_id.x = clamp (blend_id.x, 0u, prev_blend_img_width - 1u); + reconstruct_y (y_id, blend_id); + + y_id.y += 2u; + blend_id.y += 1u; + reconstruct_y (y_id, blend_id); + + uvec2 uv_id = uvec2 (g_id.x, g_id.y * 2u); + uv_id.x = clamp (uv_id.x, 0u, lap_img_width - 1u); + blend_id = g_id; + blend_id.x = clamp (blend_id.x, 0u, prev_blend_img_width - 1u); + reconstruct_uv (uv_id, blend_id); +} + +void reconstruct_y (uvec2 y_id, uvec2 blend_id) +{ + y_id.y = clamp (y_id.y, 0u, lap_img_height - 1u); + blend_id.y = clamp (blend_id.y, 0u, prev_blend_img_height - 1u); + + uvec2 mask = mask_buf.data[y_id.x]; + vec4 mask0 = unpackUnorm4x8 (mask.x); + vec4 mask1 = unpackUnorm4x8 (mask.y); + + uint idx = y_id.y * lap_img_width + y_id.x; + uvec2 lap = lap0_buf_y.data[idx]; + vec4 lap00 = unpackUnorm4x8 (lap.x); + vec4 lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_y.data[idx]; + vec4 lap10 = unpackUnorm4x8 (lap.x); + vec4 lap11 = unpackUnorm4x8 (lap.y); + + vec4 lap_blend0 = (lap00 - lap10) * mask0 + lap10; + vec4 lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + uint prev_blend_idx = blend_id.y * prev_blend_img_width + blend_id.x; + vec4 prev_blend0 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx]); + vec4 prev_blend1 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prev_blend_img_width - 1u) ? prev_blend0.wwww : prev_blend1; + + vec4 inter = (prev_blend0 + vec4 (prev_blend0.yzw, prev_blend1.x)) * 0.5f; + vec4 prev_blend_inter00 = vec4 (prev_blend0.x, inter.x, prev_blend0.y, inter.y); + vec4 prev_blend_inter01 = vec4 (prev_blend0.z, inter.z, prev_blend0.w, inter.w); + + vec4 out0 = prev_blend_inter00 + lap_blend0 * 2.0f - norm_gl; + vec4 out1 = prev_blend_inter01 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + uint out_idx = y_id.y * out_img_width + out_offset_x + y_id.x; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); + + idx = (y_id.y >= lap_img_height - 1u) ? idx : idx + lap_img_width; + lap = lap0_buf_y.data[idx]; + lap00 = unpackUnorm4x8 (lap.x); + lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_y.data[idx]; + lap10 = unpackUnorm4x8 (lap.x); + lap11 = unpackUnorm4x8 (lap.y); + + lap_blend0 = (lap00 - lap10) * mask0 + lap10; + lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + prev_blend_idx = (blend_id.y >= prev_blend_img_height - 1u) ? prev_blend_idx : prev_blend_idx + prev_blend_img_width; + prev_blend0 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx]); + prev_blend1 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prev_blend_img_width - 1u) ? prev_blend0.wwww : prev_blend1; + + inter = (prev_blend0 + vec4 (prev_blend0.yzw, prev_blend1.x)) * 0.5f; + vec4 prev_blend_inter10 = vec4 (prev_blend0.x, inter.x, prev_blend0.y, inter.y); + vec4 prev_blend_inter11 = vec4 (prev_blend0.z, inter.z, prev_blend0.w, inter.w); + prev_blend_inter10 = (prev_blend_inter00 + prev_blend_inter10) * 0.5f; + prev_blend_inter11 = (prev_blend_inter01 + prev_blend_inter11) * 0.5f; + + out0 = prev_blend_inter10 + lap_blend0 * 2.0f - norm_gl; + out1 = prev_blend_inter11 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + out_idx += out_img_width; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); +} + +void reconstruct_uv (uvec2 uv_id, uvec2 blend_id) +{ + uv_id.y = clamp (uv_id.y, 0u, lap_img_height / 2u - 1u); + blend_id.y = clamp (blend_id.y, 0u, prev_blend_img_height / 2u - 1u); + + uvec2 mask = mask_buf.data[uv_id.x]; + vec4 mask0 = unpackUnorm4x8 (mask.x); + vec4 mask1 = unpackUnorm4x8 (mask.y); + + uint idx = uv_id.y * lap_img_width + uv_id.x; + uvec2 lap = lap0_buf_uv.data[idx]; + vec4 lap00 = unpackUnorm4x8 (lap.x); + vec4 lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_uv.data[idx]; + vec4 lap10 = unpackUnorm4x8 (lap.x); + vec4 lap11 = unpackUnorm4x8 (lap.y); + + mask0.yw = mask0.xz; + mask1.yw = mask1.xz; + vec4 lap_blend0 = (lap00 - lap10) * mask0 + lap10; + vec4 lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + uint prev_blend_idx = blend_id.y * prev_blend_img_width + blend_id.x; + vec4 prev_blend0 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx]); + vec4 prev_blend1 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prev_blend_img_width - 1u) ? prev_blend0.zwzw : prev_blend1; + + vec4 inter = (prev_blend0 + vec4 (prev_blend0.zw, prev_blend1.xy)) * 0.5f; + vec4 prev_blend_inter00 = vec4 (prev_blend0.xy, inter.xy); + vec4 prev_blend_inter01 = vec4 (prev_blend0.zw, inter.zw); + + vec4 out0 = prev_blend_inter00 + lap_blend0 * 2.0f - norm_gl; + vec4 out1 = prev_blend_inter01 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + uint out_idx = uv_id.y * out_img_width + out_offset_x + uv_id.x; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); + + idx = (uv_id.y >= (lap_img_height / 2u - 1u)) ? idx : idx + lap_img_width; + lap = lap0_buf_uv.data[idx]; + lap00 = unpackUnorm4x8 (lap.x); + lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_uv.data[idx]; + lap10 = unpackUnorm4x8 (lap.x); + lap11 = unpackUnorm4x8 (lap.y); + + lap_blend0 = (lap00 - lap10) * mask0 + lap10; + lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + prev_blend_idx = (blend_id.y >= (prev_blend_img_height / 2u - 1u)) ? + prev_blend_idx : prev_blend_idx + prev_blend_img_width; + prev_blend0 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx]); + prev_blend1 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prev_blend_img_width - 1u) ? prev_blend0.zwzw : prev_blend1; + + inter = (prev_blend0 + vec4 (prev_blend0.zw, prev_blend1.xy)) * 0.5f; + vec4 prev_blend_inter10 = vec4 (prev_blend0.xy, inter.xy); + vec4 prev_blend_inter11 = vec4 (prev_blend0.zw, inter.zw); + prev_blend_inter10 = (prev_blend_inter00 + prev_blend_inter10) * 0.5f; + prev_blend_inter11 = (prev_blend_inter01 + prev_blend_inter11) * 0.5f; + + out0 = prev_blend_inter10 + lap_blend0 * 2.0f - norm_gl; + out1 = prev_blend_inter11 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + out_idx += out_img_width; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); +} diff --git a/shaders/glslx/.gitignore b/shaders/glslx/.gitignore new file mode 100644 index 0000000..c161cb9 --- /dev/null +++ b/shaders/glslx/.gitignore @@ -0,0 +1 @@ +*.slx diff --git a/shaders/glslx/Makefile.am b/shaders/glslx/Makefile.am new file mode 100644 index 0000000..9be760e --- /dev/null +++ b/shaders/glslx/Makefile.am @@ -0,0 +1,20 @@ +glslx_sources = \ + shader_copy.comp.slx \ + shader_geomap.comp.slx \ + shader_gauss_scale_pyr.comp.slx \ + shader_lap_trans_pyr.comp.slx \ + shader_blend_pyr.comp.slx \ + shader_reconstruct_pyr.comp.slx \ + $(NULL) + +add_quotation_marks_sh = \ + $(top_srcdir)/tools/add-quotation-marks.sh + +glsl_dir = $(top_srcdir)/shaders/glsl + +all-local: $(glslx_sources) + +$(glslx_sources): %.slx: $(glsl_dir)/%.sl + @$(add_quotation_marks_sh) $< $@ + +CLEANFILES = $(glslx_sources) diff --git a/shaders/spv/shader_blend_pyr.comp b/shaders/spv/shader_blend_pyr.comp new file mode 100644 index 0000000..77ff1a9 --- /dev/null +++ b/shaders/spv/shader_blend_pyr.comp @@ -0,0 +1,93 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer In0BufY { + uvec2 data[]; +} in0_buf_y; + +layout (binding = 1) readonly buffer In0BufUV { + uvec2 data[]; +} in0_buf_uv; + +layout (binding = 2) readonly buffer In1BufY { + uvec2 data[]; +} in1_buf_y; + +layout (binding = 3) readonly buffer In1BufUV { + uvec2 data[]; +} in1_buf_uv; + +layout (binding = 4) writeonly buffer OutBufY { + uvec2 data[]; +} out_buf_y; + +layout (binding = 5) writeonly buffer OutBufUV { + uvec2 data[]; +} out_buf_uv; + +layout (binding = 6) readonly buffer MaskBuf { + uvec2 data[]; +} mask_buf; + +layout (push_constant) uniform PushConsts { + uint in_img_width; +} prop; + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + g_id.x = clamp (g_id.x, 0u, prop.in_img_width - 1u); + + uvec2 mask = mask_buf.data[g_id.x]; + vec4 mask0 = unpackUnorm4x8 (mask.x); + vec4 mask1 = unpackUnorm4x8 (mask.y); + + uint y_idx = g_id.y * 2u * prop.in_img_width + g_id.x; + uvec2 in0_y = in0_buf_y.data[y_idx]; + vec4 in0_y0 = unpackUnorm4x8 (in0_y.x); + vec4 in0_y1 = unpackUnorm4x8 (in0_y.y); + + uvec2 in1_y = in1_buf_y.data[y_idx]; + vec4 in1_y0 = unpackUnorm4x8 (in1_y.x); + vec4 in1_y1 = unpackUnorm4x8 (in1_y.y); + + vec4 out_y0 = (in0_y0 - in1_y0) * mask0 + in1_y0; + vec4 out_y1 = (in0_y1 - in1_y1) * mask1 + in1_y1; + out_y0 = clamp (out_y0, 0.0f, 1.0f); + out_y1 = clamp (out_y1, 0.0f, 1.0f); + out_buf_y.data[y_idx] = uvec2 (packUnorm4x8 (out_y0), packUnorm4x8 (out_y1)); + + y_idx += prop.in_img_width; + in0_y = in0_buf_y.data[y_idx]; + in0_y0 = unpackUnorm4x8 (in0_y.x); + in0_y1 = unpackUnorm4x8 (in0_y.y); + + in1_y = in1_buf_y.data[y_idx]; + in1_y0 = unpackUnorm4x8 (in1_y.x); + in1_y1 = unpackUnorm4x8 (in1_y.y); + + out_y0 = (in0_y0 - in1_y0) * mask0 + in1_y0; + out_y1 = (in0_y1 - in1_y1) * mask1 + in1_y1; + out_y0 = clamp (out_y0, 0.0f, 1.0f); + out_y1 = clamp (out_y1, 0.0f, 1.0f); + out_buf_y.data[y_idx] = uvec2 (packUnorm4x8 (out_y0), packUnorm4x8 (out_y1)); + + uint uv_idx = g_id.y * prop.in_img_width + g_id.x; + uvec2 in0_uv = in0_buf_uv.data[uv_idx]; + vec4 in0_uv0 = unpackUnorm4x8 (in0_uv.x); + vec4 in0_uv1 = unpackUnorm4x8 (in0_uv.y); + + uvec2 in1_uv = in1_buf_uv.data[uv_idx]; + vec4 in1_uv0 = unpackUnorm4x8 (in1_uv.x); + vec4 in1_uv1 = unpackUnorm4x8 (in1_uv.y); + + mask0.yw = mask0.xz; + mask1.yw = mask1.xz; + vec4 out_uv0 = (in0_uv0 - in1_uv0) * mask0 + in1_uv0; + vec4 out_uv1 = (in0_uv1 - in1_uv1) * mask1 + in1_uv1; + + out_uv0 = clamp (out_uv0, 0.0f, 1.0f); + out_uv1 = clamp (out_uv1, 0.0f, 1.0f); + out_buf_uv.data[uv_idx] = uvec2 (packUnorm4x8 (out_uv0), packUnorm4x8 (out_uv1)); +} diff --git a/shaders/spv/shader_blend_pyr.comp.spv b/shaders/spv/shader_blend_pyr.comp.spv new file mode 100644 index 0000000..9f1d33a --- /dev/null +++ b/shaders/spv/shader_blend_pyr.comp.spv @@ -0,0 +1,228 @@ + // 7.8.2870 + 0x07230203,0x00010000,0x00080007,0x0000010e,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000005,0x00000004,0x6e69616d,0x00000000,0x0000000c,0x00060010,0x00000004, + 0x00000011,0x00000008,0x00000008,0x00000001,0x00030003,0x00000001,0x00000136,0x00040005, + 0x00000004,0x6e69616d,0x00000000,0x00040005,0x00000009,0x64695f67,0x00000000,0x00080005, + 0x0000000c,0x475f6c67,0x61626f6c,0x766e496c,0x7461636f,0x496e6f69,0x00000044,0x00050005, + 0x00000013,0x68737550,0x736e6f43,0x00007374,0x00070006,0x00000013,0x00000000,0x695f6e69, + 0x775f676d,0x68746469,0x00000000,0x00040005,0x00000015,0x706f7270,0x00000000,0x00040005, + 0x0000001f,0x6b73616d,0x00000000,0x00040005,0x00000021,0x6b73614d,0x00667542,0x00050006, + 0x00000021,0x00000000,0x61746164,0x00000000,0x00050005,0x00000023,0x6b73616d,0x6675625f, + 0x00000000,0x00040005,0x0000002c,0x6b73616d,0x00000030,0x00040005,0x00000030,0x6b73616d, + 0x00000031,0x00040005,0x00000034,0x64695f79,0x00000078,0x00040005,0x0000003f,0x5f306e69, + 0x00000079,0x00040005,0x00000041,0x42306e49,0x00596675,0x00050006,0x00000041,0x00000000, + 0x61746164,0x00000000,0x00050005,0x00000043,0x5f306e69,0x5f667562,0x00000079,0x00040005, + 0x00000047,0x5f306e69,0x00003079,0x00040005,0x0000004b,0x5f306e69,0x00003179,0x00040005, + 0x0000004f,0x5f316e69,0x00000079,0x00040005,0x00000051,0x42316e49,0x00596675,0x00050006, + 0x00000051,0x00000000,0x61746164,0x00000000,0x00050005,0x00000053,0x5f316e69,0x5f667562, + 0x00000079,0x00040005,0x00000057,0x5f316e69,0x00003079,0x00040005,0x0000005b,0x5f316e69, + 0x00003179,0x00040005,0x0000005f,0x5f74756f,0x00003079,0x00040005,0x00000067,0x5f74756f, + 0x00003179,0x00040005,0x0000007a,0x4274754f,0x00596675,0x00050006,0x0000007a,0x00000000, + 0x61746164,0x00000000,0x00050005,0x0000007c,0x5f74756f,0x5f667562,0x00000079,0x00040005, + 0x000000b7,0x695f7675,0x00007864,0x00040005,0x000000c0,0x5f306e69,0x00007675,0x00050005, + 0x000000c2,0x42306e49,0x56556675,0x00000000,0x00050006,0x000000c2,0x00000000,0x61746164, + 0x00000000,0x00050005,0x000000c4,0x5f306e69,0x5f667562,0x00007675,0x00040005,0x000000c8, + 0x5f306e69,0x00307675,0x00040005,0x000000cc,0x5f306e69,0x00317675,0x00040005,0x000000d0, + 0x5f316e69,0x00007675,0x00050005,0x000000d2,0x42316e49,0x56556675,0x00000000,0x00050006, + 0x000000d2,0x00000000,0x61746164,0x00000000,0x00050005,0x000000d4,0x5f316e69,0x5f667562, + 0x00007675,0x00040005,0x000000d8,0x5f316e69,0x00307675,0x00040005,0x000000dc,0x5f316e69, + 0x00317675,0x00040005,0x000000e9,0x5f74756f,0x00307675,0x00040005,0x000000f1,0x5f74756f, + 0x00317675,0x00050005,0x00000102,0x4274754f,0x56556675,0x00000000,0x00050006,0x00000102, + 0x00000000,0x61746164,0x00000000,0x00050005,0x00000104,0x5f74756f,0x5f667562,0x00007675, + 0x00040047,0x0000000c,0x0000000b,0x0000001c,0x00050048,0x00000013,0x00000000,0x00000023, + 0x00000000,0x00030047,0x00000013,0x00000002,0x00040047,0x00000020,0x00000006,0x00000008, + 0x00040048,0x00000021,0x00000000,0x00000018,0x00050048,0x00000021,0x00000000,0x00000023, + 0x00000000,0x00030047,0x00000021,0x00000003,0x00040047,0x00000023,0x00000022,0x00000000, + 0x00040047,0x00000023,0x00000021,0x00000006,0x00040047,0x00000040,0x00000006,0x00000008, + 0x00040048,0x00000041,0x00000000,0x00000018,0x00050048,0x00000041,0x00000000,0x00000023, + 0x00000000,0x00030047,0x00000041,0x00000003,0x00040047,0x00000043,0x00000022,0x00000000, + 0x00040047,0x00000043,0x00000021,0x00000000,0x00040047,0x00000050,0x00000006,0x00000008, + 0x00040048,0x00000051,0x00000000,0x00000018,0x00050048,0x00000051,0x00000000,0x00000023, + 0x00000000,0x00030047,0x00000051,0x00000003,0x00040047,0x00000053,0x00000022,0x00000000, + 0x00040047,0x00000053,0x00000021,0x00000002,0x00040047,0x00000079,0x00000006,0x00000008, + 0x00040048,0x0000007a,0x00000000,0x00000019,0x00050048,0x0000007a,0x00000000,0x00000023, + 0x00000000,0x00030047,0x0000007a,0x00000003,0x00040047,0x0000007c,0x00000022,0x00000000, + 0x00040047,0x0000007c,0x00000021,0x00000004,0x00040047,0x000000c1,0x00000006,0x00000008, + 0x00040048,0x000000c2,0x00000000,0x00000018,0x00050048,0x000000c2,0x00000000,0x00000023, + 0x00000000,0x00030047,0x000000c2,0x00000003,0x00040047,0x000000c4,0x00000022,0x00000000, + 0x00040047,0x000000c4,0x00000021,0x00000001,0x00040047,0x000000d1,0x00000006,0x00000008, + 0x00040048,0x000000d2,0x00000000,0x00000018,0x00050048,0x000000d2,0x00000000,0x00000023, + 0x00000000,0x00030047,0x000000d2,0x00000003,0x00040047,0x000000d4,0x00000022,0x00000000, + 0x00040047,0x000000d4,0x00000021,0x00000003,0x00040047,0x00000101,0x00000006,0x00000008, + 0x00040048,0x00000102,0x00000000,0x00000019,0x00050048,0x00000102,0x00000000,0x00000023, + 0x00000000,0x00030047,0x00000102,0x00000003,0x00040047,0x00000104,0x00000022,0x00000000, + 0x00040047,0x00000104,0x00000021,0x00000005,0x00040047,0x0000010d,0x0000000b,0x00000019, + 0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00040015,0x00000006,0x00000020, + 0x00000000,0x00040017,0x00000007,0x00000006,0x00000002,0x00040020,0x00000008,0x00000007, + 0x00000007,0x00040017,0x0000000a,0x00000006,0x00000003,0x00040020,0x0000000b,0x00000001, + 0x0000000a,0x0004003b,0x0000000b,0x0000000c,0x00000001,0x0004002b,0x00000006,0x0000000f, + 0x00000000,0x00040020,0x00000010,0x00000007,0x00000006,0x0003001e,0x00000013,0x00000006, + 0x00040020,0x00000014,0x00000009,0x00000013,0x0004003b,0x00000014,0x00000015,0x00000009, + 0x00040015,0x00000016,0x00000020,0x00000001,0x0004002b,0x00000016,0x00000017,0x00000000, + 0x00040020,0x00000018,0x00000009,0x00000006,0x0004002b,0x00000006,0x0000001b,0x00000001, + 0x0003001d,0x00000020,0x00000007,0x0003001e,0x00000021,0x00000020,0x00040020,0x00000022, + 0x00000002,0x00000021,0x0004003b,0x00000022,0x00000023,0x00000002,0x00040020,0x00000026, + 0x00000002,0x00000007,0x00030016,0x00000029,0x00000020,0x00040017,0x0000002a,0x00000029, + 0x00000004,0x00040020,0x0000002b,0x00000007,0x0000002a,0x0004002b,0x00000006,0x00000037, + 0x00000002,0x0003001d,0x00000040,0x00000007,0x0003001e,0x00000041,0x00000040,0x00040020, + 0x00000042,0x00000002,0x00000041,0x0004003b,0x00000042,0x00000043,0x00000002,0x0003001d, + 0x00000050,0x00000007,0x0003001e,0x00000051,0x00000050,0x00040020,0x00000052,0x00000002, + 0x00000051,0x0004003b,0x00000052,0x00000053,0x00000002,0x0004002b,0x00000029,0x00000070, + 0x00000000,0x0004002b,0x00000029,0x00000071,0x3f800000,0x0003001d,0x00000079,0x00000007, + 0x0003001e,0x0000007a,0x00000079,0x00040020,0x0000007b,0x00000002,0x0000007a,0x0004003b, + 0x0000007b,0x0000007c,0x00000002,0x0003001d,0x000000c1,0x00000007,0x0003001e,0x000000c2, + 0x000000c1,0x00040020,0x000000c3,0x00000002,0x000000c2,0x0004003b,0x000000c3,0x000000c4, + 0x00000002,0x0003001d,0x000000d1,0x00000007,0x0003001e,0x000000d2,0x000000d1,0x00040020, + 0x000000d3,0x00000002,0x000000d2,0x0004003b,0x000000d3,0x000000d4,0x00000002,0x00040017, + 0x000000e0,0x00000029,0x00000002,0x0003001d,0x00000101,0x00000007,0x0003001e,0x00000102, + 0x00000101,0x00040020,0x00000103,0x00000002,0x00000102,0x0004003b,0x00000103,0x00000104, + 0x00000002,0x0004002b,0x00000006,0x0000010c,0x00000008,0x0006002c,0x0000000a,0x0000010d, + 0x0000010c,0x0000010c,0x0000001b,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003, + 0x000200f8,0x00000005,0x0004003b,0x00000008,0x00000009,0x00000007,0x0004003b,0x00000008, + 0x0000001f,0x00000007,0x0004003b,0x0000002b,0x0000002c,0x00000007,0x0004003b,0x0000002b, + 0x00000030,0x00000007,0x0004003b,0x00000010,0x00000034,0x00000007,0x0004003b,0x00000008, + 0x0000003f,0x00000007,0x0004003b,0x0000002b,0x00000047,0x00000007,0x0004003b,0x0000002b, + 0x0000004b,0x00000007,0x0004003b,0x00000008,0x0000004f,0x00000007,0x0004003b,0x0000002b, + 0x00000057,0x00000007,0x0004003b,0x0000002b,0x0000005b,0x00000007,0x0004003b,0x0000002b, + 0x0000005f,0x00000007,0x0004003b,0x0000002b,0x00000067,0x00000007,0x0004003b,0x00000010, + 0x000000b7,0x00000007,0x0004003b,0x00000008,0x000000c0,0x00000007,0x0004003b,0x0000002b, + 0x000000c8,0x00000007,0x0004003b,0x0000002b,0x000000cc,0x00000007,0x0004003b,0x00000008, + 0x000000d0,0x00000007,0x0004003b,0x0000002b,0x000000d8,0x00000007,0x0004003b,0x0000002b, + 0x000000dc,0x00000007,0x0004003b,0x0000002b,0x000000e9,0x00000007,0x0004003b,0x0000002b, + 0x000000f1,0x00000007,0x0004003d,0x0000000a,0x0000000d,0x0000000c,0x0007004f,0x00000007, + 0x0000000e,0x0000000d,0x0000000d,0x00000000,0x00000001,0x0003003e,0x00000009,0x0000000e, + 0x00050041,0x00000010,0x00000011,0x00000009,0x0000000f,0x0004003d,0x00000006,0x00000012, + 0x00000011,0x00050041,0x00000018,0x00000019,0x00000015,0x00000017,0x0004003d,0x00000006, + 0x0000001a,0x00000019,0x00050082,0x00000006,0x0000001c,0x0000001a,0x0000001b,0x0008000c, + 0x00000006,0x0000001d,0x00000001,0x0000002c,0x00000012,0x0000000f,0x0000001c,0x00050041, + 0x00000010,0x0000001e,0x00000009,0x0000000f,0x0003003e,0x0000001e,0x0000001d,0x00050041, + 0x00000010,0x00000024,0x00000009,0x0000000f,0x0004003d,0x00000006,0x00000025,0x00000024, + 0x00060041,0x00000026,0x00000027,0x00000023,0x00000017,0x00000025,0x0004003d,0x00000007, + 0x00000028,0x00000027,0x0003003e,0x0000001f,0x00000028,0x00050041,0x00000010,0x0000002d, + 0x0000001f,0x0000000f,0x0004003d,0x00000006,0x0000002e,0x0000002d,0x0006000c,0x0000002a, + 0x0000002f,0x00000001,0x00000040,0x0000002e,0x0003003e,0x0000002c,0x0000002f,0x00050041, + 0x00000010,0x00000031,0x0000001f,0x0000001b,0x0004003d,0x00000006,0x00000032,0x00000031, + 0x0006000c,0x0000002a,0x00000033,0x00000001,0x00000040,0x00000032,0x0003003e,0x00000030, + 0x00000033,0x00050041,0x00000010,0x00000035,0x00000009,0x0000001b,0x0004003d,0x00000006, + 0x00000036,0x00000035,0x00050084,0x00000006,0x00000038,0x00000036,0x00000037,0x00050041, + 0x00000018,0x00000039,0x00000015,0x00000017,0x0004003d,0x00000006,0x0000003a,0x00000039, + 0x00050084,0x00000006,0x0000003b,0x00000038,0x0000003a,0x00050041,0x00000010,0x0000003c, + 0x00000009,0x0000000f,0x0004003d,0x00000006,0x0000003d,0x0000003c,0x00050080,0x00000006, + 0x0000003e,0x0000003b,0x0000003d,0x0003003e,0x00000034,0x0000003e,0x0004003d,0x00000006, + 0x00000044,0x00000034,0x00060041,0x00000026,0x00000045,0x00000043,0x00000017,0x00000044, + 0x0004003d,0x00000007,0x00000046,0x00000045,0x0003003e,0x0000003f,0x00000046,0x00050041, + 0x00000010,0x00000048,0x0000003f,0x0000000f,0x0004003d,0x00000006,0x00000049,0x00000048, + 0x0006000c,0x0000002a,0x0000004a,0x00000001,0x00000040,0x00000049,0x0003003e,0x00000047, + 0x0000004a,0x00050041,0x00000010,0x0000004c,0x0000003f,0x0000001b,0x0004003d,0x00000006, + 0x0000004d,0x0000004c,0x0006000c,0x0000002a,0x0000004e,0x00000001,0x00000040,0x0000004d, + 0x0003003e,0x0000004b,0x0000004e,0x0004003d,0x00000006,0x00000054,0x00000034,0x00060041, + 0x00000026,0x00000055,0x00000053,0x00000017,0x00000054,0x0004003d,0x00000007,0x00000056, + 0x00000055,0x0003003e,0x0000004f,0x00000056,0x00050041,0x00000010,0x00000058,0x0000004f, + 0x0000000f,0x0004003d,0x00000006,0x00000059,0x00000058,0x0006000c,0x0000002a,0x0000005a, + 0x00000001,0x00000040,0x00000059,0x0003003e,0x00000057,0x0000005a,0x00050041,0x00000010, + 0x0000005c,0x0000004f,0x0000001b,0x0004003d,0x00000006,0x0000005d,0x0000005c,0x0006000c, + 0x0000002a,0x0000005e,0x00000001,0x00000040,0x0000005d,0x0003003e,0x0000005b,0x0000005e, + 0x0004003d,0x0000002a,0x00000060,0x00000047,0x0004003d,0x0000002a,0x00000061,0x00000057, + 0x00050083,0x0000002a,0x00000062,0x00000060,0x00000061,0x0004003d,0x0000002a,0x00000063, + 0x0000002c,0x00050085,0x0000002a,0x00000064,0x00000062,0x00000063,0x0004003d,0x0000002a, + 0x00000065,0x00000057,0x00050081,0x0000002a,0x00000066,0x00000064,0x00000065,0x0003003e, + 0x0000005f,0x00000066,0x0004003d,0x0000002a,0x00000068,0x0000004b,0x0004003d,0x0000002a, + 0x00000069,0x0000005b,0x00050083,0x0000002a,0x0000006a,0x00000068,0x00000069,0x0004003d, + 0x0000002a,0x0000006b,0x00000030,0x00050085,0x0000002a,0x0000006c,0x0000006a,0x0000006b, + 0x0004003d,0x0000002a,0x0000006d,0x0000005b,0x00050081,0x0000002a,0x0000006e,0x0000006c, + 0x0000006d,0x0003003e,0x00000067,0x0000006e,0x0004003d,0x0000002a,0x0000006f,0x0000005f, + 0x00070050,0x0000002a,0x00000072,0x00000070,0x00000070,0x00000070,0x00000070,0x00070050, + 0x0000002a,0x00000073,0x00000071,0x00000071,0x00000071,0x00000071,0x0008000c,0x0000002a, + 0x00000074,0x00000001,0x0000002b,0x0000006f,0x00000072,0x00000073,0x0003003e,0x0000005f, + 0x00000074,0x0004003d,0x0000002a,0x00000075,0x00000067,0x00070050,0x0000002a,0x00000076, + 0x00000070,0x00000070,0x00000070,0x00000070,0x00070050,0x0000002a,0x00000077,0x00000071, + 0x00000071,0x00000071,0x00000071,0x0008000c,0x0000002a,0x00000078,0x00000001,0x0000002b, + 0x00000075,0x00000076,0x00000077,0x0003003e,0x00000067,0x00000078,0x0004003d,0x00000006, + 0x0000007d,0x00000034,0x0004003d,0x0000002a,0x0000007e,0x0000005f,0x0006000c,0x00000006, + 0x0000007f,0x00000001,0x00000037,0x0000007e,0x0004003d,0x0000002a,0x00000080,0x00000067, + 0x0006000c,0x00000006,0x00000081,0x00000001,0x00000037,0x00000080,0x00050050,0x00000007, + 0x00000082,0x0000007f,0x00000081,0x00060041,0x00000026,0x00000083,0x0000007c,0x00000017, + 0x0000007d,0x0003003e,0x00000083,0x00000082,0x00050041,0x00000018,0x00000084,0x00000015, + 0x00000017,0x0004003d,0x00000006,0x00000085,0x00000084,0x0004003d,0x00000006,0x00000086, + 0x00000034,0x00050080,0x00000006,0x00000087,0x00000086,0x00000085,0x0003003e,0x00000034, + 0x00000087,0x0004003d,0x00000006,0x00000088,0x00000034,0x00060041,0x00000026,0x00000089, + 0x00000043,0x00000017,0x00000088,0x0004003d,0x00000007,0x0000008a,0x00000089,0x0003003e, + 0x0000003f,0x0000008a,0x00050041,0x00000010,0x0000008b,0x0000003f,0x0000000f,0x0004003d, + 0x00000006,0x0000008c,0x0000008b,0x0006000c,0x0000002a,0x0000008d,0x00000001,0x00000040, + 0x0000008c,0x0003003e,0x00000047,0x0000008d,0x00050041,0x00000010,0x0000008e,0x0000003f, + 0x0000001b,0x0004003d,0x00000006,0x0000008f,0x0000008e,0x0006000c,0x0000002a,0x00000090, + 0x00000001,0x00000040,0x0000008f,0x0003003e,0x0000004b,0x00000090,0x0004003d,0x00000006, + 0x00000091,0x00000034,0x00060041,0x00000026,0x00000092,0x00000053,0x00000017,0x00000091, + 0x0004003d,0x00000007,0x00000093,0x00000092,0x0003003e,0x0000004f,0x00000093,0x00050041, + 0x00000010,0x00000094,0x0000004f,0x0000000f,0x0004003d,0x00000006,0x00000095,0x00000094, + 0x0006000c,0x0000002a,0x00000096,0x00000001,0x00000040,0x00000095,0x0003003e,0x00000057, + 0x00000096,0x00050041,0x00000010,0x00000097,0x0000004f,0x0000001b,0x0004003d,0x00000006, + 0x00000098,0x00000097,0x0006000c,0x0000002a,0x00000099,0x00000001,0x00000040,0x00000098, + 0x0003003e,0x0000005b,0x00000099,0x0004003d,0x0000002a,0x0000009a,0x00000047,0x0004003d, + 0x0000002a,0x0000009b,0x00000057,0x00050083,0x0000002a,0x0000009c,0x0000009a,0x0000009b, + 0x0004003d,0x0000002a,0x0000009d,0x0000002c,0x00050085,0x0000002a,0x0000009e,0x0000009c, + 0x0000009d,0x0004003d,0x0000002a,0x0000009f,0x00000057,0x00050081,0x0000002a,0x000000a0, + 0x0000009e,0x0000009f,0x0003003e,0x0000005f,0x000000a0,0x0004003d,0x0000002a,0x000000a1, + 0x0000004b,0x0004003d,0x0000002a,0x000000a2,0x0000005b,0x00050083,0x0000002a,0x000000a3, + 0x000000a1,0x000000a2,0x0004003d,0x0000002a,0x000000a4,0x00000030,0x00050085,0x0000002a, + 0x000000a5,0x000000a3,0x000000a4,0x0004003d,0x0000002a,0x000000a6,0x0000005b,0x00050081, + 0x0000002a,0x000000a7,0x000000a5,0x000000a6,0x0003003e,0x00000067,0x000000a7,0x0004003d, + 0x0000002a,0x000000a8,0x0000005f,0x00070050,0x0000002a,0x000000a9,0x00000070,0x00000070, + 0x00000070,0x00000070,0x00070050,0x0000002a,0x000000aa,0x00000071,0x00000071,0x00000071, + 0x00000071,0x0008000c,0x0000002a,0x000000ab,0x00000001,0x0000002b,0x000000a8,0x000000a9, + 0x000000aa,0x0003003e,0x0000005f,0x000000ab,0x0004003d,0x0000002a,0x000000ac,0x00000067, + 0x00070050,0x0000002a,0x000000ad,0x00000070,0x00000070,0x00000070,0x00000070,0x00070050, + 0x0000002a,0x000000ae,0x00000071,0x00000071,0x00000071,0x00000071,0x0008000c,0x0000002a, + 0x000000af,0x00000001,0x0000002b,0x000000ac,0x000000ad,0x000000ae,0x0003003e,0x00000067, + 0x000000af,0x0004003d,0x00000006,0x000000b0,0x00000034,0x0004003d,0x0000002a,0x000000b1, + 0x0000005f,0x0006000c,0x00000006,0x000000b2,0x00000001,0x00000037,0x000000b1,0x0004003d, + 0x0000002a,0x000000b3,0x00000067,0x0006000c,0x00000006,0x000000b4,0x00000001,0x00000037, + 0x000000b3,0x00050050,0x00000007,0x000000b5,0x000000b2,0x000000b4,0x00060041,0x00000026, + 0x000000b6,0x0000007c,0x00000017,0x000000b0,0x0003003e,0x000000b6,0x000000b5,0x00050041, + 0x00000010,0x000000b8,0x00000009,0x0000001b,0x0004003d,0x00000006,0x000000b9,0x000000b8, + 0x00050041,0x00000018,0x000000ba,0x00000015,0x00000017,0x0004003d,0x00000006,0x000000bb, + 0x000000ba,0x00050084,0x00000006,0x000000bc,0x000000b9,0x000000bb,0x00050041,0x00000010, + 0x000000bd,0x00000009,0x0000000f,0x0004003d,0x00000006,0x000000be,0x000000bd,0x00050080, + 0x00000006,0x000000bf,0x000000bc,0x000000be,0x0003003e,0x000000b7,0x000000bf,0x0004003d, + 0x00000006,0x000000c5,0x000000b7,0x00060041,0x00000026,0x000000c6,0x000000c4,0x00000017, + 0x000000c5,0x0004003d,0x00000007,0x000000c7,0x000000c6,0x0003003e,0x000000c0,0x000000c7, + 0x00050041,0x00000010,0x000000c9,0x000000c0,0x0000000f,0x0004003d,0x00000006,0x000000ca, + 0x000000c9,0x0006000c,0x0000002a,0x000000cb,0x00000001,0x00000040,0x000000ca,0x0003003e, + 0x000000c8,0x000000cb,0x00050041,0x00000010,0x000000cd,0x000000c0,0x0000001b,0x0004003d, + 0x00000006,0x000000ce,0x000000cd,0x0006000c,0x0000002a,0x000000cf,0x00000001,0x00000040, + 0x000000ce,0x0003003e,0x000000cc,0x000000cf,0x0004003d,0x00000006,0x000000d5,0x000000b7, + 0x00060041,0x00000026,0x000000d6,0x000000d4,0x00000017,0x000000d5,0x0004003d,0x00000007, + 0x000000d7,0x000000d6,0x0003003e,0x000000d0,0x000000d7,0x00050041,0x00000010,0x000000d9, + 0x000000d0,0x0000000f,0x0004003d,0x00000006,0x000000da,0x000000d9,0x0006000c,0x0000002a, + 0x000000db,0x00000001,0x00000040,0x000000da,0x0003003e,0x000000d8,0x000000db,0x00050041, + 0x00000010,0x000000dd,0x000000d0,0x0000001b,0x0004003d,0x00000006,0x000000de,0x000000dd, + 0x0006000c,0x0000002a,0x000000df,0x00000001,0x00000040,0x000000de,0x0003003e,0x000000dc, + 0x000000df,0x0004003d,0x0000002a,0x000000e1,0x0000002c,0x0007004f,0x000000e0,0x000000e2, + 0x000000e1,0x000000e1,0x00000000,0x00000002,0x0004003d,0x0000002a,0x000000e3,0x0000002c, + 0x0009004f,0x0000002a,0x000000e4,0x000000e3,0x000000e2,0x00000000,0x00000004,0x00000002, + 0x00000005,0x0003003e,0x0000002c,0x000000e4,0x0004003d,0x0000002a,0x000000e5,0x00000030, + 0x0007004f,0x000000e0,0x000000e6,0x000000e5,0x000000e5,0x00000000,0x00000002,0x0004003d, + 0x0000002a,0x000000e7,0x00000030,0x0009004f,0x0000002a,0x000000e8,0x000000e7,0x000000e6, + 0x00000000,0x00000004,0x00000002,0x00000005,0x0003003e,0x00000030,0x000000e8,0x0004003d, + 0x0000002a,0x000000ea,0x000000c8,0x0004003d,0x0000002a,0x000000eb,0x000000d8,0x00050083, + 0x0000002a,0x000000ec,0x000000ea,0x000000eb,0x0004003d,0x0000002a,0x000000ed,0x0000002c, + 0x00050085,0x0000002a,0x000000ee,0x000000ec,0x000000ed,0x0004003d,0x0000002a,0x000000ef, + 0x000000d8,0x00050081,0x0000002a,0x000000f0,0x000000ee,0x000000ef,0x0003003e,0x000000e9, + 0x000000f0,0x0004003d,0x0000002a,0x000000f2,0x000000cc,0x0004003d,0x0000002a,0x000000f3, + 0x000000dc,0x00050083,0x0000002a,0x000000f4,0x000000f2,0x000000f3,0x0004003d,0x0000002a, + 0x000000f5,0x00000030,0x00050085,0x0000002a,0x000000f6,0x000000f4,0x000000f5,0x0004003d, + 0x0000002a,0x000000f7,0x000000dc,0x00050081,0x0000002a,0x000000f8,0x000000f6,0x000000f7, + 0x0003003e,0x000000f1,0x000000f8,0x0004003d,0x0000002a,0x000000f9,0x000000e9,0x00070050, + 0x0000002a,0x000000fa,0x00000070,0x00000070,0x00000070,0x00000070,0x00070050,0x0000002a, + 0x000000fb,0x00000071,0x00000071,0x00000071,0x00000071,0x0008000c,0x0000002a,0x000000fc, + 0x00000001,0x0000002b,0x000000f9,0x000000fa,0x000000fb,0x0003003e,0x000000e9,0x000000fc, + 0x0004003d,0x0000002a,0x000000fd,0x000000f1,0x00070050,0x0000002a,0x000000fe,0x00000070, + 0x00000070,0x00000070,0x00000070,0x00070050,0x0000002a,0x000000ff,0x00000071,0x00000071, + 0x00000071,0x00000071,0x0008000c,0x0000002a,0x00000100,0x00000001,0x0000002b,0x000000fd, + 0x000000fe,0x000000ff,0x0003003e,0x000000f1,0x00000100,0x0004003d,0x00000006,0x00000105, + 0x000000b7,0x0004003d,0x0000002a,0x00000106,0x000000e9,0x0006000c,0x00000006,0x00000107, + 0x00000001,0x00000037,0x00000106,0x0004003d,0x0000002a,0x00000108,0x000000f1,0x0006000c, + 0x00000006,0x00000109,0x00000001,0x00000037,0x00000108,0x00050050,0x00000007,0x0000010a, + 0x00000107,0x00000109,0x00060041,0x00000026,0x0000010b,0x00000104,0x00000017,0x00000105, + 0x0003003e,0x0000010b,0x0000010a,0x000100fd,0x00010038 diff --git a/shaders/spv/shader_copy.comp b/shaders/spv/shader_copy.comp new file mode 100644 index 0000000..876bdf7 --- /dev/null +++ b/shaders/spv/shader_copy.comp @@ -0,0 +1,28 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBuf { + uvec4 data[]; +} in_buf; + +layout (binding = 1) writeonly buffer OutBuf { + uvec4 data[]; +} out_buf; + +layout (push_constant) uniform PushConsts { + uint in_img_width; + uint in_x_offset; + uint out_img_width; + uint out_x_offset; + uint copy_width; +} prop; + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + g_id.x = min (g_id.x, prop.copy_width - 1u); + + out_buf.data[g_id.y * prop.out_img_width + prop.out_x_offset + g_id.x] = + in_buf.data[g_id.y * prop.in_img_width + prop.in_x_offset + g_id.x]; +} diff --git a/shaders/spv/shader_copy.comp.spv b/shaders/spv/shader_copy.comp.spv new file mode 100644 index 0000000..240daab --- /dev/null +++ b/shaders/spv/shader_copy.comp.spv @@ -0,0 +1,66 @@ + // 7.8.2870 + 0x07230203,0x00010000,0x00080007,0x00000048,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000005,0x00000004,0x6e69616d,0x00000000,0x0000000c,0x00060010,0x00000004, + 0x00000011,0x00000008,0x00000008,0x00000001,0x00030003,0x00000001,0x00000136,0x00040005, + 0x00000004,0x6e69616d,0x00000000,0x00040005,0x00000009,0x64695f67,0x00000000,0x00080005, + 0x0000000c,0x475f6c67,0x61626f6c,0x766e496c,0x7461636f,0x496e6f69,0x00000044,0x00050005, + 0x00000013,0x68737550,0x736e6f43,0x00007374,0x00070006,0x00000013,0x00000000,0x695f6e69, + 0x775f676d,0x68746469,0x00000000,0x00060006,0x00000013,0x00000001,0x785f6e69,0x66666f5f, + 0x00746573,0x00070006,0x00000013,0x00000002,0x5f74756f,0x5f676d69,0x74646977,0x00000068, + 0x00070006,0x00000013,0x00000003,0x5f74756f,0x666f5f78,0x74657366,0x00000000,0x00060006, + 0x00000013,0x00000004,0x79706f63,0x6469775f,0x00006874,0x00040005,0x00000015,0x706f7270, + 0x00000000,0x00040005,0x00000021,0x4274754f,0x00006675,0x00050006,0x00000021,0x00000000, + 0x61746164,0x00000000,0x00040005,0x00000023,0x5f74756f,0x00667562,0x00040005,0x00000033, + 0x75426e49,0x00000066,0x00050006,0x00000033,0x00000000,0x61746164,0x00000000,0x00040005, + 0x00000035,0x625f6e69,0x00006675,0x00040047,0x0000000c,0x0000000b,0x0000001c,0x00050048, + 0x00000013,0x00000000,0x00000023,0x00000000,0x00050048,0x00000013,0x00000001,0x00000023, + 0x00000004,0x00050048,0x00000013,0x00000002,0x00000023,0x00000008,0x00050048,0x00000013, + 0x00000003,0x00000023,0x0000000c,0x00050048,0x00000013,0x00000004,0x00000023,0x00000010, + 0x00030047,0x00000013,0x00000002,0x00040047,0x00000020,0x00000006,0x00000010,0x00040048, + 0x00000021,0x00000000,0x00000019,0x00050048,0x00000021,0x00000000,0x00000023,0x00000000, + 0x00030047,0x00000021,0x00000003,0x00040047,0x00000023,0x00000022,0x00000000,0x00040047, + 0x00000023,0x00000021,0x00000001,0x00040047,0x00000032,0x00000006,0x00000010,0x00040048, + 0x00000033,0x00000000,0x00000018,0x00050048,0x00000033,0x00000000,0x00000023,0x00000000, + 0x00030047,0x00000033,0x00000003,0x00040047,0x00000035,0x00000022,0x00000000,0x00040047, + 0x00000035,0x00000021,0x00000000,0x00040047,0x00000047,0x0000000b,0x00000019,0x00020013, + 0x00000002,0x00030021,0x00000003,0x00000002,0x00040015,0x00000006,0x00000020,0x00000000, + 0x00040017,0x00000007,0x00000006,0x00000002,0x00040020,0x00000008,0x00000007,0x00000007, + 0x00040017,0x0000000a,0x00000006,0x00000003,0x00040020,0x0000000b,0x00000001,0x0000000a, + 0x0004003b,0x0000000b,0x0000000c,0x00000001,0x0004002b,0x00000006,0x0000000f,0x00000000, + 0x00040020,0x00000010,0x00000007,0x00000006,0x0007001e,0x00000013,0x00000006,0x00000006, + 0x00000006,0x00000006,0x00000006,0x00040020,0x00000014,0x00000009,0x00000013,0x0004003b, + 0x00000014,0x00000015,0x00000009,0x00040015,0x00000016,0x00000020,0x00000001,0x0004002b, + 0x00000016,0x00000017,0x00000004,0x00040020,0x00000018,0x00000009,0x00000006,0x0004002b, + 0x00000006,0x0000001b,0x00000001,0x00040017,0x0000001f,0x00000006,0x00000004,0x0003001d, + 0x00000020,0x0000001f,0x0003001e,0x00000021,0x00000020,0x00040020,0x00000022,0x00000002, + 0x00000021,0x0004003b,0x00000022,0x00000023,0x00000002,0x0004002b,0x00000016,0x00000024, + 0x00000000,0x0004002b,0x00000016,0x00000027,0x00000002,0x0004002b,0x00000016,0x0000002b, + 0x00000003,0x0003001d,0x00000032,0x0000001f,0x0003001e,0x00000033,0x00000032,0x00040020, + 0x00000034,0x00000002,0x00000033,0x0004003b,0x00000034,0x00000035,0x00000002,0x0004002b, + 0x00000016,0x0000003b,0x00000001,0x00040020,0x00000042,0x00000002,0x0000001f,0x0004002b, + 0x00000006,0x00000046,0x00000008,0x0006002c,0x0000000a,0x00000047,0x00000046,0x00000046, + 0x0000001b,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005, + 0x0004003b,0x00000008,0x00000009,0x00000007,0x0004003d,0x0000000a,0x0000000d,0x0000000c, + 0x0007004f,0x00000007,0x0000000e,0x0000000d,0x0000000d,0x00000000,0x00000001,0x0003003e, + 0x00000009,0x0000000e,0x00050041,0x00000010,0x00000011,0x00000009,0x0000000f,0x0004003d, + 0x00000006,0x00000012,0x00000011,0x00050041,0x00000018,0x00000019,0x00000015,0x00000017, + 0x0004003d,0x00000006,0x0000001a,0x00000019,0x00050082,0x00000006,0x0000001c,0x0000001a, + 0x0000001b,0x0007000c,0x00000006,0x0000001d,0x00000001,0x00000026,0x00000012,0x0000001c, + 0x00050041,0x00000010,0x0000001e,0x00000009,0x0000000f,0x0003003e,0x0000001e,0x0000001d, + 0x00050041,0x00000010,0x00000025,0x00000009,0x0000001b,0x0004003d,0x00000006,0x00000026, + 0x00000025,0x00050041,0x00000018,0x00000028,0x00000015,0x00000027,0x0004003d,0x00000006, + 0x00000029,0x00000028,0x00050084,0x00000006,0x0000002a,0x00000026,0x00000029,0x00050041, + 0x00000018,0x0000002c,0x00000015,0x0000002b,0x0004003d,0x00000006,0x0000002d,0x0000002c, + 0x00050080,0x00000006,0x0000002e,0x0000002a,0x0000002d,0x00050041,0x00000010,0x0000002f, + 0x00000009,0x0000000f,0x0004003d,0x00000006,0x00000030,0x0000002f,0x00050080,0x00000006, + 0x00000031,0x0000002e,0x00000030,0x00050041,0x00000010,0x00000036,0x00000009,0x0000001b, + 0x0004003d,0x00000006,0x00000037,0x00000036,0x00050041,0x00000018,0x00000038,0x00000015, + 0x00000024,0x0004003d,0x00000006,0x00000039,0x00000038,0x00050084,0x00000006,0x0000003a, + 0x00000037,0x00000039,0x00050041,0x00000018,0x0000003c,0x00000015,0x0000003b,0x0004003d, + 0x00000006,0x0000003d,0x0000003c,0x00050080,0x00000006,0x0000003e,0x0000003a,0x0000003d, + 0x00050041,0x00000010,0x0000003f,0x00000009,0x0000000f,0x0004003d,0x00000006,0x00000040, + 0x0000003f,0x00050080,0x00000006,0x00000041,0x0000003e,0x00000040,0x00060041,0x00000042, + 0x00000043,0x00000035,0x00000024,0x00000041,0x0004003d,0x0000001f,0x00000044,0x00000043, + 0x00060041,0x00000042,0x00000045,0x00000023,0x00000024,0x00000031,0x0003003e,0x00000045, + 0x00000044,0x000100fd,0x00010038 diff --git a/shaders/spv/shader_gauss_scale_pyr.comp b/shaders/spv/shader_gauss_scale_pyr.comp new file mode 100644 index 0000000..fa9f49d --- /dev/null +++ b/shaders/spv/shader_gauss_scale_pyr.comp @@ -0,0 +1,176 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBufY { + uint data[]; +} in_buf_y; + +layout (binding = 1) readonly buffer InBufUV { + uint data[]; +} in_buf_uv; + +layout (binding = 2) writeonly buffer OutBufY { + uint data[]; +} out_buf_y; + +layout (binding = 3) writeonly buffer OutBufUV { + uint data[]; +} out_buf_uv; + +layout (push_constant) uniform PushConsts { + uint in_img_width; + uint in_img_height; + uint in_offset_x; + uint out_img_width; + uint out_img_height; + uint merge_width; +} prop; + +const float coeffs[5] = float[] (0.152f, 0.222f, 0.252f, 0.222f, 0.152f); + +#define unpack_unorm(buf, pixel, idx) \ + { \ + pixel[0] = unpackUnorm4x8 (buf.data[idx]); \ + pixel[1] = unpackUnorm4x8 (buf.data[idx + 1u]); \ + pixel[2] = unpackUnorm4x8 (buf.data[idx + 2u]); \ + pixel[3] = unpackUnorm4x8 (buf.data[idx + 3u]); \ + } + +#define multiply_coeff(sum, pixel, idx) \ + { \ + sum[0] += pixel[0] * coeffs[idx]; \ + sum[1] += pixel[1] * coeffs[idx]; \ + sum[2] += pixel[2] * coeffs[idx]; \ + sum[3] += pixel[3] * coeffs[idx]; \ + } + +void gauss_scale_y (uvec2 y_id, uvec2 g_id); +void gauss_scale_uv (uvec2 uv_id); + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + g_id.x = clamp (g_id.x, 0u, prop.merge_width - 1u); + + uvec2 y_id = g_id * uvec2 (1u, 2u); + gauss_scale_y (y_id, g_id); + + gauss_scale_uv (g_id); +} + +void gauss_scale_y (uvec2 y_id, uvec2 g_id) +{ + uvec2 in_id = y_id * 2u; + uvec2 gauss_start = in_id - uvec2 (1u, 2u); + gauss_start.y = clamp (gauss_start.y, 0u, prop.in_img_height - 7u); + + vec4 sum0[4] = vec4[] (vec4 (0.0f), vec4 (0.0f), vec4 (0.0f), vec4 (0.0f)); + vec4 sum1[4] = vec4[] (vec4 (0.0f), vec4 (0.0f), vec4 (0.0f), vec4 (0.0f)); + + vec4 pixel_y[4]; + uint in_idx = (in_id.y == 0u) ? (in_id.x - 1u) : (gauss_start.y * prop.in_img_width + gauss_start.x); + in_idx += prop.in_offset_x; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 0u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + prop.in_img_width); + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 1u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + prop.in_img_width); + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 2u); + multiply_coeff (sum1, pixel_y, 0u); + + in_idx += prop.in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 3u); + multiply_coeff (sum1, pixel_y, 1u); + + in_idx += prop.in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum0, pixel_y, 4u); + multiply_coeff (sum1, pixel_y, 2u); + + in_idx += prop.in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum1, pixel_y, 3u); + + in_idx += prop.in_img_width; + unpack_unorm (in_buf_y, pixel_y, in_idx); + multiply_coeff (sum1, pixel_y, 4u); + + sum0[0] = (in_id.x == 0u) ? vec4 (sum0[1].x) : sum0[0]; + sum1[0] = (in_id.x == 0u) ? vec4 (sum1[1].x) : sum1[0]; + sum0[3] = (in_id.x == prop.merge_width - 2u) ? vec4 (sum0[2].w) : sum0[3]; + sum1[3] = (in_id.x == prop.merge_width - 2u) ? vec4 (sum1[2].w) : sum1[3]; + + vec4 out_data0 = + vec4 (sum0[0].z, sum0[1].x, sum0[1].z, sum0[2].x) * coeffs[0] + + vec4 (sum0[0].w, sum0[1].y, sum0[1].w, sum0[2].y) * coeffs[1] + + vec4 (sum0[1].x, sum0[1].z, sum0[2].x, sum0[2].z) * coeffs[2] + + vec4 (sum0[1].y, sum0[1].w, sum0[2].y, sum0[2].w) * coeffs[3] + + vec4 (sum0[1].z, sum0[2].x, sum0[2].z, sum0[3].x) * coeffs[4]; + + vec4 out_data1 = + vec4 (sum1[0].z, sum1[1].x, sum1[1].z, sum1[2].x) * coeffs[0] + + vec4 (sum1[0].w, sum1[1].y, sum1[1].w, sum1[2].y) * coeffs[1] + + vec4 (sum1[1].x, sum1[1].z, sum1[2].x, sum1[2].z) * coeffs[2] + + vec4 (sum1[1].y, sum1[1].w, sum1[2].y, sum1[2].w) * coeffs[3] + + vec4 (sum1[1].z, sum1[2].x, sum1[2].z, sum1[3].x) * coeffs[4]; + + out_data0 = clamp (out_data0, 0.0f, 1.0f); + out_data1 = clamp (out_data1, 0.0f, 1.0f); + + y_id.x = clamp (y_id.x, 0u, prop.out_img_width - 1u); + y_id.y = clamp (y_id.y, 0u, prop.out_img_height - 2u); + uint out_idx = y_id.y * prop.out_img_width + y_id.x; + out_buf_y.data[out_idx] = packUnorm4x8 (out_data0); + out_buf_y.data[out_idx + prop.out_img_width] = packUnorm4x8 (out_data1); +} + +void gauss_scale_uv (uvec2 uv_id) +{ + uvec2 in_id = uv_id * 2u; + uvec2 gauss_start = in_id - uvec2 (1u, 2u); + gauss_start.y = clamp (gauss_start.y, 0u, prop.in_img_height / 2u - 5u); + + vec4 sum[4] = vec4[] (vec4 (0.0f), vec4 (0.0f), vec4 (0.0f), vec4 (0.0f)); + uint in_idx = (in_id.y == 0u) ? (in_id.x - 1u) : (gauss_start.y * prop.in_img_width + gauss_start.x); + in_idx += prop.in_offset_x; + + vec4 pixel_uv[4]; + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 0u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + prop.in_img_width); + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 1u); + + in_idx = (in_id.y == 0u) ? in_idx : (in_idx + prop.in_img_width); + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 2u); + + in_idx += prop.in_img_width; + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 3u); + + in_idx += prop.in_img_width; + unpack_unorm (in_buf_uv, pixel_uv, in_idx); + multiply_coeff (sum, pixel_uv, 4u); + + sum[0] = (in_id.x == 0u) ? vec4 (sum[1]) : sum[0]; + sum[3] = (in_id.x == prop.merge_width - 2u) ? vec4 (sum[2]) : sum[3]; + + vec4 out_data = + vec4 (sum[0].x, sum[0].y, sum[1].x, sum[1].y) * coeffs[0] + + vec4 (sum[0].z, sum[0].w, sum[1].z, sum[1].w) * coeffs[1] + + vec4 (sum[1].x, sum[1].y, sum[2].x, sum[2].y) * coeffs[2] + + vec4 (sum[1].z, sum[1].w, sum[2].z, sum[2].w) * coeffs[3] + + vec4 (sum[2].x, sum[2].y, sum[3].x, sum[3].y) * coeffs[4]; + + out_data = clamp (out_data, 0.0f, 1.0f); + uv_id.x = clamp (uv_id.x, 0u, prop.out_img_width - 1u); + out_buf_uv.data[uv_id.y * prop.out_img_width + uv_id.x] = packUnorm4x8 (out_data); +} diff --git a/shaders/spv/shader_gauss_scale_pyr.comp.spv b/shaders/spv/shader_gauss_scale_pyr.comp.spv new file mode 100644 index 0000000..16235d3 --- /dev/null +++ b/shaders/spv/shader_gauss_scale_pyr.comp.spv @@ -0,0 +1,891 @@ + // 7.8.2870 + 0x07230203,0x00010000,0x00080007,0x00000501,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000005,0x00000004,0x6e69616d,0x00000000,0x00000015,0x00060010,0x00000004, + 0x00000011,0x00000008,0x00000008,0x00000001,0x00030003,0x00000001,0x00000136,0x00040005, + 0x00000004,0x6e69616d,0x00000000,0x00080005,0x0000000c,0x73756167,0x63735f73,0x5f656c61, + 0x75762879,0x75763b32,0x00003b32,0x00040005,0x0000000a,0x64695f79,0x00000000,0x00040005, + 0x0000000b,0x64695f67,0x00000000,0x00070005,0x00000010,0x73756167,0x63735f73,0x5f656c61, + 0x76287675,0x003b3275,0x00040005,0x0000000f,0x695f7675,0x00000064,0x00040005,0x00000012, + 0x64695f67,0x00000000,0x00080005,0x00000015,0x475f6c67,0x61626f6c,0x766e496c,0x7461636f, + 0x496e6f69,0x00000044,0x00050005,0x0000001c,0x68737550,0x736e6f43,0x00007374,0x00070006, + 0x0000001c,0x00000000,0x695f6e69,0x775f676d,0x68746469,0x00000000,0x00070006,0x0000001c, + 0x00000001,0x695f6e69,0x685f676d,0x68676965,0x00000074,0x00060006,0x0000001c,0x00000002, + 0x6f5f6e69,0x65736666,0x00785f74,0x00070006,0x0000001c,0x00000003,0x5f74756f,0x5f676d69, + 0x74646977,0x00000068,0x00070006,0x0000001c,0x00000004,0x5f74756f,0x5f676d69,0x67696568, + 0x00007468,0x00060006,0x0000001c,0x00000005,0x6772656d,0x69775f65,0x00687464,0x00040005, + 0x0000001e,0x706f7270,0x00000000,0x00040005,0x00000028,0x64695f79,0x00000000,0x00040005, + 0x0000002d,0x61726170,0x0000006d,0x00040005,0x0000002f,0x61726170,0x0000006d,0x00040005, + 0x00000032,0x61726170,0x0000006d,0x00040005,0x00000035,0x695f6e69,0x00000064,0x00050005, + 0x00000039,0x73756167,0x74735f73,0x00747261,0x00040005,0x0000004a,0x306d7573,0x00000000, + 0x00040005,0x0000004e,0x316d7573,0x00000000,0x00040005,0x0000004f,0x695f6e69,0x00007864, + 0x00040005,0x0000006a,0x65786970,0x00795f6c,0x00040005,0x0000006c,0x75426e49,0x00005966, + 0x00050006,0x0000006c,0x00000000,0x61746164,0x00000000,0x00050005,0x0000006e,0x625f6e69, + 0x795f6675,0x00000000,0x00050005,0x00000298,0x5f74756f,0x61746164,0x00000030,0x00050005, + 0x000002cf,0x5f74756f,0x61746164,0x00000031,0x00040005,0x0000031e,0x5f74756f,0x00786469, + 0x00040005,0x00000328,0x4274754f,0x00596675,0x00050006,0x00000328,0x00000000,0x61746164, + 0x00000000,0x00050005,0x0000032a,0x5f74756f,0x5f667562,0x00000079,0x00040005,0x00000336, + 0x695f6e69,0x00000064,0x00050005,0x0000033a,0x73756167,0x74735f73,0x00747261,0x00030005, + 0x00000346,0x006d7573,0x00040005,0x00000347,0x695f6e69,0x00007864,0x00050005,0x0000035f, + 0x65786970,0x76755f6c,0x00000000,0x00040005,0x00000361,0x75426e49,0x00565566,0x00050006, + 0x00000361,0x00000000,0x61746164,0x00000000,0x00050005,0x00000363,0x625f6e69,0x755f6675, + 0x00000076,0x00050005,0x000004ac,0x5f74756f,0x61746164,0x00000000,0x00050005,0x000004ef, + 0x4274754f,0x56556675,0x00000000,0x00050006,0x000004ef,0x00000000,0x61746164,0x00000000, + 0x00050005,0x000004f1,0x5f74756f,0x5f667562,0x00007675,0x00040047,0x00000015,0x0000000b, + 0x0000001c,0x00050048,0x0000001c,0x00000000,0x00000023,0x00000000,0x00050048,0x0000001c, + 0x00000001,0x00000023,0x00000004,0x00050048,0x0000001c,0x00000002,0x00000023,0x00000008, + 0x00050048,0x0000001c,0x00000003,0x00000023,0x0000000c,0x00050048,0x0000001c,0x00000004, + 0x00000023,0x00000010,0x00050048,0x0000001c,0x00000005,0x00000023,0x00000014,0x00030047, + 0x0000001c,0x00000002,0x00040047,0x0000006b,0x00000006,0x00000004,0x00040048,0x0000006c, + 0x00000000,0x00000018,0x00050048,0x0000006c,0x00000000,0x00000023,0x00000000,0x00030047, + 0x0000006c,0x00000003,0x00040047,0x0000006e,0x00000022,0x00000000,0x00040047,0x0000006e, + 0x00000021,0x00000000,0x00040047,0x00000327,0x00000006,0x00000004,0x00040048,0x00000328, + 0x00000000,0x00000019,0x00050048,0x00000328,0x00000000,0x00000023,0x00000000,0x00030047, + 0x00000328,0x00000003,0x00040047,0x0000032a,0x00000022,0x00000000,0x00040047,0x0000032a, + 0x00000021,0x00000002,0x00040047,0x00000360,0x00000006,0x00000004,0x00040048,0x00000361, + 0x00000000,0x00000018,0x00050048,0x00000361,0x00000000,0x00000023,0x00000000,0x00030047, + 0x00000361,0x00000003,0x00040047,0x00000363,0x00000022,0x00000000,0x00040047,0x00000363, + 0x00000021,0x00000001,0x00040047,0x000004ee,0x00000006,0x00000004,0x00040048,0x000004ef, + 0x00000000,0x00000019,0x00050048,0x000004ef,0x00000000,0x00000023,0x00000000,0x00030047, + 0x000004ef,0x00000003,0x00040047,0x000004f1,0x00000022,0x00000000,0x00040047,0x000004f1, + 0x00000021,0x00000003,0x00040047,0x000004fe,0x0000000b,0x00000019,0x00020013,0x00000002, + 0x00030021,0x00000003,0x00000002,0x00040015,0x00000006,0x00000020,0x00000000,0x00040017, + 0x00000007,0x00000006,0x00000002,0x00040020,0x00000008,0x00000007,0x00000007,0x00050021, + 0x00000009,0x00000002,0x00000008,0x00000008,0x00040021,0x0000000e,0x00000002,0x00000008, + 0x00040017,0x00000013,0x00000006,0x00000003,0x00040020,0x00000014,0x00000001,0x00000013, + 0x0004003b,0x00000014,0x00000015,0x00000001,0x0004002b,0x00000006,0x00000018,0x00000000, + 0x00040020,0x00000019,0x00000007,0x00000006,0x0008001e,0x0000001c,0x00000006,0x00000006, + 0x00000006,0x00000006,0x00000006,0x00000006,0x00040020,0x0000001d,0x00000009,0x0000001c, + 0x0004003b,0x0000001d,0x0000001e,0x00000009,0x00040015,0x0000001f,0x00000020,0x00000001, + 0x0004002b,0x0000001f,0x00000020,0x00000005,0x00040020,0x00000021,0x00000009,0x00000006, + 0x0004002b,0x00000006,0x00000024,0x00000001,0x0004002b,0x00000006,0x0000002a,0x00000002, + 0x0005002c,0x00000007,0x0000002b,0x00000024,0x0000002a,0x0004002b,0x0000001f,0x0000003e, + 0x00000001,0x0004002b,0x00000006,0x00000041,0x00000007,0x00030016,0x00000045,0x00000020, + 0x00040017,0x00000046,0x00000045,0x00000004,0x0004002b,0x00000006,0x00000047,0x00000004, + 0x0004001c,0x00000048,0x00000046,0x00000047,0x00040020,0x00000049,0x00000007,0x00000048, + 0x0004002b,0x00000045,0x0000004b,0x00000000,0x0007002c,0x00000046,0x0000004c,0x0000004b, + 0x0000004b,0x0000004b,0x0000004b,0x0007002c,0x00000048,0x0000004d,0x0000004c,0x0000004c, + 0x0000004c,0x0000004c,0x00020014,0x00000052,0x0004002b,0x0000001f,0x0000005d,0x00000000, + 0x0004002b,0x0000001f,0x00000065,0x00000002,0x0003001d,0x0000006b,0x00000006,0x0003001e, + 0x0000006c,0x0000006b,0x00040020,0x0000006d,0x00000002,0x0000006c,0x0004003b,0x0000006d, + 0x0000006e,0x00000002,0x00040020,0x00000070,0x00000002,0x00000006,0x00040020,0x00000074, + 0x00000007,0x00000046,0x0004002b,0x0000001f,0x00000082,0x00000003,0x0004002b,0x00000006, + 0x00000084,0x00000003,0x0004002b,0x00000045,0x0000008c,0x3e1ba5e3,0x0004002b,0x00000045, + 0x000000cd,0x3e6353f8,0x0004002b,0x00000045,0x0000010e,0x3e810625,0x00040020,0x0000025f, + 0x00000007,0x00000045,0x0004002b,0x00000045,0x00000307,0x3f800000,0x0004002b,0x0000001f, + 0x00000318,0x00000004,0x0003001d,0x00000327,0x00000006,0x0003001e,0x00000328,0x00000327, + 0x00040020,0x00000329,0x00000002,0x00000328,0x0004003b,0x00000329,0x0000032a,0x00000002, + 0x0004002b,0x00000006,0x00000342,0x00000005,0x0003001d,0x00000360,0x00000006,0x0003001e, + 0x00000361,0x00000360,0x00040020,0x00000362,0x00000002,0x00000361,0x0004003b,0x00000362, + 0x00000363,0x00000002,0x0003001d,0x000004ee,0x00000006,0x0003001e,0x000004ef,0x000004ee, + 0x00040020,0x000004f0,0x00000002,0x000004ef,0x0004003b,0x000004f0,0x000004f1,0x00000002, + 0x0004002b,0x00000006,0x000004fd,0x00000008,0x0006002c,0x00000013,0x000004fe,0x000004fd, + 0x000004fd,0x00000024,0x0004001c,0x000004ff,0x00000045,0x00000342,0x0008002c,0x000004ff, + 0x00000500,0x0000008c,0x000000cd,0x0000010e,0x000000cd,0x0000008c,0x00050036,0x00000002, + 0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x00000008,0x00000012, + 0x00000007,0x0004003b,0x00000008,0x00000028,0x00000007,0x0004003b,0x00000008,0x0000002d, + 0x00000007,0x0004003b,0x00000008,0x0000002f,0x00000007,0x0004003b,0x00000008,0x00000032, + 0x00000007,0x0004003d,0x00000013,0x00000016,0x00000015,0x0007004f,0x00000007,0x00000017, + 0x00000016,0x00000016,0x00000000,0x00000001,0x0003003e,0x00000012,0x00000017,0x00050041, + 0x00000019,0x0000001a,0x00000012,0x00000018,0x0004003d,0x00000006,0x0000001b,0x0000001a, + 0x00050041,0x00000021,0x00000022,0x0000001e,0x00000020,0x0004003d,0x00000006,0x00000023, + 0x00000022,0x00050082,0x00000006,0x00000025,0x00000023,0x00000024,0x0008000c,0x00000006, + 0x00000026,0x00000001,0x0000002c,0x0000001b,0x00000018,0x00000025,0x00050041,0x00000019, + 0x00000027,0x00000012,0x00000018,0x0003003e,0x00000027,0x00000026,0x0004003d,0x00000007, + 0x00000029,0x00000012,0x00050084,0x00000007,0x0000002c,0x00000029,0x0000002b,0x0003003e, + 0x00000028,0x0000002c,0x0004003d,0x00000007,0x0000002e,0x00000028,0x0003003e,0x0000002d, + 0x0000002e,0x0004003d,0x00000007,0x00000030,0x00000012,0x0003003e,0x0000002f,0x00000030, + 0x00060039,0x00000002,0x00000031,0x0000000c,0x0000002d,0x0000002f,0x0004003d,0x00000007, + 0x00000033,0x00000012,0x0003003e,0x00000032,0x00000033,0x00050039,0x00000002,0x00000034, + 0x00000010,0x00000032,0x000100fd,0x00010038,0x00050036,0x00000002,0x0000000c,0x00000000, + 0x00000009,0x00030037,0x00000008,0x0000000a,0x00030037,0x00000008,0x0000000b,0x000200f8, + 0x0000000d,0x0004003b,0x00000008,0x00000035,0x00000007,0x0004003b,0x00000008,0x00000039, + 0x00000007,0x0004003b,0x00000049,0x0000004a,0x00000007,0x0004003b,0x00000049,0x0000004e, + 0x00000007,0x0004003b,0x00000019,0x0000004f,0x00000007,0x0004003b,0x00000019,0x00000054, + 0x00000007,0x0004003b,0x00000049,0x0000006a,0x00000007,0x0004003b,0x00000019,0x000000aa, + 0x00000007,0x0004003b,0x00000019,0x000000eb,0x00000007,0x0004003b,0x00000074,0x0000025c, + 0x00000007,0x0004003b,0x00000074,0x0000026b,0x00000007,0x0004003b,0x00000074,0x0000027c, + 0x00000007,0x0004003b,0x00000074,0x0000028d,0x00000007,0x0004003b,0x00000074,0x00000298, + 0x00000007,0x0004003b,0x00000074,0x000002cf,0x00000007,0x0004003b,0x00000019,0x0000031e, + 0x00000007,0x0004003d,0x00000007,0x00000036,0x0000000a,0x00050050,0x00000007,0x00000037, + 0x0000002a,0x0000002a,0x00050084,0x00000007,0x00000038,0x00000036,0x00000037,0x0003003e, + 0x00000035,0x00000038,0x0004003d,0x00000007,0x0000003a,0x00000035,0x00050082,0x00000007, + 0x0000003b,0x0000003a,0x0000002b,0x0003003e,0x00000039,0x0000003b,0x00050041,0x00000019, + 0x0000003c,0x00000039,0x00000024,0x0004003d,0x00000006,0x0000003d,0x0000003c,0x00050041, + 0x00000021,0x0000003f,0x0000001e,0x0000003e,0x0004003d,0x00000006,0x00000040,0x0000003f, + 0x00050082,0x00000006,0x00000042,0x00000040,0x00000041,0x0008000c,0x00000006,0x00000043, + 0x00000001,0x0000002c,0x0000003d,0x00000018,0x00000042,0x00050041,0x00000019,0x00000044, + 0x00000039,0x00000024,0x0003003e,0x00000044,0x00000043,0x0003003e,0x0000004a,0x0000004d, + 0x0003003e,0x0000004e,0x0000004d,0x00050041,0x00000019,0x00000050,0x00000035,0x00000024, + 0x0004003d,0x00000006,0x00000051,0x00000050,0x000500aa,0x00000052,0x00000053,0x00000051, + 0x00000018,0x000300f7,0x00000056,0x00000000,0x000400fa,0x00000053,0x00000055,0x0000005a, + 0x000200f8,0x00000055,0x00050041,0x00000019,0x00000057,0x00000035,0x00000018,0x0004003d, + 0x00000006,0x00000058,0x00000057,0x00050082,0x00000006,0x00000059,0x00000058,0x00000024, + 0x0003003e,0x00000054,0x00000059,0x000200f9,0x00000056,0x000200f8,0x0000005a,0x00050041, + 0x00000019,0x0000005b,0x00000039,0x00000024,0x0004003d,0x00000006,0x0000005c,0x0000005b, + 0x00050041,0x00000021,0x0000005e,0x0000001e,0x0000005d,0x0004003d,0x00000006,0x0000005f, + 0x0000005e,0x00050084,0x00000006,0x00000060,0x0000005c,0x0000005f,0x00050041,0x00000019, + 0x00000061,0x00000039,0x00000018,0x0004003d,0x00000006,0x00000062,0x00000061,0x00050080, + 0x00000006,0x00000063,0x00000060,0x00000062,0x0003003e,0x00000054,0x00000063,0x000200f9, + 0x00000056,0x000200f8,0x00000056,0x0004003d,0x00000006,0x00000064,0x00000054,0x0003003e, + 0x0000004f,0x00000064,0x00050041,0x00000021,0x00000066,0x0000001e,0x00000065,0x0004003d, + 0x00000006,0x00000067,0x00000066,0x0004003d,0x00000006,0x00000068,0x0000004f,0x00050080, + 0x00000006,0x00000069,0x00000068,0x00000067,0x0003003e,0x0000004f,0x00000069,0x0004003d, + 0x00000006,0x0000006f,0x0000004f,0x00060041,0x00000070,0x00000071,0x0000006e,0x0000005d, + 0x0000006f,0x0004003d,0x00000006,0x00000072,0x00000071,0x0006000c,0x00000046,0x00000073, + 0x00000001,0x00000040,0x00000072,0x00050041,0x00000074,0x00000075,0x0000006a,0x0000005d, + 0x0003003e,0x00000075,0x00000073,0x0004003d,0x00000006,0x00000076,0x0000004f,0x00050080, + 0x00000006,0x00000077,0x00000076,0x00000024,0x00060041,0x00000070,0x00000078,0x0000006e, + 0x0000005d,0x00000077,0x0004003d,0x00000006,0x00000079,0x00000078,0x0006000c,0x00000046, + 0x0000007a,0x00000001,0x00000040,0x00000079,0x00050041,0x00000074,0x0000007b,0x0000006a, + 0x0000003e,0x0003003e,0x0000007b,0x0000007a,0x0004003d,0x00000006,0x0000007c,0x0000004f, + 0x00050080,0x00000006,0x0000007d,0x0000007c,0x0000002a,0x00060041,0x00000070,0x0000007e, + 0x0000006e,0x0000005d,0x0000007d,0x0004003d,0x00000006,0x0000007f,0x0000007e,0x0006000c, + 0x00000046,0x00000080,0x00000001,0x00000040,0x0000007f,0x00050041,0x00000074,0x00000081, + 0x0000006a,0x00000065,0x0003003e,0x00000081,0x00000080,0x0004003d,0x00000006,0x00000083, + 0x0000004f,0x00050080,0x00000006,0x00000085,0x00000083,0x00000084,0x00060041,0x00000070, + 0x00000086,0x0000006e,0x0000005d,0x00000085,0x0004003d,0x00000006,0x00000087,0x00000086, + 0x0006000c,0x00000046,0x00000088,0x00000001,0x00000040,0x00000087,0x00050041,0x00000074, + 0x00000089,0x0000006a,0x00000082,0x0003003e,0x00000089,0x00000088,0x00050041,0x00000074, + 0x0000008a,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x0000008b,0x0000008a,0x0005008e, + 0x00000046,0x0000008d,0x0000008b,0x0000008c,0x00050041,0x00000074,0x0000008e,0x0000004a, + 0x0000005d,0x0004003d,0x00000046,0x0000008f,0x0000008e,0x00050081,0x00000046,0x00000090, + 0x0000008f,0x0000008d,0x00050041,0x00000074,0x00000091,0x0000004a,0x0000005d,0x0003003e, + 0x00000091,0x00000090,0x00050041,0x00000074,0x00000092,0x0000006a,0x0000003e,0x0004003d, + 0x00000046,0x00000093,0x00000092,0x0005008e,0x00000046,0x00000094,0x00000093,0x0000008c, + 0x00050041,0x00000074,0x00000095,0x0000004a,0x0000003e,0x0004003d,0x00000046,0x00000096, + 0x00000095,0x00050081,0x00000046,0x00000097,0x00000096,0x00000094,0x00050041,0x00000074, + 0x00000098,0x0000004a,0x0000003e,0x0003003e,0x00000098,0x00000097,0x00050041,0x00000074, + 0x00000099,0x0000006a,0x00000065,0x0004003d,0x00000046,0x0000009a,0x00000099,0x0005008e, + 0x00000046,0x0000009b,0x0000009a,0x0000008c,0x00050041,0x00000074,0x0000009c,0x0000004a, + 0x00000065,0x0004003d,0x00000046,0x0000009d,0x0000009c,0x00050081,0x00000046,0x0000009e, + 0x0000009d,0x0000009b,0x00050041,0x00000074,0x0000009f,0x0000004a,0x00000065,0x0003003e, + 0x0000009f,0x0000009e,0x00050041,0x00000074,0x000000a0,0x0000006a,0x00000082,0x0004003d, + 0x00000046,0x000000a1,0x000000a0,0x0005008e,0x00000046,0x000000a2,0x000000a1,0x0000008c, + 0x00050041,0x00000074,0x000000a3,0x0000004a,0x00000082,0x0004003d,0x00000046,0x000000a4, + 0x000000a3,0x00050081,0x00000046,0x000000a5,0x000000a4,0x000000a2,0x00050041,0x00000074, + 0x000000a6,0x0000004a,0x00000082,0x0003003e,0x000000a6,0x000000a5,0x00050041,0x00000019, + 0x000000a7,0x00000035,0x00000024,0x0004003d,0x00000006,0x000000a8,0x000000a7,0x000500aa, + 0x00000052,0x000000a9,0x000000a8,0x00000018,0x000300f7,0x000000ac,0x00000000,0x000400fa, + 0x000000a9,0x000000ab,0x000000ae,0x000200f8,0x000000ab,0x0004003d,0x00000006,0x000000ad, + 0x0000004f,0x0003003e,0x000000aa,0x000000ad,0x000200f9,0x000000ac,0x000200f8,0x000000ae, + 0x0004003d,0x00000006,0x000000af,0x0000004f,0x00050041,0x00000021,0x000000b0,0x0000001e, + 0x0000005d,0x0004003d,0x00000006,0x000000b1,0x000000b0,0x00050080,0x00000006,0x000000b2, + 0x000000af,0x000000b1,0x0003003e,0x000000aa,0x000000b2,0x000200f9,0x000000ac,0x000200f8, + 0x000000ac,0x0004003d,0x00000006,0x000000b3,0x000000aa,0x0003003e,0x0000004f,0x000000b3, + 0x0004003d,0x00000006,0x000000b4,0x0000004f,0x00060041,0x00000070,0x000000b5,0x0000006e, + 0x0000005d,0x000000b4,0x0004003d,0x00000006,0x000000b6,0x000000b5,0x0006000c,0x00000046, + 0x000000b7,0x00000001,0x00000040,0x000000b6,0x00050041,0x00000074,0x000000b8,0x0000006a, + 0x0000005d,0x0003003e,0x000000b8,0x000000b7,0x0004003d,0x00000006,0x000000b9,0x0000004f, + 0x00050080,0x00000006,0x000000ba,0x000000b9,0x00000024,0x00060041,0x00000070,0x000000bb, + 0x0000006e,0x0000005d,0x000000ba,0x0004003d,0x00000006,0x000000bc,0x000000bb,0x0006000c, + 0x00000046,0x000000bd,0x00000001,0x00000040,0x000000bc,0x00050041,0x00000074,0x000000be, + 0x0000006a,0x0000003e,0x0003003e,0x000000be,0x000000bd,0x0004003d,0x00000006,0x000000bf, + 0x0000004f,0x00050080,0x00000006,0x000000c0,0x000000bf,0x0000002a,0x00060041,0x00000070, + 0x000000c1,0x0000006e,0x0000005d,0x000000c0,0x0004003d,0x00000006,0x000000c2,0x000000c1, + 0x0006000c,0x00000046,0x000000c3,0x00000001,0x00000040,0x000000c2,0x00050041,0x00000074, + 0x000000c4,0x0000006a,0x00000065,0x0003003e,0x000000c4,0x000000c3,0x0004003d,0x00000006, + 0x000000c5,0x0000004f,0x00050080,0x00000006,0x000000c6,0x000000c5,0x00000084,0x00060041, + 0x00000070,0x000000c7,0x0000006e,0x0000005d,0x000000c6,0x0004003d,0x00000006,0x000000c8, + 0x000000c7,0x0006000c,0x00000046,0x000000c9,0x00000001,0x00000040,0x000000c8,0x00050041, + 0x00000074,0x000000ca,0x0000006a,0x00000082,0x0003003e,0x000000ca,0x000000c9,0x00050041, + 0x00000074,0x000000cb,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x000000cc,0x000000cb, + 0x0005008e,0x00000046,0x000000ce,0x000000cc,0x000000cd,0x00050041,0x00000074,0x000000cf, + 0x0000004a,0x0000005d,0x0004003d,0x00000046,0x000000d0,0x000000cf,0x00050081,0x00000046, + 0x000000d1,0x000000d0,0x000000ce,0x00050041,0x00000074,0x000000d2,0x0000004a,0x0000005d, + 0x0003003e,0x000000d2,0x000000d1,0x00050041,0x00000074,0x000000d3,0x0000006a,0x0000003e, + 0x0004003d,0x00000046,0x000000d4,0x000000d3,0x0005008e,0x00000046,0x000000d5,0x000000d4, + 0x000000cd,0x00050041,0x00000074,0x000000d6,0x0000004a,0x0000003e,0x0004003d,0x00000046, + 0x000000d7,0x000000d6,0x00050081,0x00000046,0x000000d8,0x000000d7,0x000000d5,0x00050041, + 0x00000074,0x000000d9,0x0000004a,0x0000003e,0x0003003e,0x000000d9,0x000000d8,0x00050041, + 0x00000074,0x000000da,0x0000006a,0x00000065,0x0004003d,0x00000046,0x000000db,0x000000da, + 0x0005008e,0x00000046,0x000000dc,0x000000db,0x000000cd,0x00050041,0x00000074,0x000000dd, + 0x0000004a,0x00000065,0x0004003d,0x00000046,0x000000de,0x000000dd,0x00050081,0x00000046, + 0x000000df,0x000000de,0x000000dc,0x00050041,0x00000074,0x000000e0,0x0000004a,0x00000065, + 0x0003003e,0x000000e0,0x000000df,0x00050041,0x00000074,0x000000e1,0x0000006a,0x00000082, + 0x0004003d,0x00000046,0x000000e2,0x000000e1,0x0005008e,0x00000046,0x000000e3,0x000000e2, + 0x000000cd,0x00050041,0x00000074,0x000000e4,0x0000004a,0x00000082,0x0004003d,0x00000046, + 0x000000e5,0x000000e4,0x00050081,0x00000046,0x000000e6,0x000000e5,0x000000e3,0x00050041, + 0x00000074,0x000000e7,0x0000004a,0x00000082,0x0003003e,0x000000e7,0x000000e6,0x00050041, + 0x00000019,0x000000e8,0x00000035,0x00000024,0x0004003d,0x00000006,0x000000e9,0x000000e8, + 0x000500aa,0x00000052,0x000000ea,0x000000e9,0x00000018,0x000300f7,0x000000ed,0x00000000, + 0x000400fa,0x000000ea,0x000000ec,0x000000ef,0x000200f8,0x000000ec,0x0004003d,0x00000006, + 0x000000ee,0x0000004f,0x0003003e,0x000000eb,0x000000ee,0x000200f9,0x000000ed,0x000200f8, + 0x000000ef,0x0004003d,0x00000006,0x000000f0,0x0000004f,0x00050041,0x00000021,0x000000f1, + 0x0000001e,0x0000005d,0x0004003d,0x00000006,0x000000f2,0x000000f1,0x00050080,0x00000006, + 0x000000f3,0x000000f0,0x000000f2,0x0003003e,0x000000eb,0x000000f3,0x000200f9,0x000000ed, + 0x000200f8,0x000000ed,0x0004003d,0x00000006,0x000000f4,0x000000eb,0x0003003e,0x0000004f, + 0x000000f4,0x0004003d,0x00000006,0x000000f5,0x0000004f,0x00060041,0x00000070,0x000000f6, + 0x0000006e,0x0000005d,0x000000f5,0x0004003d,0x00000006,0x000000f7,0x000000f6,0x0006000c, + 0x00000046,0x000000f8,0x00000001,0x00000040,0x000000f7,0x00050041,0x00000074,0x000000f9, + 0x0000006a,0x0000005d,0x0003003e,0x000000f9,0x000000f8,0x0004003d,0x00000006,0x000000fa, + 0x0000004f,0x00050080,0x00000006,0x000000fb,0x000000fa,0x00000024,0x00060041,0x00000070, + 0x000000fc,0x0000006e,0x0000005d,0x000000fb,0x0004003d,0x00000006,0x000000fd,0x000000fc, + 0x0006000c,0x00000046,0x000000fe,0x00000001,0x00000040,0x000000fd,0x00050041,0x00000074, + 0x000000ff,0x0000006a,0x0000003e,0x0003003e,0x000000ff,0x000000fe,0x0004003d,0x00000006, + 0x00000100,0x0000004f,0x00050080,0x00000006,0x00000101,0x00000100,0x0000002a,0x00060041, + 0x00000070,0x00000102,0x0000006e,0x0000005d,0x00000101,0x0004003d,0x00000006,0x00000103, + 0x00000102,0x0006000c,0x00000046,0x00000104,0x00000001,0x00000040,0x00000103,0x00050041, + 0x00000074,0x00000105,0x0000006a,0x00000065,0x0003003e,0x00000105,0x00000104,0x0004003d, + 0x00000006,0x00000106,0x0000004f,0x00050080,0x00000006,0x00000107,0x00000106,0x00000084, + 0x00060041,0x00000070,0x00000108,0x0000006e,0x0000005d,0x00000107,0x0004003d,0x00000006, + 0x00000109,0x00000108,0x0006000c,0x00000046,0x0000010a,0x00000001,0x00000040,0x00000109, + 0x00050041,0x00000074,0x0000010b,0x0000006a,0x00000082,0x0003003e,0x0000010b,0x0000010a, + 0x00050041,0x00000074,0x0000010c,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x0000010d, + 0x0000010c,0x0005008e,0x00000046,0x0000010f,0x0000010d,0x0000010e,0x00050041,0x00000074, + 0x00000110,0x0000004a,0x0000005d,0x0004003d,0x00000046,0x00000111,0x00000110,0x00050081, + 0x00000046,0x00000112,0x00000111,0x0000010f,0x00050041,0x00000074,0x00000113,0x0000004a, + 0x0000005d,0x0003003e,0x00000113,0x00000112,0x00050041,0x00000074,0x00000114,0x0000006a, + 0x0000003e,0x0004003d,0x00000046,0x00000115,0x00000114,0x0005008e,0x00000046,0x00000116, + 0x00000115,0x0000010e,0x00050041,0x00000074,0x00000117,0x0000004a,0x0000003e,0x0004003d, + 0x00000046,0x00000118,0x00000117,0x00050081,0x00000046,0x00000119,0x00000118,0x00000116, + 0x00050041,0x00000074,0x0000011a,0x0000004a,0x0000003e,0x0003003e,0x0000011a,0x00000119, + 0x00050041,0x00000074,0x0000011b,0x0000006a,0x00000065,0x0004003d,0x00000046,0x0000011c, + 0x0000011b,0x0005008e,0x00000046,0x0000011d,0x0000011c,0x0000010e,0x00050041,0x00000074, + 0x0000011e,0x0000004a,0x00000065,0x0004003d,0x00000046,0x0000011f,0x0000011e,0x00050081, + 0x00000046,0x00000120,0x0000011f,0x0000011d,0x00050041,0x00000074,0x00000121,0x0000004a, + 0x00000065,0x0003003e,0x00000121,0x00000120,0x00050041,0x00000074,0x00000122,0x0000006a, + 0x00000082,0x0004003d,0x00000046,0x00000123,0x00000122,0x0005008e,0x00000046,0x00000124, + 0x00000123,0x0000010e,0x00050041,0x00000074,0x00000125,0x0000004a,0x00000082,0x0004003d, + 0x00000046,0x00000126,0x00000125,0x00050081,0x00000046,0x00000127,0x00000126,0x00000124, + 0x00050041,0x00000074,0x00000128,0x0000004a,0x00000082,0x0003003e,0x00000128,0x00000127, + 0x00050041,0x00000074,0x00000129,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x0000012a, + 0x00000129,0x0005008e,0x00000046,0x0000012b,0x0000012a,0x0000008c,0x00050041,0x00000074, + 0x0000012c,0x0000004e,0x0000005d,0x0004003d,0x00000046,0x0000012d,0x0000012c,0x00050081, + 0x00000046,0x0000012e,0x0000012d,0x0000012b,0x00050041,0x00000074,0x0000012f,0x0000004e, + 0x0000005d,0x0003003e,0x0000012f,0x0000012e,0x00050041,0x00000074,0x00000130,0x0000006a, + 0x0000003e,0x0004003d,0x00000046,0x00000131,0x00000130,0x0005008e,0x00000046,0x00000132, + 0x00000131,0x0000008c,0x00050041,0x00000074,0x00000133,0x0000004e,0x0000003e,0x0004003d, + 0x00000046,0x00000134,0x00000133,0x00050081,0x00000046,0x00000135,0x00000134,0x00000132, + 0x00050041,0x00000074,0x00000136,0x0000004e,0x0000003e,0x0003003e,0x00000136,0x00000135, + 0x00050041,0x00000074,0x00000137,0x0000006a,0x00000065,0x0004003d,0x00000046,0x00000138, + 0x00000137,0x0005008e,0x00000046,0x00000139,0x00000138,0x0000008c,0x00050041,0x00000074, + 0x0000013a,0x0000004e,0x00000065,0x0004003d,0x00000046,0x0000013b,0x0000013a,0x00050081, + 0x00000046,0x0000013c,0x0000013b,0x00000139,0x00050041,0x00000074,0x0000013d,0x0000004e, + 0x00000065,0x0003003e,0x0000013d,0x0000013c,0x00050041,0x00000074,0x0000013e,0x0000006a, + 0x00000082,0x0004003d,0x00000046,0x0000013f,0x0000013e,0x0005008e,0x00000046,0x00000140, + 0x0000013f,0x0000008c,0x00050041,0x00000074,0x00000141,0x0000004e,0x00000082,0x0004003d, + 0x00000046,0x00000142,0x00000141,0x00050081,0x00000046,0x00000143,0x00000142,0x00000140, + 0x00050041,0x00000074,0x00000144,0x0000004e,0x00000082,0x0003003e,0x00000144,0x00000143, + 0x00050041,0x00000021,0x00000145,0x0000001e,0x0000005d,0x0004003d,0x00000006,0x00000146, + 0x00000145,0x0004003d,0x00000006,0x00000147,0x0000004f,0x00050080,0x00000006,0x00000148, + 0x00000147,0x00000146,0x0003003e,0x0000004f,0x00000148,0x0004003d,0x00000006,0x00000149, + 0x0000004f,0x00060041,0x00000070,0x0000014a,0x0000006e,0x0000005d,0x00000149,0x0004003d, + 0x00000006,0x0000014b,0x0000014a,0x0006000c,0x00000046,0x0000014c,0x00000001,0x00000040, + 0x0000014b,0x00050041,0x00000074,0x0000014d,0x0000006a,0x0000005d,0x0003003e,0x0000014d, + 0x0000014c,0x0004003d,0x00000006,0x0000014e,0x0000004f,0x00050080,0x00000006,0x0000014f, + 0x0000014e,0x00000024,0x00060041,0x00000070,0x00000150,0x0000006e,0x0000005d,0x0000014f, + 0x0004003d,0x00000006,0x00000151,0x00000150,0x0006000c,0x00000046,0x00000152,0x00000001, + 0x00000040,0x00000151,0x00050041,0x00000074,0x00000153,0x0000006a,0x0000003e,0x0003003e, + 0x00000153,0x00000152,0x0004003d,0x00000006,0x00000154,0x0000004f,0x00050080,0x00000006, + 0x00000155,0x00000154,0x0000002a,0x00060041,0x00000070,0x00000156,0x0000006e,0x0000005d, + 0x00000155,0x0004003d,0x00000006,0x00000157,0x00000156,0x0006000c,0x00000046,0x00000158, + 0x00000001,0x00000040,0x00000157,0x00050041,0x00000074,0x00000159,0x0000006a,0x00000065, + 0x0003003e,0x00000159,0x00000158,0x0004003d,0x00000006,0x0000015a,0x0000004f,0x00050080, + 0x00000006,0x0000015b,0x0000015a,0x00000084,0x00060041,0x00000070,0x0000015c,0x0000006e, + 0x0000005d,0x0000015b,0x0004003d,0x00000006,0x0000015d,0x0000015c,0x0006000c,0x00000046, + 0x0000015e,0x00000001,0x00000040,0x0000015d,0x00050041,0x00000074,0x0000015f,0x0000006a, + 0x00000082,0x0003003e,0x0000015f,0x0000015e,0x00050041,0x00000074,0x00000160,0x0000006a, + 0x0000005d,0x0004003d,0x00000046,0x00000161,0x00000160,0x0005008e,0x00000046,0x00000162, + 0x00000161,0x000000cd,0x00050041,0x00000074,0x00000163,0x0000004a,0x0000005d,0x0004003d, + 0x00000046,0x00000164,0x00000163,0x00050081,0x00000046,0x00000165,0x00000164,0x00000162, + 0x00050041,0x00000074,0x00000166,0x0000004a,0x0000005d,0x0003003e,0x00000166,0x00000165, + 0x00050041,0x00000074,0x00000167,0x0000006a,0x0000003e,0x0004003d,0x00000046,0x00000168, + 0x00000167,0x0005008e,0x00000046,0x00000169,0x00000168,0x000000cd,0x00050041,0x00000074, + 0x0000016a,0x0000004a,0x0000003e,0x0004003d,0x00000046,0x0000016b,0x0000016a,0x00050081, + 0x00000046,0x0000016c,0x0000016b,0x00000169,0x00050041,0x00000074,0x0000016d,0x0000004a, + 0x0000003e,0x0003003e,0x0000016d,0x0000016c,0x00050041,0x00000074,0x0000016e,0x0000006a, + 0x00000065,0x0004003d,0x00000046,0x0000016f,0x0000016e,0x0005008e,0x00000046,0x00000170, + 0x0000016f,0x000000cd,0x00050041,0x00000074,0x00000171,0x0000004a,0x00000065,0x0004003d, + 0x00000046,0x00000172,0x00000171,0x00050081,0x00000046,0x00000173,0x00000172,0x00000170, + 0x00050041,0x00000074,0x00000174,0x0000004a,0x00000065,0x0003003e,0x00000174,0x00000173, + 0x00050041,0x00000074,0x00000175,0x0000006a,0x00000082,0x0004003d,0x00000046,0x00000176, + 0x00000175,0x0005008e,0x00000046,0x00000177,0x00000176,0x000000cd,0x00050041,0x00000074, + 0x00000178,0x0000004a,0x00000082,0x0004003d,0x00000046,0x00000179,0x00000178,0x00050081, + 0x00000046,0x0000017a,0x00000179,0x00000177,0x00050041,0x00000074,0x0000017b,0x0000004a, + 0x00000082,0x0003003e,0x0000017b,0x0000017a,0x00050041,0x00000074,0x0000017c,0x0000006a, + 0x0000005d,0x0004003d,0x00000046,0x0000017d,0x0000017c,0x0005008e,0x00000046,0x0000017e, + 0x0000017d,0x000000cd,0x00050041,0x00000074,0x0000017f,0x0000004e,0x0000005d,0x0004003d, + 0x00000046,0x00000180,0x0000017f,0x00050081,0x00000046,0x00000181,0x00000180,0x0000017e, + 0x00050041,0x00000074,0x00000182,0x0000004e,0x0000005d,0x0003003e,0x00000182,0x00000181, + 0x00050041,0x00000074,0x00000183,0x0000006a,0x0000003e,0x0004003d,0x00000046,0x00000184, + 0x00000183,0x0005008e,0x00000046,0x00000185,0x00000184,0x000000cd,0x00050041,0x00000074, + 0x00000186,0x0000004e,0x0000003e,0x0004003d,0x00000046,0x00000187,0x00000186,0x00050081, + 0x00000046,0x00000188,0x00000187,0x00000185,0x00050041,0x00000074,0x00000189,0x0000004e, + 0x0000003e,0x0003003e,0x00000189,0x00000188,0x00050041,0x00000074,0x0000018a,0x0000006a, + 0x00000065,0x0004003d,0x00000046,0x0000018b,0x0000018a,0x0005008e,0x00000046,0x0000018c, + 0x0000018b,0x000000cd,0x00050041,0x00000074,0x0000018d,0x0000004e,0x00000065,0x0004003d, + 0x00000046,0x0000018e,0x0000018d,0x00050081,0x00000046,0x0000018f,0x0000018e,0x0000018c, + 0x00050041,0x00000074,0x00000190,0x0000004e,0x00000065,0x0003003e,0x00000190,0x0000018f, + 0x00050041,0x00000074,0x00000191,0x0000006a,0x00000082,0x0004003d,0x00000046,0x00000192, + 0x00000191,0x0005008e,0x00000046,0x00000193,0x00000192,0x000000cd,0x00050041,0x00000074, + 0x00000194,0x0000004e,0x00000082,0x0004003d,0x00000046,0x00000195,0x00000194,0x00050081, + 0x00000046,0x00000196,0x00000195,0x00000193,0x00050041,0x00000074,0x00000197,0x0000004e, + 0x00000082,0x0003003e,0x00000197,0x00000196,0x00050041,0x00000021,0x00000198,0x0000001e, + 0x0000005d,0x0004003d,0x00000006,0x00000199,0x00000198,0x0004003d,0x00000006,0x0000019a, + 0x0000004f,0x00050080,0x00000006,0x0000019b,0x0000019a,0x00000199,0x0003003e,0x0000004f, + 0x0000019b,0x0004003d,0x00000006,0x0000019c,0x0000004f,0x00060041,0x00000070,0x0000019d, + 0x0000006e,0x0000005d,0x0000019c,0x0004003d,0x00000006,0x0000019e,0x0000019d,0x0006000c, + 0x00000046,0x0000019f,0x00000001,0x00000040,0x0000019e,0x00050041,0x00000074,0x000001a0, + 0x0000006a,0x0000005d,0x0003003e,0x000001a0,0x0000019f,0x0004003d,0x00000006,0x000001a1, + 0x0000004f,0x00050080,0x00000006,0x000001a2,0x000001a1,0x00000024,0x00060041,0x00000070, + 0x000001a3,0x0000006e,0x0000005d,0x000001a2,0x0004003d,0x00000006,0x000001a4,0x000001a3, + 0x0006000c,0x00000046,0x000001a5,0x00000001,0x00000040,0x000001a4,0x00050041,0x00000074, + 0x000001a6,0x0000006a,0x0000003e,0x0003003e,0x000001a6,0x000001a5,0x0004003d,0x00000006, + 0x000001a7,0x0000004f,0x00050080,0x00000006,0x000001a8,0x000001a7,0x0000002a,0x00060041, + 0x00000070,0x000001a9,0x0000006e,0x0000005d,0x000001a8,0x0004003d,0x00000006,0x000001aa, + 0x000001a9,0x0006000c,0x00000046,0x000001ab,0x00000001,0x00000040,0x000001aa,0x00050041, + 0x00000074,0x000001ac,0x0000006a,0x00000065,0x0003003e,0x000001ac,0x000001ab,0x0004003d, + 0x00000006,0x000001ad,0x0000004f,0x00050080,0x00000006,0x000001ae,0x000001ad,0x00000084, + 0x00060041,0x00000070,0x000001af,0x0000006e,0x0000005d,0x000001ae,0x0004003d,0x00000006, + 0x000001b0,0x000001af,0x0006000c,0x00000046,0x000001b1,0x00000001,0x00000040,0x000001b0, + 0x00050041,0x00000074,0x000001b2,0x0000006a,0x00000082,0x0003003e,0x000001b2,0x000001b1, + 0x00050041,0x00000074,0x000001b3,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x000001b4, + 0x000001b3,0x0005008e,0x00000046,0x000001b5,0x000001b4,0x0000008c,0x00050041,0x00000074, + 0x000001b6,0x0000004a,0x0000005d,0x0004003d,0x00000046,0x000001b7,0x000001b6,0x00050081, + 0x00000046,0x000001b8,0x000001b7,0x000001b5,0x00050041,0x00000074,0x000001b9,0x0000004a, + 0x0000005d,0x0003003e,0x000001b9,0x000001b8,0x00050041,0x00000074,0x000001ba,0x0000006a, + 0x0000003e,0x0004003d,0x00000046,0x000001bb,0x000001ba,0x0005008e,0x00000046,0x000001bc, + 0x000001bb,0x0000008c,0x00050041,0x00000074,0x000001bd,0x0000004a,0x0000003e,0x0004003d, + 0x00000046,0x000001be,0x000001bd,0x00050081,0x00000046,0x000001bf,0x000001be,0x000001bc, + 0x00050041,0x00000074,0x000001c0,0x0000004a,0x0000003e,0x0003003e,0x000001c0,0x000001bf, + 0x00050041,0x00000074,0x000001c1,0x0000006a,0x00000065,0x0004003d,0x00000046,0x000001c2, + 0x000001c1,0x0005008e,0x00000046,0x000001c3,0x000001c2,0x0000008c,0x00050041,0x00000074, + 0x000001c4,0x0000004a,0x00000065,0x0004003d,0x00000046,0x000001c5,0x000001c4,0x00050081, + 0x00000046,0x000001c6,0x000001c5,0x000001c3,0x00050041,0x00000074,0x000001c7,0x0000004a, + 0x00000065,0x0003003e,0x000001c7,0x000001c6,0x00050041,0x00000074,0x000001c8,0x0000006a, + 0x00000082,0x0004003d,0x00000046,0x000001c9,0x000001c8,0x0005008e,0x00000046,0x000001ca, + 0x000001c9,0x0000008c,0x00050041,0x00000074,0x000001cb,0x0000004a,0x00000082,0x0004003d, + 0x00000046,0x000001cc,0x000001cb,0x00050081,0x00000046,0x000001cd,0x000001cc,0x000001ca, + 0x00050041,0x00000074,0x000001ce,0x0000004a,0x00000082,0x0003003e,0x000001ce,0x000001cd, + 0x00050041,0x00000074,0x000001cf,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x000001d0, + 0x000001cf,0x0005008e,0x00000046,0x000001d1,0x000001d0,0x0000010e,0x00050041,0x00000074, + 0x000001d2,0x0000004e,0x0000005d,0x0004003d,0x00000046,0x000001d3,0x000001d2,0x00050081, + 0x00000046,0x000001d4,0x000001d3,0x000001d1,0x00050041,0x00000074,0x000001d5,0x0000004e, + 0x0000005d,0x0003003e,0x000001d5,0x000001d4,0x00050041,0x00000074,0x000001d6,0x0000006a, + 0x0000003e,0x0004003d,0x00000046,0x000001d7,0x000001d6,0x0005008e,0x00000046,0x000001d8, + 0x000001d7,0x0000010e,0x00050041,0x00000074,0x000001d9,0x0000004e,0x0000003e,0x0004003d, + 0x00000046,0x000001da,0x000001d9,0x00050081,0x00000046,0x000001db,0x000001da,0x000001d8, + 0x00050041,0x00000074,0x000001dc,0x0000004e,0x0000003e,0x0003003e,0x000001dc,0x000001db, + 0x00050041,0x00000074,0x000001dd,0x0000006a,0x00000065,0x0004003d,0x00000046,0x000001de, + 0x000001dd,0x0005008e,0x00000046,0x000001df,0x000001de,0x0000010e,0x00050041,0x00000074, + 0x000001e0,0x0000004e,0x00000065,0x0004003d,0x00000046,0x000001e1,0x000001e0,0x00050081, + 0x00000046,0x000001e2,0x000001e1,0x000001df,0x00050041,0x00000074,0x000001e3,0x0000004e, + 0x00000065,0x0003003e,0x000001e3,0x000001e2,0x00050041,0x00000074,0x000001e4,0x0000006a, + 0x00000082,0x0004003d,0x00000046,0x000001e5,0x000001e4,0x0005008e,0x00000046,0x000001e6, + 0x000001e5,0x0000010e,0x00050041,0x00000074,0x000001e7,0x0000004e,0x00000082,0x0004003d, + 0x00000046,0x000001e8,0x000001e7,0x00050081,0x00000046,0x000001e9,0x000001e8,0x000001e6, + 0x00050041,0x00000074,0x000001ea,0x0000004e,0x00000082,0x0003003e,0x000001ea,0x000001e9, + 0x00050041,0x00000021,0x000001eb,0x0000001e,0x0000005d,0x0004003d,0x00000006,0x000001ec, + 0x000001eb,0x0004003d,0x00000006,0x000001ed,0x0000004f,0x00050080,0x00000006,0x000001ee, + 0x000001ed,0x000001ec,0x0003003e,0x0000004f,0x000001ee,0x0004003d,0x00000006,0x000001ef, + 0x0000004f,0x00060041,0x00000070,0x000001f0,0x0000006e,0x0000005d,0x000001ef,0x0004003d, + 0x00000006,0x000001f1,0x000001f0,0x0006000c,0x00000046,0x000001f2,0x00000001,0x00000040, + 0x000001f1,0x00050041,0x00000074,0x000001f3,0x0000006a,0x0000005d,0x0003003e,0x000001f3, + 0x000001f2,0x0004003d,0x00000006,0x000001f4,0x0000004f,0x00050080,0x00000006,0x000001f5, + 0x000001f4,0x00000024,0x00060041,0x00000070,0x000001f6,0x0000006e,0x0000005d,0x000001f5, + 0x0004003d,0x00000006,0x000001f7,0x000001f6,0x0006000c,0x00000046,0x000001f8,0x00000001, + 0x00000040,0x000001f7,0x00050041,0x00000074,0x000001f9,0x0000006a,0x0000003e,0x0003003e, + 0x000001f9,0x000001f8,0x0004003d,0x00000006,0x000001fa,0x0000004f,0x00050080,0x00000006, + 0x000001fb,0x000001fa,0x0000002a,0x00060041,0x00000070,0x000001fc,0x0000006e,0x0000005d, + 0x000001fb,0x0004003d,0x00000006,0x000001fd,0x000001fc,0x0006000c,0x00000046,0x000001fe, + 0x00000001,0x00000040,0x000001fd,0x00050041,0x00000074,0x000001ff,0x0000006a,0x00000065, + 0x0003003e,0x000001ff,0x000001fe,0x0004003d,0x00000006,0x00000200,0x0000004f,0x00050080, + 0x00000006,0x00000201,0x00000200,0x00000084,0x00060041,0x00000070,0x00000202,0x0000006e, + 0x0000005d,0x00000201,0x0004003d,0x00000006,0x00000203,0x00000202,0x0006000c,0x00000046, + 0x00000204,0x00000001,0x00000040,0x00000203,0x00050041,0x00000074,0x00000205,0x0000006a, + 0x00000082,0x0003003e,0x00000205,0x00000204,0x00050041,0x00000074,0x00000206,0x0000006a, + 0x0000005d,0x0004003d,0x00000046,0x00000207,0x00000206,0x0005008e,0x00000046,0x00000208, + 0x00000207,0x000000cd,0x00050041,0x00000074,0x00000209,0x0000004e,0x0000005d,0x0004003d, + 0x00000046,0x0000020a,0x00000209,0x00050081,0x00000046,0x0000020b,0x0000020a,0x00000208, + 0x00050041,0x00000074,0x0000020c,0x0000004e,0x0000005d,0x0003003e,0x0000020c,0x0000020b, + 0x00050041,0x00000074,0x0000020d,0x0000006a,0x0000003e,0x0004003d,0x00000046,0x0000020e, + 0x0000020d,0x0005008e,0x00000046,0x0000020f,0x0000020e,0x000000cd,0x00050041,0x00000074, + 0x00000210,0x0000004e,0x0000003e,0x0004003d,0x00000046,0x00000211,0x00000210,0x00050081, + 0x00000046,0x00000212,0x00000211,0x0000020f,0x00050041,0x00000074,0x00000213,0x0000004e, + 0x0000003e,0x0003003e,0x00000213,0x00000212,0x00050041,0x00000074,0x00000214,0x0000006a, + 0x00000065,0x0004003d,0x00000046,0x00000215,0x00000214,0x0005008e,0x00000046,0x00000216, + 0x00000215,0x000000cd,0x00050041,0x00000074,0x00000217,0x0000004e,0x00000065,0x0004003d, + 0x00000046,0x00000218,0x00000217,0x00050081,0x00000046,0x00000219,0x00000218,0x00000216, + 0x00050041,0x00000074,0x0000021a,0x0000004e,0x00000065,0x0003003e,0x0000021a,0x00000219, + 0x00050041,0x00000074,0x0000021b,0x0000006a,0x00000082,0x0004003d,0x00000046,0x0000021c, + 0x0000021b,0x0005008e,0x00000046,0x0000021d,0x0000021c,0x000000cd,0x00050041,0x00000074, + 0x0000021e,0x0000004e,0x00000082,0x0004003d,0x00000046,0x0000021f,0x0000021e,0x00050081, + 0x00000046,0x00000220,0x0000021f,0x0000021d,0x00050041,0x00000074,0x00000221,0x0000004e, + 0x00000082,0x0003003e,0x00000221,0x00000220,0x00050041,0x00000021,0x00000222,0x0000001e, + 0x0000005d,0x0004003d,0x00000006,0x00000223,0x00000222,0x0004003d,0x00000006,0x00000224, + 0x0000004f,0x00050080,0x00000006,0x00000225,0x00000224,0x00000223,0x0003003e,0x0000004f, + 0x00000225,0x0004003d,0x00000006,0x00000226,0x0000004f,0x00060041,0x00000070,0x00000227, + 0x0000006e,0x0000005d,0x00000226,0x0004003d,0x00000006,0x00000228,0x00000227,0x0006000c, + 0x00000046,0x00000229,0x00000001,0x00000040,0x00000228,0x00050041,0x00000074,0x0000022a, + 0x0000006a,0x0000005d,0x0003003e,0x0000022a,0x00000229,0x0004003d,0x00000006,0x0000022b, + 0x0000004f,0x00050080,0x00000006,0x0000022c,0x0000022b,0x00000024,0x00060041,0x00000070, + 0x0000022d,0x0000006e,0x0000005d,0x0000022c,0x0004003d,0x00000006,0x0000022e,0x0000022d, + 0x0006000c,0x00000046,0x0000022f,0x00000001,0x00000040,0x0000022e,0x00050041,0x00000074, + 0x00000230,0x0000006a,0x0000003e,0x0003003e,0x00000230,0x0000022f,0x0004003d,0x00000006, + 0x00000231,0x0000004f,0x00050080,0x00000006,0x00000232,0x00000231,0x0000002a,0x00060041, + 0x00000070,0x00000233,0x0000006e,0x0000005d,0x00000232,0x0004003d,0x00000006,0x00000234, + 0x00000233,0x0006000c,0x00000046,0x00000235,0x00000001,0x00000040,0x00000234,0x00050041, + 0x00000074,0x00000236,0x0000006a,0x00000065,0x0003003e,0x00000236,0x00000235,0x0004003d, + 0x00000006,0x00000237,0x0000004f,0x00050080,0x00000006,0x00000238,0x00000237,0x00000084, + 0x00060041,0x00000070,0x00000239,0x0000006e,0x0000005d,0x00000238,0x0004003d,0x00000006, + 0x0000023a,0x00000239,0x0006000c,0x00000046,0x0000023b,0x00000001,0x00000040,0x0000023a, + 0x00050041,0x00000074,0x0000023c,0x0000006a,0x00000082,0x0003003e,0x0000023c,0x0000023b, + 0x00050041,0x00000074,0x0000023d,0x0000006a,0x0000005d,0x0004003d,0x00000046,0x0000023e, + 0x0000023d,0x0005008e,0x00000046,0x0000023f,0x0000023e,0x0000008c,0x00050041,0x00000074, + 0x00000240,0x0000004e,0x0000005d,0x0004003d,0x00000046,0x00000241,0x00000240,0x00050081, + 0x00000046,0x00000242,0x00000241,0x0000023f,0x00050041,0x00000074,0x00000243,0x0000004e, + 0x0000005d,0x0003003e,0x00000243,0x00000242,0x00050041,0x00000074,0x00000244,0x0000006a, + 0x0000003e,0x0004003d,0x00000046,0x00000245,0x00000244,0x0005008e,0x00000046,0x00000246, + 0x00000245,0x0000008c,0x00050041,0x00000074,0x00000247,0x0000004e,0x0000003e,0x0004003d, + 0x00000046,0x00000248,0x00000247,0x00050081,0x00000046,0x00000249,0x00000248,0x00000246, + 0x00050041,0x00000074,0x0000024a,0x0000004e,0x0000003e,0x0003003e,0x0000024a,0x00000249, + 0x00050041,0x00000074,0x0000024b,0x0000006a,0x00000065,0x0004003d,0x00000046,0x0000024c, + 0x0000024b,0x0005008e,0x00000046,0x0000024d,0x0000024c,0x0000008c,0x00050041,0x00000074, + 0x0000024e,0x0000004e,0x00000065,0x0004003d,0x00000046,0x0000024f,0x0000024e,0x00050081, + 0x00000046,0x00000250,0x0000024f,0x0000024d,0x00050041,0x00000074,0x00000251,0x0000004e, + 0x00000065,0x0003003e,0x00000251,0x00000250,0x00050041,0x00000074,0x00000252,0x0000006a, + 0x00000082,0x0004003d,0x00000046,0x00000253,0x00000252,0x0005008e,0x00000046,0x00000254, + 0x00000253,0x0000008c,0x00050041,0x00000074,0x00000255,0x0000004e,0x00000082,0x0004003d, + 0x00000046,0x00000256,0x00000255,0x00050081,0x00000046,0x00000257,0x00000256,0x00000254, + 0x00050041,0x00000074,0x00000258,0x0000004e,0x00000082,0x0003003e,0x00000258,0x00000257, + 0x00050041,0x00000019,0x00000259,0x00000035,0x00000018,0x0004003d,0x00000006,0x0000025a, + 0x00000259,0x000500aa,0x00000052,0x0000025b,0x0000025a,0x00000018,0x000300f7,0x0000025e, + 0x00000000,0x000400fa,0x0000025b,0x0000025d,0x00000263,0x000200f8,0x0000025d,0x00060041, + 0x0000025f,0x00000260,0x0000004a,0x0000003e,0x00000018,0x0004003d,0x00000045,0x00000261, + 0x00000260,0x00070050,0x00000046,0x00000262,0x00000261,0x00000261,0x00000261,0x00000261, + 0x0003003e,0x0000025c,0x00000262,0x000200f9,0x0000025e,0x000200f8,0x00000263,0x00050041, + 0x00000074,0x00000264,0x0000004a,0x0000005d,0x0004003d,0x00000046,0x00000265,0x00000264, + 0x0003003e,0x0000025c,0x00000265,0x000200f9,0x0000025e,0x000200f8,0x0000025e,0x0004003d, + 0x00000046,0x00000266,0x0000025c,0x00050041,0x00000074,0x00000267,0x0000004a,0x0000005d, + 0x0003003e,0x00000267,0x00000266,0x00050041,0x00000019,0x00000268,0x00000035,0x00000018, + 0x0004003d,0x00000006,0x00000269,0x00000268,0x000500aa,0x00000052,0x0000026a,0x00000269, + 0x00000018,0x000300f7,0x0000026d,0x00000000,0x000400fa,0x0000026a,0x0000026c,0x00000271, + 0x000200f8,0x0000026c,0x00060041,0x0000025f,0x0000026e,0x0000004e,0x0000003e,0x00000018, + 0x0004003d,0x00000045,0x0000026f,0x0000026e,0x00070050,0x00000046,0x00000270,0x0000026f, + 0x0000026f,0x0000026f,0x0000026f,0x0003003e,0x0000026b,0x00000270,0x000200f9,0x0000026d, + 0x000200f8,0x00000271,0x00050041,0x00000074,0x00000272,0x0000004e,0x0000005d,0x0004003d, + 0x00000046,0x00000273,0x00000272,0x0003003e,0x0000026b,0x00000273,0x000200f9,0x0000026d, + 0x000200f8,0x0000026d,0x0004003d,0x00000046,0x00000274,0x0000026b,0x00050041,0x00000074, + 0x00000275,0x0000004e,0x0000005d,0x0003003e,0x00000275,0x00000274,0x00050041,0x00000019, + 0x00000276,0x00000035,0x00000018,0x0004003d,0x00000006,0x00000277,0x00000276,0x00050041, + 0x00000021,0x00000278,0x0000001e,0x00000020,0x0004003d,0x00000006,0x00000279,0x00000278, + 0x00050082,0x00000006,0x0000027a,0x00000279,0x0000002a,0x000500aa,0x00000052,0x0000027b, + 0x00000277,0x0000027a,0x000300f7,0x0000027e,0x00000000,0x000400fa,0x0000027b,0x0000027d, + 0x00000282,0x000200f8,0x0000027d,0x00060041,0x0000025f,0x0000027f,0x0000004a,0x00000065, + 0x00000084,0x0004003d,0x00000045,0x00000280,0x0000027f,0x00070050,0x00000046,0x00000281, + 0x00000280,0x00000280,0x00000280,0x00000280,0x0003003e,0x0000027c,0x00000281,0x000200f9, + 0x0000027e,0x000200f8,0x00000282,0x00050041,0x00000074,0x00000283,0x0000004a,0x00000082, + 0x0004003d,0x00000046,0x00000284,0x00000283,0x0003003e,0x0000027c,0x00000284,0x000200f9, + 0x0000027e,0x000200f8,0x0000027e,0x0004003d,0x00000046,0x00000285,0x0000027c,0x00050041, + 0x00000074,0x00000286,0x0000004a,0x00000082,0x0003003e,0x00000286,0x00000285,0x00050041, + 0x00000019,0x00000287,0x00000035,0x00000018,0x0004003d,0x00000006,0x00000288,0x00000287, + 0x00050041,0x00000021,0x00000289,0x0000001e,0x00000020,0x0004003d,0x00000006,0x0000028a, + 0x00000289,0x00050082,0x00000006,0x0000028b,0x0000028a,0x0000002a,0x000500aa,0x00000052, + 0x0000028c,0x00000288,0x0000028b,0x000300f7,0x0000028f,0x00000000,0x000400fa,0x0000028c, + 0x0000028e,0x00000293,0x000200f8,0x0000028e,0x00060041,0x0000025f,0x00000290,0x0000004e, + 0x00000065,0x00000084,0x0004003d,0x00000045,0x00000291,0x00000290,0x00070050,0x00000046, + 0x00000292,0x00000291,0x00000291,0x00000291,0x00000291,0x0003003e,0x0000028d,0x00000292, + 0x000200f9,0x0000028f,0x000200f8,0x00000293,0x00050041,0x00000074,0x00000294,0x0000004e, + 0x00000082,0x0004003d,0x00000046,0x00000295,0x00000294,0x0003003e,0x0000028d,0x00000295, + 0x000200f9,0x0000028f,0x000200f8,0x0000028f,0x0004003d,0x00000046,0x00000296,0x0000028d, + 0x00050041,0x00000074,0x00000297,0x0000004e,0x00000082,0x0003003e,0x00000297,0x00000296, + 0x00060041,0x0000025f,0x00000299,0x0000004a,0x0000005d,0x0000002a,0x0004003d,0x00000045, + 0x0000029a,0x00000299,0x00060041,0x0000025f,0x0000029b,0x0000004a,0x0000003e,0x00000018, + 0x0004003d,0x00000045,0x0000029c,0x0000029b,0x00060041,0x0000025f,0x0000029d,0x0000004a, + 0x0000003e,0x0000002a,0x0004003d,0x00000045,0x0000029e,0x0000029d,0x00060041,0x0000025f, + 0x0000029f,0x0000004a,0x00000065,0x00000018,0x0004003d,0x00000045,0x000002a0,0x0000029f, + 0x00070050,0x00000046,0x000002a1,0x0000029a,0x0000029c,0x0000029e,0x000002a0,0x0005008e, + 0x00000046,0x000002a2,0x000002a1,0x0000008c,0x00060041,0x0000025f,0x000002a3,0x0000004a, + 0x0000005d,0x00000084,0x0004003d,0x00000045,0x000002a4,0x000002a3,0x00060041,0x0000025f, + 0x000002a5,0x0000004a,0x0000003e,0x00000024,0x0004003d,0x00000045,0x000002a6,0x000002a5, + 0x00060041,0x0000025f,0x000002a7,0x0000004a,0x0000003e,0x00000084,0x0004003d,0x00000045, + 0x000002a8,0x000002a7,0x00060041,0x0000025f,0x000002a9,0x0000004a,0x00000065,0x00000024, + 0x0004003d,0x00000045,0x000002aa,0x000002a9,0x00070050,0x00000046,0x000002ab,0x000002a4, + 0x000002a6,0x000002a8,0x000002aa,0x0005008e,0x00000046,0x000002ac,0x000002ab,0x000000cd, + 0x00050081,0x00000046,0x000002ad,0x000002a2,0x000002ac,0x00060041,0x0000025f,0x000002ae, + 0x0000004a,0x0000003e,0x00000018,0x0004003d,0x00000045,0x000002af,0x000002ae,0x00060041, + 0x0000025f,0x000002b0,0x0000004a,0x0000003e,0x0000002a,0x0004003d,0x00000045,0x000002b1, + 0x000002b0,0x00060041,0x0000025f,0x000002b2,0x0000004a,0x00000065,0x00000018,0x0004003d, + 0x00000045,0x000002b3,0x000002b2,0x00060041,0x0000025f,0x000002b4,0x0000004a,0x00000065, + 0x0000002a,0x0004003d,0x00000045,0x000002b5,0x000002b4,0x00070050,0x00000046,0x000002b6, + 0x000002af,0x000002b1,0x000002b3,0x000002b5,0x0005008e,0x00000046,0x000002b7,0x000002b6, + 0x0000010e,0x00050081,0x00000046,0x000002b8,0x000002ad,0x000002b7,0x00060041,0x0000025f, + 0x000002b9,0x0000004a,0x0000003e,0x00000024,0x0004003d,0x00000045,0x000002ba,0x000002b9, + 0x00060041,0x0000025f,0x000002bb,0x0000004a,0x0000003e,0x00000084,0x0004003d,0x00000045, + 0x000002bc,0x000002bb,0x00060041,0x0000025f,0x000002bd,0x0000004a,0x00000065,0x00000024, + 0x0004003d,0x00000045,0x000002be,0x000002bd,0x00060041,0x0000025f,0x000002bf,0x0000004a, + 0x00000065,0x00000084,0x0004003d,0x00000045,0x000002c0,0x000002bf,0x00070050,0x00000046, + 0x000002c1,0x000002ba,0x000002bc,0x000002be,0x000002c0,0x0005008e,0x00000046,0x000002c2, + 0x000002c1,0x000000cd,0x00050081,0x00000046,0x000002c3,0x000002b8,0x000002c2,0x00060041, + 0x0000025f,0x000002c4,0x0000004a,0x0000003e,0x0000002a,0x0004003d,0x00000045,0x000002c5, + 0x000002c4,0x00060041,0x0000025f,0x000002c6,0x0000004a,0x00000065,0x00000018,0x0004003d, + 0x00000045,0x000002c7,0x000002c6,0x00060041,0x0000025f,0x000002c8,0x0000004a,0x00000065, + 0x0000002a,0x0004003d,0x00000045,0x000002c9,0x000002c8,0x00060041,0x0000025f,0x000002ca, + 0x0000004a,0x00000082,0x00000018,0x0004003d,0x00000045,0x000002cb,0x000002ca,0x00070050, + 0x00000046,0x000002cc,0x000002c5,0x000002c7,0x000002c9,0x000002cb,0x0005008e,0x00000046, + 0x000002cd,0x000002cc,0x0000008c,0x00050081,0x00000046,0x000002ce,0x000002c3,0x000002cd, + 0x0003003e,0x00000298,0x000002ce,0x00060041,0x0000025f,0x000002d0,0x0000004e,0x0000005d, + 0x0000002a,0x0004003d,0x00000045,0x000002d1,0x000002d0,0x00060041,0x0000025f,0x000002d2, + 0x0000004e,0x0000003e,0x00000018,0x0004003d,0x00000045,0x000002d3,0x000002d2,0x00060041, + 0x0000025f,0x000002d4,0x0000004e,0x0000003e,0x0000002a,0x0004003d,0x00000045,0x000002d5, + 0x000002d4,0x00060041,0x0000025f,0x000002d6,0x0000004e,0x00000065,0x00000018,0x0004003d, + 0x00000045,0x000002d7,0x000002d6,0x00070050,0x00000046,0x000002d8,0x000002d1,0x000002d3, + 0x000002d5,0x000002d7,0x0005008e,0x00000046,0x000002d9,0x000002d8,0x0000008c,0x00060041, + 0x0000025f,0x000002da,0x0000004e,0x0000005d,0x00000084,0x0004003d,0x00000045,0x000002db, + 0x000002da,0x00060041,0x0000025f,0x000002dc,0x0000004e,0x0000003e,0x00000024,0x0004003d, + 0x00000045,0x000002dd,0x000002dc,0x00060041,0x0000025f,0x000002de,0x0000004e,0x0000003e, + 0x00000084,0x0004003d,0x00000045,0x000002df,0x000002de,0x00060041,0x0000025f,0x000002e0, + 0x0000004e,0x00000065,0x00000024,0x0004003d,0x00000045,0x000002e1,0x000002e0,0x00070050, + 0x00000046,0x000002e2,0x000002db,0x000002dd,0x000002df,0x000002e1,0x0005008e,0x00000046, + 0x000002e3,0x000002e2,0x000000cd,0x00050081,0x00000046,0x000002e4,0x000002d9,0x000002e3, + 0x00060041,0x0000025f,0x000002e5,0x0000004e,0x0000003e,0x00000018,0x0004003d,0x00000045, + 0x000002e6,0x000002e5,0x00060041,0x0000025f,0x000002e7,0x0000004e,0x0000003e,0x0000002a, + 0x0004003d,0x00000045,0x000002e8,0x000002e7,0x00060041,0x0000025f,0x000002e9,0x0000004e, + 0x00000065,0x00000018,0x0004003d,0x00000045,0x000002ea,0x000002e9,0x00060041,0x0000025f, + 0x000002eb,0x0000004e,0x00000065,0x0000002a,0x0004003d,0x00000045,0x000002ec,0x000002eb, + 0x00070050,0x00000046,0x000002ed,0x000002e6,0x000002e8,0x000002ea,0x000002ec,0x0005008e, + 0x00000046,0x000002ee,0x000002ed,0x0000010e,0x00050081,0x00000046,0x000002ef,0x000002e4, + 0x000002ee,0x00060041,0x0000025f,0x000002f0,0x0000004e,0x0000003e,0x00000024,0x0004003d, + 0x00000045,0x000002f1,0x000002f0,0x00060041,0x0000025f,0x000002f2,0x0000004e,0x0000003e, + 0x00000084,0x0004003d,0x00000045,0x000002f3,0x000002f2,0x00060041,0x0000025f,0x000002f4, + 0x0000004e,0x00000065,0x00000024,0x0004003d,0x00000045,0x000002f5,0x000002f4,0x00060041, + 0x0000025f,0x000002f6,0x0000004e,0x00000065,0x00000084,0x0004003d,0x00000045,0x000002f7, + 0x000002f6,0x00070050,0x00000046,0x000002f8,0x000002f1,0x000002f3,0x000002f5,0x000002f7, + 0x0005008e,0x00000046,0x000002f9,0x000002f8,0x000000cd,0x00050081,0x00000046,0x000002fa, + 0x000002ef,0x000002f9,0x00060041,0x0000025f,0x000002fb,0x0000004e,0x0000003e,0x0000002a, + 0x0004003d,0x00000045,0x000002fc,0x000002fb,0x00060041,0x0000025f,0x000002fd,0x0000004e, + 0x00000065,0x00000018,0x0004003d,0x00000045,0x000002fe,0x000002fd,0x00060041,0x0000025f, + 0x000002ff,0x0000004e,0x00000065,0x0000002a,0x0004003d,0x00000045,0x00000300,0x000002ff, + 0x00060041,0x0000025f,0x00000301,0x0000004e,0x00000082,0x00000018,0x0004003d,0x00000045, + 0x00000302,0x00000301,0x00070050,0x00000046,0x00000303,0x000002fc,0x000002fe,0x00000300, + 0x00000302,0x0005008e,0x00000046,0x00000304,0x00000303,0x0000008c,0x00050081,0x00000046, + 0x00000305,0x000002fa,0x00000304,0x0003003e,0x000002cf,0x00000305,0x0004003d,0x00000046, + 0x00000306,0x00000298,0x00070050,0x00000046,0x00000308,0x0000004b,0x0000004b,0x0000004b, + 0x0000004b,0x00070050,0x00000046,0x00000309,0x00000307,0x00000307,0x00000307,0x00000307, + 0x0008000c,0x00000046,0x0000030a,0x00000001,0x0000002b,0x00000306,0x00000308,0x00000309, + 0x0003003e,0x00000298,0x0000030a,0x0004003d,0x00000046,0x0000030b,0x000002cf,0x00070050, + 0x00000046,0x0000030c,0x0000004b,0x0000004b,0x0000004b,0x0000004b,0x00070050,0x00000046, + 0x0000030d,0x00000307,0x00000307,0x00000307,0x00000307,0x0008000c,0x00000046,0x0000030e, + 0x00000001,0x0000002b,0x0000030b,0x0000030c,0x0000030d,0x0003003e,0x000002cf,0x0000030e, + 0x00050041,0x00000019,0x0000030f,0x0000000a,0x00000018,0x0004003d,0x00000006,0x00000310, + 0x0000030f,0x00050041,0x00000021,0x00000311,0x0000001e,0x00000082,0x0004003d,0x00000006, + 0x00000312,0x00000311,0x00050082,0x00000006,0x00000313,0x00000312,0x00000024,0x0008000c, + 0x00000006,0x00000314,0x00000001,0x0000002c,0x00000310,0x00000018,0x00000313,0x00050041, + 0x00000019,0x00000315,0x0000000a,0x00000018,0x0003003e,0x00000315,0x00000314,0x00050041, + 0x00000019,0x00000316,0x0000000a,0x00000024,0x0004003d,0x00000006,0x00000317,0x00000316, + 0x00050041,0x00000021,0x00000319,0x0000001e,0x00000318,0x0004003d,0x00000006,0x0000031a, + 0x00000319,0x00050082,0x00000006,0x0000031b,0x0000031a,0x0000002a,0x0008000c,0x00000006, + 0x0000031c,0x00000001,0x0000002c,0x00000317,0x00000018,0x0000031b,0x00050041,0x00000019, + 0x0000031d,0x0000000a,0x00000024,0x0003003e,0x0000031d,0x0000031c,0x00050041,0x00000019, + 0x0000031f,0x0000000a,0x00000024,0x0004003d,0x00000006,0x00000320,0x0000031f,0x00050041, + 0x00000021,0x00000321,0x0000001e,0x00000082,0x0004003d,0x00000006,0x00000322,0x00000321, + 0x00050084,0x00000006,0x00000323,0x00000320,0x00000322,0x00050041,0x00000019,0x00000324, + 0x0000000a,0x00000018,0x0004003d,0x00000006,0x00000325,0x00000324,0x00050080,0x00000006, + 0x00000326,0x00000323,0x00000325,0x0003003e,0x0000031e,0x00000326,0x0004003d,0x00000006, + 0x0000032b,0x0000031e,0x0004003d,0x00000046,0x0000032c,0x00000298,0x0006000c,0x00000006, + 0x0000032d,0x00000001,0x00000037,0x0000032c,0x00060041,0x00000070,0x0000032e,0x0000032a, + 0x0000005d,0x0000032b,0x0003003e,0x0000032e,0x0000032d,0x0004003d,0x00000006,0x0000032f, + 0x0000031e,0x00050041,0x00000021,0x00000330,0x0000001e,0x00000082,0x0004003d,0x00000006, + 0x00000331,0x00000330,0x00050080,0x00000006,0x00000332,0x0000032f,0x00000331,0x0004003d, + 0x00000046,0x00000333,0x000002cf,0x0006000c,0x00000006,0x00000334,0x00000001,0x00000037, + 0x00000333,0x00060041,0x00000070,0x00000335,0x0000032a,0x0000005d,0x00000332,0x0003003e, + 0x00000335,0x00000334,0x000100fd,0x00010038,0x00050036,0x00000002,0x00000010,0x00000000, + 0x0000000e,0x00030037,0x00000008,0x0000000f,0x000200f8,0x00000011,0x0004003b,0x00000008, + 0x00000336,0x00000007,0x0004003b,0x00000008,0x0000033a,0x00000007,0x0004003b,0x00000049, + 0x00000346,0x00000007,0x0004003b,0x00000019,0x00000347,0x00000007,0x0004003b,0x00000019, + 0x0000034b,0x00000007,0x0004003b,0x00000049,0x0000035f,0x00000007,0x0004003b,0x00000019, + 0x0000039a,0x00000007,0x0004003b,0x00000019,0x000003da,0x00000007,0x0004003b,0x00000074, + 0x00000488,0x00000007,0x0004003b,0x00000074,0x0000049d,0x00000007,0x0004003b,0x00000074, + 0x000004ac,0x00000007,0x0004003d,0x00000007,0x00000337,0x0000000f,0x00050050,0x00000007, + 0x00000338,0x0000002a,0x0000002a,0x00050084,0x00000007,0x00000339,0x00000337,0x00000338, + 0x0003003e,0x00000336,0x00000339,0x0004003d,0x00000007,0x0000033b,0x00000336,0x00050082, + 0x00000007,0x0000033c,0x0000033b,0x0000002b,0x0003003e,0x0000033a,0x0000033c,0x00050041, + 0x00000019,0x0000033d,0x0000033a,0x00000024,0x0004003d,0x00000006,0x0000033e,0x0000033d, + 0x00050041,0x00000021,0x0000033f,0x0000001e,0x0000003e,0x0004003d,0x00000006,0x00000340, + 0x0000033f,0x00050086,0x00000006,0x00000341,0x00000340,0x0000002a,0x00050082,0x00000006, + 0x00000343,0x00000341,0x00000342,0x0008000c,0x00000006,0x00000344,0x00000001,0x0000002c, + 0x0000033e,0x00000018,0x00000343,0x00050041,0x00000019,0x00000345,0x0000033a,0x00000024, + 0x0003003e,0x00000345,0x00000344,0x0003003e,0x00000346,0x0000004d,0x00050041,0x00000019, + 0x00000348,0x00000336,0x00000024,0x0004003d,0x00000006,0x00000349,0x00000348,0x000500aa, + 0x00000052,0x0000034a,0x00000349,0x00000018,0x000300f7,0x0000034d,0x00000000,0x000400fa, + 0x0000034a,0x0000034c,0x00000351,0x000200f8,0x0000034c,0x00050041,0x00000019,0x0000034e, + 0x00000336,0x00000018,0x0004003d,0x00000006,0x0000034f,0x0000034e,0x00050082,0x00000006, + 0x00000350,0x0000034f,0x00000024,0x0003003e,0x0000034b,0x00000350,0x000200f9,0x0000034d, + 0x000200f8,0x00000351,0x00050041,0x00000019,0x00000352,0x0000033a,0x00000024,0x0004003d, + 0x00000006,0x00000353,0x00000352,0x00050041,0x00000021,0x00000354,0x0000001e,0x0000005d, + 0x0004003d,0x00000006,0x00000355,0x00000354,0x00050084,0x00000006,0x00000356,0x00000353, + 0x00000355,0x00050041,0x00000019,0x00000357,0x0000033a,0x00000018,0x0004003d,0x00000006, + 0x00000358,0x00000357,0x00050080,0x00000006,0x00000359,0x00000356,0x00000358,0x0003003e, + 0x0000034b,0x00000359,0x000200f9,0x0000034d,0x000200f8,0x0000034d,0x0004003d,0x00000006, + 0x0000035a,0x0000034b,0x0003003e,0x00000347,0x0000035a,0x00050041,0x00000021,0x0000035b, + 0x0000001e,0x00000065,0x0004003d,0x00000006,0x0000035c,0x0000035b,0x0004003d,0x00000006, + 0x0000035d,0x00000347,0x00050080,0x00000006,0x0000035e,0x0000035d,0x0000035c,0x0003003e, + 0x00000347,0x0000035e,0x0004003d,0x00000006,0x00000364,0x00000347,0x00060041,0x00000070, + 0x00000365,0x00000363,0x0000005d,0x00000364,0x0004003d,0x00000006,0x00000366,0x00000365, + 0x0006000c,0x00000046,0x00000367,0x00000001,0x00000040,0x00000366,0x00050041,0x00000074, + 0x00000368,0x0000035f,0x0000005d,0x0003003e,0x00000368,0x00000367,0x0004003d,0x00000006, + 0x00000369,0x00000347,0x00050080,0x00000006,0x0000036a,0x00000369,0x00000024,0x00060041, + 0x00000070,0x0000036b,0x00000363,0x0000005d,0x0000036a,0x0004003d,0x00000006,0x0000036c, + 0x0000036b,0x0006000c,0x00000046,0x0000036d,0x00000001,0x00000040,0x0000036c,0x00050041, + 0x00000074,0x0000036e,0x0000035f,0x0000003e,0x0003003e,0x0000036e,0x0000036d,0x0004003d, + 0x00000006,0x0000036f,0x00000347,0x00050080,0x00000006,0x00000370,0x0000036f,0x0000002a, + 0x00060041,0x00000070,0x00000371,0x00000363,0x0000005d,0x00000370,0x0004003d,0x00000006, + 0x00000372,0x00000371,0x0006000c,0x00000046,0x00000373,0x00000001,0x00000040,0x00000372, + 0x00050041,0x00000074,0x00000374,0x0000035f,0x00000065,0x0003003e,0x00000374,0x00000373, + 0x0004003d,0x00000006,0x00000375,0x00000347,0x00050080,0x00000006,0x00000376,0x00000375, + 0x00000084,0x00060041,0x00000070,0x00000377,0x00000363,0x0000005d,0x00000376,0x0004003d, + 0x00000006,0x00000378,0x00000377,0x0006000c,0x00000046,0x00000379,0x00000001,0x00000040, + 0x00000378,0x00050041,0x00000074,0x0000037a,0x0000035f,0x00000082,0x0003003e,0x0000037a, + 0x00000379,0x00050041,0x00000074,0x0000037b,0x0000035f,0x0000005d,0x0004003d,0x00000046, + 0x0000037c,0x0000037b,0x0005008e,0x00000046,0x0000037d,0x0000037c,0x0000008c,0x00050041, + 0x00000074,0x0000037e,0x00000346,0x0000005d,0x0004003d,0x00000046,0x0000037f,0x0000037e, + 0x00050081,0x00000046,0x00000380,0x0000037f,0x0000037d,0x00050041,0x00000074,0x00000381, + 0x00000346,0x0000005d,0x0003003e,0x00000381,0x00000380,0x00050041,0x00000074,0x00000382, + 0x0000035f,0x0000003e,0x0004003d,0x00000046,0x00000383,0x00000382,0x0005008e,0x00000046, + 0x00000384,0x00000383,0x0000008c,0x00050041,0x00000074,0x00000385,0x00000346,0x0000003e, + 0x0004003d,0x00000046,0x00000386,0x00000385,0x00050081,0x00000046,0x00000387,0x00000386, + 0x00000384,0x00050041,0x00000074,0x00000388,0x00000346,0x0000003e,0x0003003e,0x00000388, + 0x00000387,0x00050041,0x00000074,0x00000389,0x0000035f,0x00000065,0x0004003d,0x00000046, + 0x0000038a,0x00000389,0x0005008e,0x00000046,0x0000038b,0x0000038a,0x0000008c,0x00050041, + 0x00000074,0x0000038c,0x00000346,0x00000065,0x0004003d,0x00000046,0x0000038d,0x0000038c, + 0x00050081,0x00000046,0x0000038e,0x0000038d,0x0000038b,0x00050041,0x00000074,0x0000038f, + 0x00000346,0x00000065,0x0003003e,0x0000038f,0x0000038e,0x00050041,0x00000074,0x00000390, + 0x0000035f,0x00000082,0x0004003d,0x00000046,0x00000391,0x00000390,0x0005008e,0x00000046, + 0x00000392,0x00000391,0x0000008c,0x00050041,0x00000074,0x00000393,0x00000346,0x00000082, + 0x0004003d,0x00000046,0x00000394,0x00000393,0x00050081,0x00000046,0x00000395,0x00000394, + 0x00000392,0x00050041,0x00000074,0x00000396,0x00000346,0x00000082,0x0003003e,0x00000396, + 0x00000395,0x00050041,0x00000019,0x00000397,0x00000336,0x00000024,0x0004003d,0x00000006, + 0x00000398,0x00000397,0x000500aa,0x00000052,0x00000399,0x00000398,0x00000018,0x000300f7, + 0x0000039c,0x00000000,0x000400fa,0x00000399,0x0000039b,0x0000039e,0x000200f8,0x0000039b, + 0x0004003d,0x00000006,0x0000039d,0x00000347,0x0003003e,0x0000039a,0x0000039d,0x000200f9, + 0x0000039c,0x000200f8,0x0000039e,0x0004003d,0x00000006,0x0000039f,0x00000347,0x00050041, + 0x00000021,0x000003a0,0x0000001e,0x0000005d,0x0004003d,0x00000006,0x000003a1,0x000003a0, + 0x00050080,0x00000006,0x000003a2,0x0000039f,0x000003a1,0x0003003e,0x0000039a,0x000003a2, + 0x000200f9,0x0000039c,0x000200f8,0x0000039c,0x0004003d,0x00000006,0x000003a3,0x0000039a, + 0x0003003e,0x00000347,0x000003a3,0x0004003d,0x00000006,0x000003a4,0x00000347,0x00060041, + 0x00000070,0x000003a5,0x00000363,0x0000005d,0x000003a4,0x0004003d,0x00000006,0x000003a6, + 0x000003a5,0x0006000c,0x00000046,0x000003a7,0x00000001,0x00000040,0x000003a6,0x00050041, + 0x00000074,0x000003a8,0x0000035f,0x0000005d,0x0003003e,0x000003a8,0x000003a7,0x0004003d, + 0x00000006,0x000003a9,0x00000347,0x00050080,0x00000006,0x000003aa,0x000003a9,0x00000024, + 0x00060041,0x00000070,0x000003ab,0x00000363,0x0000005d,0x000003aa,0x0004003d,0x00000006, + 0x000003ac,0x000003ab,0x0006000c,0x00000046,0x000003ad,0x00000001,0x00000040,0x000003ac, + 0x00050041,0x00000074,0x000003ae,0x0000035f,0x0000003e,0x0003003e,0x000003ae,0x000003ad, + 0x0004003d,0x00000006,0x000003af,0x00000347,0x00050080,0x00000006,0x000003b0,0x000003af, + 0x0000002a,0x00060041,0x00000070,0x000003b1,0x00000363,0x0000005d,0x000003b0,0x0004003d, + 0x00000006,0x000003b2,0x000003b1,0x0006000c,0x00000046,0x000003b3,0x00000001,0x00000040, + 0x000003b2,0x00050041,0x00000074,0x000003b4,0x0000035f,0x00000065,0x0003003e,0x000003b4, + 0x000003b3,0x0004003d,0x00000006,0x000003b5,0x00000347,0x00050080,0x00000006,0x000003b6, + 0x000003b5,0x00000084,0x00060041,0x00000070,0x000003b7,0x00000363,0x0000005d,0x000003b6, + 0x0004003d,0x00000006,0x000003b8,0x000003b7,0x0006000c,0x00000046,0x000003b9,0x00000001, + 0x00000040,0x000003b8,0x00050041,0x00000074,0x000003ba,0x0000035f,0x00000082,0x0003003e, + 0x000003ba,0x000003b9,0x00050041,0x00000074,0x000003bb,0x0000035f,0x0000005d,0x0004003d, + 0x00000046,0x000003bc,0x000003bb,0x0005008e,0x00000046,0x000003bd,0x000003bc,0x000000cd, + 0x00050041,0x00000074,0x000003be,0x00000346,0x0000005d,0x0004003d,0x00000046,0x000003bf, + 0x000003be,0x00050081,0x00000046,0x000003c0,0x000003bf,0x000003bd,0x00050041,0x00000074, + 0x000003c1,0x00000346,0x0000005d,0x0003003e,0x000003c1,0x000003c0,0x00050041,0x00000074, + 0x000003c2,0x0000035f,0x0000003e,0x0004003d,0x00000046,0x000003c3,0x000003c2,0x0005008e, + 0x00000046,0x000003c4,0x000003c3,0x000000cd,0x00050041,0x00000074,0x000003c5,0x00000346, + 0x0000003e,0x0004003d,0x00000046,0x000003c6,0x000003c5,0x00050081,0x00000046,0x000003c7, + 0x000003c6,0x000003c4,0x00050041,0x00000074,0x000003c8,0x00000346,0x0000003e,0x0003003e, + 0x000003c8,0x000003c7,0x00050041,0x00000074,0x000003c9,0x0000035f,0x00000065,0x0004003d, + 0x00000046,0x000003ca,0x000003c9,0x0005008e,0x00000046,0x000003cb,0x000003ca,0x000000cd, + 0x00050041,0x00000074,0x000003cc,0x00000346,0x00000065,0x0004003d,0x00000046,0x000003cd, + 0x000003cc,0x00050081,0x00000046,0x000003ce,0x000003cd,0x000003cb,0x00050041,0x00000074, + 0x000003cf,0x00000346,0x00000065,0x0003003e,0x000003cf,0x000003ce,0x00050041,0x00000074, + 0x000003d0,0x0000035f,0x00000082,0x0004003d,0x00000046,0x000003d1,0x000003d0,0x0005008e, + 0x00000046,0x000003d2,0x000003d1,0x000000cd,0x00050041,0x00000074,0x000003d3,0x00000346, + 0x00000082,0x0004003d,0x00000046,0x000003d4,0x000003d3,0x00050081,0x00000046,0x000003d5, + 0x000003d4,0x000003d2,0x00050041,0x00000074,0x000003d6,0x00000346,0x00000082,0x0003003e, + 0x000003d6,0x000003d5,0x00050041,0x00000019,0x000003d7,0x00000336,0x00000024,0x0004003d, + 0x00000006,0x000003d8,0x000003d7,0x000500aa,0x00000052,0x000003d9,0x000003d8,0x00000018, + 0x000300f7,0x000003dc,0x00000000,0x000400fa,0x000003d9,0x000003db,0x000003de,0x000200f8, + 0x000003db,0x0004003d,0x00000006,0x000003dd,0x00000347,0x0003003e,0x000003da,0x000003dd, + 0x000200f9,0x000003dc,0x000200f8,0x000003de,0x0004003d,0x00000006,0x000003df,0x00000347, + 0x00050041,0x00000021,0x000003e0,0x0000001e,0x0000005d,0x0004003d,0x00000006,0x000003e1, + 0x000003e0,0x00050080,0x00000006,0x000003e2,0x000003df,0x000003e1,0x0003003e,0x000003da, + 0x000003e2,0x000200f9,0x000003dc,0x000200f8,0x000003dc,0x0004003d,0x00000006,0x000003e3, + 0x000003da,0x0003003e,0x00000347,0x000003e3,0x0004003d,0x00000006,0x000003e4,0x00000347, + 0x00060041,0x00000070,0x000003e5,0x00000363,0x0000005d,0x000003e4,0x0004003d,0x00000006, + 0x000003e6,0x000003e5,0x0006000c,0x00000046,0x000003e7,0x00000001,0x00000040,0x000003e6, + 0x00050041,0x00000074,0x000003e8,0x0000035f,0x0000005d,0x0003003e,0x000003e8,0x000003e7, + 0x0004003d,0x00000006,0x000003e9,0x00000347,0x00050080,0x00000006,0x000003ea,0x000003e9, + 0x00000024,0x00060041,0x00000070,0x000003eb,0x00000363,0x0000005d,0x000003ea,0x0004003d, + 0x00000006,0x000003ec,0x000003eb,0x0006000c,0x00000046,0x000003ed,0x00000001,0x00000040, + 0x000003ec,0x00050041,0x00000074,0x000003ee,0x0000035f,0x0000003e,0x0003003e,0x000003ee, + 0x000003ed,0x0004003d,0x00000006,0x000003ef,0x00000347,0x00050080,0x00000006,0x000003f0, + 0x000003ef,0x0000002a,0x00060041,0x00000070,0x000003f1,0x00000363,0x0000005d,0x000003f0, + 0x0004003d,0x00000006,0x000003f2,0x000003f1,0x0006000c,0x00000046,0x000003f3,0x00000001, + 0x00000040,0x000003f2,0x00050041,0x00000074,0x000003f4,0x0000035f,0x00000065,0x0003003e, + 0x000003f4,0x000003f3,0x0004003d,0x00000006,0x000003f5,0x00000347,0x00050080,0x00000006, + 0x000003f6,0x000003f5,0x00000084,0x00060041,0x00000070,0x000003f7,0x00000363,0x0000005d, + 0x000003f6,0x0004003d,0x00000006,0x000003f8,0x000003f7,0x0006000c,0x00000046,0x000003f9, + 0x00000001,0x00000040,0x000003f8,0x00050041,0x00000074,0x000003fa,0x0000035f,0x00000082, + 0x0003003e,0x000003fa,0x000003f9,0x00050041,0x00000074,0x000003fb,0x0000035f,0x0000005d, + 0x0004003d,0x00000046,0x000003fc,0x000003fb,0x0005008e,0x00000046,0x000003fd,0x000003fc, + 0x0000010e,0x00050041,0x00000074,0x000003fe,0x00000346,0x0000005d,0x0004003d,0x00000046, + 0x000003ff,0x000003fe,0x00050081,0x00000046,0x00000400,0x000003ff,0x000003fd,0x00050041, + 0x00000074,0x00000401,0x00000346,0x0000005d,0x0003003e,0x00000401,0x00000400,0x00050041, + 0x00000074,0x00000402,0x0000035f,0x0000003e,0x0004003d,0x00000046,0x00000403,0x00000402, + 0x0005008e,0x00000046,0x00000404,0x00000403,0x0000010e,0x00050041,0x00000074,0x00000405, + 0x00000346,0x0000003e,0x0004003d,0x00000046,0x00000406,0x00000405,0x00050081,0x00000046, + 0x00000407,0x00000406,0x00000404,0x00050041,0x00000074,0x00000408,0x00000346,0x0000003e, + 0x0003003e,0x00000408,0x00000407,0x00050041,0x00000074,0x00000409,0x0000035f,0x00000065, + 0x0004003d,0x00000046,0x0000040a,0x00000409,0x0005008e,0x00000046,0x0000040b,0x0000040a, + 0x0000010e,0x00050041,0x00000074,0x0000040c,0x00000346,0x00000065,0x0004003d,0x00000046, + 0x0000040d,0x0000040c,0x00050081,0x00000046,0x0000040e,0x0000040d,0x0000040b,0x00050041, + 0x00000074,0x0000040f,0x00000346,0x00000065,0x0003003e,0x0000040f,0x0000040e,0x00050041, + 0x00000074,0x00000410,0x0000035f,0x00000082,0x0004003d,0x00000046,0x00000411,0x00000410, + 0x0005008e,0x00000046,0x00000412,0x00000411,0x0000010e,0x00050041,0x00000074,0x00000413, + 0x00000346,0x00000082,0x0004003d,0x00000046,0x00000414,0x00000413,0x00050081,0x00000046, + 0x00000415,0x00000414,0x00000412,0x00050041,0x00000074,0x00000416,0x00000346,0x00000082, + 0x0003003e,0x00000416,0x00000415,0x00050041,0x00000021,0x00000417,0x0000001e,0x0000005d, + 0x0004003d,0x00000006,0x00000418,0x00000417,0x0004003d,0x00000006,0x00000419,0x00000347, + 0x00050080,0x00000006,0x0000041a,0x00000419,0x00000418,0x0003003e,0x00000347,0x0000041a, + 0x0004003d,0x00000006,0x0000041b,0x00000347,0x00060041,0x00000070,0x0000041c,0x00000363, + 0x0000005d,0x0000041b,0x0004003d,0x00000006,0x0000041d,0x0000041c,0x0006000c,0x00000046, + 0x0000041e,0x00000001,0x00000040,0x0000041d,0x00050041,0x00000074,0x0000041f,0x0000035f, + 0x0000005d,0x0003003e,0x0000041f,0x0000041e,0x0004003d,0x00000006,0x00000420,0x00000347, + 0x00050080,0x00000006,0x00000421,0x00000420,0x00000024,0x00060041,0x00000070,0x00000422, + 0x00000363,0x0000005d,0x00000421,0x0004003d,0x00000006,0x00000423,0x00000422,0x0006000c, + 0x00000046,0x00000424,0x00000001,0x00000040,0x00000423,0x00050041,0x00000074,0x00000425, + 0x0000035f,0x0000003e,0x0003003e,0x00000425,0x00000424,0x0004003d,0x00000006,0x00000426, + 0x00000347,0x00050080,0x00000006,0x00000427,0x00000426,0x0000002a,0x00060041,0x00000070, + 0x00000428,0x00000363,0x0000005d,0x00000427,0x0004003d,0x00000006,0x00000429,0x00000428, + 0x0006000c,0x00000046,0x0000042a,0x00000001,0x00000040,0x00000429,0x00050041,0x00000074, + 0x0000042b,0x0000035f,0x00000065,0x0003003e,0x0000042b,0x0000042a,0x0004003d,0x00000006, + 0x0000042c,0x00000347,0x00050080,0x00000006,0x0000042d,0x0000042c,0x00000084,0x00060041, + 0x00000070,0x0000042e,0x00000363,0x0000005d,0x0000042d,0x0004003d,0x00000006,0x0000042f, + 0x0000042e,0x0006000c,0x00000046,0x00000430,0x00000001,0x00000040,0x0000042f,0x00050041, + 0x00000074,0x00000431,0x0000035f,0x00000082,0x0003003e,0x00000431,0x00000430,0x00050041, + 0x00000074,0x00000432,0x0000035f,0x0000005d,0x0004003d,0x00000046,0x00000433,0x00000432, + 0x0005008e,0x00000046,0x00000434,0x00000433,0x000000cd,0x00050041,0x00000074,0x00000435, + 0x00000346,0x0000005d,0x0004003d,0x00000046,0x00000436,0x00000435,0x00050081,0x00000046, + 0x00000437,0x00000436,0x00000434,0x00050041,0x00000074,0x00000438,0x00000346,0x0000005d, + 0x0003003e,0x00000438,0x00000437,0x00050041,0x00000074,0x00000439,0x0000035f,0x0000003e, + 0x0004003d,0x00000046,0x0000043a,0x00000439,0x0005008e,0x00000046,0x0000043b,0x0000043a, + 0x000000cd,0x00050041,0x00000074,0x0000043c,0x00000346,0x0000003e,0x0004003d,0x00000046, + 0x0000043d,0x0000043c,0x00050081,0x00000046,0x0000043e,0x0000043d,0x0000043b,0x00050041, + 0x00000074,0x0000043f,0x00000346,0x0000003e,0x0003003e,0x0000043f,0x0000043e,0x00050041, + 0x00000074,0x00000440,0x0000035f,0x00000065,0x0004003d,0x00000046,0x00000441,0x00000440, + 0x0005008e,0x00000046,0x00000442,0x00000441,0x000000cd,0x00050041,0x00000074,0x00000443, + 0x00000346,0x00000065,0x0004003d,0x00000046,0x00000444,0x00000443,0x00050081,0x00000046, + 0x00000445,0x00000444,0x00000442,0x00050041,0x00000074,0x00000446,0x00000346,0x00000065, + 0x0003003e,0x00000446,0x00000445,0x00050041,0x00000074,0x00000447,0x0000035f,0x00000082, + 0x0004003d,0x00000046,0x00000448,0x00000447,0x0005008e,0x00000046,0x00000449,0x00000448, + 0x000000cd,0x00050041,0x00000074,0x0000044a,0x00000346,0x00000082,0x0004003d,0x00000046, + 0x0000044b,0x0000044a,0x00050081,0x00000046,0x0000044c,0x0000044b,0x00000449,0x00050041, + 0x00000074,0x0000044d,0x00000346,0x00000082,0x0003003e,0x0000044d,0x0000044c,0x00050041, + 0x00000021,0x0000044e,0x0000001e,0x0000005d,0x0004003d,0x00000006,0x0000044f,0x0000044e, + 0x0004003d,0x00000006,0x00000450,0x00000347,0x00050080,0x00000006,0x00000451,0x00000450, + 0x0000044f,0x0003003e,0x00000347,0x00000451,0x0004003d,0x00000006,0x00000452,0x00000347, + 0x00060041,0x00000070,0x00000453,0x00000363,0x0000005d,0x00000452,0x0004003d,0x00000006, + 0x00000454,0x00000453,0x0006000c,0x00000046,0x00000455,0x00000001,0x00000040,0x00000454, + 0x00050041,0x00000074,0x00000456,0x0000035f,0x0000005d,0x0003003e,0x00000456,0x00000455, + 0x0004003d,0x00000006,0x00000457,0x00000347,0x00050080,0x00000006,0x00000458,0x00000457, + 0x00000024,0x00060041,0x00000070,0x00000459,0x00000363,0x0000005d,0x00000458,0x0004003d, + 0x00000006,0x0000045a,0x00000459,0x0006000c,0x00000046,0x0000045b,0x00000001,0x00000040, + 0x0000045a,0x00050041,0x00000074,0x0000045c,0x0000035f,0x0000003e,0x0003003e,0x0000045c, + 0x0000045b,0x0004003d,0x00000006,0x0000045d,0x00000347,0x00050080,0x00000006,0x0000045e, + 0x0000045d,0x0000002a,0x00060041,0x00000070,0x0000045f,0x00000363,0x0000005d,0x0000045e, + 0x0004003d,0x00000006,0x00000460,0x0000045f,0x0006000c,0x00000046,0x00000461,0x00000001, + 0x00000040,0x00000460,0x00050041,0x00000074,0x00000462,0x0000035f,0x00000065,0x0003003e, + 0x00000462,0x00000461,0x0004003d,0x00000006,0x00000463,0x00000347,0x00050080,0x00000006, + 0x00000464,0x00000463,0x00000084,0x00060041,0x00000070,0x00000465,0x00000363,0x0000005d, + 0x00000464,0x0004003d,0x00000006,0x00000466,0x00000465,0x0006000c,0x00000046,0x00000467, + 0x00000001,0x00000040,0x00000466,0x00050041,0x00000074,0x00000468,0x0000035f,0x00000082, + 0x0003003e,0x00000468,0x00000467,0x00050041,0x00000074,0x00000469,0x0000035f,0x0000005d, + 0x0004003d,0x00000046,0x0000046a,0x00000469,0x0005008e,0x00000046,0x0000046b,0x0000046a, + 0x0000008c,0x00050041,0x00000074,0x0000046c,0x00000346,0x0000005d,0x0004003d,0x00000046, + 0x0000046d,0x0000046c,0x00050081,0x00000046,0x0000046e,0x0000046d,0x0000046b,0x00050041, + 0x00000074,0x0000046f,0x00000346,0x0000005d,0x0003003e,0x0000046f,0x0000046e,0x00050041, + 0x00000074,0x00000470,0x0000035f,0x0000003e,0x0004003d,0x00000046,0x00000471,0x00000470, + 0x0005008e,0x00000046,0x00000472,0x00000471,0x0000008c,0x00050041,0x00000074,0x00000473, + 0x00000346,0x0000003e,0x0004003d,0x00000046,0x00000474,0x00000473,0x00050081,0x00000046, + 0x00000475,0x00000474,0x00000472,0x00050041,0x00000074,0x00000476,0x00000346,0x0000003e, + 0x0003003e,0x00000476,0x00000475,0x00050041,0x00000074,0x00000477,0x0000035f,0x00000065, + 0x0004003d,0x00000046,0x00000478,0x00000477,0x0005008e,0x00000046,0x00000479,0x00000478, + 0x0000008c,0x00050041,0x00000074,0x0000047a,0x00000346,0x00000065,0x0004003d,0x00000046, + 0x0000047b,0x0000047a,0x00050081,0x00000046,0x0000047c,0x0000047b,0x00000479,0x00050041, + 0x00000074,0x0000047d,0x00000346,0x00000065,0x0003003e,0x0000047d,0x0000047c,0x00050041, + 0x00000074,0x0000047e,0x0000035f,0x00000082,0x0004003d,0x00000046,0x0000047f,0x0000047e, + 0x0005008e,0x00000046,0x00000480,0x0000047f,0x0000008c,0x00050041,0x00000074,0x00000481, + 0x00000346,0x00000082,0x0004003d,0x00000046,0x00000482,0x00000481,0x00050081,0x00000046, + 0x00000483,0x00000482,0x00000480,0x00050041,0x00000074,0x00000484,0x00000346,0x00000082, + 0x0003003e,0x00000484,0x00000483,0x00050041,0x00000019,0x00000485,0x00000336,0x00000018, + 0x0004003d,0x00000006,0x00000486,0x00000485,0x000500aa,0x00000052,0x00000487,0x00000486, + 0x00000018,0x000300f7,0x0000048a,0x00000000,0x000400fa,0x00000487,0x00000489,0x00000492, + 0x000200f8,0x00000489,0x00050041,0x00000074,0x0000048b,0x00000346,0x0000003e,0x0004003d, + 0x00000046,0x0000048c,0x0000048b,0x00050051,0x00000045,0x0000048d,0x0000048c,0x00000000, + 0x00050051,0x00000045,0x0000048e,0x0000048c,0x00000001,0x00050051,0x00000045,0x0000048f, + 0x0000048c,0x00000002,0x00050051,0x00000045,0x00000490,0x0000048c,0x00000003,0x00070050, + 0x00000046,0x00000491,0x0000048d,0x0000048e,0x0000048f,0x00000490,0x0003003e,0x00000488, + 0x00000491,0x000200f9,0x0000048a,0x000200f8,0x00000492,0x00050041,0x00000074,0x00000493, + 0x00000346,0x0000005d,0x0004003d,0x00000046,0x00000494,0x00000493,0x0003003e,0x00000488, + 0x00000494,0x000200f9,0x0000048a,0x000200f8,0x0000048a,0x0004003d,0x00000046,0x00000495, + 0x00000488,0x00050041,0x00000074,0x00000496,0x00000346,0x0000005d,0x0003003e,0x00000496, + 0x00000495,0x00050041,0x00000019,0x00000497,0x00000336,0x00000018,0x0004003d,0x00000006, + 0x00000498,0x00000497,0x00050041,0x00000021,0x00000499,0x0000001e,0x00000020,0x0004003d, + 0x00000006,0x0000049a,0x00000499,0x00050082,0x00000006,0x0000049b,0x0000049a,0x0000002a, + 0x000500aa,0x00000052,0x0000049c,0x00000498,0x0000049b,0x000300f7,0x0000049f,0x00000000, + 0x000400fa,0x0000049c,0x0000049e,0x000004a7,0x000200f8,0x0000049e,0x00050041,0x00000074, + 0x000004a0,0x00000346,0x00000065,0x0004003d,0x00000046,0x000004a1,0x000004a0,0x00050051, + 0x00000045,0x000004a2,0x000004a1,0x00000000,0x00050051,0x00000045,0x000004a3,0x000004a1, + 0x00000001,0x00050051,0x00000045,0x000004a4,0x000004a1,0x00000002,0x00050051,0x00000045, + 0x000004a5,0x000004a1,0x00000003,0x00070050,0x00000046,0x000004a6,0x000004a2,0x000004a3, + 0x000004a4,0x000004a5,0x0003003e,0x0000049d,0x000004a6,0x000200f9,0x0000049f,0x000200f8, + 0x000004a7,0x00050041,0x00000074,0x000004a8,0x00000346,0x00000082,0x0004003d,0x00000046, + 0x000004a9,0x000004a8,0x0003003e,0x0000049d,0x000004a9,0x000200f9,0x0000049f,0x000200f8, + 0x0000049f,0x0004003d,0x00000046,0x000004aa,0x0000049d,0x00050041,0x00000074,0x000004ab, + 0x00000346,0x00000082,0x0003003e,0x000004ab,0x000004aa,0x00060041,0x0000025f,0x000004ad, + 0x00000346,0x0000005d,0x00000018,0x0004003d,0x00000045,0x000004ae,0x000004ad,0x00060041, + 0x0000025f,0x000004af,0x00000346,0x0000005d,0x00000024,0x0004003d,0x00000045,0x000004b0, + 0x000004af,0x00060041,0x0000025f,0x000004b1,0x00000346,0x0000003e,0x00000018,0x0004003d, + 0x00000045,0x000004b2,0x000004b1,0x00060041,0x0000025f,0x000004b3,0x00000346,0x0000003e, + 0x00000024,0x0004003d,0x00000045,0x000004b4,0x000004b3,0x00070050,0x00000046,0x000004b5, + 0x000004ae,0x000004b0,0x000004b2,0x000004b4,0x0005008e,0x00000046,0x000004b6,0x000004b5, + 0x0000008c,0x00060041,0x0000025f,0x000004b7,0x00000346,0x0000005d,0x0000002a,0x0004003d, + 0x00000045,0x000004b8,0x000004b7,0x00060041,0x0000025f,0x000004b9,0x00000346,0x0000005d, + 0x00000084,0x0004003d,0x00000045,0x000004ba,0x000004b9,0x00060041,0x0000025f,0x000004bb, + 0x00000346,0x0000003e,0x0000002a,0x0004003d,0x00000045,0x000004bc,0x000004bb,0x00060041, + 0x0000025f,0x000004bd,0x00000346,0x0000003e,0x00000084,0x0004003d,0x00000045,0x000004be, + 0x000004bd,0x00070050,0x00000046,0x000004bf,0x000004b8,0x000004ba,0x000004bc,0x000004be, + 0x0005008e,0x00000046,0x000004c0,0x000004bf,0x000000cd,0x00050081,0x00000046,0x000004c1, + 0x000004b6,0x000004c0,0x00060041,0x0000025f,0x000004c2,0x00000346,0x0000003e,0x00000018, + 0x0004003d,0x00000045,0x000004c3,0x000004c2,0x00060041,0x0000025f,0x000004c4,0x00000346, + 0x0000003e,0x00000024,0x0004003d,0x00000045,0x000004c5,0x000004c4,0x00060041,0x0000025f, + 0x000004c6,0x00000346,0x00000065,0x00000018,0x0004003d,0x00000045,0x000004c7,0x000004c6, + 0x00060041,0x0000025f,0x000004c8,0x00000346,0x00000065,0x00000024,0x0004003d,0x00000045, + 0x000004c9,0x000004c8,0x00070050,0x00000046,0x000004ca,0x000004c3,0x000004c5,0x000004c7, + 0x000004c9,0x0005008e,0x00000046,0x000004cb,0x000004ca,0x0000010e,0x00050081,0x00000046, + 0x000004cc,0x000004c1,0x000004cb,0x00060041,0x0000025f,0x000004cd,0x00000346,0x0000003e, + 0x0000002a,0x0004003d,0x00000045,0x000004ce,0x000004cd,0x00060041,0x0000025f,0x000004cf, + 0x00000346,0x0000003e,0x00000084,0x0004003d,0x00000045,0x000004d0,0x000004cf,0x00060041, + 0x0000025f,0x000004d1,0x00000346,0x00000065,0x0000002a,0x0004003d,0x00000045,0x000004d2, + 0x000004d1,0x00060041,0x0000025f,0x000004d3,0x00000346,0x00000065,0x00000084,0x0004003d, + 0x00000045,0x000004d4,0x000004d3,0x00070050,0x00000046,0x000004d5,0x000004ce,0x000004d0, + 0x000004d2,0x000004d4,0x0005008e,0x00000046,0x000004d6,0x000004d5,0x000000cd,0x00050081, + 0x00000046,0x000004d7,0x000004cc,0x000004d6,0x00060041,0x0000025f,0x000004d8,0x00000346, + 0x00000065,0x00000018,0x0004003d,0x00000045,0x000004d9,0x000004d8,0x00060041,0x0000025f, + 0x000004da,0x00000346,0x00000065,0x00000024,0x0004003d,0x00000045,0x000004db,0x000004da, + 0x00060041,0x0000025f,0x000004dc,0x00000346,0x00000082,0x00000018,0x0004003d,0x00000045, + 0x000004dd,0x000004dc,0x00060041,0x0000025f,0x000004de,0x00000346,0x00000082,0x00000024, + 0x0004003d,0x00000045,0x000004df,0x000004de,0x00070050,0x00000046,0x000004e0,0x000004d9, + 0x000004db,0x000004dd,0x000004df,0x0005008e,0x00000046,0x000004e1,0x000004e0,0x0000008c, + 0x00050081,0x00000046,0x000004e2,0x000004d7,0x000004e1,0x0003003e,0x000004ac,0x000004e2, + 0x0004003d,0x00000046,0x000004e3,0x000004ac,0x00070050,0x00000046,0x000004e4,0x0000004b, + 0x0000004b,0x0000004b,0x0000004b,0x00070050,0x00000046,0x000004e5,0x00000307,0x00000307, + 0x00000307,0x00000307,0x0008000c,0x00000046,0x000004e6,0x00000001,0x0000002b,0x000004e3, + 0x000004e4,0x000004e5,0x0003003e,0x000004ac,0x000004e6,0x00050041,0x00000019,0x000004e7, + 0x0000000f,0x00000018,0x0004003d,0x00000006,0x000004e8,0x000004e7,0x00050041,0x00000021, + 0x000004e9,0x0000001e,0x00000082,0x0004003d,0x00000006,0x000004ea,0x000004e9,0x00050082, + 0x00000006,0x000004eb,0x000004ea,0x00000024,0x0008000c,0x00000006,0x000004ec,0x00000001, + 0x0000002c,0x000004e8,0x00000018,0x000004eb,0x00050041,0x00000019,0x000004ed,0x0000000f, + 0x00000018,0x0003003e,0x000004ed,0x000004ec,0x00050041,0x00000019,0x000004f2,0x0000000f, + 0x00000024,0x0004003d,0x00000006,0x000004f3,0x000004f2,0x00050041,0x00000021,0x000004f4, + 0x0000001e,0x00000082,0x0004003d,0x00000006,0x000004f5,0x000004f4,0x00050084,0x00000006, + 0x000004f6,0x000004f3,0x000004f5,0x00050041,0x00000019,0x000004f7,0x0000000f,0x00000018, + 0x0004003d,0x00000006,0x000004f8,0x000004f7,0x00050080,0x00000006,0x000004f9,0x000004f6, + 0x000004f8,0x0004003d,0x00000046,0x000004fa,0x000004ac,0x0006000c,0x00000006,0x000004fb, + 0x00000001,0x00000037,0x000004fa,0x00060041,0x00000070,0x000004fc,0x000004f1,0x0000005d, + 0x000004f9,0x0003003e,0x000004fc,0x000004fb,0x000100fd,0x00010038 diff --git a/shaders/spv/shader_geomap.comp b/shaders/spv/shader_geomap.comp new file mode 100644 index 0000000..f92dcb4 --- /dev/null +++ b/shaders/spv/shader_geomap.comp @@ -0,0 +1,238 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBufY { + uint data[]; +} in_buf_y; + +layout (binding = 1) readonly buffer InBufUV { + uint data[]; +} in_buf_uv; + +layout (binding = 2) writeonly buffer OutBufY { + uint data[]; +} out_buf_y; + +layout (binding = 3) writeonly buffer OutBufUV { + uint data[]; +} out_buf_uv; + +layout (binding = 4) readonly buffer GeoMapTable { + vec2 data[]; +} lut; + +layout (push_constant) uniform PushConsts { + uint in_img_width; + uint in_img_height; + uint out_img_width; + uint out_img_height; + uint lut_width; + uint lut_height; + float lut_step[4]; + float lut_std_step[2]; +} prop; + +#define UNIT_SIZE 4u + +#define unpack_unorm_y(index) \ + { \ + vec4 value = unpackUnorm4x8 (in_buf_y.data[index00[index]]); \ + out_y00[index] = value[x00_fract[index]]; \ + value = unpackUnorm4x8 (in_buf_y.data[index01[index]]); \ + out_y01[index] = value[x01_fract[index]]; \ + value = unpackUnorm4x8 (in_buf_y.data[index10[index]]); \ + out_y10[index] = value[x10_fract[index]]; \ + value = unpackUnorm4x8 (in_buf_y.data[index11[index]]); \ + out_y11[index] = value[x11_fract[index]]; \ + } + +void geomap_y (vec4 lut_x, vec4 lut_y, out vec4 in_img_x, out vec4 in_img_y, out bvec4 out_bound, out uint out_data); +void geomap_uv (vec2 in_uv_x, vec2 in_uv_y, bvec4 out_bound_uv, out uint out_data); + +void main () +{ + uint g_x = gl_GlobalInvocationID.x; + uint g_y = gl_GlobalInvocationID.y * 2u; + + vec2 cent = (vec2 (prop.out_img_width, prop.out_img_height) - 1.0f) / 2.0f; + vec2 step = g_x < uint (cent.x) ? vec2 (prop.lut_step[0], prop.lut_step[1]) : + vec2 (prop.lut_step[2], prop.lut_step[3]); + + vec2 start = (vec2 (g_x, g_y) - cent) * step + cent * vec2 (prop.lut_std_step[0], prop.lut_std_step[1]); + vec4 lut_x = start.x * float (UNIT_SIZE) + vec4 (0.0f, step.x, step.x * 2.0f, step.x * 3.0f); + vec4 lut_y = start.yyyy; + lut_x = clamp (lut_x, 0.0f, float (prop.lut_width) - 1.0f); + lut_y = clamp (lut_y, 0.0f, float (prop.lut_height) - 1.0f - step.y); + + uint out_data; + vec4 in_img_x, in_img_y; + bvec4 out_bound; + geomap_y (lut_x, lut_y, in_img_x, in_img_y, out_bound, out_data); + out_buf_y.data[g_y * prop.out_img_width + g_x] = out_data; + + bvec4 out_bound_uv = out_bound.xxzz; + if (all (out_bound_uv)) { + out_data = packUnorm4x8 (vec4 (0.5f)); + } else { + vec2 in_uv_x = in_img_x.xz; + vec2 in_uv_y = in_img_y.xz / 2.0f; + in_uv_y = clamp (in_uv_y, 0.0f, float (prop.in_img_height / 2u - 1u)); + geomap_uv (in_uv_x, in_uv_y, out_bound_uv, out_data); + } + out_buf_uv.data[g_y / 2u * prop.out_img_width + g_x] = out_data; + + lut_y += step.y; + geomap_y (lut_x, lut_y, in_img_x, in_img_y, out_bound, out_data); + out_buf_y.data[(g_y + 1u) * prop.out_img_width + g_x] = out_data; +} + +void geomap_y (vec4 lut_x, vec4 lut_y, out vec4 in_img_x, out vec4 in_img_y, out bvec4 out_bound, out uint out_data) +{ + uvec4 x00 = uvec4 (lut_x); + uvec4 y00 = uvec4 (lut_y); + uvec4 x01 = x00 + 1u; + uvec4 y01 = y00; + uvec4 x10 = x00; + uvec4 y10 = y00 + 1u; + uvec4 x11 = x01; + uvec4 y11 = y10; + + vec4 fract_x = fract (lut_x); + vec4 fract_y = fract (lut_y); + vec4 weight00 = (1.0f - fract_x) * (1.0f - fract_y); + vec4 weight01 = fract_x * (1.0f - fract_y); + vec4 weight10 = (1.0f - fract_x) * fract_y; + vec4 weight11 = fract_x * fract_y; + + uvec4 index00 = y00 * prop.lut_width + x00; + uvec4 index01 = y01 * prop.lut_width + x01; + uvec4 index10 = y10 * prop.lut_width + x10; + uvec4 index11 = y11 * prop.lut_width + x11; + + vec4 in_img_x00, in_img_x01, in_img_x10, in_img_x11; + vec4 in_img_y00, in_img_y01, in_img_y10, in_img_y11; + for (uint i = 0u; i < UNIT_SIZE; ++i) { + vec2 value = lut.data[index00[i]]; + in_img_x00[i] = value.x; + in_img_y00[i] = value.y; + value = lut.data[index01[i]]; + in_img_x01[i] = value.x; + in_img_y01[i] = value.y; + value = lut.data[index10[i]]; + in_img_x10[i] = value.x; + in_img_y10[i] = value.y; + value = lut.data[index11[i]]; + in_img_x11[i] = value.x; + in_img_y11[i] = value.y; + } + in_img_x = in_img_x00 * weight00 + in_img_x01 * weight01 + in_img_x10 * weight10 + in_img_x11 * weight11; + in_img_y = in_img_y00 * weight00 + in_img_y01 * weight01 + in_img_y10 * weight10 + in_img_y11 * weight11; + + for (uint i = 0u; i < UNIT_SIZE; ++i) { + out_bound[i] = in_img_x[i] < 0.0f || in_img_x[i] > float (prop.in_img_width * UNIT_SIZE - 1u) || + in_img_y[i] < 0.0f || in_img_y[i] > float (prop.in_img_height - 1u); + } + if (all (out_bound)) { + out_data = 0u; + return; + } + + x00 = uvec4 (in_img_x); + y00 = uvec4 (in_img_y); + x01 = x00 + 1u; + y01 = y00; + x10 = x00; + y10 = y00 + 1u; + x11 = x01; + y11 = y10; + + fract_x = fract (in_img_x); + fract_y = fract (in_img_y); + weight00 = (1.0f - fract_x) * (1.0f - fract_y); + weight01 = fract_x * (1.0f - fract_y); + weight10 = (1.0f - fract_x) * fract_y; + weight11 = fract_x * fract_y; + + uvec4 x00_floor = x00 / UNIT_SIZE; + uvec4 x01_floor = x01 / UNIT_SIZE; + uvec4 x10_floor = x10 / UNIT_SIZE; + uvec4 x11_floor = x11 / UNIT_SIZE; + uvec4 x00_fract = x00 % UNIT_SIZE; + uvec4 x01_fract = x01 % UNIT_SIZE; + uvec4 x10_fract = x10 % UNIT_SIZE; + uvec4 x11_fract = x11 % UNIT_SIZE; + + index00 = y00 * prop.in_img_width + x00_floor; + index01 = y01 * prop.in_img_width + x01_floor; + index10 = y10 * prop.in_img_width + x10_floor; + index11 = y11 * prop.in_img_width + x11_floor; + + // pixel Y-value + vec4 out_y00, out_y01, out_y10, out_y11; + unpack_unorm_y (0); + unpack_unorm_y (1); + unpack_unorm_y (2); + unpack_unorm_y (3); + + vec4 inter_y = out_y00 * weight00 + out_y01 * weight01 + out_y10 * weight10 + out_y11 * weight11; + out_data = packUnorm4x8 (inter_y * vec4 (not (out_bound))); +} + +void geomap_uv (vec2 in_uv_x, vec2 in_uv_y, bvec4 out_bound_uv, out uint out_data) +{ + uvec2 x00 = uvec2 (in_uv_x); + uvec2 y00 = uvec2 (in_uv_y); + uvec2 x01 = x00 + 1u; + uvec2 y01 = y00; + uvec2 x10 = x00; + uvec2 y10 = y00 + 1u; + uvec2 x11 = x01; + uvec2 y11 = y10; + + vec2 fract_x = fract (in_uv_x); + vec2 fract_y = fract (in_uv_y); + vec2 weight00 = (1.0f - fract_x) * (1.0f - fract_y); + vec2 weight01 = fract_x * (1.0f - fract_y); + vec2 weight10 = (1.0f - fract_x) * fract_y; + vec2 weight11 = fract_x * fract_y; + + uvec2 x00_floor = x00 / UNIT_SIZE; + uvec2 x01_floor = x01 / UNIT_SIZE; + uvec2 x10_floor = x10 / UNIT_SIZE; + uvec2 x11_floor = x11 / UNIT_SIZE; + uvec2 x00_fract = (x00 % UNIT_SIZE) / 2u; + uvec2 x01_fract = (x01 % UNIT_SIZE) / 2u; + uvec2 x10_fract = (x10 % UNIT_SIZE) / 2u; + uvec2 x11_fract = (x11 % UNIT_SIZE) / 2u; + + uvec2 index00 = y00 * prop.in_img_width + x00_floor; + uvec2 index01 = y01 * prop.in_img_width + x01_floor; + uvec2 index10 = y10 * prop.in_img_width + x10_floor; + uvec2 index11 = y11 * prop.in_img_width + x11_floor; + + // pixel UV-value + vec4 out_uv00, out_uv01, out_uv10, out_uv11; + vec4 value = unpackUnorm4x8 (in_buf_uv.data[index00.x]); + out_uv00.xy = x00_fract.x == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index01.x]); + out_uv01.xy = x01_fract.x == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index10.x]); + out_uv10.xy = x10_fract.x == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index11.x]); + out_uv11.xy = x11_fract.x == 0u ? value.xy : value.zw; + + value = unpackUnorm4x8 (in_buf_uv.data[index00.y]); + out_uv00.zw = x00_fract.y == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index01.y]); + out_uv01.zw = x01_fract.y == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index10.y]); + out_uv10.zw = x10_fract.y == 0u ? value.xy : value.zw; + value = unpackUnorm4x8 (in_buf_uv.data[index11.y]); + out_uv11.zw = x11_fract.y == 0u ? value.xy : value.zw; + + vec4 inter_uv = out_uv00 * weight00.xxyy + out_uv01 * weight01.xxyy + + out_uv10 * weight10.xxyy + out_uv11 * weight11.xxyy; + inter_uv = inter_uv * vec4 (not (out_bound_uv)) + vec4 (out_bound_uv) * 0.5f; + out_data = packUnorm4x8 (inter_uv); +} diff --git a/shaders/spv/shader_geomap.comp.spv b/shaders/spv/shader_geomap.comp.spv new file mode 100644 index 0000000..6f822b8 --- /dev/null +++ b/shaders/spv/shader_geomap.comp.spv @@ -0,0 +1,847 @@ + // 7.8.2870 + 0x07230203,0x00010000,0x00080007,0x00000466,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000005,0x00000004,0x6e69616d,0x00000000,0x00000023,0x00060010,0x00000004, + 0x00000011,0x00000008,0x00000008,0x00000001,0x00030003,0x00000001,0x00000136,0x00040005, + 0x00000004,0x6e69616d,0x00000000,0x000b0005,0x00000015,0x6d6f6567,0x795f7061,0x34667628, + 0x3466763b,0x3466763b,0x3466763b,0x3462763b,0x3b31753b,0x00000000,0x00040005,0x0000000f, + 0x5f74756c,0x00000078,0x00040005,0x00000010,0x5f74756c,0x00000079,0x00050005,0x00000011, + 0x695f6e69,0x785f676d,0x00000000,0x00050005,0x00000012,0x695f6e69,0x795f676d,0x00000000, + 0x00050005,0x00000013,0x5f74756f,0x6e756f62,0x00000064,0x00050005,0x00000014,0x5f74756f, + 0x61746164,0x00000000,0x00090005,0x0000001e,0x6d6f6567,0x755f7061,0x66762876,0x66763b32, + 0x62763b32,0x31753b34,0x0000003b,0x00040005,0x0000001a,0x755f6e69,0x00785f76,0x00040005, + 0x0000001b,0x755f6e69,0x00795f76,0x00060005,0x0000001c,0x5f74756f,0x6e756f62,0x76755f64, + 0x00000000,0x00050005,0x0000001d,0x5f74756f,0x61746164,0x00000000,0x00030005,0x00000020, + 0x00785f67,0x00080005,0x00000023,0x475f6c67,0x61626f6c,0x766e496c,0x7461636f,0x496e6f69, + 0x00000044,0x00030005,0x00000028,0x00795f67,0x00040005,0x0000002e,0x746e6563,0x00000000, + 0x00050005,0x00000032,0x68737550,0x736e6f43,0x00007374,0x00070006,0x00000032,0x00000000, + 0x695f6e69,0x775f676d,0x68746469,0x00000000,0x00070006,0x00000032,0x00000001,0x695f6e69, + 0x685f676d,0x68676965,0x00000074,0x00070006,0x00000032,0x00000002,0x5f74756f,0x5f676d69, + 0x74646977,0x00000068,0x00070006,0x00000032,0x00000003,0x5f74756f,0x5f676d69,0x67696568, + 0x00007468,0x00060006,0x00000032,0x00000004,0x5f74756c,0x74646977,0x00000068,0x00060006, + 0x00000032,0x00000005,0x5f74756c,0x67696568,0x00007468,0x00060006,0x00000032,0x00000006, + 0x5f74756c,0x70657473,0x00000000,0x00070006,0x00000032,0x00000007,0x5f74756c,0x5f647473, + 0x70657473,0x00000000,0x00040005,0x00000034,0x706f7270,0x00000000,0x00040005,0x00000046, + 0x70657473,0x00000000,0x00040005,0x00000060,0x72617473,0x00000074,0x00040005,0x00000073, + 0x5f74756c,0x00000078,0x00040005,0x00000085,0x5f74756c,0x00000079,0x00050005,0x0000009d, + 0x695f6e69,0x785f676d,0x00000000,0x00050005,0x0000009e,0x695f6e69,0x795f676d,0x00000000, + 0x00050005,0x0000009f,0x5f74756f,0x6e756f62,0x00000064,0x00050005,0x000000a0,0x5f74756f, + 0x61746164,0x00000000,0x00040005,0x000000a1,0x61726170,0x0000006d,0x00040005,0x000000a3, + 0x61726170,0x0000006d,0x00040005,0x000000a5,0x61726170,0x0000006d,0x00040005,0x000000a6, + 0x61726170,0x0000006d,0x00040005,0x000000a7,0x61726170,0x0000006d,0x00040005,0x000000a8, + 0x61726170,0x0000006d,0x00040005,0x000000af,0x4274754f,0x00596675,0x00050006,0x000000af, + 0x00000000,0x61746164,0x00000000,0x00050005,0x000000b1,0x5f74756f,0x5f667562,0x00000079, + 0x00060005,0x000000bb,0x5f74756f,0x6e756f62,0x76755f64,0x00000000,0x00040005,0x000000c6, + 0x755f6e69,0x00785f76,0x00040005,0x000000c9,0x755f6e69,0x00795f76,0x00040005,0x000000d7, + 0x61726170,0x0000006d,0x00040005,0x000000d9,0x61726170,0x0000006d,0x00040005,0x000000db, + 0x61726170,0x0000006d,0x00040005,0x000000dd,0x61726170,0x0000006d,0x00050005,0x000000e1, + 0x4274754f,0x56556675,0x00000000,0x00050006,0x000000e1,0x00000000,0x61746164,0x00000000, + 0x00050005,0x000000e3,0x5f74756f,0x5f667562,0x00007675,0x00040005,0x000000f2,0x61726170, + 0x0000006d,0x00040005,0x000000f4,0x61726170,0x0000006d,0x00040005,0x000000f6,0x61726170, + 0x0000006d,0x00040005,0x000000f7,0x61726170,0x0000006d,0x00040005,0x000000f8,0x61726170, + 0x0000006d,0x00040005,0x000000f9,0x61726170,0x0000006d,0x00030005,0x0000010a,0x00303078, + 0x00030005,0x0000010d,0x00303079,0x00030005,0x00000110,0x00313078,0x00030005,0x00000114, + 0x00313079,0x00030005,0x00000116,0x00303178,0x00030005,0x00000118,0x00303179,0x00030005, + 0x0000011c,0x00313178,0x00030005,0x0000011e,0x00313179,0x00040005,0x00000120,0x63617266, + 0x00785f74,0x00040005,0x00000123,0x63617266,0x00795f74,0x00050005,0x00000126,0x67696577, + 0x30307468,0x00000000,0x00050005,0x0000012e,0x67696577,0x31307468,0x00000000,0x00050005, + 0x00000134,0x67696577,0x30317468,0x00000000,0x00050005,0x0000013a,0x67696577,0x31317468, + 0x00000000,0x00040005,0x0000013e,0x65646e69,0x00303078,0x00040005,0x00000146,0x65646e69, + 0x00313078,0x00040005,0x0000014e,0x65646e69,0x00303178,0x00040005,0x00000156,0x65646e69, + 0x00313178,0x00030005,0x0000015e,0x00000069,0x00040005,0x00000166,0x756c6176,0x00000065, + 0x00050005,0x00000168,0x4d6f6547,0x61547061,0x00656c62,0x00050006,0x00000168,0x00000000, + 0x61746164,0x00000000,0x00030005,0x0000016a,0x0074756c,0x00050005,0x00000171,0x695f6e69, + 0x785f676d,0x00003030,0x00050005,0x00000176,0x695f6e69,0x795f676d,0x00003030,0x00050005, + 0x00000180,0x695f6e69,0x785f676d,0x00003130,0x00050005,0x00000185,0x695f6e69,0x795f676d, + 0x00003130,0x00050005,0x0000018f,0x695f6e69,0x785f676d,0x00003031,0x00050005,0x00000194, + 0x695f6e69,0x795f676d,0x00003031,0x00050005,0x0000019e,0x695f6e69,0x785f676d,0x00003131, + 0x00050005,0x000001a3,0x695f6e69,0x795f676d,0x00003131,0x00030005,0x000001c8,0x00000069, + 0x00050005,0x00000225,0x5f303078,0x6f6f6c66,0x00000072,0x00050005,0x00000229,0x5f313078, + 0x6f6f6c66,0x00000072,0x00050005,0x0000022d,0x5f303178,0x6f6f6c66,0x00000072,0x00050005, + 0x00000231,0x5f313178,0x6f6f6c66,0x00000072,0x00050005,0x00000235,0x5f303078,0x63617266, + 0x00000074,0x00050005,0x00000239,0x5f313078,0x63617266,0x00000074,0x00050005,0x0000023d, + 0x5f303178,0x63617266,0x00000074,0x00050005,0x00000241,0x5f313178,0x63617266,0x00000074, + 0x00040005,0x00000261,0x756c6176,0x00000065,0x00040005,0x00000263,0x75426e49,0x00005966, + 0x00050006,0x00000263,0x00000000,0x61746164,0x00000000,0x00050005,0x00000265,0x625f6e69, + 0x795f6675,0x00000000,0x00040005,0x0000026b,0x5f74756f,0x00303079,0x00040005,0x00000276, + 0x5f74756f,0x00313079,0x00040005,0x00000281,0x5f74756f,0x00303179,0x00040005,0x0000028c, + 0x5f74756f,0x00313179,0x00040005,0x00000292,0x756c6176,0x00000065,0x00040005,0x000002bb, + 0x756c6176,0x00000065,0x00040005,0x000002e4,0x756c6176,0x00000065,0x00040005,0x0000030e, + 0x65746e69,0x00795f72,0x00030005,0x00000328,0x00303078,0x00030005,0x0000032b,0x00303079, + 0x00030005,0x0000032e,0x00313078,0x00030005,0x00000332,0x00313079,0x00030005,0x00000334, + 0x00303178,0x00030005,0x00000336,0x00303179,0x00030005,0x0000033a,0x00313178,0x00030005, + 0x0000033c,0x00313179,0x00040005,0x0000033e,0x63617266,0x00785f74,0x00040005,0x00000341, + 0x63617266,0x00795f74,0x00050005,0x00000344,0x67696577,0x30307468,0x00000000,0x00050005, + 0x0000034c,0x67696577,0x31307468,0x00000000,0x00050005,0x00000352,0x67696577,0x30317468, + 0x00000000,0x00050005,0x00000358,0x67696577,0x31317468,0x00000000,0x00050005,0x0000035c, + 0x5f303078,0x6f6f6c66,0x00000072,0x00050005,0x00000360,0x5f313078,0x6f6f6c66,0x00000072, + 0x00050005,0x00000364,0x5f303178,0x6f6f6c66,0x00000072,0x00050005,0x00000368,0x5f313178, + 0x6f6f6c66,0x00000072,0x00050005,0x0000036c,0x5f303078,0x63617266,0x00000074,0x00050005, + 0x00000372,0x5f313078,0x63617266,0x00000074,0x00050005,0x00000378,0x5f303178,0x63617266, + 0x00000074,0x00050005,0x0000037e,0x5f313178,0x63617266,0x00000074,0x00040005,0x00000384, + 0x65646e69,0x00303078,0x00040005,0x0000038c,0x65646e69,0x00313078,0x00040005,0x00000394, + 0x65646e69,0x00303178,0x00040005,0x0000039c,0x65646e69,0x00313178,0x00040005,0x000003a4, + 0x756c6176,0x00000065,0x00040005,0x000003a6,0x75426e49,0x00565566,0x00050006,0x000003a6, + 0x00000000,0x61746164,0x00000000,0x00050005,0x000003a8,0x625f6e69,0x755f6675,0x00000076, + 0x00050005,0x000003ae,0x5f74756f,0x30307675,0x00000000,0x00050005,0x000003c2,0x5f74756f, + 0x31307675,0x00000000,0x00050005,0x000003d6,0x5f74756f,0x30317675,0x00000000,0x00050005, + 0x000003ea,0x5f74756f,0x31317675,0x00000000,0x00050005,0x00000445,0x65746e69,0x76755f72, + 0x00000000,0x00040047,0x00000023,0x0000000b,0x0000001c,0x00040047,0x00000030,0x00000006, + 0x00000004,0x00040047,0x00000031,0x00000006,0x00000004,0x00050048,0x00000032,0x00000000, + 0x00000023,0x00000000,0x00050048,0x00000032,0x00000001,0x00000023,0x00000004,0x00050048, + 0x00000032,0x00000002,0x00000023,0x00000008,0x00050048,0x00000032,0x00000003,0x00000023, + 0x0000000c,0x00050048,0x00000032,0x00000004,0x00000023,0x00000010,0x00050048,0x00000032, + 0x00000005,0x00000023,0x00000014,0x00050048,0x00000032,0x00000006,0x00000023,0x00000018, + 0x00050048,0x00000032,0x00000007,0x00000023,0x00000028,0x00030047,0x00000032,0x00000002, + 0x00040047,0x000000ae,0x00000006,0x00000004,0x00040048,0x000000af,0x00000000,0x00000019, + 0x00050048,0x000000af,0x00000000,0x00000023,0x00000000,0x00030047,0x000000af,0x00000003, + 0x00040047,0x000000b1,0x00000022,0x00000000,0x00040047,0x000000b1,0x00000021,0x00000002, + 0x00040047,0x000000e0,0x00000006,0x00000004,0x00040048,0x000000e1,0x00000000,0x00000019, + 0x00050048,0x000000e1,0x00000000,0x00000023,0x00000000,0x00030047,0x000000e1,0x00000003, + 0x00040047,0x000000e3,0x00000022,0x00000000,0x00040047,0x000000e3,0x00000021,0x00000003, + 0x00040047,0x00000167,0x00000006,0x00000008,0x00040048,0x00000168,0x00000000,0x00000018, + 0x00050048,0x00000168,0x00000000,0x00000023,0x00000000,0x00030047,0x00000168,0x00000003, + 0x00040047,0x0000016a,0x00000022,0x00000000,0x00040047,0x0000016a,0x00000021,0x00000004, + 0x00040047,0x00000262,0x00000006,0x00000004,0x00040048,0x00000263,0x00000000,0x00000018, + 0x00050048,0x00000263,0x00000000,0x00000023,0x00000000,0x00030047,0x00000263,0x00000003, + 0x00040047,0x00000265,0x00000022,0x00000000,0x00040047,0x00000265,0x00000021,0x00000000, + 0x00040047,0x000003a5,0x00000006,0x00000004,0x00040048,0x000003a6,0x00000000,0x00000018, + 0x00050048,0x000003a6,0x00000000,0x00000023,0x00000000,0x00030047,0x000003a6,0x00000003, + 0x00040047,0x000003a8,0x00000022,0x00000000,0x00040047,0x000003a8,0x00000021,0x00000001, + 0x00040047,0x00000465,0x0000000b,0x00000019,0x00020013,0x00000002,0x00030021,0x00000003, + 0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004, + 0x00040020,0x00000008,0x00000007,0x00000007,0x00020014,0x00000009,0x00040017,0x0000000a, + 0x00000009,0x00000004,0x00040020,0x0000000b,0x00000007,0x0000000a,0x00040015,0x0000000c, + 0x00000020,0x00000000,0x00040020,0x0000000d,0x00000007,0x0000000c,0x00090021,0x0000000e, + 0x00000002,0x00000008,0x00000008,0x00000008,0x00000008,0x0000000b,0x0000000d,0x00040017, + 0x00000017,0x00000006,0x00000002,0x00040020,0x00000018,0x00000007,0x00000017,0x00070021, + 0x00000019,0x00000002,0x00000018,0x00000018,0x0000000b,0x0000000d,0x00040017,0x00000021, + 0x0000000c,0x00000003,0x00040020,0x00000022,0x00000001,0x00000021,0x0004003b,0x00000022, + 0x00000023,0x00000001,0x0004002b,0x0000000c,0x00000024,0x00000000,0x00040020,0x00000025, + 0x00000001,0x0000000c,0x0004002b,0x0000000c,0x00000029,0x00000001,0x0004002b,0x0000000c, + 0x0000002c,0x00000002,0x0004002b,0x0000000c,0x0000002f,0x00000004,0x0004001c,0x00000030, + 0x00000006,0x0000002f,0x0004001c,0x00000031,0x00000006,0x0000002c,0x000a001e,0x00000032, + 0x0000000c,0x0000000c,0x0000000c,0x0000000c,0x0000000c,0x0000000c,0x00000030,0x00000031, + 0x00040020,0x00000033,0x00000009,0x00000032,0x0004003b,0x00000033,0x00000034,0x00000009, + 0x00040015,0x00000035,0x00000020,0x00000001,0x0004002b,0x00000035,0x00000036,0x00000002, + 0x00040020,0x00000037,0x00000009,0x0000000c,0x0004002b,0x00000035,0x0000003b,0x00000003, + 0x0004002b,0x00000006,0x00000040,0x3f800000,0x0004002b,0x00000006,0x00000043,0x40000000, + 0x00040020,0x00000048,0x00000007,0x00000006,0x0004002b,0x00000035,0x00000050,0x00000006, + 0x0004002b,0x00000035,0x00000051,0x00000000,0x00040020,0x00000052,0x00000009,0x00000006, + 0x0004002b,0x00000035,0x00000055,0x00000001,0x0004002b,0x00000035,0x0000006b,0x00000007, + 0x0004002b,0x00000006,0x00000076,0x40800000,0x0004002b,0x00000006,0x00000078,0x00000000, + 0x0004002b,0x00000006,0x00000080,0x40400000,0x0004002b,0x00000035,0x00000089,0x00000004, + 0x0004002b,0x00000035,0x00000092,0x00000005,0x0003001d,0x000000ae,0x0000000c,0x0003001e, + 0x000000af,0x000000ae,0x00040020,0x000000b0,0x00000002,0x000000af,0x0004003b,0x000000b0, + 0x000000b1,0x00000002,0x00040020,0x000000b9,0x00000002,0x0000000c,0x0004002b,0x00000006, + 0x000000c2,0x3f000000,0x0007002c,0x00000007,0x000000c3,0x000000c2,0x000000c2,0x000000c2, + 0x000000c2,0x0003001d,0x000000e0,0x0000000c,0x0003001e,0x000000e1,0x000000e0,0x00040020, + 0x000000e2,0x00000002,0x000000e1,0x0004003b,0x000000e2,0x000000e3,0x00000002,0x00040017, + 0x00000108,0x0000000c,0x00000004,0x00040020,0x00000109,0x00000007,0x00000108,0x0003001d, + 0x00000167,0x00000017,0x0003001e,0x00000168,0x00000167,0x00040020,0x00000169,0x00000002, + 0x00000168,0x0004003b,0x00000169,0x0000016a,0x00000002,0x00040020,0x0000016e,0x00000002, + 0x00000017,0x00040020,0x000001f6,0x00000007,0x00000009,0x0003001d,0x00000262,0x0000000c, + 0x0003001e,0x00000263,0x00000262,0x00040020,0x00000264,0x00000002,0x00000263,0x0004003b, + 0x00000264,0x00000265,0x00000002,0x0004002b,0x0000000c,0x000002e5,0x00000003,0x0007002c, + 0x00000007,0x00000321,0x00000078,0x00000078,0x00000078,0x00000078,0x0007002c,0x00000007, + 0x00000322,0x00000040,0x00000040,0x00000040,0x00000040,0x00040017,0x00000326,0x0000000c, + 0x00000002,0x00040020,0x00000327,0x00000007,0x00000326,0x0003001d,0x000003a5,0x0000000c, + 0x0003001e,0x000003a6,0x000003a5,0x00040020,0x000003a7,0x00000002,0x000003a6,0x0004003b, + 0x000003a7,0x000003a8,0x00000002,0x0004002b,0x0000000c,0x00000464,0x00000008,0x0006002c, + 0x00000021,0x00000465,0x00000464,0x00000464,0x00000029,0x00050036,0x00000002,0x00000004, + 0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x0000000d,0x00000020,0x00000007, + 0x0004003b,0x0000000d,0x00000028,0x00000007,0x0004003b,0x00000018,0x0000002e,0x00000007, + 0x0004003b,0x00000018,0x00000046,0x00000007,0x0004003b,0x00000018,0x0000004d,0x00000007, + 0x0004003b,0x00000018,0x00000060,0x00000007,0x0004003b,0x00000008,0x00000073,0x00000007, + 0x0004003b,0x00000008,0x00000085,0x00000007,0x0004003b,0x00000008,0x0000009d,0x00000007, + 0x0004003b,0x00000008,0x0000009e,0x00000007,0x0004003b,0x0000000b,0x0000009f,0x00000007, + 0x0004003b,0x0000000d,0x000000a0,0x00000007,0x0004003b,0x00000008,0x000000a1,0x00000007, + 0x0004003b,0x00000008,0x000000a3,0x00000007,0x0004003b,0x00000008,0x000000a5,0x00000007, + 0x0004003b,0x00000008,0x000000a6,0x00000007,0x0004003b,0x0000000b,0x000000a7,0x00000007, + 0x0004003b,0x0000000d,0x000000a8,0x00000007,0x0004003b,0x0000000b,0x000000bb,0x00000007, + 0x0004003b,0x00000018,0x000000c6,0x00000007,0x0004003b,0x00000018,0x000000c9,0x00000007, + 0x0004003b,0x00000018,0x000000d7,0x00000007,0x0004003b,0x00000018,0x000000d9,0x00000007, + 0x0004003b,0x0000000b,0x000000db,0x00000007,0x0004003b,0x0000000d,0x000000dd,0x00000007, + 0x0004003b,0x00000008,0x000000f2,0x00000007,0x0004003b,0x00000008,0x000000f4,0x00000007, + 0x0004003b,0x00000008,0x000000f6,0x00000007,0x0004003b,0x00000008,0x000000f7,0x00000007, + 0x0004003b,0x0000000b,0x000000f8,0x00000007,0x0004003b,0x0000000d,0x000000f9,0x00000007, + 0x00050041,0x00000025,0x00000026,0x00000023,0x00000024,0x0004003d,0x0000000c,0x00000027, + 0x00000026,0x0003003e,0x00000020,0x00000027,0x00050041,0x00000025,0x0000002a,0x00000023, + 0x00000029,0x0004003d,0x0000000c,0x0000002b,0x0000002a,0x00050084,0x0000000c,0x0000002d, + 0x0000002b,0x0000002c,0x0003003e,0x00000028,0x0000002d,0x00050041,0x00000037,0x00000038, + 0x00000034,0x00000036,0x0004003d,0x0000000c,0x00000039,0x00000038,0x00040070,0x00000006, + 0x0000003a,0x00000039,0x00050041,0x00000037,0x0000003c,0x00000034,0x0000003b,0x0004003d, + 0x0000000c,0x0000003d,0x0000003c,0x00040070,0x00000006,0x0000003e,0x0000003d,0x00050050, + 0x00000017,0x0000003f,0x0000003a,0x0000003e,0x00050050,0x00000017,0x00000041,0x00000040, + 0x00000040,0x00050083,0x00000017,0x00000042,0x0000003f,0x00000041,0x00050050,0x00000017, + 0x00000044,0x00000043,0x00000043,0x00050088,0x00000017,0x00000045,0x00000042,0x00000044, + 0x0003003e,0x0000002e,0x00000045,0x0004003d,0x0000000c,0x00000047,0x00000020,0x00050041, + 0x00000048,0x00000049,0x0000002e,0x00000024,0x0004003d,0x00000006,0x0000004a,0x00000049, + 0x0004006d,0x0000000c,0x0000004b,0x0000004a,0x000500b0,0x00000009,0x0000004c,0x00000047, + 0x0000004b,0x000300f7,0x0000004f,0x00000000,0x000400fa,0x0000004c,0x0000004e,0x00000059, + 0x000200f8,0x0000004e,0x00060041,0x00000052,0x00000053,0x00000034,0x00000050,0x00000051, + 0x0004003d,0x00000006,0x00000054,0x00000053,0x00060041,0x00000052,0x00000056,0x00000034, + 0x00000050,0x00000055,0x0004003d,0x00000006,0x00000057,0x00000056,0x00050050,0x00000017, + 0x00000058,0x00000054,0x00000057,0x0003003e,0x0000004d,0x00000058,0x000200f9,0x0000004f, + 0x000200f8,0x00000059,0x00060041,0x00000052,0x0000005a,0x00000034,0x00000050,0x00000036, + 0x0004003d,0x00000006,0x0000005b,0x0000005a,0x00060041,0x00000052,0x0000005c,0x00000034, + 0x00000050,0x0000003b,0x0004003d,0x00000006,0x0000005d,0x0000005c,0x00050050,0x00000017, + 0x0000005e,0x0000005b,0x0000005d,0x0003003e,0x0000004d,0x0000005e,0x000200f9,0x0000004f, + 0x000200f8,0x0000004f,0x0004003d,0x00000017,0x0000005f,0x0000004d,0x0003003e,0x00000046, + 0x0000005f,0x0004003d,0x0000000c,0x00000061,0x00000020,0x00040070,0x00000006,0x00000062, + 0x00000061,0x0004003d,0x0000000c,0x00000063,0x00000028,0x00040070,0x00000006,0x00000064, + 0x00000063,0x00050050,0x00000017,0x00000065,0x00000062,0x00000064,0x0004003d,0x00000017, + 0x00000066,0x0000002e,0x00050083,0x00000017,0x00000067,0x00000065,0x00000066,0x0004003d, + 0x00000017,0x00000068,0x00000046,0x00050085,0x00000017,0x00000069,0x00000067,0x00000068, + 0x0004003d,0x00000017,0x0000006a,0x0000002e,0x00060041,0x00000052,0x0000006c,0x00000034, + 0x0000006b,0x00000051,0x0004003d,0x00000006,0x0000006d,0x0000006c,0x00060041,0x00000052, + 0x0000006e,0x00000034,0x0000006b,0x00000055,0x0004003d,0x00000006,0x0000006f,0x0000006e, + 0x00050050,0x00000017,0x00000070,0x0000006d,0x0000006f,0x00050085,0x00000017,0x00000071, + 0x0000006a,0x00000070,0x00050081,0x00000017,0x00000072,0x00000069,0x00000071,0x0003003e, + 0x00000060,0x00000072,0x00050041,0x00000048,0x00000074,0x00000060,0x00000024,0x0004003d, + 0x00000006,0x00000075,0x00000074,0x00050085,0x00000006,0x00000077,0x00000075,0x00000076, + 0x00050041,0x00000048,0x00000079,0x00000046,0x00000024,0x0004003d,0x00000006,0x0000007a, + 0x00000079,0x00050041,0x00000048,0x0000007b,0x00000046,0x00000024,0x0004003d,0x00000006, + 0x0000007c,0x0000007b,0x00050085,0x00000006,0x0000007d,0x0000007c,0x00000043,0x00050041, + 0x00000048,0x0000007e,0x00000046,0x00000024,0x0004003d,0x00000006,0x0000007f,0x0000007e, + 0x00050085,0x00000006,0x00000081,0x0000007f,0x00000080,0x00070050,0x00000007,0x00000082, + 0x00000078,0x0000007a,0x0000007d,0x00000081,0x00070050,0x00000007,0x00000083,0x00000077, + 0x00000077,0x00000077,0x00000077,0x00050081,0x00000007,0x00000084,0x00000083,0x00000082, + 0x0003003e,0x00000073,0x00000084,0x0004003d,0x00000017,0x00000086,0x00000060,0x0009004f, + 0x00000007,0x00000087,0x00000086,0x00000086,0x00000001,0x00000001,0x00000001,0x00000001, + 0x0003003e,0x00000085,0x00000087,0x0004003d,0x00000007,0x00000088,0x00000073,0x00050041, + 0x00000037,0x0000008a,0x00000034,0x00000089,0x0004003d,0x0000000c,0x0000008b,0x0000008a, + 0x00040070,0x00000006,0x0000008c,0x0000008b,0x00050083,0x00000006,0x0000008d,0x0000008c, + 0x00000040,0x00070050,0x00000007,0x0000008e,0x00000078,0x00000078,0x00000078,0x00000078, + 0x00070050,0x00000007,0x0000008f,0x0000008d,0x0000008d,0x0000008d,0x0000008d,0x0008000c, + 0x00000007,0x00000090,0x00000001,0x0000002b,0x00000088,0x0000008e,0x0000008f,0x0003003e, + 0x00000073,0x00000090,0x0004003d,0x00000007,0x00000091,0x00000085,0x00050041,0x00000037, + 0x00000093,0x00000034,0x00000092,0x0004003d,0x0000000c,0x00000094,0x00000093,0x00040070, + 0x00000006,0x00000095,0x00000094,0x00050083,0x00000006,0x00000096,0x00000095,0x00000040, + 0x00050041,0x00000048,0x00000097,0x00000046,0x00000029,0x0004003d,0x00000006,0x00000098, + 0x00000097,0x00050083,0x00000006,0x00000099,0x00000096,0x00000098,0x00070050,0x00000007, + 0x0000009a,0x00000078,0x00000078,0x00000078,0x00000078,0x00070050,0x00000007,0x0000009b, + 0x00000099,0x00000099,0x00000099,0x00000099,0x0008000c,0x00000007,0x0000009c,0x00000001, + 0x0000002b,0x00000091,0x0000009a,0x0000009b,0x0003003e,0x00000085,0x0000009c,0x0004003d, + 0x00000007,0x000000a2,0x00000073,0x0003003e,0x000000a1,0x000000a2,0x0004003d,0x00000007, + 0x000000a4,0x00000085,0x0003003e,0x000000a3,0x000000a4,0x000a0039,0x00000002,0x000000a9, + 0x00000015,0x000000a1,0x000000a3,0x000000a5,0x000000a6,0x000000a7,0x000000a8,0x0004003d, + 0x00000007,0x000000aa,0x000000a5,0x0003003e,0x0000009d,0x000000aa,0x0004003d,0x00000007, + 0x000000ab,0x000000a6,0x0003003e,0x0000009e,0x000000ab,0x0004003d,0x0000000a,0x000000ac, + 0x000000a7,0x0003003e,0x0000009f,0x000000ac,0x0004003d,0x0000000c,0x000000ad,0x000000a8, + 0x0003003e,0x000000a0,0x000000ad,0x0004003d,0x0000000c,0x000000b2,0x00000028,0x00050041, + 0x00000037,0x000000b3,0x00000034,0x00000036,0x0004003d,0x0000000c,0x000000b4,0x000000b3, + 0x00050084,0x0000000c,0x000000b5,0x000000b2,0x000000b4,0x0004003d,0x0000000c,0x000000b6, + 0x00000020,0x00050080,0x0000000c,0x000000b7,0x000000b5,0x000000b6,0x0004003d,0x0000000c, + 0x000000b8,0x000000a0,0x00060041,0x000000b9,0x000000ba,0x000000b1,0x00000051,0x000000b7, + 0x0003003e,0x000000ba,0x000000b8,0x0004003d,0x0000000a,0x000000bc,0x0000009f,0x0009004f, + 0x0000000a,0x000000bd,0x000000bc,0x000000bc,0x00000000,0x00000000,0x00000002,0x00000002, + 0x0003003e,0x000000bb,0x000000bd,0x0004003d,0x0000000a,0x000000be,0x000000bb,0x0004009b, + 0x00000009,0x000000bf,0x000000be,0x000300f7,0x000000c1,0x00000000,0x000400fa,0x000000bf, + 0x000000c0,0x000000c5,0x000200f8,0x000000c0,0x0006000c,0x0000000c,0x000000c4,0x00000001, + 0x00000037,0x000000c3,0x0003003e,0x000000a0,0x000000c4,0x000200f9,0x000000c1,0x000200f8, + 0x000000c5,0x0004003d,0x00000007,0x000000c7,0x0000009d,0x0007004f,0x00000017,0x000000c8, + 0x000000c7,0x000000c7,0x00000000,0x00000002,0x0003003e,0x000000c6,0x000000c8,0x0004003d, + 0x00000007,0x000000ca,0x0000009e,0x0007004f,0x00000017,0x000000cb,0x000000ca,0x000000ca, + 0x00000000,0x00000002,0x00050050,0x00000017,0x000000cc,0x00000043,0x00000043,0x00050088, + 0x00000017,0x000000cd,0x000000cb,0x000000cc,0x0003003e,0x000000c9,0x000000cd,0x0004003d, + 0x00000017,0x000000ce,0x000000c9,0x00050041,0x00000037,0x000000cf,0x00000034,0x00000055, + 0x0004003d,0x0000000c,0x000000d0,0x000000cf,0x00050086,0x0000000c,0x000000d1,0x000000d0, + 0x0000002c,0x00050082,0x0000000c,0x000000d2,0x000000d1,0x00000029,0x00040070,0x00000006, + 0x000000d3,0x000000d2,0x00050050,0x00000017,0x000000d4,0x00000078,0x00000078,0x00050050, + 0x00000017,0x000000d5,0x000000d3,0x000000d3,0x0008000c,0x00000017,0x000000d6,0x00000001, + 0x0000002b,0x000000ce,0x000000d4,0x000000d5,0x0003003e,0x000000c9,0x000000d6,0x0004003d, + 0x00000017,0x000000d8,0x000000c6,0x0003003e,0x000000d7,0x000000d8,0x0004003d,0x00000017, + 0x000000da,0x000000c9,0x0003003e,0x000000d9,0x000000da,0x0004003d,0x0000000a,0x000000dc, + 0x000000bb,0x0003003e,0x000000db,0x000000dc,0x00080039,0x00000002,0x000000de,0x0000001e, + 0x000000d7,0x000000d9,0x000000db,0x000000dd,0x0004003d,0x0000000c,0x000000df,0x000000dd, + 0x0003003e,0x000000a0,0x000000df,0x000200f9,0x000000c1,0x000200f8,0x000000c1,0x0004003d, + 0x0000000c,0x000000e4,0x00000028,0x00050086,0x0000000c,0x000000e5,0x000000e4,0x0000002c, + 0x00050041,0x00000037,0x000000e6,0x00000034,0x00000036,0x0004003d,0x0000000c,0x000000e7, + 0x000000e6,0x00050084,0x0000000c,0x000000e8,0x000000e5,0x000000e7,0x0004003d,0x0000000c, + 0x000000e9,0x00000020,0x00050080,0x0000000c,0x000000ea,0x000000e8,0x000000e9,0x0004003d, + 0x0000000c,0x000000eb,0x000000a0,0x00060041,0x000000b9,0x000000ec,0x000000e3,0x00000051, + 0x000000ea,0x0003003e,0x000000ec,0x000000eb,0x00050041,0x00000048,0x000000ed,0x00000046, + 0x00000029,0x0004003d,0x00000006,0x000000ee,0x000000ed,0x0004003d,0x00000007,0x000000ef, + 0x00000085,0x00070050,0x00000007,0x000000f0,0x000000ee,0x000000ee,0x000000ee,0x000000ee, + 0x00050081,0x00000007,0x000000f1,0x000000ef,0x000000f0,0x0003003e,0x00000085,0x000000f1, + 0x0004003d,0x00000007,0x000000f3,0x00000073,0x0003003e,0x000000f2,0x000000f3,0x0004003d, + 0x00000007,0x000000f5,0x00000085,0x0003003e,0x000000f4,0x000000f5,0x000a0039,0x00000002, + 0x000000fa,0x00000015,0x000000f2,0x000000f4,0x000000f6,0x000000f7,0x000000f8,0x000000f9, + 0x0004003d,0x00000007,0x000000fb,0x000000f6,0x0003003e,0x0000009d,0x000000fb,0x0004003d, + 0x00000007,0x000000fc,0x000000f7,0x0003003e,0x0000009e,0x000000fc,0x0004003d,0x0000000a, + 0x000000fd,0x000000f8,0x0003003e,0x0000009f,0x000000fd,0x0004003d,0x0000000c,0x000000fe, + 0x000000f9,0x0003003e,0x000000a0,0x000000fe,0x0004003d,0x0000000c,0x000000ff,0x00000028, + 0x00050080,0x0000000c,0x00000100,0x000000ff,0x00000029,0x00050041,0x00000037,0x00000101, + 0x00000034,0x00000036,0x0004003d,0x0000000c,0x00000102,0x00000101,0x00050084,0x0000000c, + 0x00000103,0x00000100,0x00000102,0x0004003d,0x0000000c,0x00000104,0x00000020,0x00050080, + 0x0000000c,0x00000105,0x00000103,0x00000104,0x0004003d,0x0000000c,0x00000106,0x000000a0, + 0x00060041,0x000000b9,0x00000107,0x000000b1,0x00000051,0x00000105,0x0003003e,0x00000107, + 0x00000106,0x000100fd,0x00010038,0x00050036,0x00000002,0x00000015,0x00000000,0x0000000e, + 0x00030037,0x00000008,0x0000000f,0x00030037,0x00000008,0x00000010,0x00030037,0x00000008, + 0x00000011,0x00030037,0x00000008,0x00000012,0x00030037,0x0000000b,0x00000013,0x00030037, + 0x0000000d,0x00000014,0x000200f8,0x00000016,0x0004003b,0x00000109,0x0000010a,0x00000007, + 0x0004003b,0x00000109,0x0000010d,0x00000007,0x0004003b,0x00000109,0x00000110,0x00000007, + 0x0004003b,0x00000109,0x00000114,0x00000007,0x0004003b,0x00000109,0x00000116,0x00000007, + 0x0004003b,0x00000109,0x00000118,0x00000007,0x0004003b,0x00000109,0x0000011c,0x00000007, + 0x0004003b,0x00000109,0x0000011e,0x00000007,0x0004003b,0x00000008,0x00000120,0x00000007, + 0x0004003b,0x00000008,0x00000123,0x00000007,0x0004003b,0x00000008,0x00000126,0x00000007, + 0x0004003b,0x00000008,0x0000012e,0x00000007,0x0004003b,0x00000008,0x00000134,0x00000007, + 0x0004003b,0x00000008,0x0000013a,0x00000007,0x0004003b,0x00000109,0x0000013e,0x00000007, + 0x0004003b,0x00000109,0x00000146,0x00000007,0x0004003b,0x00000109,0x0000014e,0x00000007, + 0x0004003b,0x00000109,0x00000156,0x00000007,0x0004003b,0x0000000d,0x0000015e,0x00000007, + 0x0004003b,0x00000018,0x00000166,0x00000007,0x0004003b,0x00000008,0x00000171,0x00000007, + 0x0004003b,0x00000008,0x00000176,0x00000007,0x0004003b,0x00000008,0x00000180,0x00000007, + 0x0004003b,0x00000008,0x00000185,0x00000007,0x0004003b,0x00000008,0x0000018f,0x00000007, + 0x0004003b,0x00000008,0x00000194,0x00000007,0x0004003b,0x00000008,0x0000019e,0x00000007, + 0x0004003b,0x00000008,0x000001a3,0x00000007,0x0004003b,0x0000000d,0x000001c8,0x00000007, + 0x0004003b,0x00000109,0x00000225,0x00000007,0x0004003b,0x00000109,0x00000229,0x00000007, + 0x0004003b,0x00000109,0x0000022d,0x00000007,0x0004003b,0x00000109,0x00000231,0x00000007, + 0x0004003b,0x00000109,0x00000235,0x00000007,0x0004003b,0x00000109,0x00000239,0x00000007, + 0x0004003b,0x00000109,0x0000023d,0x00000007,0x0004003b,0x00000109,0x00000241,0x00000007, + 0x0004003b,0x00000008,0x00000261,0x00000007,0x0004003b,0x00000008,0x0000026b,0x00000007, + 0x0004003b,0x00000008,0x00000276,0x00000007,0x0004003b,0x00000008,0x00000281,0x00000007, + 0x0004003b,0x00000008,0x0000028c,0x00000007,0x0004003b,0x00000008,0x00000292,0x00000007, + 0x0004003b,0x00000008,0x000002bb,0x00000007,0x0004003b,0x00000008,0x000002e4,0x00000007, + 0x0004003b,0x00000008,0x0000030e,0x00000007,0x0004003d,0x00000007,0x0000010b,0x0000000f, + 0x0004006d,0x00000108,0x0000010c,0x0000010b,0x0003003e,0x0000010a,0x0000010c,0x0004003d, + 0x00000007,0x0000010e,0x00000010,0x0004006d,0x00000108,0x0000010f,0x0000010e,0x0003003e, + 0x0000010d,0x0000010f,0x0004003d,0x00000108,0x00000111,0x0000010a,0x00070050,0x00000108, + 0x00000112,0x00000029,0x00000029,0x00000029,0x00000029,0x00050080,0x00000108,0x00000113, + 0x00000111,0x00000112,0x0003003e,0x00000110,0x00000113,0x0004003d,0x00000108,0x00000115, + 0x0000010d,0x0003003e,0x00000114,0x00000115,0x0004003d,0x00000108,0x00000117,0x0000010a, + 0x0003003e,0x00000116,0x00000117,0x0004003d,0x00000108,0x00000119,0x0000010d,0x00070050, + 0x00000108,0x0000011a,0x00000029,0x00000029,0x00000029,0x00000029,0x00050080,0x00000108, + 0x0000011b,0x00000119,0x0000011a,0x0003003e,0x00000118,0x0000011b,0x0004003d,0x00000108, + 0x0000011d,0x00000110,0x0003003e,0x0000011c,0x0000011d,0x0004003d,0x00000108,0x0000011f, + 0x00000118,0x0003003e,0x0000011e,0x0000011f,0x0004003d,0x00000007,0x00000121,0x0000000f, + 0x0006000c,0x00000007,0x00000122,0x00000001,0x0000000a,0x00000121,0x0003003e,0x00000120, + 0x00000122,0x0004003d,0x00000007,0x00000124,0x00000010,0x0006000c,0x00000007,0x00000125, + 0x00000001,0x0000000a,0x00000124,0x0003003e,0x00000123,0x00000125,0x0004003d,0x00000007, + 0x00000127,0x00000120,0x00070050,0x00000007,0x00000128,0x00000040,0x00000040,0x00000040, + 0x00000040,0x00050083,0x00000007,0x00000129,0x00000128,0x00000127,0x0004003d,0x00000007, + 0x0000012a,0x00000123,0x00070050,0x00000007,0x0000012b,0x00000040,0x00000040,0x00000040, + 0x00000040,0x00050083,0x00000007,0x0000012c,0x0000012b,0x0000012a,0x00050085,0x00000007, + 0x0000012d,0x00000129,0x0000012c,0x0003003e,0x00000126,0x0000012d,0x0004003d,0x00000007, + 0x0000012f,0x00000120,0x0004003d,0x00000007,0x00000130,0x00000123,0x00070050,0x00000007, + 0x00000131,0x00000040,0x00000040,0x00000040,0x00000040,0x00050083,0x00000007,0x00000132, + 0x00000131,0x00000130,0x00050085,0x00000007,0x00000133,0x0000012f,0x00000132,0x0003003e, + 0x0000012e,0x00000133,0x0004003d,0x00000007,0x00000135,0x00000120,0x00070050,0x00000007, + 0x00000136,0x00000040,0x00000040,0x00000040,0x00000040,0x00050083,0x00000007,0x00000137, + 0x00000136,0x00000135,0x0004003d,0x00000007,0x00000138,0x00000123,0x00050085,0x00000007, + 0x00000139,0x00000137,0x00000138,0x0003003e,0x00000134,0x00000139,0x0004003d,0x00000007, + 0x0000013b,0x00000120,0x0004003d,0x00000007,0x0000013c,0x00000123,0x00050085,0x00000007, + 0x0000013d,0x0000013b,0x0000013c,0x0003003e,0x0000013a,0x0000013d,0x0004003d,0x00000108, + 0x0000013f,0x0000010d,0x00050041,0x00000037,0x00000140,0x00000034,0x00000089,0x0004003d, + 0x0000000c,0x00000141,0x00000140,0x00070050,0x00000108,0x00000142,0x00000141,0x00000141, + 0x00000141,0x00000141,0x00050084,0x00000108,0x00000143,0x0000013f,0x00000142,0x0004003d, + 0x00000108,0x00000144,0x0000010a,0x00050080,0x00000108,0x00000145,0x00000143,0x00000144, + 0x0003003e,0x0000013e,0x00000145,0x0004003d,0x00000108,0x00000147,0x00000114,0x00050041, + 0x00000037,0x00000148,0x00000034,0x00000089,0x0004003d,0x0000000c,0x00000149,0x00000148, + 0x00070050,0x00000108,0x0000014a,0x00000149,0x00000149,0x00000149,0x00000149,0x00050084, + 0x00000108,0x0000014b,0x00000147,0x0000014a,0x0004003d,0x00000108,0x0000014c,0x00000110, + 0x00050080,0x00000108,0x0000014d,0x0000014b,0x0000014c,0x0003003e,0x00000146,0x0000014d, + 0x0004003d,0x00000108,0x0000014f,0x00000118,0x00050041,0x00000037,0x00000150,0x00000034, + 0x00000089,0x0004003d,0x0000000c,0x00000151,0x00000150,0x00070050,0x00000108,0x00000152, + 0x00000151,0x00000151,0x00000151,0x00000151,0x00050084,0x00000108,0x00000153,0x0000014f, + 0x00000152,0x0004003d,0x00000108,0x00000154,0x00000116,0x00050080,0x00000108,0x00000155, + 0x00000153,0x00000154,0x0003003e,0x0000014e,0x00000155,0x0004003d,0x00000108,0x00000157, + 0x0000011e,0x00050041,0x00000037,0x00000158,0x00000034,0x00000089,0x0004003d,0x0000000c, + 0x00000159,0x00000158,0x00070050,0x00000108,0x0000015a,0x00000159,0x00000159,0x00000159, + 0x00000159,0x00050084,0x00000108,0x0000015b,0x00000157,0x0000015a,0x0004003d,0x00000108, + 0x0000015c,0x0000011c,0x00050080,0x00000108,0x0000015d,0x0000015b,0x0000015c,0x0003003e, + 0x00000156,0x0000015d,0x0003003e,0x0000015e,0x00000024,0x000200f9,0x0000015f,0x000200f8, + 0x0000015f,0x000400f6,0x00000161,0x00000162,0x00000000,0x000200f9,0x00000163,0x000200f8, + 0x00000163,0x0004003d,0x0000000c,0x00000164,0x0000015e,0x000500b0,0x00000009,0x00000165, + 0x00000164,0x0000002f,0x000400fa,0x00000165,0x00000160,0x00000161,0x000200f8,0x00000160, + 0x0004003d,0x0000000c,0x0000016b,0x0000015e,0x00050041,0x0000000d,0x0000016c,0x0000013e, + 0x0000016b,0x0004003d,0x0000000c,0x0000016d,0x0000016c,0x00060041,0x0000016e,0x0000016f, + 0x0000016a,0x00000051,0x0000016d,0x0004003d,0x00000017,0x00000170,0x0000016f,0x0003003e, + 0x00000166,0x00000170,0x0004003d,0x0000000c,0x00000172,0x0000015e,0x00050041,0x00000048, + 0x00000173,0x00000166,0x00000024,0x0004003d,0x00000006,0x00000174,0x00000173,0x00050041, + 0x00000048,0x00000175,0x00000171,0x00000172,0x0003003e,0x00000175,0x00000174,0x0004003d, + 0x0000000c,0x00000177,0x0000015e,0x00050041,0x00000048,0x00000178,0x00000166,0x00000029, + 0x0004003d,0x00000006,0x00000179,0x00000178,0x00050041,0x00000048,0x0000017a,0x00000176, + 0x00000177,0x0003003e,0x0000017a,0x00000179,0x0004003d,0x0000000c,0x0000017b,0x0000015e, + 0x00050041,0x0000000d,0x0000017c,0x00000146,0x0000017b,0x0004003d,0x0000000c,0x0000017d, + 0x0000017c,0x00060041,0x0000016e,0x0000017e,0x0000016a,0x00000051,0x0000017d,0x0004003d, + 0x00000017,0x0000017f,0x0000017e,0x0003003e,0x00000166,0x0000017f,0x0004003d,0x0000000c, + 0x00000181,0x0000015e,0x00050041,0x00000048,0x00000182,0x00000166,0x00000024,0x0004003d, + 0x00000006,0x00000183,0x00000182,0x00050041,0x00000048,0x00000184,0x00000180,0x00000181, + 0x0003003e,0x00000184,0x00000183,0x0004003d,0x0000000c,0x00000186,0x0000015e,0x00050041, + 0x00000048,0x00000187,0x00000166,0x00000029,0x0004003d,0x00000006,0x00000188,0x00000187, + 0x00050041,0x00000048,0x00000189,0x00000185,0x00000186,0x0003003e,0x00000189,0x00000188, + 0x0004003d,0x0000000c,0x0000018a,0x0000015e,0x00050041,0x0000000d,0x0000018b,0x0000014e, + 0x0000018a,0x0004003d,0x0000000c,0x0000018c,0x0000018b,0x00060041,0x0000016e,0x0000018d, + 0x0000016a,0x00000051,0x0000018c,0x0004003d,0x00000017,0x0000018e,0x0000018d,0x0003003e, + 0x00000166,0x0000018e,0x0004003d,0x0000000c,0x00000190,0x0000015e,0x00050041,0x00000048, + 0x00000191,0x00000166,0x00000024,0x0004003d,0x00000006,0x00000192,0x00000191,0x00050041, + 0x00000048,0x00000193,0x0000018f,0x00000190,0x0003003e,0x00000193,0x00000192,0x0004003d, + 0x0000000c,0x00000195,0x0000015e,0x00050041,0x00000048,0x00000196,0x00000166,0x00000029, + 0x0004003d,0x00000006,0x00000197,0x00000196,0x00050041,0x00000048,0x00000198,0x00000194, + 0x00000195,0x0003003e,0x00000198,0x00000197,0x0004003d,0x0000000c,0x00000199,0x0000015e, + 0x00050041,0x0000000d,0x0000019a,0x00000156,0x00000199,0x0004003d,0x0000000c,0x0000019b, + 0x0000019a,0x00060041,0x0000016e,0x0000019c,0x0000016a,0x00000051,0x0000019b,0x0004003d, + 0x00000017,0x0000019d,0x0000019c,0x0003003e,0x00000166,0x0000019d,0x0004003d,0x0000000c, + 0x0000019f,0x0000015e,0x00050041,0x00000048,0x000001a0,0x00000166,0x00000024,0x0004003d, + 0x00000006,0x000001a1,0x000001a0,0x00050041,0x00000048,0x000001a2,0x0000019e,0x0000019f, + 0x0003003e,0x000001a2,0x000001a1,0x0004003d,0x0000000c,0x000001a4,0x0000015e,0x00050041, + 0x00000048,0x000001a5,0x00000166,0x00000029,0x0004003d,0x00000006,0x000001a6,0x000001a5, + 0x00050041,0x00000048,0x000001a7,0x000001a3,0x000001a4,0x0003003e,0x000001a7,0x000001a6, + 0x000200f9,0x00000162,0x000200f8,0x00000162,0x0004003d,0x0000000c,0x000001a8,0x0000015e, + 0x00050080,0x0000000c,0x000001a9,0x000001a8,0x00000055,0x0003003e,0x0000015e,0x000001a9, + 0x000200f9,0x0000015f,0x000200f8,0x00000161,0x0004003d,0x00000007,0x000001aa,0x00000171, + 0x0004003d,0x00000007,0x000001ab,0x00000126,0x00050085,0x00000007,0x000001ac,0x000001aa, + 0x000001ab,0x0004003d,0x00000007,0x000001ad,0x00000180,0x0004003d,0x00000007,0x000001ae, + 0x0000012e,0x00050085,0x00000007,0x000001af,0x000001ad,0x000001ae,0x00050081,0x00000007, + 0x000001b0,0x000001ac,0x000001af,0x0004003d,0x00000007,0x000001b1,0x0000018f,0x0004003d, + 0x00000007,0x000001b2,0x00000134,0x00050085,0x00000007,0x000001b3,0x000001b1,0x000001b2, + 0x00050081,0x00000007,0x000001b4,0x000001b0,0x000001b3,0x0004003d,0x00000007,0x000001b5, + 0x0000019e,0x0004003d,0x00000007,0x000001b6,0x0000013a,0x00050085,0x00000007,0x000001b7, + 0x000001b5,0x000001b6,0x00050081,0x00000007,0x000001b8,0x000001b4,0x000001b7,0x0003003e, + 0x00000011,0x000001b8,0x0004003d,0x00000007,0x000001b9,0x00000176,0x0004003d,0x00000007, + 0x000001ba,0x00000126,0x00050085,0x00000007,0x000001bb,0x000001b9,0x000001ba,0x0004003d, + 0x00000007,0x000001bc,0x00000185,0x0004003d,0x00000007,0x000001bd,0x0000012e,0x00050085, + 0x00000007,0x000001be,0x000001bc,0x000001bd,0x00050081,0x00000007,0x000001bf,0x000001bb, + 0x000001be,0x0004003d,0x00000007,0x000001c0,0x00000194,0x0004003d,0x00000007,0x000001c1, + 0x00000134,0x00050085,0x00000007,0x000001c2,0x000001c0,0x000001c1,0x00050081,0x00000007, + 0x000001c3,0x000001bf,0x000001c2,0x0004003d,0x00000007,0x000001c4,0x000001a3,0x0004003d, + 0x00000007,0x000001c5,0x0000013a,0x00050085,0x00000007,0x000001c6,0x000001c4,0x000001c5, + 0x00050081,0x00000007,0x000001c7,0x000001c3,0x000001c6,0x0003003e,0x00000012,0x000001c7, + 0x0003003e,0x000001c8,0x00000024,0x000200f9,0x000001c9,0x000200f8,0x000001c9,0x000400f6, + 0x000001cb,0x000001cc,0x00000000,0x000200f9,0x000001cd,0x000200f8,0x000001cd,0x0004003d, + 0x0000000c,0x000001ce,0x000001c8,0x000500b0,0x00000009,0x000001cf,0x000001ce,0x0000002f, + 0x000400fa,0x000001cf,0x000001ca,0x000001cb,0x000200f8,0x000001ca,0x0004003d,0x0000000c, + 0x000001d0,0x000001c8,0x0004003d,0x0000000c,0x000001d1,0x000001c8,0x00050041,0x00000048, + 0x000001d2,0x00000011,0x000001d1,0x0004003d,0x00000006,0x000001d3,0x000001d2,0x000500b8, + 0x00000009,0x000001d4,0x000001d3,0x00000078,0x000400a8,0x00000009,0x000001d5,0x000001d4, + 0x000300f7,0x000001d7,0x00000000,0x000400fa,0x000001d5,0x000001d6,0x000001d7,0x000200f8, + 0x000001d6,0x0004003d,0x0000000c,0x000001d8,0x000001c8,0x00050041,0x00000048,0x000001d9, + 0x00000011,0x000001d8,0x0004003d,0x00000006,0x000001da,0x000001d9,0x00050041,0x00000037, + 0x000001db,0x00000034,0x00000051,0x0004003d,0x0000000c,0x000001dc,0x000001db,0x00050084, + 0x0000000c,0x000001dd,0x000001dc,0x0000002f,0x00050082,0x0000000c,0x000001de,0x000001dd, + 0x00000029,0x00040070,0x00000006,0x000001df,0x000001de,0x000500ba,0x00000009,0x000001e0, + 0x000001da,0x000001df,0x000200f9,0x000001d7,0x000200f8,0x000001d7,0x000700f5,0x00000009, + 0x000001e1,0x000001d4,0x000001ca,0x000001e0,0x000001d6,0x000400a8,0x00000009,0x000001e2, + 0x000001e1,0x000300f7,0x000001e4,0x00000000,0x000400fa,0x000001e2,0x000001e3,0x000001e4, + 0x000200f8,0x000001e3,0x0004003d,0x0000000c,0x000001e5,0x000001c8,0x00050041,0x00000048, + 0x000001e6,0x00000012,0x000001e5,0x0004003d,0x00000006,0x000001e7,0x000001e6,0x000500b8, + 0x00000009,0x000001e8,0x000001e7,0x00000078,0x000200f9,0x000001e4,0x000200f8,0x000001e4, + 0x000700f5,0x00000009,0x000001e9,0x000001e1,0x000001d7,0x000001e8,0x000001e3,0x000400a8, + 0x00000009,0x000001ea,0x000001e9,0x000300f7,0x000001ec,0x00000000,0x000400fa,0x000001ea, + 0x000001eb,0x000001ec,0x000200f8,0x000001eb,0x0004003d,0x0000000c,0x000001ed,0x000001c8, + 0x00050041,0x00000048,0x000001ee,0x00000012,0x000001ed,0x0004003d,0x00000006,0x000001ef, + 0x000001ee,0x00050041,0x00000037,0x000001f0,0x00000034,0x00000055,0x0004003d,0x0000000c, + 0x000001f1,0x000001f0,0x00050082,0x0000000c,0x000001f2,0x000001f1,0x00000029,0x00040070, + 0x00000006,0x000001f3,0x000001f2,0x000500ba,0x00000009,0x000001f4,0x000001ef,0x000001f3, + 0x000200f9,0x000001ec,0x000200f8,0x000001ec,0x000700f5,0x00000009,0x000001f5,0x000001e9, + 0x000001e4,0x000001f4,0x000001eb,0x00050041,0x000001f6,0x000001f7,0x00000013,0x000001d0, + 0x0003003e,0x000001f7,0x000001f5,0x000200f9,0x000001cc,0x000200f8,0x000001cc,0x0004003d, + 0x0000000c,0x000001f8,0x000001c8,0x00050080,0x0000000c,0x000001f9,0x000001f8,0x00000055, + 0x0003003e,0x000001c8,0x000001f9,0x000200f9,0x000001c9,0x000200f8,0x000001cb,0x0004003d, + 0x0000000a,0x000001fa,0x00000013,0x0004009b,0x00000009,0x000001fb,0x000001fa,0x000300f7, + 0x000001fd,0x00000000,0x000400fa,0x000001fb,0x000001fc,0x000001fd,0x000200f8,0x000001fc, + 0x0003003e,0x00000014,0x00000024,0x000100fd,0x000200f8,0x000001fd,0x0004003d,0x00000007, + 0x000001ff,0x00000011,0x0004006d,0x00000108,0x00000200,0x000001ff,0x0003003e,0x0000010a, + 0x00000200,0x0004003d,0x00000007,0x00000201,0x00000012,0x0004006d,0x00000108,0x00000202, + 0x00000201,0x0003003e,0x0000010d,0x00000202,0x0004003d,0x00000108,0x00000203,0x0000010a, + 0x00070050,0x00000108,0x00000204,0x00000029,0x00000029,0x00000029,0x00000029,0x00050080, + 0x00000108,0x00000205,0x00000203,0x00000204,0x0003003e,0x00000110,0x00000205,0x0004003d, + 0x00000108,0x00000206,0x0000010d,0x0003003e,0x00000114,0x00000206,0x0004003d,0x00000108, + 0x00000207,0x0000010a,0x0003003e,0x00000116,0x00000207,0x0004003d,0x00000108,0x00000208, + 0x0000010d,0x00070050,0x00000108,0x00000209,0x00000029,0x00000029,0x00000029,0x00000029, + 0x00050080,0x00000108,0x0000020a,0x00000208,0x00000209,0x0003003e,0x00000118,0x0000020a, + 0x0004003d,0x00000108,0x0000020b,0x00000110,0x0003003e,0x0000011c,0x0000020b,0x0004003d, + 0x00000108,0x0000020c,0x00000118,0x0003003e,0x0000011e,0x0000020c,0x0004003d,0x00000007, + 0x0000020d,0x00000011,0x0006000c,0x00000007,0x0000020e,0x00000001,0x0000000a,0x0000020d, + 0x0003003e,0x00000120,0x0000020e,0x0004003d,0x00000007,0x0000020f,0x00000012,0x0006000c, + 0x00000007,0x00000210,0x00000001,0x0000000a,0x0000020f,0x0003003e,0x00000123,0x00000210, + 0x0004003d,0x00000007,0x00000211,0x00000120,0x00070050,0x00000007,0x00000212,0x00000040, + 0x00000040,0x00000040,0x00000040,0x00050083,0x00000007,0x00000213,0x00000212,0x00000211, + 0x0004003d,0x00000007,0x00000214,0x00000123,0x00070050,0x00000007,0x00000215,0x00000040, + 0x00000040,0x00000040,0x00000040,0x00050083,0x00000007,0x00000216,0x00000215,0x00000214, + 0x00050085,0x00000007,0x00000217,0x00000213,0x00000216,0x0003003e,0x00000126,0x00000217, + 0x0004003d,0x00000007,0x00000218,0x00000120,0x0004003d,0x00000007,0x00000219,0x00000123, + 0x00070050,0x00000007,0x0000021a,0x00000040,0x00000040,0x00000040,0x00000040,0x00050083, + 0x00000007,0x0000021b,0x0000021a,0x00000219,0x00050085,0x00000007,0x0000021c,0x00000218, + 0x0000021b,0x0003003e,0x0000012e,0x0000021c,0x0004003d,0x00000007,0x0000021d,0x00000120, + 0x00070050,0x00000007,0x0000021e,0x00000040,0x00000040,0x00000040,0x00000040,0x00050083, + 0x00000007,0x0000021f,0x0000021e,0x0000021d,0x0004003d,0x00000007,0x00000220,0x00000123, + 0x00050085,0x00000007,0x00000221,0x0000021f,0x00000220,0x0003003e,0x00000134,0x00000221, + 0x0004003d,0x00000007,0x00000222,0x00000120,0x0004003d,0x00000007,0x00000223,0x00000123, + 0x00050085,0x00000007,0x00000224,0x00000222,0x00000223,0x0003003e,0x0000013a,0x00000224, + 0x0004003d,0x00000108,0x00000226,0x0000010a,0x00070050,0x00000108,0x00000227,0x0000002f, + 0x0000002f,0x0000002f,0x0000002f,0x00050086,0x00000108,0x00000228,0x00000226,0x00000227, + 0x0003003e,0x00000225,0x00000228,0x0004003d,0x00000108,0x0000022a,0x00000110,0x00070050, + 0x00000108,0x0000022b,0x0000002f,0x0000002f,0x0000002f,0x0000002f,0x00050086,0x00000108, + 0x0000022c,0x0000022a,0x0000022b,0x0003003e,0x00000229,0x0000022c,0x0004003d,0x00000108, + 0x0000022e,0x00000116,0x00070050,0x00000108,0x0000022f,0x0000002f,0x0000002f,0x0000002f, + 0x0000002f,0x00050086,0x00000108,0x00000230,0x0000022e,0x0000022f,0x0003003e,0x0000022d, + 0x00000230,0x0004003d,0x00000108,0x00000232,0x0000011c,0x00070050,0x00000108,0x00000233, + 0x0000002f,0x0000002f,0x0000002f,0x0000002f,0x00050086,0x00000108,0x00000234,0x00000232, + 0x00000233,0x0003003e,0x00000231,0x00000234,0x0004003d,0x00000108,0x00000236,0x0000010a, + 0x00070050,0x00000108,0x00000237,0x0000002f,0x0000002f,0x0000002f,0x0000002f,0x00050089, + 0x00000108,0x00000238,0x00000236,0x00000237,0x0003003e,0x00000235,0x00000238,0x0004003d, + 0x00000108,0x0000023a,0x00000110,0x00070050,0x00000108,0x0000023b,0x0000002f,0x0000002f, + 0x0000002f,0x0000002f,0x00050089,0x00000108,0x0000023c,0x0000023a,0x0000023b,0x0003003e, + 0x00000239,0x0000023c,0x0004003d,0x00000108,0x0000023e,0x00000116,0x00070050,0x00000108, + 0x0000023f,0x0000002f,0x0000002f,0x0000002f,0x0000002f,0x00050089,0x00000108,0x00000240, + 0x0000023e,0x0000023f,0x0003003e,0x0000023d,0x00000240,0x0004003d,0x00000108,0x00000242, + 0x0000011c,0x00070050,0x00000108,0x00000243,0x0000002f,0x0000002f,0x0000002f,0x0000002f, + 0x00050089,0x00000108,0x00000244,0x00000242,0x00000243,0x0003003e,0x00000241,0x00000244, + 0x0004003d,0x00000108,0x00000245,0x0000010d,0x00050041,0x00000037,0x00000246,0x00000034, + 0x00000051,0x0004003d,0x0000000c,0x00000247,0x00000246,0x00070050,0x00000108,0x00000248, + 0x00000247,0x00000247,0x00000247,0x00000247,0x00050084,0x00000108,0x00000249,0x00000245, + 0x00000248,0x0004003d,0x00000108,0x0000024a,0x00000225,0x00050080,0x00000108,0x0000024b, + 0x00000249,0x0000024a,0x0003003e,0x0000013e,0x0000024b,0x0004003d,0x00000108,0x0000024c, + 0x00000114,0x00050041,0x00000037,0x0000024d,0x00000034,0x00000051,0x0004003d,0x0000000c, + 0x0000024e,0x0000024d,0x00070050,0x00000108,0x0000024f,0x0000024e,0x0000024e,0x0000024e, + 0x0000024e,0x00050084,0x00000108,0x00000250,0x0000024c,0x0000024f,0x0004003d,0x00000108, + 0x00000251,0x00000229,0x00050080,0x00000108,0x00000252,0x00000250,0x00000251,0x0003003e, + 0x00000146,0x00000252,0x0004003d,0x00000108,0x00000253,0x00000118,0x00050041,0x00000037, + 0x00000254,0x00000034,0x00000051,0x0004003d,0x0000000c,0x00000255,0x00000254,0x00070050, + 0x00000108,0x00000256,0x00000255,0x00000255,0x00000255,0x00000255,0x00050084,0x00000108, + 0x00000257,0x00000253,0x00000256,0x0004003d,0x00000108,0x00000258,0x0000022d,0x00050080, + 0x00000108,0x00000259,0x00000257,0x00000258,0x0003003e,0x0000014e,0x00000259,0x0004003d, + 0x00000108,0x0000025a,0x0000011e,0x00050041,0x00000037,0x0000025b,0x00000034,0x00000051, + 0x0004003d,0x0000000c,0x0000025c,0x0000025b,0x00070050,0x00000108,0x0000025d,0x0000025c, + 0x0000025c,0x0000025c,0x0000025c,0x00050084,0x00000108,0x0000025e,0x0000025a,0x0000025d, + 0x0004003d,0x00000108,0x0000025f,0x00000231,0x00050080,0x00000108,0x00000260,0x0000025e, + 0x0000025f,0x0003003e,0x00000156,0x00000260,0x00050041,0x0000000d,0x00000266,0x0000013e, + 0x00000024,0x0004003d,0x0000000c,0x00000267,0x00000266,0x00060041,0x000000b9,0x00000268, + 0x00000265,0x00000051,0x00000267,0x0004003d,0x0000000c,0x00000269,0x00000268,0x0006000c, + 0x00000007,0x0000026a,0x00000001,0x00000040,0x00000269,0x0003003e,0x00000261,0x0000026a, + 0x00050041,0x0000000d,0x0000026c,0x00000235,0x00000024,0x0004003d,0x0000000c,0x0000026d, + 0x0000026c,0x00050041,0x00000048,0x0000026e,0x00000261,0x0000026d,0x0004003d,0x00000006, + 0x0000026f,0x0000026e,0x00050041,0x00000048,0x00000270,0x0000026b,0x00000024,0x0003003e, + 0x00000270,0x0000026f,0x00050041,0x0000000d,0x00000271,0x00000146,0x00000024,0x0004003d, + 0x0000000c,0x00000272,0x00000271,0x00060041,0x000000b9,0x00000273,0x00000265,0x00000051, + 0x00000272,0x0004003d,0x0000000c,0x00000274,0x00000273,0x0006000c,0x00000007,0x00000275, + 0x00000001,0x00000040,0x00000274,0x0003003e,0x00000261,0x00000275,0x00050041,0x0000000d, + 0x00000277,0x00000239,0x00000024,0x0004003d,0x0000000c,0x00000278,0x00000277,0x00050041, + 0x00000048,0x00000279,0x00000261,0x00000278,0x0004003d,0x00000006,0x0000027a,0x00000279, + 0x00050041,0x00000048,0x0000027b,0x00000276,0x00000024,0x0003003e,0x0000027b,0x0000027a, + 0x00050041,0x0000000d,0x0000027c,0x0000014e,0x00000024,0x0004003d,0x0000000c,0x0000027d, + 0x0000027c,0x00060041,0x000000b9,0x0000027e,0x00000265,0x00000051,0x0000027d,0x0004003d, + 0x0000000c,0x0000027f,0x0000027e,0x0006000c,0x00000007,0x00000280,0x00000001,0x00000040, + 0x0000027f,0x0003003e,0x00000261,0x00000280,0x00050041,0x0000000d,0x00000282,0x0000023d, + 0x00000024,0x0004003d,0x0000000c,0x00000283,0x00000282,0x00050041,0x00000048,0x00000284, + 0x00000261,0x00000283,0x0004003d,0x00000006,0x00000285,0x00000284,0x00050041,0x00000048, + 0x00000286,0x00000281,0x00000024,0x0003003e,0x00000286,0x00000285,0x00050041,0x0000000d, + 0x00000287,0x00000156,0x00000024,0x0004003d,0x0000000c,0x00000288,0x00000287,0x00060041, + 0x000000b9,0x00000289,0x00000265,0x00000051,0x00000288,0x0004003d,0x0000000c,0x0000028a, + 0x00000289,0x0006000c,0x00000007,0x0000028b,0x00000001,0x00000040,0x0000028a,0x0003003e, + 0x00000261,0x0000028b,0x00050041,0x0000000d,0x0000028d,0x00000241,0x00000024,0x0004003d, + 0x0000000c,0x0000028e,0x0000028d,0x00050041,0x00000048,0x0000028f,0x00000261,0x0000028e, + 0x0004003d,0x00000006,0x00000290,0x0000028f,0x00050041,0x00000048,0x00000291,0x0000028c, + 0x00000024,0x0003003e,0x00000291,0x00000290,0x00050041,0x0000000d,0x00000293,0x0000013e, + 0x00000029,0x0004003d,0x0000000c,0x00000294,0x00000293,0x00060041,0x000000b9,0x00000295, + 0x00000265,0x00000051,0x00000294,0x0004003d,0x0000000c,0x00000296,0x00000295,0x0006000c, + 0x00000007,0x00000297,0x00000001,0x00000040,0x00000296,0x0003003e,0x00000292,0x00000297, + 0x00050041,0x0000000d,0x00000298,0x00000235,0x00000029,0x0004003d,0x0000000c,0x00000299, + 0x00000298,0x00050041,0x00000048,0x0000029a,0x00000292,0x00000299,0x0004003d,0x00000006, + 0x0000029b,0x0000029a,0x00050041,0x00000048,0x0000029c,0x0000026b,0x00000029,0x0003003e, + 0x0000029c,0x0000029b,0x00050041,0x0000000d,0x0000029d,0x00000146,0x00000029,0x0004003d, + 0x0000000c,0x0000029e,0x0000029d,0x00060041,0x000000b9,0x0000029f,0x00000265,0x00000051, + 0x0000029e,0x0004003d,0x0000000c,0x000002a0,0x0000029f,0x0006000c,0x00000007,0x000002a1, + 0x00000001,0x00000040,0x000002a0,0x0003003e,0x00000292,0x000002a1,0x00050041,0x0000000d, + 0x000002a2,0x00000239,0x00000029,0x0004003d,0x0000000c,0x000002a3,0x000002a2,0x00050041, + 0x00000048,0x000002a4,0x00000292,0x000002a3,0x0004003d,0x00000006,0x000002a5,0x000002a4, + 0x00050041,0x00000048,0x000002a6,0x00000276,0x00000029,0x0003003e,0x000002a6,0x000002a5, + 0x00050041,0x0000000d,0x000002a7,0x0000014e,0x00000029,0x0004003d,0x0000000c,0x000002a8, + 0x000002a7,0x00060041,0x000000b9,0x000002a9,0x00000265,0x00000051,0x000002a8,0x0004003d, + 0x0000000c,0x000002aa,0x000002a9,0x0006000c,0x00000007,0x000002ab,0x00000001,0x00000040, + 0x000002aa,0x0003003e,0x00000292,0x000002ab,0x00050041,0x0000000d,0x000002ac,0x0000023d, + 0x00000029,0x0004003d,0x0000000c,0x000002ad,0x000002ac,0x00050041,0x00000048,0x000002ae, + 0x00000292,0x000002ad,0x0004003d,0x00000006,0x000002af,0x000002ae,0x00050041,0x00000048, + 0x000002b0,0x00000281,0x00000029,0x0003003e,0x000002b0,0x000002af,0x00050041,0x0000000d, + 0x000002b1,0x00000156,0x00000029,0x0004003d,0x0000000c,0x000002b2,0x000002b1,0x00060041, + 0x000000b9,0x000002b3,0x00000265,0x00000051,0x000002b2,0x0004003d,0x0000000c,0x000002b4, + 0x000002b3,0x0006000c,0x00000007,0x000002b5,0x00000001,0x00000040,0x000002b4,0x0003003e, + 0x00000292,0x000002b5,0x00050041,0x0000000d,0x000002b6,0x00000241,0x00000029,0x0004003d, + 0x0000000c,0x000002b7,0x000002b6,0x00050041,0x00000048,0x000002b8,0x00000292,0x000002b7, + 0x0004003d,0x00000006,0x000002b9,0x000002b8,0x00050041,0x00000048,0x000002ba,0x0000028c, + 0x00000029,0x0003003e,0x000002ba,0x000002b9,0x00050041,0x0000000d,0x000002bc,0x0000013e, + 0x0000002c,0x0004003d,0x0000000c,0x000002bd,0x000002bc,0x00060041,0x000000b9,0x000002be, + 0x00000265,0x00000051,0x000002bd,0x0004003d,0x0000000c,0x000002bf,0x000002be,0x0006000c, + 0x00000007,0x000002c0,0x00000001,0x00000040,0x000002bf,0x0003003e,0x000002bb,0x000002c0, + 0x00050041,0x0000000d,0x000002c1,0x00000235,0x0000002c,0x0004003d,0x0000000c,0x000002c2, + 0x000002c1,0x00050041,0x00000048,0x000002c3,0x000002bb,0x000002c2,0x0004003d,0x00000006, + 0x000002c4,0x000002c3,0x00050041,0x00000048,0x000002c5,0x0000026b,0x0000002c,0x0003003e, + 0x000002c5,0x000002c4,0x00050041,0x0000000d,0x000002c6,0x00000146,0x0000002c,0x0004003d, + 0x0000000c,0x000002c7,0x000002c6,0x00060041,0x000000b9,0x000002c8,0x00000265,0x00000051, + 0x000002c7,0x0004003d,0x0000000c,0x000002c9,0x000002c8,0x0006000c,0x00000007,0x000002ca, + 0x00000001,0x00000040,0x000002c9,0x0003003e,0x000002bb,0x000002ca,0x00050041,0x0000000d, + 0x000002cb,0x00000239,0x0000002c,0x0004003d,0x0000000c,0x000002cc,0x000002cb,0x00050041, + 0x00000048,0x000002cd,0x000002bb,0x000002cc,0x0004003d,0x00000006,0x000002ce,0x000002cd, + 0x00050041,0x00000048,0x000002cf,0x00000276,0x0000002c,0x0003003e,0x000002cf,0x000002ce, + 0x00050041,0x0000000d,0x000002d0,0x0000014e,0x0000002c,0x0004003d,0x0000000c,0x000002d1, + 0x000002d0,0x00060041,0x000000b9,0x000002d2,0x00000265,0x00000051,0x000002d1,0x0004003d, + 0x0000000c,0x000002d3,0x000002d2,0x0006000c,0x00000007,0x000002d4,0x00000001,0x00000040, + 0x000002d3,0x0003003e,0x000002bb,0x000002d4,0x00050041,0x0000000d,0x000002d5,0x0000023d, + 0x0000002c,0x0004003d,0x0000000c,0x000002d6,0x000002d5,0x00050041,0x00000048,0x000002d7, + 0x000002bb,0x000002d6,0x0004003d,0x00000006,0x000002d8,0x000002d7,0x00050041,0x00000048, + 0x000002d9,0x00000281,0x0000002c,0x0003003e,0x000002d9,0x000002d8,0x00050041,0x0000000d, + 0x000002da,0x00000156,0x0000002c,0x0004003d,0x0000000c,0x000002db,0x000002da,0x00060041, + 0x000000b9,0x000002dc,0x00000265,0x00000051,0x000002db,0x0004003d,0x0000000c,0x000002dd, + 0x000002dc,0x0006000c,0x00000007,0x000002de,0x00000001,0x00000040,0x000002dd,0x0003003e, + 0x000002bb,0x000002de,0x00050041,0x0000000d,0x000002df,0x00000241,0x0000002c,0x0004003d, + 0x0000000c,0x000002e0,0x000002df,0x00050041,0x00000048,0x000002e1,0x000002bb,0x000002e0, + 0x0004003d,0x00000006,0x000002e2,0x000002e1,0x00050041,0x00000048,0x000002e3,0x0000028c, + 0x0000002c,0x0003003e,0x000002e3,0x000002e2,0x00050041,0x0000000d,0x000002e6,0x0000013e, + 0x000002e5,0x0004003d,0x0000000c,0x000002e7,0x000002e6,0x00060041,0x000000b9,0x000002e8, + 0x00000265,0x00000051,0x000002e7,0x0004003d,0x0000000c,0x000002e9,0x000002e8,0x0006000c, + 0x00000007,0x000002ea,0x00000001,0x00000040,0x000002e9,0x0003003e,0x000002e4,0x000002ea, + 0x00050041,0x0000000d,0x000002eb,0x00000235,0x000002e5,0x0004003d,0x0000000c,0x000002ec, + 0x000002eb,0x00050041,0x00000048,0x000002ed,0x000002e4,0x000002ec,0x0004003d,0x00000006, + 0x000002ee,0x000002ed,0x00050041,0x00000048,0x000002ef,0x0000026b,0x000002e5,0x0003003e, + 0x000002ef,0x000002ee,0x00050041,0x0000000d,0x000002f0,0x00000146,0x000002e5,0x0004003d, + 0x0000000c,0x000002f1,0x000002f0,0x00060041,0x000000b9,0x000002f2,0x00000265,0x00000051, + 0x000002f1,0x0004003d,0x0000000c,0x000002f3,0x000002f2,0x0006000c,0x00000007,0x000002f4, + 0x00000001,0x00000040,0x000002f3,0x0003003e,0x000002e4,0x000002f4,0x00050041,0x0000000d, + 0x000002f5,0x00000239,0x000002e5,0x0004003d,0x0000000c,0x000002f6,0x000002f5,0x00050041, + 0x00000048,0x000002f7,0x000002e4,0x000002f6,0x0004003d,0x00000006,0x000002f8,0x000002f7, + 0x00050041,0x00000048,0x000002f9,0x00000276,0x000002e5,0x0003003e,0x000002f9,0x000002f8, + 0x00050041,0x0000000d,0x000002fa,0x0000014e,0x000002e5,0x0004003d,0x0000000c,0x000002fb, + 0x000002fa,0x00060041,0x000000b9,0x000002fc,0x00000265,0x00000051,0x000002fb,0x0004003d, + 0x0000000c,0x000002fd,0x000002fc,0x0006000c,0x00000007,0x000002fe,0x00000001,0x00000040, + 0x000002fd,0x0003003e,0x000002e4,0x000002fe,0x00050041,0x0000000d,0x000002ff,0x0000023d, + 0x000002e5,0x0004003d,0x0000000c,0x00000300,0x000002ff,0x00050041,0x00000048,0x00000301, + 0x000002e4,0x00000300,0x0004003d,0x00000006,0x00000302,0x00000301,0x00050041,0x00000048, + 0x00000303,0x00000281,0x000002e5,0x0003003e,0x00000303,0x00000302,0x00050041,0x0000000d, + 0x00000304,0x00000156,0x000002e5,0x0004003d,0x0000000c,0x00000305,0x00000304,0x00060041, + 0x000000b9,0x00000306,0x00000265,0x00000051,0x00000305,0x0004003d,0x0000000c,0x00000307, + 0x00000306,0x0006000c,0x00000007,0x00000308,0x00000001,0x00000040,0x00000307,0x0003003e, + 0x000002e4,0x00000308,0x00050041,0x0000000d,0x00000309,0x00000241,0x000002e5,0x0004003d, + 0x0000000c,0x0000030a,0x00000309,0x00050041,0x00000048,0x0000030b,0x000002e4,0x0000030a, + 0x0004003d,0x00000006,0x0000030c,0x0000030b,0x00050041,0x00000048,0x0000030d,0x0000028c, + 0x000002e5,0x0003003e,0x0000030d,0x0000030c,0x0004003d,0x00000007,0x0000030f,0x0000026b, + 0x0004003d,0x00000007,0x00000310,0x00000126,0x00050085,0x00000007,0x00000311,0x0000030f, + 0x00000310,0x0004003d,0x00000007,0x00000312,0x00000276,0x0004003d,0x00000007,0x00000313, + 0x0000012e,0x00050085,0x00000007,0x00000314,0x00000312,0x00000313,0x00050081,0x00000007, + 0x00000315,0x00000311,0x00000314,0x0004003d,0x00000007,0x00000316,0x00000281,0x0004003d, + 0x00000007,0x00000317,0x00000134,0x00050085,0x00000007,0x00000318,0x00000316,0x00000317, + 0x00050081,0x00000007,0x00000319,0x00000315,0x00000318,0x0004003d,0x00000007,0x0000031a, + 0x0000028c,0x0004003d,0x00000007,0x0000031b,0x0000013a,0x00050085,0x00000007,0x0000031c, + 0x0000031a,0x0000031b,0x00050081,0x00000007,0x0000031d,0x00000319,0x0000031c,0x0003003e, + 0x0000030e,0x0000031d,0x0004003d,0x00000007,0x0000031e,0x0000030e,0x0004003d,0x0000000a, + 0x0000031f,0x00000013,0x000400a8,0x0000000a,0x00000320,0x0000031f,0x000600a9,0x00000007, + 0x00000323,0x00000320,0x00000322,0x00000321,0x00050085,0x00000007,0x00000324,0x0000031e, + 0x00000323,0x0006000c,0x0000000c,0x00000325,0x00000001,0x00000037,0x00000324,0x0003003e, + 0x00000014,0x00000325,0x000100fd,0x00010038,0x00050036,0x00000002,0x0000001e,0x00000000, + 0x00000019,0x00030037,0x00000018,0x0000001a,0x00030037,0x00000018,0x0000001b,0x00030037, + 0x0000000b,0x0000001c,0x00030037,0x0000000d,0x0000001d,0x000200f8,0x0000001f,0x0004003b, + 0x00000327,0x00000328,0x00000007,0x0004003b,0x00000327,0x0000032b,0x00000007,0x0004003b, + 0x00000327,0x0000032e,0x00000007,0x0004003b,0x00000327,0x00000332,0x00000007,0x0004003b, + 0x00000327,0x00000334,0x00000007,0x0004003b,0x00000327,0x00000336,0x00000007,0x0004003b, + 0x00000327,0x0000033a,0x00000007,0x0004003b,0x00000327,0x0000033c,0x00000007,0x0004003b, + 0x00000018,0x0000033e,0x00000007,0x0004003b,0x00000018,0x00000341,0x00000007,0x0004003b, + 0x00000018,0x00000344,0x00000007,0x0004003b,0x00000018,0x0000034c,0x00000007,0x0004003b, + 0x00000018,0x00000352,0x00000007,0x0004003b,0x00000018,0x00000358,0x00000007,0x0004003b, + 0x00000327,0x0000035c,0x00000007,0x0004003b,0x00000327,0x00000360,0x00000007,0x0004003b, + 0x00000327,0x00000364,0x00000007,0x0004003b,0x00000327,0x00000368,0x00000007,0x0004003b, + 0x00000327,0x0000036c,0x00000007,0x0004003b,0x00000327,0x00000372,0x00000007,0x0004003b, + 0x00000327,0x00000378,0x00000007,0x0004003b,0x00000327,0x0000037e,0x00000007,0x0004003b, + 0x00000327,0x00000384,0x00000007,0x0004003b,0x00000327,0x0000038c,0x00000007,0x0004003b, + 0x00000327,0x00000394,0x00000007,0x0004003b,0x00000327,0x0000039c,0x00000007,0x0004003b, + 0x00000008,0x000003a4,0x00000007,0x0004003b,0x00000008,0x000003ae,0x00000007,0x0004003b, + 0x00000018,0x000003b2,0x00000007,0x0004003b,0x00000008,0x000003c2,0x00000007,0x0004003b, + 0x00000018,0x000003c6,0x00000007,0x0004003b,0x00000008,0x000003d6,0x00000007,0x0004003b, + 0x00000018,0x000003da,0x00000007,0x0004003b,0x00000008,0x000003ea,0x00000007,0x0004003b, + 0x00000018,0x000003ee,0x00000007,0x0004003b,0x00000018,0x00000401,0x00000007,0x0004003b, + 0x00000018,0x00000414,0x00000007,0x0004003b,0x00000018,0x00000427,0x00000007,0x0004003b, + 0x00000018,0x0000043a,0x00000007,0x0004003b,0x00000008,0x00000445,0x00000007,0x0004003d, + 0x00000017,0x00000329,0x0000001a,0x0004006d,0x00000326,0x0000032a,0x00000329,0x0003003e, + 0x00000328,0x0000032a,0x0004003d,0x00000017,0x0000032c,0x0000001b,0x0004006d,0x00000326, + 0x0000032d,0x0000032c,0x0003003e,0x0000032b,0x0000032d,0x0004003d,0x00000326,0x0000032f, + 0x00000328,0x00050050,0x00000326,0x00000330,0x00000029,0x00000029,0x00050080,0x00000326, + 0x00000331,0x0000032f,0x00000330,0x0003003e,0x0000032e,0x00000331,0x0004003d,0x00000326, + 0x00000333,0x0000032b,0x0003003e,0x00000332,0x00000333,0x0004003d,0x00000326,0x00000335, + 0x00000328,0x0003003e,0x00000334,0x00000335,0x0004003d,0x00000326,0x00000337,0x0000032b, + 0x00050050,0x00000326,0x00000338,0x00000029,0x00000029,0x00050080,0x00000326,0x00000339, + 0x00000337,0x00000338,0x0003003e,0x00000336,0x00000339,0x0004003d,0x00000326,0x0000033b, + 0x0000032e,0x0003003e,0x0000033a,0x0000033b,0x0004003d,0x00000326,0x0000033d,0x00000336, + 0x0003003e,0x0000033c,0x0000033d,0x0004003d,0x00000017,0x0000033f,0x0000001a,0x0006000c, + 0x00000017,0x00000340,0x00000001,0x0000000a,0x0000033f,0x0003003e,0x0000033e,0x00000340, + 0x0004003d,0x00000017,0x00000342,0x0000001b,0x0006000c,0x00000017,0x00000343,0x00000001, + 0x0000000a,0x00000342,0x0003003e,0x00000341,0x00000343,0x0004003d,0x00000017,0x00000345, + 0x0000033e,0x00050050,0x00000017,0x00000346,0x00000040,0x00000040,0x00050083,0x00000017, + 0x00000347,0x00000346,0x00000345,0x0004003d,0x00000017,0x00000348,0x00000341,0x00050050, + 0x00000017,0x00000349,0x00000040,0x00000040,0x00050083,0x00000017,0x0000034a,0x00000349, + 0x00000348,0x00050085,0x00000017,0x0000034b,0x00000347,0x0000034a,0x0003003e,0x00000344, + 0x0000034b,0x0004003d,0x00000017,0x0000034d,0x0000033e,0x0004003d,0x00000017,0x0000034e, + 0x00000341,0x00050050,0x00000017,0x0000034f,0x00000040,0x00000040,0x00050083,0x00000017, + 0x00000350,0x0000034f,0x0000034e,0x00050085,0x00000017,0x00000351,0x0000034d,0x00000350, + 0x0003003e,0x0000034c,0x00000351,0x0004003d,0x00000017,0x00000353,0x0000033e,0x00050050, + 0x00000017,0x00000354,0x00000040,0x00000040,0x00050083,0x00000017,0x00000355,0x00000354, + 0x00000353,0x0004003d,0x00000017,0x00000356,0x00000341,0x00050085,0x00000017,0x00000357, + 0x00000355,0x00000356,0x0003003e,0x00000352,0x00000357,0x0004003d,0x00000017,0x00000359, + 0x0000033e,0x0004003d,0x00000017,0x0000035a,0x00000341,0x00050085,0x00000017,0x0000035b, + 0x00000359,0x0000035a,0x0003003e,0x00000358,0x0000035b,0x0004003d,0x00000326,0x0000035d, + 0x00000328,0x00050050,0x00000326,0x0000035e,0x0000002f,0x0000002f,0x00050086,0x00000326, + 0x0000035f,0x0000035d,0x0000035e,0x0003003e,0x0000035c,0x0000035f,0x0004003d,0x00000326, + 0x00000361,0x0000032e,0x00050050,0x00000326,0x00000362,0x0000002f,0x0000002f,0x00050086, + 0x00000326,0x00000363,0x00000361,0x00000362,0x0003003e,0x00000360,0x00000363,0x0004003d, + 0x00000326,0x00000365,0x00000334,0x00050050,0x00000326,0x00000366,0x0000002f,0x0000002f, + 0x00050086,0x00000326,0x00000367,0x00000365,0x00000366,0x0003003e,0x00000364,0x00000367, + 0x0004003d,0x00000326,0x00000369,0x0000033a,0x00050050,0x00000326,0x0000036a,0x0000002f, + 0x0000002f,0x00050086,0x00000326,0x0000036b,0x00000369,0x0000036a,0x0003003e,0x00000368, + 0x0000036b,0x0004003d,0x00000326,0x0000036d,0x00000328,0x00050050,0x00000326,0x0000036e, + 0x0000002f,0x0000002f,0x00050089,0x00000326,0x0000036f,0x0000036d,0x0000036e,0x00050050, + 0x00000326,0x00000370,0x0000002c,0x0000002c,0x00050086,0x00000326,0x00000371,0x0000036f, + 0x00000370,0x0003003e,0x0000036c,0x00000371,0x0004003d,0x00000326,0x00000373,0x0000032e, + 0x00050050,0x00000326,0x00000374,0x0000002f,0x0000002f,0x00050089,0x00000326,0x00000375, + 0x00000373,0x00000374,0x00050050,0x00000326,0x00000376,0x0000002c,0x0000002c,0x00050086, + 0x00000326,0x00000377,0x00000375,0x00000376,0x0003003e,0x00000372,0x00000377,0x0004003d, + 0x00000326,0x00000379,0x00000334,0x00050050,0x00000326,0x0000037a,0x0000002f,0x0000002f, + 0x00050089,0x00000326,0x0000037b,0x00000379,0x0000037a,0x00050050,0x00000326,0x0000037c, + 0x0000002c,0x0000002c,0x00050086,0x00000326,0x0000037d,0x0000037b,0x0000037c,0x0003003e, + 0x00000378,0x0000037d,0x0004003d,0x00000326,0x0000037f,0x0000033a,0x00050050,0x00000326, + 0x00000380,0x0000002f,0x0000002f,0x00050089,0x00000326,0x00000381,0x0000037f,0x00000380, + 0x00050050,0x00000326,0x00000382,0x0000002c,0x0000002c,0x00050086,0x00000326,0x00000383, + 0x00000381,0x00000382,0x0003003e,0x0000037e,0x00000383,0x0004003d,0x00000326,0x00000385, + 0x0000032b,0x00050041,0x00000037,0x00000386,0x00000034,0x00000051,0x0004003d,0x0000000c, + 0x00000387,0x00000386,0x00050050,0x00000326,0x00000388,0x00000387,0x00000387,0x00050084, + 0x00000326,0x00000389,0x00000385,0x00000388,0x0004003d,0x00000326,0x0000038a,0x0000035c, + 0x00050080,0x00000326,0x0000038b,0x00000389,0x0000038a,0x0003003e,0x00000384,0x0000038b, + 0x0004003d,0x00000326,0x0000038d,0x00000332,0x00050041,0x00000037,0x0000038e,0x00000034, + 0x00000051,0x0004003d,0x0000000c,0x0000038f,0x0000038e,0x00050050,0x00000326,0x00000390, + 0x0000038f,0x0000038f,0x00050084,0x00000326,0x00000391,0x0000038d,0x00000390,0x0004003d, + 0x00000326,0x00000392,0x00000360,0x00050080,0x00000326,0x00000393,0x00000391,0x00000392, + 0x0003003e,0x0000038c,0x00000393,0x0004003d,0x00000326,0x00000395,0x00000336,0x00050041, + 0x00000037,0x00000396,0x00000034,0x00000051,0x0004003d,0x0000000c,0x00000397,0x00000396, + 0x00050050,0x00000326,0x00000398,0x00000397,0x00000397,0x00050084,0x00000326,0x00000399, + 0x00000395,0x00000398,0x0004003d,0x00000326,0x0000039a,0x00000364,0x00050080,0x00000326, + 0x0000039b,0x00000399,0x0000039a,0x0003003e,0x00000394,0x0000039b,0x0004003d,0x00000326, + 0x0000039d,0x0000033c,0x00050041,0x00000037,0x0000039e,0x00000034,0x00000051,0x0004003d, + 0x0000000c,0x0000039f,0x0000039e,0x00050050,0x00000326,0x000003a0,0x0000039f,0x0000039f, + 0x00050084,0x00000326,0x000003a1,0x0000039d,0x000003a0,0x0004003d,0x00000326,0x000003a2, + 0x00000368,0x00050080,0x00000326,0x000003a3,0x000003a1,0x000003a2,0x0003003e,0x0000039c, + 0x000003a3,0x00050041,0x0000000d,0x000003a9,0x00000384,0x00000024,0x0004003d,0x0000000c, + 0x000003aa,0x000003a9,0x00060041,0x000000b9,0x000003ab,0x000003a8,0x00000051,0x000003aa, + 0x0004003d,0x0000000c,0x000003ac,0x000003ab,0x0006000c,0x00000007,0x000003ad,0x00000001, + 0x00000040,0x000003ac,0x0003003e,0x000003a4,0x000003ad,0x00050041,0x0000000d,0x000003af, + 0x0000036c,0x00000024,0x0004003d,0x0000000c,0x000003b0,0x000003af,0x000500aa,0x00000009, + 0x000003b1,0x000003b0,0x00000024,0x000300f7,0x000003b4,0x00000000,0x000400fa,0x000003b1, + 0x000003b3,0x000003b7,0x000200f8,0x000003b3,0x0004003d,0x00000007,0x000003b5,0x000003a4, + 0x0007004f,0x00000017,0x000003b6,0x000003b5,0x000003b5,0x00000000,0x00000001,0x0003003e, + 0x000003b2,0x000003b6,0x000200f9,0x000003b4,0x000200f8,0x000003b7,0x0004003d,0x00000007, + 0x000003b8,0x000003a4,0x0007004f,0x00000017,0x000003b9,0x000003b8,0x000003b8,0x00000002, + 0x00000003,0x0003003e,0x000003b2,0x000003b9,0x000200f9,0x000003b4,0x000200f8,0x000003b4, + 0x0004003d,0x00000017,0x000003ba,0x000003b2,0x0004003d,0x00000007,0x000003bb,0x000003ae, + 0x0009004f,0x00000007,0x000003bc,0x000003bb,0x000003ba,0x00000004,0x00000005,0x00000002, + 0x00000003,0x0003003e,0x000003ae,0x000003bc,0x00050041,0x0000000d,0x000003bd,0x0000038c, + 0x00000024,0x0004003d,0x0000000c,0x000003be,0x000003bd,0x00060041,0x000000b9,0x000003bf, + 0x000003a8,0x00000051,0x000003be,0x0004003d,0x0000000c,0x000003c0,0x000003bf,0x0006000c, + 0x00000007,0x000003c1,0x00000001,0x00000040,0x000003c0,0x0003003e,0x000003a4,0x000003c1, + 0x00050041,0x0000000d,0x000003c3,0x00000372,0x00000024,0x0004003d,0x0000000c,0x000003c4, + 0x000003c3,0x000500aa,0x00000009,0x000003c5,0x000003c4,0x00000024,0x000300f7,0x000003c8, + 0x00000000,0x000400fa,0x000003c5,0x000003c7,0x000003cb,0x000200f8,0x000003c7,0x0004003d, + 0x00000007,0x000003c9,0x000003a4,0x0007004f,0x00000017,0x000003ca,0x000003c9,0x000003c9, + 0x00000000,0x00000001,0x0003003e,0x000003c6,0x000003ca,0x000200f9,0x000003c8,0x000200f8, + 0x000003cb,0x0004003d,0x00000007,0x000003cc,0x000003a4,0x0007004f,0x00000017,0x000003cd, + 0x000003cc,0x000003cc,0x00000002,0x00000003,0x0003003e,0x000003c6,0x000003cd,0x000200f9, + 0x000003c8,0x000200f8,0x000003c8,0x0004003d,0x00000017,0x000003ce,0x000003c6,0x0004003d, + 0x00000007,0x000003cf,0x000003c2,0x0009004f,0x00000007,0x000003d0,0x000003cf,0x000003ce, + 0x00000004,0x00000005,0x00000002,0x00000003,0x0003003e,0x000003c2,0x000003d0,0x00050041, + 0x0000000d,0x000003d1,0x00000394,0x00000024,0x0004003d,0x0000000c,0x000003d2,0x000003d1, + 0x00060041,0x000000b9,0x000003d3,0x000003a8,0x00000051,0x000003d2,0x0004003d,0x0000000c, + 0x000003d4,0x000003d3,0x0006000c,0x00000007,0x000003d5,0x00000001,0x00000040,0x000003d4, + 0x0003003e,0x000003a4,0x000003d5,0x00050041,0x0000000d,0x000003d7,0x00000378,0x00000024, + 0x0004003d,0x0000000c,0x000003d8,0x000003d7,0x000500aa,0x00000009,0x000003d9,0x000003d8, + 0x00000024,0x000300f7,0x000003dc,0x00000000,0x000400fa,0x000003d9,0x000003db,0x000003df, + 0x000200f8,0x000003db,0x0004003d,0x00000007,0x000003dd,0x000003a4,0x0007004f,0x00000017, + 0x000003de,0x000003dd,0x000003dd,0x00000000,0x00000001,0x0003003e,0x000003da,0x000003de, + 0x000200f9,0x000003dc,0x000200f8,0x000003df,0x0004003d,0x00000007,0x000003e0,0x000003a4, + 0x0007004f,0x00000017,0x000003e1,0x000003e0,0x000003e0,0x00000002,0x00000003,0x0003003e, + 0x000003da,0x000003e1,0x000200f9,0x000003dc,0x000200f8,0x000003dc,0x0004003d,0x00000017, + 0x000003e2,0x000003da,0x0004003d,0x00000007,0x000003e3,0x000003d6,0x0009004f,0x00000007, + 0x000003e4,0x000003e3,0x000003e2,0x00000004,0x00000005,0x00000002,0x00000003,0x0003003e, + 0x000003d6,0x000003e4,0x00050041,0x0000000d,0x000003e5,0x0000039c,0x00000024,0x0004003d, + 0x0000000c,0x000003e6,0x000003e5,0x00060041,0x000000b9,0x000003e7,0x000003a8,0x00000051, + 0x000003e6,0x0004003d,0x0000000c,0x000003e8,0x000003e7,0x0006000c,0x00000007,0x000003e9, + 0x00000001,0x00000040,0x000003e8,0x0003003e,0x000003a4,0x000003e9,0x00050041,0x0000000d, + 0x000003eb,0x0000037e,0x00000024,0x0004003d,0x0000000c,0x000003ec,0x000003eb,0x000500aa, + 0x00000009,0x000003ed,0x000003ec,0x00000024,0x000300f7,0x000003f0,0x00000000,0x000400fa, + 0x000003ed,0x000003ef,0x000003f3,0x000200f8,0x000003ef,0x0004003d,0x00000007,0x000003f1, + 0x000003a4,0x0007004f,0x00000017,0x000003f2,0x000003f1,0x000003f1,0x00000000,0x00000001, + 0x0003003e,0x000003ee,0x000003f2,0x000200f9,0x000003f0,0x000200f8,0x000003f3,0x0004003d, + 0x00000007,0x000003f4,0x000003a4,0x0007004f,0x00000017,0x000003f5,0x000003f4,0x000003f4, + 0x00000002,0x00000003,0x0003003e,0x000003ee,0x000003f5,0x000200f9,0x000003f0,0x000200f8, + 0x000003f0,0x0004003d,0x00000017,0x000003f6,0x000003ee,0x0004003d,0x00000007,0x000003f7, + 0x000003ea,0x0009004f,0x00000007,0x000003f8,0x000003f7,0x000003f6,0x00000004,0x00000005, + 0x00000002,0x00000003,0x0003003e,0x000003ea,0x000003f8,0x00050041,0x0000000d,0x000003f9, + 0x00000384,0x00000029,0x0004003d,0x0000000c,0x000003fa,0x000003f9,0x00060041,0x000000b9, + 0x000003fb,0x000003a8,0x00000051,0x000003fa,0x0004003d,0x0000000c,0x000003fc,0x000003fb, + 0x0006000c,0x00000007,0x000003fd,0x00000001,0x00000040,0x000003fc,0x0003003e,0x000003a4, + 0x000003fd,0x00050041,0x0000000d,0x000003fe,0x0000036c,0x00000029,0x0004003d,0x0000000c, + 0x000003ff,0x000003fe,0x000500aa,0x00000009,0x00000400,0x000003ff,0x00000024,0x000300f7, + 0x00000403,0x00000000,0x000400fa,0x00000400,0x00000402,0x00000406,0x000200f8,0x00000402, + 0x0004003d,0x00000007,0x00000404,0x000003a4,0x0007004f,0x00000017,0x00000405,0x00000404, + 0x00000404,0x00000000,0x00000001,0x0003003e,0x00000401,0x00000405,0x000200f9,0x00000403, + 0x000200f8,0x00000406,0x0004003d,0x00000007,0x00000407,0x000003a4,0x0007004f,0x00000017, + 0x00000408,0x00000407,0x00000407,0x00000002,0x00000003,0x0003003e,0x00000401,0x00000408, + 0x000200f9,0x00000403,0x000200f8,0x00000403,0x0004003d,0x00000017,0x00000409,0x00000401, + 0x0004003d,0x00000007,0x0000040a,0x000003ae,0x0009004f,0x00000007,0x0000040b,0x0000040a, + 0x00000409,0x00000000,0x00000001,0x00000004,0x00000005,0x0003003e,0x000003ae,0x0000040b, + 0x00050041,0x0000000d,0x0000040c,0x0000038c,0x00000029,0x0004003d,0x0000000c,0x0000040d, + 0x0000040c,0x00060041,0x000000b9,0x0000040e,0x000003a8,0x00000051,0x0000040d,0x0004003d, + 0x0000000c,0x0000040f,0x0000040e,0x0006000c,0x00000007,0x00000410,0x00000001,0x00000040, + 0x0000040f,0x0003003e,0x000003a4,0x00000410,0x00050041,0x0000000d,0x00000411,0x00000372, + 0x00000029,0x0004003d,0x0000000c,0x00000412,0x00000411,0x000500aa,0x00000009,0x00000413, + 0x00000412,0x00000024,0x000300f7,0x00000416,0x00000000,0x000400fa,0x00000413,0x00000415, + 0x00000419,0x000200f8,0x00000415,0x0004003d,0x00000007,0x00000417,0x000003a4,0x0007004f, + 0x00000017,0x00000418,0x00000417,0x00000417,0x00000000,0x00000001,0x0003003e,0x00000414, + 0x00000418,0x000200f9,0x00000416,0x000200f8,0x00000419,0x0004003d,0x00000007,0x0000041a, + 0x000003a4,0x0007004f,0x00000017,0x0000041b,0x0000041a,0x0000041a,0x00000002,0x00000003, + 0x0003003e,0x00000414,0x0000041b,0x000200f9,0x00000416,0x000200f8,0x00000416,0x0004003d, + 0x00000017,0x0000041c,0x00000414,0x0004003d,0x00000007,0x0000041d,0x000003c2,0x0009004f, + 0x00000007,0x0000041e,0x0000041d,0x0000041c,0x00000000,0x00000001,0x00000004,0x00000005, + 0x0003003e,0x000003c2,0x0000041e,0x00050041,0x0000000d,0x0000041f,0x00000394,0x00000029, + 0x0004003d,0x0000000c,0x00000420,0x0000041f,0x00060041,0x000000b9,0x00000421,0x000003a8, + 0x00000051,0x00000420,0x0004003d,0x0000000c,0x00000422,0x00000421,0x0006000c,0x00000007, + 0x00000423,0x00000001,0x00000040,0x00000422,0x0003003e,0x000003a4,0x00000423,0x00050041, + 0x0000000d,0x00000424,0x00000378,0x00000029,0x0004003d,0x0000000c,0x00000425,0x00000424, + 0x000500aa,0x00000009,0x00000426,0x00000425,0x00000024,0x000300f7,0x00000429,0x00000000, + 0x000400fa,0x00000426,0x00000428,0x0000042c,0x000200f8,0x00000428,0x0004003d,0x00000007, + 0x0000042a,0x000003a4,0x0007004f,0x00000017,0x0000042b,0x0000042a,0x0000042a,0x00000000, + 0x00000001,0x0003003e,0x00000427,0x0000042b,0x000200f9,0x00000429,0x000200f8,0x0000042c, + 0x0004003d,0x00000007,0x0000042d,0x000003a4,0x0007004f,0x00000017,0x0000042e,0x0000042d, + 0x0000042d,0x00000002,0x00000003,0x0003003e,0x00000427,0x0000042e,0x000200f9,0x00000429, + 0x000200f8,0x00000429,0x0004003d,0x00000017,0x0000042f,0x00000427,0x0004003d,0x00000007, + 0x00000430,0x000003d6,0x0009004f,0x00000007,0x00000431,0x00000430,0x0000042f,0x00000000, + 0x00000001,0x00000004,0x00000005,0x0003003e,0x000003d6,0x00000431,0x00050041,0x0000000d, + 0x00000432,0x0000039c,0x00000029,0x0004003d,0x0000000c,0x00000433,0x00000432,0x00060041, + 0x000000b9,0x00000434,0x000003a8,0x00000051,0x00000433,0x0004003d,0x0000000c,0x00000435, + 0x00000434,0x0006000c,0x00000007,0x00000436,0x00000001,0x00000040,0x00000435,0x0003003e, + 0x000003a4,0x00000436,0x00050041,0x0000000d,0x00000437,0x0000037e,0x00000029,0x0004003d, + 0x0000000c,0x00000438,0x00000437,0x000500aa,0x00000009,0x00000439,0x00000438,0x00000024, + 0x000300f7,0x0000043c,0x00000000,0x000400fa,0x00000439,0x0000043b,0x0000043f,0x000200f8, + 0x0000043b,0x0004003d,0x00000007,0x0000043d,0x000003a4,0x0007004f,0x00000017,0x0000043e, + 0x0000043d,0x0000043d,0x00000000,0x00000001,0x0003003e,0x0000043a,0x0000043e,0x000200f9, + 0x0000043c,0x000200f8,0x0000043f,0x0004003d,0x00000007,0x00000440,0x000003a4,0x0007004f, + 0x00000017,0x00000441,0x00000440,0x00000440,0x00000002,0x00000003,0x0003003e,0x0000043a, + 0x00000441,0x000200f9,0x0000043c,0x000200f8,0x0000043c,0x0004003d,0x00000017,0x00000442, + 0x0000043a,0x0004003d,0x00000007,0x00000443,0x000003ea,0x0009004f,0x00000007,0x00000444, + 0x00000443,0x00000442,0x00000000,0x00000001,0x00000004,0x00000005,0x0003003e,0x000003ea, + 0x00000444,0x0004003d,0x00000007,0x00000446,0x000003ae,0x0004003d,0x00000017,0x00000447, + 0x00000344,0x0009004f,0x00000007,0x00000448,0x00000447,0x00000447,0x00000000,0x00000000, + 0x00000001,0x00000001,0x00050085,0x00000007,0x00000449,0x00000446,0x00000448,0x0004003d, + 0x00000007,0x0000044a,0x000003c2,0x0004003d,0x00000017,0x0000044b,0x0000034c,0x0009004f, + 0x00000007,0x0000044c,0x0000044b,0x0000044b,0x00000000,0x00000000,0x00000001,0x00000001, + 0x00050085,0x00000007,0x0000044d,0x0000044a,0x0000044c,0x00050081,0x00000007,0x0000044e, + 0x00000449,0x0000044d,0x0004003d,0x00000007,0x0000044f,0x000003d6,0x0004003d,0x00000017, + 0x00000450,0x00000352,0x0009004f,0x00000007,0x00000451,0x00000450,0x00000450,0x00000000, + 0x00000000,0x00000001,0x00000001,0x00050085,0x00000007,0x00000452,0x0000044f,0x00000451, + 0x00050081,0x00000007,0x00000453,0x0000044e,0x00000452,0x0004003d,0x00000007,0x00000454, + 0x000003ea,0x0004003d,0x00000017,0x00000455,0x00000358,0x0009004f,0x00000007,0x00000456, + 0x00000455,0x00000455,0x00000000,0x00000000,0x00000001,0x00000001,0x00050085,0x00000007, + 0x00000457,0x00000454,0x00000456,0x00050081,0x00000007,0x00000458,0x00000453,0x00000457, + 0x0003003e,0x00000445,0x00000458,0x0004003d,0x00000007,0x00000459,0x00000445,0x0004003d, + 0x0000000a,0x0000045a,0x0000001c,0x000400a8,0x0000000a,0x0000045b,0x0000045a,0x000600a9, + 0x00000007,0x0000045c,0x0000045b,0x00000322,0x00000321,0x00050085,0x00000007,0x0000045d, + 0x00000459,0x0000045c,0x0004003d,0x0000000a,0x0000045e,0x0000001c,0x000600a9,0x00000007, + 0x0000045f,0x0000045e,0x00000322,0x00000321,0x0005008e,0x00000007,0x00000460,0x0000045f, + 0x000000c2,0x00050081,0x00000007,0x00000461,0x0000045d,0x00000460,0x0003003e,0x00000445, + 0x00000461,0x0004003d,0x00000007,0x00000462,0x00000445,0x0006000c,0x0000000c,0x00000463, + 0x00000001,0x00000037,0x00000462,0x0003003e,0x0000001d,0x00000463,0x000100fd,0x00010038 diff --git a/shaders/spv/shader_lap_trans_pyr.comp b/shaders/spv/shader_lap_trans_pyr.comp new file mode 100644 index 0000000..a1f29ee --- /dev/null +++ b/shaders/spv/shader_lap_trans_pyr.comp @@ -0,0 +1,162 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer InBufY { + uvec2 data[]; +} in_buf_y; + +layout (binding = 1) readonly buffer InBufUV { + uvec2 data[]; +} in_buf_uv; + +layout (binding = 2) readonly buffer GaussScaleBufY { + uint data[]; +} gaussscale_buf_y; + +layout (binding = 3) readonly buffer GaussScaleBufUV { + uint data[]; +} gaussscale_buf_uv; + +layout (binding = 4) writeonly buffer OutBufY { + uvec2 data[]; +} out_buf_y; + +layout (binding = 5) writeonly buffer OutBufUV { + uvec2 data[]; +} out_buf_uv; + +layout (push_constant) uniform PushConsts { + uint in_img_width; + uint in_img_height; + uint in_offset_x; + uint gaussscale_img_width; + uint gaussscale_img_height; + uint merge_width; +} prop; + +// normalization of half gray level +const float norm_half_gl = 128.0f / 255.0f; + +void lap_trans_y (uvec2 y_id, uvec2 gs_id); +void lap_trans_uv (uvec2 uv_id, uvec2 gs_id); + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + + uvec2 y_id = uvec2 (g_id.x, g_id.y * 4u); + y_id.x = clamp (y_id.x, 0u, prop.merge_width - 1u); + + uvec2 gs_id = uvec2 (g_id.x, g_id.y * 2u); + gs_id.x = clamp (gs_id.x, 0u, prop.gaussscale_img_width - 1u); + lap_trans_y (y_id, gs_id); + + y_id.y += 2u; + gs_id.y += 1u; + lap_trans_y (y_id, gs_id); + + uvec2 uv_id = uvec2 (y_id.x, g_id.y * 2u); + gs_id.y = g_id.y; + lap_trans_uv (uv_id, gs_id); +} + +void lap_trans_y (uvec2 y_id, uvec2 gs_id) +{ + y_id.y = clamp (y_id.y, 0u, prop.in_img_height - 1u); + gs_id.y = clamp (gs_id.y, 0u, prop.gaussscale_img_height - 1u); + + uint y_idx = y_id.y * prop.in_img_width + prop.in_offset_x + y_id.x; + uvec2 in_pack = in_buf_y.data[y_idx]; + vec4 in0 = unpackUnorm4x8 (in_pack.x); + vec4 in1 = unpackUnorm4x8 (in_pack.y); + + uint gs_idx = gs_id.y * prop.gaussscale_img_width + gs_id.x; + vec4 gs0 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx]); + vec4 gs1 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx + 1u]); + gs1 = (gs_id.x == prop.gaussscale_img_width - 1u) ? gs0.wwww : gs1; + + vec4 inter = (gs0 + vec4 (gs0.yzw, gs1.x)) * 0.5f; + vec4 inter00 = vec4 (gs0.x, inter.x, gs0.y, inter.y); + vec4 inter01 = vec4 (gs0.z, inter.z, gs0.w, inter.w); + + vec4 lap0 = (in0 - inter00) * 0.5f + norm_half_gl; + vec4 lap1 = (in1 - inter01) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + uint out_idx = y_id.y * prop.merge_width + y_id.x; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); + + y_idx = (y_id.y >= prop.in_img_height - 1u) ? y_idx : y_idx + prop.in_img_width; + in_pack = in_buf_y.data[y_idx]; + in0 = unpackUnorm4x8 (in_pack.x); + in1 = unpackUnorm4x8 (in_pack.y); + + gs_idx = (gs_id.y >= prop.gaussscale_img_height - 1u) ? gs_idx : gs_idx + prop.gaussscale_img_width; + gs0 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx]); + gs1 = unpackUnorm4x8 (gaussscale_buf_y.data[gs_idx + 1u]); + gs1 = (gs_id.x == prop.gaussscale_img_width - 1u) ? gs0.wwww : gs1; + + inter = (gs0 + vec4 (gs0.yzw, gs1.x)) * 0.5f; + vec4 inter10 = (inter00 + vec4 (gs0.x, inter.x, gs0.y, inter.y)) * 0.5f; + vec4 inter11 = (inter01 + vec4 (gs0.z, inter.z, gs0.w, inter.w)) * 0.5f; + + lap0 = (in0 - inter10) * 0.5f + norm_half_gl; + lap1 = (in1 - inter11) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + out_idx = (y_id.y >= prop.in_img_height - 1u) ? out_idx : out_idx + prop.merge_width; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); +} + +void lap_trans_uv (uvec2 uv_id, uvec2 gs_id) +{ + uv_id.y = clamp (uv_id.y, 0u, prop.in_img_height / 2u - 1u); + gs_id.y = clamp (gs_id.y, 0u, prop.gaussscale_img_height / 2u - 1u); + + uint uv_idx = uv_id.y * prop.in_img_width + prop.in_offset_x + uv_id.x; + uvec2 in_pack = in_buf_uv.data[uv_idx]; + vec4 in0 = unpackUnorm4x8 (in_pack.x); + vec4 in1 = unpackUnorm4x8 (in_pack.y); + + uint gs_idx = gs_id.y * prop.gaussscale_img_width + gs_id.x; + vec4 gs0 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx]); + vec4 gs1 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx + 1u]); + gs1 = (gs_id.x == prop.gaussscale_img_width - 1u) ? gs0.zwzw : gs1; + + vec4 inter = (gs0 + vec4 (gs0.zw, gs1.xy)) * 0.5f; + vec4 inter00 = vec4 (gs0.xy, inter.xy); + vec4 inter01 = vec4 (gs0.zw, inter.zw); + + vec4 lap0 = (in0 - inter00) * 0.5f + norm_half_gl; + vec4 lap1 = (in1 - inter01) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + uint out_idx = uv_id.y * prop.merge_width + uv_id.x; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); + + uv_idx = (uv_id.y >= (prop.in_img_height / 2u - 1u)) ? uv_idx : uv_idx + prop.in_img_width; + in_pack = in_buf_uv.data[uv_idx]; + in0 = unpackUnorm4x8 (in_pack.x); + in1 = unpackUnorm4x8 (in_pack.y); + + gs_idx = (gs_id.y >= (prop.gaussscale_img_height / 2u - 1u)) ? gs_idx : gs_idx + prop.gaussscale_img_width; + gs0 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx]); + gs1 = unpackUnorm4x8 (gaussscale_buf_uv.data[gs_idx + 1u]); + gs1 = (gs_id.x == prop.gaussscale_img_width - 1u) ? gs0.zwzw : gs1; + + inter = (gs0 + vec4 (gs0.zw, gs1.xy)) * 0.5f; + vec4 inter10 = (inter00 + vec4 (gs0.xy, inter.xy)) * 0.5f; + vec4 inter11 = (inter01 + vec4 (gs0.zw, inter.zw)) * 0.5f; + + lap0 = (in0 - inter10) * 0.5f + norm_half_gl; + lap1 = (in1 - inter11) * 0.5f + norm_half_gl; + lap0 = clamp (lap0, 0.0f, 1.0f); + lap1 = clamp (lap1, 0.0f, 1.0f); + + out_idx += prop.merge_width; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (lap0), packUnorm4x8 (lap1)); +} diff --git a/shaders/spv/shader_lap_trans_pyr.comp.spv b/shaders/spv/shader_lap_trans_pyr.comp.spv new file mode 100644 index 0000000..d137ab2 --- /dev/null +++ b/shaders/spv/shader_lap_trans_pyr.comp.spv @@ -0,0 +1,536 @@ + // 7.8.2870 + 0x07230203,0x00010000,0x00080007,0x000002c3,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000005,0x00000004,0x6e69616d,0x00000000,0x00000015,0x00060010,0x00000004, + 0x00000011,0x00000008,0x00000008,0x00000001,0x00030003,0x00000001,0x00000136,0x00040005, + 0x00000004,0x6e69616d,0x00000000,0x00080005,0x0000000c,0x5f70616c,0x6e617274,0x28795f73, + 0x3b327576,0x3b327576,0x00000000,0x00040005,0x0000000a,0x64695f79,0x00000000,0x00040005, + 0x0000000b,0x695f7367,0x00000064,0x00080005,0x00000010,0x5f70616c,0x6e617274,0x76755f73, + 0x32757628,0x3275763b,0x0000003b,0x00040005,0x0000000e,0x695f7675,0x00000064,0x00040005, + 0x0000000f,0x695f7367,0x00000064,0x00040005,0x00000012,0x64695f67,0x00000000,0x00080005, + 0x00000015,0x475f6c67,0x61626f6c,0x766e496c,0x7461636f,0x496e6f69,0x00000044,0x00040005, + 0x00000018,0x64695f79,0x00000000,0x00050005,0x00000025,0x68737550,0x736e6f43,0x00007374, + 0x00070006,0x00000025,0x00000000,0x695f6e69,0x775f676d,0x68746469,0x00000000,0x00070006, + 0x00000025,0x00000001,0x695f6e69,0x685f676d,0x68676965,0x00000074,0x00060006,0x00000025, + 0x00000002,0x6f5f6e69,0x65736666,0x00785f74,0x00090006,0x00000025,0x00000003,0x73756167, + 0x61637373,0x695f656c,0x775f676d,0x68746469,0x00000000,0x00090006,0x00000025,0x00000004, + 0x73756167,0x61637373,0x695f656c,0x685f676d,0x68676965,0x00000074,0x00060006,0x00000025, + 0x00000005,0x6772656d,0x69775f65,0x00687464,0x00040005,0x00000027,0x706f7270,0x00000000, + 0x00040005,0x00000030,0x695f7367,0x00000064,0x00040005,0x00000040,0x61726170,0x0000006d, + 0x00040005,0x00000042,0x61726170,0x0000006d,0x00040005,0x0000004d,0x61726170,0x0000006d, + 0x00040005,0x0000004f,0x61726170,0x0000006d,0x00040005,0x00000052,0x695f7675,0x00000064, + 0x00040005,0x0000005c,0x61726170,0x0000006d,0x00040005,0x0000005e,0x61726170,0x0000006d, + 0x00040005,0x00000071,0x64695f79,0x00000078,0x00040005,0x0000007f,0x705f6e69,0x006b6361, + 0x00040005,0x00000081,0x75426e49,0x00005966,0x00050006,0x00000081,0x00000000,0x61746164, + 0x00000000,0x00050005,0x00000083,0x625f6e69,0x795f6675,0x00000000,0x00030005,0x0000008b, + 0x00306e69,0x00030005,0x0000008f,0x00316e69,0x00040005,0x00000093,0x695f7367,0x00007864, + 0x00030005,0x0000009c,0x00307367,0x00060005,0x0000009e,0x73756147,0x61635373,0x7542656c, + 0x00005966,0x00050006,0x0000009e,0x00000000,0x61746164,0x00000000,0x00070005,0x000000a0, + 0x73756167,0x61637373,0x625f656c,0x795f6675,0x00000000,0x00030005,0x000000a6,0x00317367, + 0x00040005,0x000000bb,0x65746e69,0x00000072,0x00040005,0x000000ca,0x65746e69,0x00303072, + 0x00040005,0x000000d4,0x65746e69,0x00313072,0x00040005,0x000000df,0x3070616c,0x00000000, + 0x00040005,0x000000e7,0x3170616c,0x00000000,0x00040005,0x000000f8,0x5f74756f,0x00786469, + 0x00040005,0x00000102,0x4274754f,0x00596675,0x00050006,0x00000102,0x00000000,0x61746164, + 0x00000000,0x00050005,0x00000104,0x5f74756f,0x5f667562,0x00000079,0x00040005,0x00000157, + 0x65746e69,0x00303172,0x00040005,0x00000164,0x65746e69,0x00313172,0x00040005,0x000001ac, + 0x695f7675,0x00007864,0x00040005,0x000001b8,0x705f6e69,0x006b6361,0x00040005,0x000001ba, + 0x75426e49,0x00565566,0x00050006,0x000001ba,0x00000000,0x61746164,0x00000000,0x00050005, + 0x000001bc,0x625f6e69,0x755f6675,0x00000076,0x00030005,0x000001c0,0x00306e69,0x00030005, + 0x000001c4,0x00316e69,0x00040005,0x000001c8,0x695f7367,0x00007864,0x00030005,0x000001d1, + 0x00307367,0x00060005,0x000001d3,0x73756147,0x61635373,0x7542656c,0x00565566,0x00050006, + 0x000001d3,0x00000000,0x61746164,0x00000000,0x00070005,0x000001d5,0x73756167,0x61637373, + 0x625f656c,0x755f6675,0x00000076,0x00030005,0x000001da,0x00317367,0x00040005,0x000001ee, + 0x65746e69,0x00000072,0x00040005,0x000001fc,0x65746e69,0x00303072,0x00040005,0x00000206, + 0x65746e69,0x00313072,0x00040005,0x00000210,0x3070616c,0x00000000,0x00040005,0x00000217, + 0x3170616c,0x00000000,0x00040005,0x00000226,0x5f74756f,0x00786469,0x00050005,0x00000230, + 0x4274754f,0x56556675,0x00000000,0x00050006,0x00000230,0x00000000,0x61746164,0x00000000, + 0x00050005,0x00000232,0x5f74756f,0x5f667562,0x00007675,0x00040005,0x00000288,0x65746e69, + 0x00303172,0x00040005,0x00000295,0x65746e69,0x00313172,0x00040047,0x00000015,0x0000000b, + 0x0000001c,0x00050048,0x00000025,0x00000000,0x00000023,0x00000000,0x00050048,0x00000025, + 0x00000001,0x00000023,0x00000004,0x00050048,0x00000025,0x00000002,0x00000023,0x00000008, + 0x00050048,0x00000025,0x00000003,0x00000023,0x0000000c,0x00050048,0x00000025,0x00000004, + 0x00000023,0x00000010,0x00050048,0x00000025,0x00000005,0x00000023,0x00000014,0x00030047, + 0x00000025,0x00000002,0x00040047,0x00000080,0x00000006,0x00000008,0x00040048,0x00000081, + 0x00000000,0x00000018,0x00050048,0x00000081,0x00000000,0x00000023,0x00000000,0x00030047, + 0x00000081,0x00000003,0x00040047,0x00000083,0x00000022,0x00000000,0x00040047,0x00000083, + 0x00000021,0x00000000,0x00040047,0x0000009d,0x00000006,0x00000004,0x00040048,0x0000009e, + 0x00000000,0x00000018,0x00050048,0x0000009e,0x00000000,0x00000023,0x00000000,0x00030047, + 0x0000009e,0x00000003,0x00040047,0x000000a0,0x00000022,0x00000000,0x00040047,0x000000a0, + 0x00000021,0x00000002,0x00040047,0x00000101,0x00000006,0x00000008,0x00040048,0x00000102, + 0x00000000,0x00000019,0x00050048,0x00000102,0x00000000,0x00000023,0x00000000,0x00030047, + 0x00000102,0x00000003,0x00040047,0x00000104,0x00000022,0x00000000,0x00040047,0x00000104, + 0x00000021,0x00000004,0x00040047,0x000001b9,0x00000006,0x00000008,0x00040048,0x000001ba, + 0x00000000,0x00000018,0x00050048,0x000001ba,0x00000000,0x00000023,0x00000000,0x00030047, + 0x000001ba,0x00000003,0x00040047,0x000001bc,0x00000022,0x00000000,0x00040047,0x000001bc, + 0x00000021,0x00000001,0x00040047,0x000001d2,0x00000006,0x00000004,0x00040048,0x000001d3, + 0x00000000,0x00000018,0x00050048,0x000001d3,0x00000000,0x00000023,0x00000000,0x00030047, + 0x000001d3,0x00000003,0x00040047,0x000001d5,0x00000022,0x00000000,0x00040047,0x000001d5, + 0x00000021,0x00000003,0x00040047,0x0000022f,0x00000006,0x00000008,0x00040048,0x00000230, + 0x00000000,0x00000019,0x00050048,0x00000230,0x00000000,0x00000023,0x00000000,0x00030047, + 0x00000230,0x00000003,0x00040047,0x00000232,0x00000022,0x00000000,0x00040047,0x00000232, + 0x00000021,0x00000005,0x00040047,0x000002c2,0x0000000b,0x00000019,0x00020013,0x00000002, + 0x00030021,0x00000003,0x00000002,0x00040015,0x00000006,0x00000020,0x00000000,0x00040017, + 0x00000007,0x00000006,0x00000002,0x00040020,0x00000008,0x00000007,0x00000007,0x00050021, + 0x00000009,0x00000002,0x00000008,0x00000008,0x00040017,0x00000013,0x00000006,0x00000003, + 0x00040020,0x00000014,0x00000001,0x00000013,0x0004003b,0x00000014,0x00000015,0x00000001, + 0x0004002b,0x00000006,0x00000019,0x00000000,0x00040020,0x0000001a,0x00000007,0x00000006, + 0x0004002b,0x00000006,0x0000001d,0x00000001,0x0004002b,0x00000006,0x00000020,0x00000004, + 0x0008001e,0x00000025,0x00000006,0x00000006,0x00000006,0x00000006,0x00000006,0x00000006, + 0x00040020,0x00000026,0x00000009,0x00000025,0x0004003b,0x00000026,0x00000027,0x00000009, + 0x00040015,0x00000028,0x00000020,0x00000001,0x0004002b,0x00000028,0x00000029,0x00000005, + 0x00040020,0x0000002a,0x00000009,0x00000006,0x0004002b,0x00000006,0x00000035,0x00000002, + 0x0004002b,0x00000028,0x0000003a,0x00000003,0x0004002b,0x00000028,0x00000063,0x00000001, + 0x0004002b,0x00000028,0x0000006b,0x00000004,0x0004002b,0x00000028,0x00000074,0x00000000, + 0x0004002b,0x00000028,0x00000078,0x00000002,0x0003001d,0x00000080,0x00000007,0x0003001e, + 0x00000081,0x00000080,0x00040020,0x00000082,0x00000002,0x00000081,0x0004003b,0x00000082, + 0x00000083,0x00000002,0x00040020,0x00000085,0x00000002,0x00000007,0x00030016,0x00000088, + 0x00000020,0x00040017,0x00000089,0x00000088,0x00000004,0x00040020,0x0000008a,0x00000007, + 0x00000089,0x0003001d,0x0000009d,0x00000006,0x0003001e,0x0000009e,0x0000009d,0x00040020, + 0x0000009f,0x00000002,0x0000009e,0x0004003b,0x0000009f,0x000000a0,0x00000002,0x00040020, + 0x000000a2,0x00000002,0x00000006,0x00020014,0x000000b1,0x00040017,0x000000bd,0x00000088, + 0x00000003,0x00040020,0x000000c0,0x00000007,0x00000088,0x0004002b,0x00000088,0x000000c8, + 0x3f000000,0x0004002b,0x00000006,0x000000d9,0x00000003,0x0004002b,0x00000088,0x000000e4, + 0x3f008081,0x0004002b,0x00000088,0x000000ef,0x00000000,0x0004002b,0x00000088,0x000000f0, + 0x3f800000,0x0003001d,0x00000101,0x00000007,0x0003001e,0x00000102,0x00000101,0x00040020, + 0x00000103,0x00000002,0x00000102,0x0004003b,0x00000103,0x00000104,0x00000002,0x0003001d, + 0x000001b9,0x00000007,0x0003001e,0x000001ba,0x000001b9,0x00040020,0x000001bb,0x00000002, + 0x000001ba,0x0004003b,0x000001bb,0x000001bc,0x00000002,0x0003001d,0x000001d2,0x00000006, + 0x0003001e,0x000001d3,0x000001d2,0x00040020,0x000001d4,0x00000002,0x000001d3,0x0004003b, + 0x000001d4,0x000001d5,0x00000002,0x00040017,0x000001f0,0x00000088,0x00000002,0x0003001d, + 0x0000022f,0x00000007,0x0003001e,0x00000230,0x0000022f,0x00040020,0x00000231,0x00000002, + 0x00000230,0x0004003b,0x00000231,0x00000232,0x00000002,0x0004002b,0x00000006,0x000002c1, + 0x00000008,0x0006002c,0x00000013,0x000002c2,0x000002c1,0x000002c1,0x0000001d,0x00050036, + 0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x00000008, + 0x00000012,0x00000007,0x0004003b,0x00000008,0x00000018,0x00000007,0x0004003b,0x00000008, + 0x00000030,0x00000007,0x0004003b,0x00000008,0x00000040,0x00000007,0x0004003b,0x00000008, + 0x00000042,0x00000007,0x0004003b,0x00000008,0x0000004d,0x00000007,0x0004003b,0x00000008, + 0x0000004f,0x00000007,0x0004003b,0x00000008,0x00000052,0x00000007,0x0004003b,0x00000008, + 0x0000005c,0x00000007,0x0004003b,0x00000008,0x0000005e,0x00000007,0x0004003d,0x00000013, + 0x00000016,0x00000015,0x0007004f,0x00000007,0x00000017,0x00000016,0x00000016,0x00000000, + 0x00000001,0x0003003e,0x00000012,0x00000017,0x00050041,0x0000001a,0x0000001b,0x00000012, + 0x00000019,0x0004003d,0x00000006,0x0000001c,0x0000001b,0x00050041,0x0000001a,0x0000001e, + 0x00000012,0x0000001d,0x0004003d,0x00000006,0x0000001f,0x0000001e,0x00050084,0x00000006, + 0x00000021,0x0000001f,0x00000020,0x00050050,0x00000007,0x00000022,0x0000001c,0x00000021, + 0x0003003e,0x00000018,0x00000022,0x00050041,0x0000001a,0x00000023,0x00000018,0x00000019, + 0x0004003d,0x00000006,0x00000024,0x00000023,0x00050041,0x0000002a,0x0000002b,0x00000027, + 0x00000029,0x0004003d,0x00000006,0x0000002c,0x0000002b,0x00050082,0x00000006,0x0000002d, + 0x0000002c,0x0000001d,0x0008000c,0x00000006,0x0000002e,0x00000001,0x0000002c,0x00000024, + 0x00000019,0x0000002d,0x00050041,0x0000001a,0x0000002f,0x00000018,0x00000019,0x0003003e, + 0x0000002f,0x0000002e,0x00050041,0x0000001a,0x00000031,0x00000012,0x00000019,0x0004003d, + 0x00000006,0x00000032,0x00000031,0x00050041,0x0000001a,0x00000033,0x00000012,0x0000001d, + 0x0004003d,0x00000006,0x00000034,0x00000033,0x00050084,0x00000006,0x00000036,0x00000034, + 0x00000035,0x00050050,0x00000007,0x00000037,0x00000032,0x00000036,0x0003003e,0x00000030, + 0x00000037,0x00050041,0x0000001a,0x00000038,0x00000030,0x00000019,0x0004003d,0x00000006, + 0x00000039,0x00000038,0x00050041,0x0000002a,0x0000003b,0x00000027,0x0000003a,0x0004003d, + 0x00000006,0x0000003c,0x0000003b,0x00050082,0x00000006,0x0000003d,0x0000003c,0x0000001d, + 0x0008000c,0x00000006,0x0000003e,0x00000001,0x0000002c,0x00000039,0x00000019,0x0000003d, + 0x00050041,0x0000001a,0x0000003f,0x00000030,0x00000019,0x0003003e,0x0000003f,0x0000003e, + 0x0004003d,0x00000007,0x00000041,0x00000018,0x0003003e,0x00000040,0x00000041,0x0004003d, + 0x00000007,0x00000043,0x00000030,0x0003003e,0x00000042,0x00000043,0x00060039,0x00000002, + 0x00000044,0x0000000c,0x00000040,0x00000042,0x00050041,0x0000001a,0x00000045,0x00000018, + 0x0000001d,0x0004003d,0x00000006,0x00000046,0x00000045,0x00050080,0x00000006,0x00000047, + 0x00000046,0x00000035,0x00050041,0x0000001a,0x00000048,0x00000018,0x0000001d,0x0003003e, + 0x00000048,0x00000047,0x00050041,0x0000001a,0x00000049,0x00000030,0x0000001d,0x0004003d, + 0x00000006,0x0000004a,0x00000049,0x00050080,0x00000006,0x0000004b,0x0000004a,0x0000001d, + 0x00050041,0x0000001a,0x0000004c,0x00000030,0x0000001d,0x0003003e,0x0000004c,0x0000004b, + 0x0004003d,0x00000007,0x0000004e,0x00000018,0x0003003e,0x0000004d,0x0000004e,0x0004003d, + 0x00000007,0x00000050,0x00000030,0x0003003e,0x0000004f,0x00000050,0x00060039,0x00000002, + 0x00000051,0x0000000c,0x0000004d,0x0000004f,0x00050041,0x0000001a,0x00000053,0x00000018, + 0x00000019,0x0004003d,0x00000006,0x00000054,0x00000053,0x00050041,0x0000001a,0x00000055, + 0x00000012,0x0000001d,0x0004003d,0x00000006,0x00000056,0x00000055,0x00050084,0x00000006, + 0x00000057,0x00000056,0x00000035,0x00050050,0x00000007,0x00000058,0x00000054,0x00000057, + 0x0003003e,0x00000052,0x00000058,0x00050041,0x0000001a,0x00000059,0x00000012,0x0000001d, + 0x0004003d,0x00000006,0x0000005a,0x00000059,0x00050041,0x0000001a,0x0000005b,0x00000030, + 0x0000001d,0x0003003e,0x0000005b,0x0000005a,0x0004003d,0x00000007,0x0000005d,0x00000052, + 0x0003003e,0x0000005c,0x0000005d,0x0004003d,0x00000007,0x0000005f,0x00000030,0x0003003e, + 0x0000005e,0x0000005f,0x00060039,0x00000002,0x00000060,0x00000010,0x0000005c,0x0000005e, + 0x000100fd,0x00010038,0x00050036,0x00000002,0x0000000c,0x00000000,0x00000009,0x00030037, + 0x00000008,0x0000000a,0x00030037,0x00000008,0x0000000b,0x000200f8,0x0000000d,0x0004003b, + 0x0000001a,0x00000071,0x00000007,0x0004003b,0x00000008,0x0000007f,0x00000007,0x0004003b, + 0x0000008a,0x0000008b,0x00000007,0x0004003b,0x0000008a,0x0000008f,0x00000007,0x0004003b, + 0x0000001a,0x00000093,0x00000007,0x0004003b,0x0000008a,0x0000009c,0x00000007,0x0004003b, + 0x0000008a,0x000000a6,0x00000007,0x0004003b,0x0000008a,0x000000b3,0x00000007,0x0004003b, + 0x0000008a,0x000000bb,0x00000007,0x0004003b,0x0000008a,0x000000ca,0x00000007,0x0004003b, + 0x0000008a,0x000000d4,0x00000007,0x0004003b,0x0000008a,0x000000df,0x00000007,0x0004003b, + 0x0000008a,0x000000e7,0x00000007,0x0004003b,0x0000001a,0x000000f8,0x00000007,0x0004003b, + 0x0000001a,0x00000112,0x00000007,0x0004003b,0x0000001a,0x0000012b,0x00000007,0x0004003b, + 0x0000008a,0x00000144,0x00000007,0x0004003b,0x0000008a,0x00000157,0x00000007,0x0004003b, + 0x0000008a,0x00000164,0x00000007,0x0004003b,0x0000001a,0x0000018b,0x00000007,0x00050041, + 0x0000001a,0x00000061,0x0000000a,0x0000001d,0x0004003d,0x00000006,0x00000062,0x00000061, + 0x00050041,0x0000002a,0x00000064,0x00000027,0x00000063,0x0004003d,0x00000006,0x00000065, + 0x00000064,0x00050082,0x00000006,0x00000066,0x00000065,0x0000001d,0x0008000c,0x00000006, + 0x00000067,0x00000001,0x0000002c,0x00000062,0x00000019,0x00000066,0x00050041,0x0000001a, + 0x00000068,0x0000000a,0x0000001d,0x0003003e,0x00000068,0x00000067,0x00050041,0x0000001a, + 0x00000069,0x0000000b,0x0000001d,0x0004003d,0x00000006,0x0000006a,0x00000069,0x00050041, + 0x0000002a,0x0000006c,0x00000027,0x0000006b,0x0004003d,0x00000006,0x0000006d,0x0000006c, + 0x00050082,0x00000006,0x0000006e,0x0000006d,0x0000001d,0x0008000c,0x00000006,0x0000006f, + 0x00000001,0x0000002c,0x0000006a,0x00000019,0x0000006e,0x00050041,0x0000001a,0x00000070, + 0x0000000b,0x0000001d,0x0003003e,0x00000070,0x0000006f,0x00050041,0x0000001a,0x00000072, + 0x0000000a,0x0000001d,0x0004003d,0x00000006,0x00000073,0x00000072,0x00050041,0x0000002a, + 0x00000075,0x00000027,0x00000074,0x0004003d,0x00000006,0x00000076,0x00000075,0x00050084, + 0x00000006,0x00000077,0x00000073,0x00000076,0x00050041,0x0000002a,0x00000079,0x00000027, + 0x00000078,0x0004003d,0x00000006,0x0000007a,0x00000079,0x00050080,0x00000006,0x0000007b, + 0x00000077,0x0000007a,0x00050041,0x0000001a,0x0000007c,0x0000000a,0x00000019,0x0004003d, + 0x00000006,0x0000007d,0x0000007c,0x00050080,0x00000006,0x0000007e,0x0000007b,0x0000007d, + 0x0003003e,0x00000071,0x0000007e,0x0004003d,0x00000006,0x00000084,0x00000071,0x00060041, + 0x00000085,0x00000086,0x00000083,0x00000074,0x00000084,0x0004003d,0x00000007,0x00000087, + 0x00000086,0x0003003e,0x0000007f,0x00000087,0x00050041,0x0000001a,0x0000008c,0x0000007f, + 0x00000019,0x0004003d,0x00000006,0x0000008d,0x0000008c,0x0006000c,0x00000089,0x0000008e, + 0x00000001,0x00000040,0x0000008d,0x0003003e,0x0000008b,0x0000008e,0x00050041,0x0000001a, + 0x00000090,0x0000007f,0x0000001d,0x0004003d,0x00000006,0x00000091,0x00000090,0x0006000c, + 0x00000089,0x00000092,0x00000001,0x00000040,0x00000091,0x0003003e,0x0000008f,0x00000092, + 0x00050041,0x0000001a,0x00000094,0x0000000b,0x0000001d,0x0004003d,0x00000006,0x00000095, + 0x00000094,0x00050041,0x0000002a,0x00000096,0x00000027,0x0000003a,0x0004003d,0x00000006, + 0x00000097,0x00000096,0x00050084,0x00000006,0x00000098,0x00000095,0x00000097,0x00050041, + 0x0000001a,0x00000099,0x0000000b,0x00000019,0x0004003d,0x00000006,0x0000009a,0x00000099, + 0x00050080,0x00000006,0x0000009b,0x00000098,0x0000009a,0x0003003e,0x00000093,0x0000009b, + 0x0004003d,0x00000006,0x000000a1,0x00000093,0x00060041,0x000000a2,0x000000a3,0x000000a0, + 0x00000074,0x000000a1,0x0004003d,0x00000006,0x000000a4,0x000000a3,0x0006000c,0x00000089, + 0x000000a5,0x00000001,0x00000040,0x000000a4,0x0003003e,0x0000009c,0x000000a5,0x0004003d, + 0x00000006,0x000000a7,0x00000093,0x00050080,0x00000006,0x000000a8,0x000000a7,0x0000001d, + 0x00060041,0x000000a2,0x000000a9,0x000000a0,0x00000074,0x000000a8,0x0004003d,0x00000006, + 0x000000aa,0x000000a9,0x0006000c,0x00000089,0x000000ab,0x00000001,0x00000040,0x000000aa, + 0x0003003e,0x000000a6,0x000000ab,0x00050041,0x0000001a,0x000000ac,0x0000000b,0x00000019, + 0x0004003d,0x00000006,0x000000ad,0x000000ac,0x00050041,0x0000002a,0x000000ae,0x00000027, + 0x0000003a,0x0004003d,0x00000006,0x000000af,0x000000ae,0x00050082,0x00000006,0x000000b0, + 0x000000af,0x0000001d,0x000500aa,0x000000b1,0x000000b2,0x000000ad,0x000000b0,0x000300f7, + 0x000000b5,0x00000000,0x000400fa,0x000000b2,0x000000b4,0x000000b8,0x000200f8,0x000000b4, + 0x0004003d,0x00000089,0x000000b6,0x0000009c,0x0009004f,0x00000089,0x000000b7,0x000000b6, + 0x000000b6,0x00000003,0x00000003,0x00000003,0x00000003,0x0003003e,0x000000b3,0x000000b7, + 0x000200f9,0x000000b5,0x000200f8,0x000000b8,0x0004003d,0x00000089,0x000000b9,0x000000a6, + 0x0003003e,0x000000b3,0x000000b9,0x000200f9,0x000000b5,0x000200f8,0x000000b5,0x0004003d, + 0x00000089,0x000000ba,0x000000b3,0x0003003e,0x000000a6,0x000000ba,0x0004003d,0x00000089, + 0x000000bc,0x0000009c,0x0004003d,0x00000089,0x000000be,0x0000009c,0x0008004f,0x000000bd, + 0x000000bf,0x000000be,0x000000be,0x00000001,0x00000002,0x00000003,0x00050041,0x000000c0, + 0x000000c1,0x000000a6,0x00000019,0x0004003d,0x00000088,0x000000c2,0x000000c1,0x00050051, + 0x00000088,0x000000c3,0x000000bf,0x00000000,0x00050051,0x00000088,0x000000c4,0x000000bf, + 0x00000001,0x00050051,0x00000088,0x000000c5,0x000000bf,0x00000002,0x00070050,0x00000089, + 0x000000c6,0x000000c3,0x000000c4,0x000000c5,0x000000c2,0x00050081,0x00000089,0x000000c7, + 0x000000bc,0x000000c6,0x0005008e,0x00000089,0x000000c9,0x000000c7,0x000000c8,0x0003003e, + 0x000000bb,0x000000c9,0x00050041,0x000000c0,0x000000cb,0x0000009c,0x00000019,0x0004003d, + 0x00000088,0x000000cc,0x000000cb,0x00050041,0x000000c0,0x000000cd,0x000000bb,0x00000019, + 0x0004003d,0x00000088,0x000000ce,0x000000cd,0x00050041,0x000000c0,0x000000cf,0x0000009c, + 0x0000001d,0x0004003d,0x00000088,0x000000d0,0x000000cf,0x00050041,0x000000c0,0x000000d1, + 0x000000bb,0x0000001d,0x0004003d,0x00000088,0x000000d2,0x000000d1,0x00070050,0x00000089, + 0x000000d3,0x000000cc,0x000000ce,0x000000d0,0x000000d2,0x0003003e,0x000000ca,0x000000d3, + 0x00050041,0x000000c0,0x000000d5,0x0000009c,0x00000035,0x0004003d,0x00000088,0x000000d6, + 0x000000d5,0x00050041,0x000000c0,0x000000d7,0x000000bb,0x00000035,0x0004003d,0x00000088, + 0x000000d8,0x000000d7,0x00050041,0x000000c0,0x000000da,0x0000009c,0x000000d9,0x0004003d, + 0x00000088,0x000000db,0x000000da,0x00050041,0x000000c0,0x000000dc,0x000000bb,0x000000d9, + 0x0004003d,0x00000088,0x000000dd,0x000000dc,0x00070050,0x00000089,0x000000de,0x000000d6, + 0x000000d8,0x000000db,0x000000dd,0x0003003e,0x000000d4,0x000000de,0x0004003d,0x00000089, + 0x000000e0,0x0000008b,0x0004003d,0x00000089,0x000000e1,0x000000ca,0x00050083,0x00000089, + 0x000000e2,0x000000e0,0x000000e1,0x0005008e,0x00000089,0x000000e3,0x000000e2,0x000000c8, + 0x00070050,0x00000089,0x000000e5,0x000000e4,0x000000e4,0x000000e4,0x000000e4,0x00050081, + 0x00000089,0x000000e6,0x000000e3,0x000000e5,0x0003003e,0x000000df,0x000000e6,0x0004003d, + 0x00000089,0x000000e8,0x0000008f,0x0004003d,0x00000089,0x000000e9,0x000000d4,0x00050083, + 0x00000089,0x000000ea,0x000000e8,0x000000e9,0x0005008e,0x00000089,0x000000eb,0x000000ea, + 0x000000c8,0x00070050,0x00000089,0x000000ec,0x000000e4,0x000000e4,0x000000e4,0x000000e4, + 0x00050081,0x00000089,0x000000ed,0x000000eb,0x000000ec,0x0003003e,0x000000e7,0x000000ed, + 0x0004003d,0x00000089,0x000000ee,0x000000df,0x00070050,0x00000089,0x000000f1,0x000000ef, + 0x000000ef,0x000000ef,0x000000ef,0x00070050,0x00000089,0x000000f2,0x000000f0,0x000000f0, + 0x000000f0,0x000000f0,0x0008000c,0x00000089,0x000000f3,0x00000001,0x0000002b,0x000000ee, + 0x000000f1,0x000000f2,0x0003003e,0x000000df,0x000000f3,0x0004003d,0x00000089,0x000000f4, + 0x000000e7,0x00070050,0x00000089,0x000000f5,0x000000ef,0x000000ef,0x000000ef,0x000000ef, + 0x00070050,0x00000089,0x000000f6,0x000000f0,0x000000f0,0x000000f0,0x000000f0,0x0008000c, + 0x00000089,0x000000f7,0x00000001,0x0000002b,0x000000f4,0x000000f5,0x000000f6,0x0003003e, + 0x000000e7,0x000000f7,0x00050041,0x0000001a,0x000000f9,0x0000000a,0x0000001d,0x0004003d, + 0x00000006,0x000000fa,0x000000f9,0x00050041,0x0000002a,0x000000fb,0x00000027,0x00000029, + 0x0004003d,0x00000006,0x000000fc,0x000000fb,0x00050084,0x00000006,0x000000fd,0x000000fa, + 0x000000fc,0x00050041,0x0000001a,0x000000fe,0x0000000a,0x00000019,0x0004003d,0x00000006, + 0x000000ff,0x000000fe,0x00050080,0x00000006,0x00000100,0x000000fd,0x000000ff,0x0003003e, + 0x000000f8,0x00000100,0x0004003d,0x00000006,0x00000105,0x000000f8,0x0004003d,0x00000089, + 0x00000106,0x000000df,0x0006000c,0x00000006,0x00000107,0x00000001,0x00000037,0x00000106, + 0x0004003d,0x00000089,0x00000108,0x000000e7,0x0006000c,0x00000006,0x00000109,0x00000001, + 0x00000037,0x00000108,0x00050050,0x00000007,0x0000010a,0x00000107,0x00000109,0x00060041, + 0x00000085,0x0000010b,0x00000104,0x00000074,0x00000105,0x0003003e,0x0000010b,0x0000010a, + 0x00050041,0x0000001a,0x0000010c,0x0000000a,0x0000001d,0x0004003d,0x00000006,0x0000010d, + 0x0000010c,0x00050041,0x0000002a,0x0000010e,0x00000027,0x00000063,0x0004003d,0x00000006, + 0x0000010f,0x0000010e,0x00050082,0x00000006,0x00000110,0x0000010f,0x0000001d,0x000500ae, + 0x000000b1,0x00000111,0x0000010d,0x00000110,0x000300f7,0x00000114,0x00000000,0x000400fa, + 0x00000111,0x00000113,0x00000116,0x000200f8,0x00000113,0x0004003d,0x00000006,0x00000115, + 0x00000071,0x0003003e,0x00000112,0x00000115,0x000200f9,0x00000114,0x000200f8,0x00000116, + 0x0004003d,0x00000006,0x00000117,0x00000071,0x00050041,0x0000002a,0x00000118,0x00000027, + 0x00000074,0x0004003d,0x00000006,0x00000119,0x00000118,0x00050080,0x00000006,0x0000011a, + 0x00000117,0x00000119,0x0003003e,0x00000112,0x0000011a,0x000200f9,0x00000114,0x000200f8, + 0x00000114,0x0004003d,0x00000006,0x0000011b,0x00000112,0x0003003e,0x00000071,0x0000011b, + 0x0004003d,0x00000006,0x0000011c,0x00000071,0x00060041,0x00000085,0x0000011d,0x00000083, + 0x00000074,0x0000011c,0x0004003d,0x00000007,0x0000011e,0x0000011d,0x0003003e,0x0000007f, + 0x0000011e,0x00050041,0x0000001a,0x0000011f,0x0000007f,0x00000019,0x0004003d,0x00000006, + 0x00000120,0x0000011f,0x0006000c,0x00000089,0x00000121,0x00000001,0x00000040,0x00000120, + 0x0003003e,0x0000008b,0x00000121,0x00050041,0x0000001a,0x00000122,0x0000007f,0x0000001d, + 0x0004003d,0x00000006,0x00000123,0x00000122,0x0006000c,0x00000089,0x00000124,0x00000001, + 0x00000040,0x00000123,0x0003003e,0x0000008f,0x00000124,0x00050041,0x0000001a,0x00000125, + 0x0000000b,0x0000001d,0x0004003d,0x00000006,0x00000126,0x00000125,0x00050041,0x0000002a, + 0x00000127,0x00000027,0x0000006b,0x0004003d,0x00000006,0x00000128,0x00000127,0x00050082, + 0x00000006,0x00000129,0x00000128,0x0000001d,0x000500ae,0x000000b1,0x0000012a,0x00000126, + 0x00000129,0x000300f7,0x0000012d,0x00000000,0x000400fa,0x0000012a,0x0000012c,0x0000012f, + 0x000200f8,0x0000012c,0x0004003d,0x00000006,0x0000012e,0x00000093,0x0003003e,0x0000012b, + 0x0000012e,0x000200f9,0x0000012d,0x000200f8,0x0000012f,0x0004003d,0x00000006,0x00000130, + 0x00000093,0x00050041,0x0000002a,0x00000131,0x00000027,0x0000003a,0x0004003d,0x00000006, + 0x00000132,0x00000131,0x00050080,0x00000006,0x00000133,0x00000130,0x00000132,0x0003003e, + 0x0000012b,0x00000133,0x000200f9,0x0000012d,0x000200f8,0x0000012d,0x0004003d,0x00000006, + 0x00000134,0x0000012b,0x0003003e,0x00000093,0x00000134,0x0004003d,0x00000006,0x00000135, + 0x00000093,0x00060041,0x000000a2,0x00000136,0x000000a0,0x00000074,0x00000135,0x0004003d, + 0x00000006,0x00000137,0x00000136,0x0006000c,0x00000089,0x00000138,0x00000001,0x00000040, + 0x00000137,0x0003003e,0x0000009c,0x00000138,0x0004003d,0x00000006,0x00000139,0x00000093, + 0x00050080,0x00000006,0x0000013a,0x00000139,0x0000001d,0x00060041,0x000000a2,0x0000013b, + 0x000000a0,0x00000074,0x0000013a,0x0004003d,0x00000006,0x0000013c,0x0000013b,0x0006000c, + 0x00000089,0x0000013d,0x00000001,0x00000040,0x0000013c,0x0003003e,0x000000a6,0x0000013d, + 0x00050041,0x0000001a,0x0000013e,0x0000000b,0x00000019,0x0004003d,0x00000006,0x0000013f, + 0x0000013e,0x00050041,0x0000002a,0x00000140,0x00000027,0x0000003a,0x0004003d,0x00000006, + 0x00000141,0x00000140,0x00050082,0x00000006,0x00000142,0x00000141,0x0000001d,0x000500aa, + 0x000000b1,0x00000143,0x0000013f,0x00000142,0x000300f7,0x00000146,0x00000000,0x000400fa, + 0x00000143,0x00000145,0x00000149,0x000200f8,0x00000145,0x0004003d,0x00000089,0x00000147, + 0x0000009c,0x0009004f,0x00000089,0x00000148,0x00000147,0x00000147,0x00000003,0x00000003, + 0x00000003,0x00000003,0x0003003e,0x00000144,0x00000148,0x000200f9,0x00000146,0x000200f8, + 0x00000149,0x0004003d,0x00000089,0x0000014a,0x000000a6,0x0003003e,0x00000144,0x0000014a, + 0x000200f9,0x00000146,0x000200f8,0x00000146,0x0004003d,0x00000089,0x0000014b,0x00000144, + 0x0003003e,0x000000a6,0x0000014b,0x0004003d,0x00000089,0x0000014c,0x0000009c,0x0004003d, + 0x00000089,0x0000014d,0x0000009c,0x0008004f,0x000000bd,0x0000014e,0x0000014d,0x0000014d, + 0x00000001,0x00000002,0x00000003,0x00050041,0x000000c0,0x0000014f,0x000000a6,0x00000019, + 0x0004003d,0x00000088,0x00000150,0x0000014f,0x00050051,0x00000088,0x00000151,0x0000014e, + 0x00000000,0x00050051,0x00000088,0x00000152,0x0000014e,0x00000001,0x00050051,0x00000088, + 0x00000153,0x0000014e,0x00000002,0x00070050,0x00000089,0x00000154,0x00000151,0x00000152, + 0x00000153,0x00000150,0x00050081,0x00000089,0x00000155,0x0000014c,0x00000154,0x0005008e, + 0x00000089,0x00000156,0x00000155,0x000000c8,0x0003003e,0x000000bb,0x00000156,0x0004003d, + 0x00000089,0x00000158,0x000000ca,0x00050041,0x000000c0,0x00000159,0x0000009c,0x00000019, + 0x0004003d,0x00000088,0x0000015a,0x00000159,0x00050041,0x000000c0,0x0000015b,0x000000bb, + 0x00000019,0x0004003d,0x00000088,0x0000015c,0x0000015b,0x00050041,0x000000c0,0x0000015d, + 0x0000009c,0x0000001d,0x0004003d,0x00000088,0x0000015e,0x0000015d,0x00050041,0x000000c0, + 0x0000015f,0x000000bb,0x0000001d,0x0004003d,0x00000088,0x00000160,0x0000015f,0x00070050, + 0x00000089,0x00000161,0x0000015a,0x0000015c,0x0000015e,0x00000160,0x00050081,0x00000089, + 0x00000162,0x00000158,0x00000161,0x0005008e,0x00000089,0x00000163,0x00000162,0x000000c8, + 0x0003003e,0x00000157,0x00000163,0x0004003d,0x00000089,0x00000165,0x000000d4,0x00050041, + 0x000000c0,0x00000166,0x0000009c,0x00000035,0x0004003d,0x00000088,0x00000167,0x00000166, + 0x00050041,0x000000c0,0x00000168,0x000000bb,0x00000035,0x0004003d,0x00000088,0x00000169, + 0x00000168,0x00050041,0x000000c0,0x0000016a,0x0000009c,0x000000d9,0x0004003d,0x00000088, + 0x0000016b,0x0000016a,0x00050041,0x000000c0,0x0000016c,0x000000bb,0x000000d9,0x0004003d, + 0x00000088,0x0000016d,0x0000016c,0x00070050,0x00000089,0x0000016e,0x00000167,0x00000169, + 0x0000016b,0x0000016d,0x00050081,0x00000089,0x0000016f,0x00000165,0x0000016e,0x0005008e, + 0x00000089,0x00000170,0x0000016f,0x000000c8,0x0003003e,0x00000164,0x00000170,0x0004003d, + 0x00000089,0x00000171,0x0000008b,0x0004003d,0x00000089,0x00000172,0x00000157,0x00050083, + 0x00000089,0x00000173,0x00000171,0x00000172,0x0005008e,0x00000089,0x00000174,0x00000173, + 0x000000c8,0x00070050,0x00000089,0x00000175,0x000000e4,0x000000e4,0x000000e4,0x000000e4, + 0x00050081,0x00000089,0x00000176,0x00000174,0x00000175,0x0003003e,0x000000df,0x00000176, + 0x0004003d,0x00000089,0x00000177,0x0000008f,0x0004003d,0x00000089,0x00000178,0x00000164, + 0x00050083,0x00000089,0x00000179,0x00000177,0x00000178,0x0005008e,0x00000089,0x0000017a, + 0x00000179,0x000000c8,0x00070050,0x00000089,0x0000017b,0x000000e4,0x000000e4,0x000000e4, + 0x000000e4,0x00050081,0x00000089,0x0000017c,0x0000017a,0x0000017b,0x0003003e,0x000000e7, + 0x0000017c,0x0004003d,0x00000089,0x0000017d,0x000000df,0x00070050,0x00000089,0x0000017e, + 0x000000ef,0x000000ef,0x000000ef,0x000000ef,0x00070050,0x00000089,0x0000017f,0x000000f0, + 0x000000f0,0x000000f0,0x000000f0,0x0008000c,0x00000089,0x00000180,0x00000001,0x0000002b, + 0x0000017d,0x0000017e,0x0000017f,0x0003003e,0x000000df,0x00000180,0x0004003d,0x00000089, + 0x00000181,0x000000e7,0x00070050,0x00000089,0x00000182,0x000000ef,0x000000ef,0x000000ef, + 0x000000ef,0x00070050,0x00000089,0x00000183,0x000000f0,0x000000f0,0x000000f0,0x000000f0, + 0x0008000c,0x00000089,0x00000184,0x00000001,0x0000002b,0x00000181,0x00000182,0x00000183, + 0x0003003e,0x000000e7,0x00000184,0x00050041,0x0000001a,0x00000185,0x0000000a,0x0000001d, + 0x0004003d,0x00000006,0x00000186,0x00000185,0x00050041,0x0000002a,0x00000187,0x00000027, + 0x00000063,0x0004003d,0x00000006,0x00000188,0x00000187,0x00050082,0x00000006,0x00000189, + 0x00000188,0x0000001d,0x000500ae,0x000000b1,0x0000018a,0x00000186,0x00000189,0x000300f7, + 0x0000018d,0x00000000,0x000400fa,0x0000018a,0x0000018c,0x0000018f,0x000200f8,0x0000018c, + 0x0004003d,0x00000006,0x0000018e,0x000000f8,0x0003003e,0x0000018b,0x0000018e,0x000200f9, + 0x0000018d,0x000200f8,0x0000018f,0x0004003d,0x00000006,0x00000190,0x000000f8,0x00050041, + 0x0000002a,0x00000191,0x00000027,0x00000029,0x0004003d,0x00000006,0x00000192,0x00000191, + 0x00050080,0x00000006,0x00000193,0x00000190,0x00000192,0x0003003e,0x0000018b,0x00000193, + 0x000200f9,0x0000018d,0x000200f8,0x0000018d,0x0004003d,0x00000006,0x00000194,0x0000018b, + 0x0003003e,0x000000f8,0x00000194,0x0004003d,0x00000006,0x00000195,0x000000f8,0x0004003d, + 0x00000089,0x00000196,0x000000df,0x0006000c,0x00000006,0x00000197,0x00000001,0x00000037, + 0x00000196,0x0004003d,0x00000089,0x00000198,0x000000e7,0x0006000c,0x00000006,0x00000199, + 0x00000001,0x00000037,0x00000198,0x00050050,0x00000007,0x0000019a,0x00000197,0x00000199, + 0x00060041,0x00000085,0x0000019b,0x00000104,0x00000074,0x00000195,0x0003003e,0x0000019b, + 0x0000019a,0x000100fd,0x00010038,0x00050036,0x00000002,0x00000010,0x00000000,0x00000009, + 0x00030037,0x00000008,0x0000000e,0x00030037,0x00000008,0x0000000f,0x000200f8,0x00000011, + 0x0004003b,0x0000001a,0x000001ac,0x00000007,0x0004003b,0x00000008,0x000001b8,0x00000007, + 0x0004003b,0x0000008a,0x000001c0,0x00000007,0x0004003b,0x0000008a,0x000001c4,0x00000007, + 0x0004003b,0x0000001a,0x000001c8,0x00000007,0x0004003b,0x0000008a,0x000001d1,0x00000007, + 0x0004003b,0x0000008a,0x000001da,0x00000007,0x0004003b,0x0000008a,0x000001e6,0x00000007, + 0x0004003b,0x0000008a,0x000001ee,0x00000007,0x0004003b,0x0000008a,0x000001fc,0x00000007, + 0x0004003b,0x0000008a,0x00000206,0x00000007,0x0004003b,0x0000008a,0x00000210,0x00000007, + 0x0004003b,0x0000008a,0x00000217,0x00000007,0x0004003b,0x0000001a,0x00000226,0x00000007, + 0x0004003b,0x0000001a,0x00000241,0x00000007,0x0004003b,0x0000001a,0x0000025b,0x00000007, + 0x0004003b,0x0000008a,0x00000274,0x00000007,0x0004003b,0x0000008a,0x00000288,0x00000007, + 0x0004003b,0x0000008a,0x00000295,0x00000007,0x00050041,0x0000001a,0x0000019c,0x0000000e, + 0x0000001d,0x0004003d,0x00000006,0x0000019d,0x0000019c,0x00050041,0x0000002a,0x0000019e, + 0x00000027,0x00000063,0x0004003d,0x00000006,0x0000019f,0x0000019e,0x00050086,0x00000006, + 0x000001a0,0x0000019f,0x00000035,0x00050082,0x00000006,0x000001a1,0x000001a0,0x0000001d, + 0x0008000c,0x00000006,0x000001a2,0x00000001,0x0000002c,0x0000019d,0x00000019,0x000001a1, + 0x00050041,0x0000001a,0x000001a3,0x0000000e,0x0000001d,0x0003003e,0x000001a3,0x000001a2, + 0x00050041,0x0000001a,0x000001a4,0x0000000f,0x0000001d,0x0004003d,0x00000006,0x000001a5, + 0x000001a4,0x00050041,0x0000002a,0x000001a6,0x00000027,0x0000006b,0x0004003d,0x00000006, + 0x000001a7,0x000001a6,0x00050086,0x00000006,0x000001a8,0x000001a7,0x00000035,0x00050082, + 0x00000006,0x000001a9,0x000001a8,0x0000001d,0x0008000c,0x00000006,0x000001aa,0x00000001, + 0x0000002c,0x000001a5,0x00000019,0x000001a9,0x00050041,0x0000001a,0x000001ab,0x0000000f, + 0x0000001d,0x0003003e,0x000001ab,0x000001aa,0x00050041,0x0000001a,0x000001ad,0x0000000e, + 0x0000001d,0x0004003d,0x00000006,0x000001ae,0x000001ad,0x00050041,0x0000002a,0x000001af, + 0x00000027,0x00000074,0x0004003d,0x00000006,0x000001b0,0x000001af,0x00050084,0x00000006, + 0x000001b1,0x000001ae,0x000001b0,0x00050041,0x0000002a,0x000001b2,0x00000027,0x00000078, + 0x0004003d,0x00000006,0x000001b3,0x000001b2,0x00050080,0x00000006,0x000001b4,0x000001b1, + 0x000001b3,0x00050041,0x0000001a,0x000001b5,0x0000000e,0x00000019,0x0004003d,0x00000006, + 0x000001b6,0x000001b5,0x00050080,0x00000006,0x000001b7,0x000001b4,0x000001b6,0x0003003e, + 0x000001ac,0x000001b7,0x0004003d,0x00000006,0x000001bd,0x000001ac,0x00060041,0x00000085, + 0x000001be,0x000001bc,0x00000074,0x000001bd,0x0004003d,0x00000007,0x000001bf,0x000001be, + 0x0003003e,0x000001b8,0x000001bf,0x00050041,0x0000001a,0x000001c1,0x000001b8,0x00000019, + 0x0004003d,0x00000006,0x000001c2,0x000001c1,0x0006000c,0x00000089,0x000001c3,0x00000001, + 0x00000040,0x000001c2,0x0003003e,0x000001c0,0x000001c3,0x00050041,0x0000001a,0x000001c5, + 0x000001b8,0x0000001d,0x0004003d,0x00000006,0x000001c6,0x000001c5,0x0006000c,0x00000089, + 0x000001c7,0x00000001,0x00000040,0x000001c6,0x0003003e,0x000001c4,0x000001c7,0x00050041, + 0x0000001a,0x000001c9,0x0000000f,0x0000001d,0x0004003d,0x00000006,0x000001ca,0x000001c9, + 0x00050041,0x0000002a,0x000001cb,0x00000027,0x0000003a,0x0004003d,0x00000006,0x000001cc, + 0x000001cb,0x00050084,0x00000006,0x000001cd,0x000001ca,0x000001cc,0x00050041,0x0000001a, + 0x000001ce,0x0000000f,0x00000019,0x0004003d,0x00000006,0x000001cf,0x000001ce,0x00050080, + 0x00000006,0x000001d0,0x000001cd,0x000001cf,0x0003003e,0x000001c8,0x000001d0,0x0004003d, + 0x00000006,0x000001d6,0x000001c8,0x00060041,0x000000a2,0x000001d7,0x000001d5,0x00000074, + 0x000001d6,0x0004003d,0x00000006,0x000001d8,0x000001d7,0x0006000c,0x00000089,0x000001d9, + 0x00000001,0x00000040,0x000001d8,0x0003003e,0x000001d1,0x000001d9,0x0004003d,0x00000006, + 0x000001db,0x000001c8,0x00050080,0x00000006,0x000001dc,0x000001db,0x0000001d,0x00060041, + 0x000000a2,0x000001dd,0x000001d5,0x00000074,0x000001dc,0x0004003d,0x00000006,0x000001de, + 0x000001dd,0x0006000c,0x00000089,0x000001df,0x00000001,0x00000040,0x000001de,0x0003003e, + 0x000001da,0x000001df,0x00050041,0x0000001a,0x000001e0,0x0000000f,0x00000019,0x0004003d, + 0x00000006,0x000001e1,0x000001e0,0x00050041,0x0000002a,0x000001e2,0x00000027,0x0000003a, + 0x0004003d,0x00000006,0x000001e3,0x000001e2,0x00050082,0x00000006,0x000001e4,0x000001e3, + 0x0000001d,0x000500aa,0x000000b1,0x000001e5,0x000001e1,0x000001e4,0x000300f7,0x000001e8, + 0x00000000,0x000400fa,0x000001e5,0x000001e7,0x000001eb,0x000200f8,0x000001e7,0x0004003d, + 0x00000089,0x000001e9,0x000001d1,0x0009004f,0x00000089,0x000001ea,0x000001e9,0x000001e9, + 0x00000002,0x00000003,0x00000002,0x00000003,0x0003003e,0x000001e6,0x000001ea,0x000200f9, + 0x000001e8,0x000200f8,0x000001eb,0x0004003d,0x00000089,0x000001ec,0x000001da,0x0003003e, + 0x000001e6,0x000001ec,0x000200f9,0x000001e8,0x000200f8,0x000001e8,0x0004003d,0x00000089, + 0x000001ed,0x000001e6,0x0003003e,0x000001da,0x000001ed,0x0004003d,0x00000089,0x000001ef, + 0x000001d1,0x0004003d,0x00000089,0x000001f1,0x000001d1,0x0007004f,0x000001f0,0x000001f2, + 0x000001f1,0x000001f1,0x00000002,0x00000003,0x0004003d,0x00000089,0x000001f3,0x000001da, + 0x0007004f,0x000001f0,0x000001f4,0x000001f3,0x000001f3,0x00000000,0x00000001,0x00050051, + 0x00000088,0x000001f5,0x000001f2,0x00000000,0x00050051,0x00000088,0x000001f6,0x000001f2, + 0x00000001,0x00050051,0x00000088,0x000001f7,0x000001f4,0x00000000,0x00050051,0x00000088, + 0x000001f8,0x000001f4,0x00000001,0x00070050,0x00000089,0x000001f9,0x000001f5,0x000001f6, + 0x000001f7,0x000001f8,0x00050081,0x00000089,0x000001fa,0x000001ef,0x000001f9,0x0005008e, + 0x00000089,0x000001fb,0x000001fa,0x000000c8,0x0003003e,0x000001ee,0x000001fb,0x0004003d, + 0x00000089,0x000001fd,0x000001d1,0x0007004f,0x000001f0,0x000001fe,0x000001fd,0x000001fd, + 0x00000000,0x00000001,0x0004003d,0x00000089,0x000001ff,0x000001ee,0x0007004f,0x000001f0, + 0x00000200,0x000001ff,0x000001ff,0x00000000,0x00000001,0x00050051,0x00000088,0x00000201, + 0x000001fe,0x00000000,0x00050051,0x00000088,0x00000202,0x000001fe,0x00000001,0x00050051, + 0x00000088,0x00000203,0x00000200,0x00000000,0x00050051,0x00000088,0x00000204,0x00000200, + 0x00000001,0x00070050,0x00000089,0x00000205,0x00000201,0x00000202,0x00000203,0x00000204, + 0x0003003e,0x000001fc,0x00000205,0x0004003d,0x00000089,0x00000207,0x000001d1,0x0007004f, + 0x000001f0,0x00000208,0x00000207,0x00000207,0x00000002,0x00000003,0x0004003d,0x00000089, + 0x00000209,0x000001ee,0x0007004f,0x000001f0,0x0000020a,0x00000209,0x00000209,0x00000002, + 0x00000003,0x00050051,0x00000088,0x0000020b,0x00000208,0x00000000,0x00050051,0x00000088, + 0x0000020c,0x00000208,0x00000001,0x00050051,0x00000088,0x0000020d,0x0000020a,0x00000000, + 0x00050051,0x00000088,0x0000020e,0x0000020a,0x00000001,0x00070050,0x00000089,0x0000020f, + 0x0000020b,0x0000020c,0x0000020d,0x0000020e,0x0003003e,0x00000206,0x0000020f,0x0004003d, + 0x00000089,0x00000211,0x000001c0,0x0004003d,0x00000089,0x00000212,0x000001fc,0x00050083, + 0x00000089,0x00000213,0x00000211,0x00000212,0x0005008e,0x00000089,0x00000214,0x00000213, + 0x000000c8,0x00070050,0x00000089,0x00000215,0x000000e4,0x000000e4,0x000000e4,0x000000e4, + 0x00050081,0x00000089,0x00000216,0x00000214,0x00000215,0x0003003e,0x00000210,0x00000216, + 0x0004003d,0x00000089,0x00000218,0x000001c4,0x0004003d,0x00000089,0x00000219,0x00000206, + 0x00050083,0x00000089,0x0000021a,0x00000218,0x00000219,0x0005008e,0x00000089,0x0000021b, + 0x0000021a,0x000000c8,0x00070050,0x00000089,0x0000021c,0x000000e4,0x000000e4,0x000000e4, + 0x000000e4,0x00050081,0x00000089,0x0000021d,0x0000021b,0x0000021c,0x0003003e,0x00000217, + 0x0000021d,0x0004003d,0x00000089,0x0000021e,0x00000210,0x00070050,0x00000089,0x0000021f, + 0x000000ef,0x000000ef,0x000000ef,0x000000ef,0x00070050,0x00000089,0x00000220,0x000000f0, + 0x000000f0,0x000000f0,0x000000f0,0x0008000c,0x00000089,0x00000221,0x00000001,0x0000002b, + 0x0000021e,0x0000021f,0x00000220,0x0003003e,0x00000210,0x00000221,0x0004003d,0x00000089, + 0x00000222,0x00000217,0x00070050,0x00000089,0x00000223,0x000000ef,0x000000ef,0x000000ef, + 0x000000ef,0x00070050,0x00000089,0x00000224,0x000000f0,0x000000f0,0x000000f0,0x000000f0, + 0x0008000c,0x00000089,0x00000225,0x00000001,0x0000002b,0x00000222,0x00000223,0x00000224, + 0x0003003e,0x00000217,0x00000225,0x00050041,0x0000001a,0x00000227,0x0000000e,0x0000001d, + 0x0004003d,0x00000006,0x00000228,0x00000227,0x00050041,0x0000002a,0x00000229,0x00000027, + 0x00000029,0x0004003d,0x00000006,0x0000022a,0x00000229,0x00050084,0x00000006,0x0000022b, + 0x00000228,0x0000022a,0x00050041,0x0000001a,0x0000022c,0x0000000e,0x00000019,0x0004003d, + 0x00000006,0x0000022d,0x0000022c,0x00050080,0x00000006,0x0000022e,0x0000022b,0x0000022d, + 0x0003003e,0x00000226,0x0000022e,0x0004003d,0x00000006,0x00000233,0x00000226,0x0004003d, + 0x00000089,0x00000234,0x00000210,0x0006000c,0x00000006,0x00000235,0x00000001,0x00000037, + 0x00000234,0x0004003d,0x00000089,0x00000236,0x00000217,0x0006000c,0x00000006,0x00000237, + 0x00000001,0x00000037,0x00000236,0x00050050,0x00000007,0x00000238,0x00000235,0x00000237, + 0x00060041,0x00000085,0x00000239,0x00000232,0x00000074,0x00000233,0x0003003e,0x00000239, + 0x00000238,0x00050041,0x0000001a,0x0000023a,0x0000000e,0x0000001d,0x0004003d,0x00000006, + 0x0000023b,0x0000023a,0x00050041,0x0000002a,0x0000023c,0x00000027,0x00000063,0x0004003d, + 0x00000006,0x0000023d,0x0000023c,0x00050086,0x00000006,0x0000023e,0x0000023d,0x00000035, + 0x00050082,0x00000006,0x0000023f,0x0000023e,0x0000001d,0x000500ae,0x000000b1,0x00000240, + 0x0000023b,0x0000023f,0x000300f7,0x00000243,0x00000000,0x000400fa,0x00000240,0x00000242, + 0x00000245,0x000200f8,0x00000242,0x0004003d,0x00000006,0x00000244,0x000001ac,0x0003003e, + 0x00000241,0x00000244,0x000200f9,0x00000243,0x000200f8,0x00000245,0x0004003d,0x00000006, + 0x00000246,0x000001ac,0x00050041,0x0000002a,0x00000247,0x00000027,0x00000074,0x0004003d, + 0x00000006,0x00000248,0x00000247,0x00050080,0x00000006,0x00000249,0x00000246,0x00000248, + 0x0003003e,0x00000241,0x00000249,0x000200f9,0x00000243,0x000200f8,0x00000243,0x0004003d, + 0x00000006,0x0000024a,0x00000241,0x0003003e,0x000001ac,0x0000024a,0x0004003d,0x00000006, + 0x0000024b,0x000001ac,0x00060041,0x00000085,0x0000024c,0x000001bc,0x00000074,0x0000024b, + 0x0004003d,0x00000007,0x0000024d,0x0000024c,0x0003003e,0x000001b8,0x0000024d,0x00050041, + 0x0000001a,0x0000024e,0x000001b8,0x00000019,0x0004003d,0x00000006,0x0000024f,0x0000024e, + 0x0006000c,0x00000089,0x00000250,0x00000001,0x00000040,0x0000024f,0x0003003e,0x000001c0, + 0x00000250,0x00050041,0x0000001a,0x00000251,0x000001b8,0x0000001d,0x0004003d,0x00000006, + 0x00000252,0x00000251,0x0006000c,0x00000089,0x00000253,0x00000001,0x00000040,0x00000252, + 0x0003003e,0x000001c4,0x00000253,0x00050041,0x0000001a,0x00000254,0x0000000f,0x0000001d, + 0x0004003d,0x00000006,0x00000255,0x00000254,0x00050041,0x0000002a,0x00000256,0x00000027, + 0x0000006b,0x0004003d,0x00000006,0x00000257,0x00000256,0x00050086,0x00000006,0x00000258, + 0x00000257,0x00000035,0x00050082,0x00000006,0x00000259,0x00000258,0x0000001d,0x000500ae, + 0x000000b1,0x0000025a,0x00000255,0x00000259,0x000300f7,0x0000025d,0x00000000,0x000400fa, + 0x0000025a,0x0000025c,0x0000025f,0x000200f8,0x0000025c,0x0004003d,0x00000006,0x0000025e, + 0x000001c8,0x0003003e,0x0000025b,0x0000025e,0x000200f9,0x0000025d,0x000200f8,0x0000025f, + 0x0004003d,0x00000006,0x00000260,0x000001c8,0x00050041,0x0000002a,0x00000261,0x00000027, + 0x0000003a,0x0004003d,0x00000006,0x00000262,0x00000261,0x00050080,0x00000006,0x00000263, + 0x00000260,0x00000262,0x0003003e,0x0000025b,0x00000263,0x000200f9,0x0000025d,0x000200f8, + 0x0000025d,0x0004003d,0x00000006,0x00000264,0x0000025b,0x0003003e,0x000001c8,0x00000264, + 0x0004003d,0x00000006,0x00000265,0x000001c8,0x00060041,0x000000a2,0x00000266,0x000001d5, + 0x00000074,0x00000265,0x0004003d,0x00000006,0x00000267,0x00000266,0x0006000c,0x00000089, + 0x00000268,0x00000001,0x00000040,0x00000267,0x0003003e,0x000001d1,0x00000268,0x0004003d, + 0x00000006,0x00000269,0x000001c8,0x00050080,0x00000006,0x0000026a,0x00000269,0x0000001d, + 0x00060041,0x000000a2,0x0000026b,0x000001d5,0x00000074,0x0000026a,0x0004003d,0x00000006, + 0x0000026c,0x0000026b,0x0006000c,0x00000089,0x0000026d,0x00000001,0x00000040,0x0000026c, + 0x0003003e,0x000001da,0x0000026d,0x00050041,0x0000001a,0x0000026e,0x0000000f,0x00000019, + 0x0004003d,0x00000006,0x0000026f,0x0000026e,0x00050041,0x0000002a,0x00000270,0x00000027, + 0x0000003a,0x0004003d,0x00000006,0x00000271,0x00000270,0x00050082,0x00000006,0x00000272, + 0x00000271,0x0000001d,0x000500aa,0x000000b1,0x00000273,0x0000026f,0x00000272,0x000300f7, + 0x00000276,0x00000000,0x000400fa,0x00000273,0x00000275,0x00000279,0x000200f8,0x00000275, + 0x0004003d,0x00000089,0x00000277,0x000001d1,0x0009004f,0x00000089,0x00000278,0x00000277, + 0x00000277,0x00000002,0x00000003,0x00000002,0x00000003,0x0003003e,0x00000274,0x00000278, + 0x000200f9,0x00000276,0x000200f8,0x00000279,0x0004003d,0x00000089,0x0000027a,0x000001da, + 0x0003003e,0x00000274,0x0000027a,0x000200f9,0x00000276,0x000200f8,0x00000276,0x0004003d, + 0x00000089,0x0000027b,0x00000274,0x0003003e,0x000001da,0x0000027b,0x0004003d,0x00000089, + 0x0000027c,0x000001d1,0x0004003d,0x00000089,0x0000027d,0x000001d1,0x0007004f,0x000001f0, + 0x0000027e,0x0000027d,0x0000027d,0x00000002,0x00000003,0x0004003d,0x00000089,0x0000027f, + 0x000001da,0x0007004f,0x000001f0,0x00000280,0x0000027f,0x0000027f,0x00000000,0x00000001, + 0x00050051,0x00000088,0x00000281,0x0000027e,0x00000000,0x00050051,0x00000088,0x00000282, + 0x0000027e,0x00000001,0x00050051,0x00000088,0x00000283,0x00000280,0x00000000,0x00050051, + 0x00000088,0x00000284,0x00000280,0x00000001,0x00070050,0x00000089,0x00000285,0x00000281, + 0x00000282,0x00000283,0x00000284,0x00050081,0x00000089,0x00000286,0x0000027c,0x00000285, + 0x0005008e,0x00000089,0x00000287,0x00000286,0x000000c8,0x0003003e,0x000001ee,0x00000287, + 0x0004003d,0x00000089,0x00000289,0x000001fc,0x0004003d,0x00000089,0x0000028a,0x000001d1, + 0x0007004f,0x000001f0,0x0000028b,0x0000028a,0x0000028a,0x00000000,0x00000001,0x0004003d, + 0x00000089,0x0000028c,0x000001ee,0x0007004f,0x000001f0,0x0000028d,0x0000028c,0x0000028c, + 0x00000000,0x00000001,0x00050051,0x00000088,0x0000028e,0x0000028b,0x00000000,0x00050051, + 0x00000088,0x0000028f,0x0000028b,0x00000001,0x00050051,0x00000088,0x00000290,0x0000028d, + 0x00000000,0x00050051,0x00000088,0x00000291,0x0000028d,0x00000001,0x00070050,0x00000089, + 0x00000292,0x0000028e,0x0000028f,0x00000290,0x00000291,0x00050081,0x00000089,0x00000293, + 0x00000289,0x00000292,0x0005008e,0x00000089,0x00000294,0x00000293,0x000000c8,0x0003003e, + 0x00000288,0x00000294,0x0004003d,0x00000089,0x00000296,0x00000206,0x0004003d,0x00000089, + 0x00000297,0x000001d1,0x0007004f,0x000001f0,0x00000298,0x00000297,0x00000297,0x00000002, + 0x00000003,0x0004003d,0x00000089,0x00000299,0x000001ee,0x0007004f,0x000001f0,0x0000029a, + 0x00000299,0x00000299,0x00000002,0x00000003,0x00050051,0x00000088,0x0000029b,0x00000298, + 0x00000000,0x00050051,0x00000088,0x0000029c,0x00000298,0x00000001,0x00050051,0x00000088, + 0x0000029d,0x0000029a,0x00000000,0x00050051,0x00000088,0x0000029e,0x0000029a,0x00000001, + 0x00070050,0x00000089,0x0000029f,0x0000029b,0x0000029c,0x0000029d,0x0000029e,0x00050081, + 0x00000089,0x000002a0,0x00000296,0x0000029f,0x0005008e,0x00000089,0x000002a1,0x000002a0, + 0x000000c8,0x0003003e,0x00000295,0x000002a1,0x0004003d,0x00000089,0x000002a2,0x000001c0, + 0x0004003d,0x00000089,0x000002a3,0x00000288,0x00050083,0x00000089,0x000002a4,0x000002a2, + 0x000002a3,0x0005008e,0x00000089,0x000002a5,0x000002a4,0x000000c8,0x00070050,0x00000089, + 0x000002a6,0x000000e4,0x000000e4,0x000000e4,0x000000e4,0x00050081,0x00000089,0x000002a7, + 0x000002a5,0x000002a6,0x0003003e,0x00000210,0x000002a7,0x0004003d,0x00000089,0x000002a8, + 0x000001c4,0x0004003d,0x00000089,0x000002a9,0x00000295,0x00050083,0x00000089,0x000002aa, + 0x000002a8,0x000002a9,0x0005008e,0x00000089,0x000002ab,0x000002aa,0x000000c8,0x00070050, + 0x00000089,0x000002ac,0x000000e4,0x000000e4,0x000000e4,0x000000e4,0x00050081,0x00000089, + 0x000002ad,0x000002ab,0x000002ac,0x0003003e,0x00000217,0x000002ad,0x0004003d,0x00000089, + 0x000002ae,0x00000210,0x00070050,0x00000089,0x000002af,0x000000ef,0x000000ef,0x000000ef, + 0x000000ef,0x00070050,0x00000089,0x000002b0,0x000000f0,0x000000f0,0x000000f0,0x000000f0, + 0x0008000c,0x00000089,0x000002b1,0x00000001,0x0000002b,0x000002ae,0x000002af,0x000002b0, + 0x0003003e,0x00000210,0x000002b1,0x0004003d,0x00000089,0x000002b2,0x00000217,0x00070050, + 0x00000089,0x000002b3,0x000000ef,0x000000ef,0x000000ef,0x000000ef,0x00070050,0x00000089, + 0x000002b4,0x000000f0,0x000000f0,0x000000f0,0x000000f0,0x0008000c,0x00000089,0x000002b5, + 0x00000001,0x0000002b,0x000002b2,0x000002b3,0x000002b4,0x0003003e,0x00000217,0x000002b5, + 0x00050041,0x0000002a,0x000002b6,0x00000027,0x00000029,0x0004003d,0x00000006,0x000002b7, + 0x000002b6,0x0004003d,0x00000006,0x000002b8,0x00000226,0x00050080,0x00000006,0x000002b9, + 0x000002b8,0x000002b7,0x0003003e,0x00000226,0x000002b9,0x0004003d,0x00000006,0x000002ba, + 0x00000226,0x0004003d,0x00000089,0x000002bb,0x00000210,0x0006000c,0x00000006,0x000002bc, + 0x00000001,0x00000037,0x000002bb,0x0004003d,0x00000089,0x000002bd,0x00000217,0x0006000c, + 0x00000006,0x000002be,0x00000001,0x00000037,0x000002bd,0x00050050,0x00000007,0x000002bf, + 0x000002bc,0x000002be,0x00060041,0x00000085,0x000002c0,0x00000232,0x00000074,0x000002ba, + 0x0003003e,0x000002c0,0x000002bf,0x000100fd,0x00010038 diff --git a/shaders/spv/shader_reconstruct_pyr.comp b/shaders/spv/shader_reconstruct_pyr.comp new file mode 100644 index 0000000..7929989 --- /dev/null +++ b/shaders/spv/shader_reconstruct_pyr.comp @@ -0,0 +1,220 @@ +#version 310 es + +layout (local_size_x = 8, local_size_y = 8) in; + +layout (binding = 0) readonly buffer Lap0BufY { + uvec2 data[]; +} lap0_buf_y; + +layout (binding = 1) readonly buffer Lap0BufUV { + uvec2 data[]; +} lap0_buf_uv; + +layout (binding = 2) readonly buffer Lap1BufY { + uvec2 data[]; +} lap1_buf_y; + +layout (binding = 3) readonly buffer Lap1BufUV { + uvec2 data[]; +} lap1_buf_uv; + +layout (binding = 4) writeonly buffer OutBufY { + uvec2 data[]; +} out_buf_y; + +layout (binding = 5) writeonly buffer OutBufUV { + uvec2 data[]; +} out_buf_uv; + +layout (binding = 6) readonly buffer PrevBlendBufY { + uint data[]; +} prev_blend_y; + +layout (binding = 7) readonly buffer PrevBlendBufUV { + uint data[]; +} prev_blend_uv; + +layout (binding = 8) readonly buffer MaskBuf { + uvec2 data[]; +} mask_buf; + +layout (push_constant) uniform PushConsts { + uint lap_img_width; + uint lap_img_height; + uint out_img_width; + uint out_offset_x; + uint prev_blend_img_width; + uint prev_blend_img_height; +} prop; + +// normalization of gray level +const float norm_gl = 256.0f / 255.0f; + +void reconstruct_y (uvec2 y_id, uvec2 blend_id); +void reconstruct_uv (uvec2 uv_id, uvec2 blend_id); + +void main () +{ + uvec2 g_id = gl_GlobalInvocationID.xy; + + uvec2 y_id = uvec2 (g_id.x, g_id.y * 4u); + y_id.x = clamp (y_id.x, 0u, prop.lap_img_width - 1u); + + uvec2 blend_id = uvec2 (g_id.x, g_id.y * 2u); + blend_id.x = clamp (blend_id.x, 0u, prop.prev_blend_img_width - 1u); + reconstruct_y (y_id, blend_id); + + y_id.y += 2u; + blend_id.y += 1u; + reconstruct_y (y_id, blend_id); + + uvec2 uv_id = uvec2 (g_id.x, g_id.y * 2u); + uv_id.x = clamp (uv_id.x, 0u, prop.lap_img_width - 1u); + blend_id = g_id; + blend_id.x = clamp (blend_id.x, 0u, prop.prev_blend_img_width - 1u); + reconstruct_uv (uv_id, blend_id); +} + +void reconstruct_y (uvec2 y_id, uvec2 blend_id) +{ + y_id.y = clamp (y_id.y, 0u, prop.lap_img_height - 1u); + blend_id.y = clamp (blend_id.y, 0u, prop.prev_blend_img_height - 2u); + + uvec2 mask = mask_buf.data[y_id.x]; + vec4 mask0 = unpackUnorm4x8 (mask.x); + vec4 mask1 = unpackUnorm4x8 (mask.y); + + uint idx = y_id.y * prop.lap_img_width + y_id.x; + uvec2 lap = lap0_buf_y.data[idx]; + vec4 lap00 = unpackUnorm4x8 (lap.x); + vec4 lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_y.data[idx]; + vec4 lap10 = unpackUnorm4x8 (lap.x); + vec4 lap11 = unpackUnorm4x8 (lap.y); + + vec4 lap_blend0 = (lap00 - lap10) * mask0 + lap10; + vec4 lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + uint prev_blend_idx = blend_id.y * prop.prev_blend_img_width + blend_id.x; + vec4 prev_blend0 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx]); + vec4 prev_blend1 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prop.prev_blend_img_width - 1u) ? prev_blend0.wwww : prev_blend1; + + vec4 inter = (prev_blend0 + vec4 (prev_blend0.yzw, prev_blend1.x)) * 0.5f; + vec4 prev_blend_inter00 = vec4 (prev_blend0.x, inter.x, prev_blend0.y, inter.y); + vec4 prev_blend_inter01 = vec4 (prev_blend0.z, inter.z, prev_blend0.w, inter.w); + + vec4 out0 = prev_blend_inter00 + lap_blend0 * 2.0f - norm_gl; + vec4 out1 = prev_blend_inter01 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + uint out_idx = y_id.y * prop.out_img_width + prop.out_offset_x + y_id.x; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); + + idx = (y_id.y >= prop.lap_img_height - 1u) ? idx : idx + prop.lap_img_width; + lap = lap0_buf_y.data[idx]; + lap00 = unpackUnorm4x8 (lap.x); + lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_y.data[idx]; + lap10 = unpackUnorm4x8 (lap.x); + lap11 = unpackUnorm4x8 (lap.y); + + lap_blend0 = (lap00 - lap10) * mask0 + lap10; + lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + prev_blend_idx = (blend_id.y >= prop.prev_blend_img_height - 1u) ? + prev_blend_idx : prev_blend_idx + prop.prev_blend_img_width; + prev_blend0 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx]); + prev_blend1 = unpackUnorm4x8 (prev_blend_y.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prop.prev_blend_img_width - 1u) ? prev_blend0.wwww : prev_blend1; + + inter = (prev_blend0 + vec4 (prev_blend0.yzw, prev_blend1.x)) * 0.5f; + vec4 prev_blend_inter10 = vec4 (prev_blend0.x, inter.x, prev_blend0.y, inter.y); + vec4 prev_blend_inter11 = vec4 (prev_blend0.z, inter.z, prev_blend0.w, inter.w); + prev_blend_inter10 = (prev_blend_inter00 + prev_blend_inter10) * 0.5f; + prev_blend_inter11 = (prev_blend_inter01 + prev_blend_inter11) * 0.5f; + + out0 = prev_blend_inter10 + lap_blend0 * 2.0f - norm_gl; + out1 = prev_blend_inter11 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + out_idx = (y_id.y >= prop.lap_img_height - 1u) ? out_idx : out_idx + prop.out_img_width; + out_buf_y.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); +} + +void reconstruct_uv (uvec2 uv_id, uvec2 blend_id) +{ + uv_id.y = clamp (uv_id.y, 0u, prop.lap_img_height / 2u - 2u); + blend_id.y = clamp (blend_id.y, 0u, prop.prev_blend_img_height / 2u - 1u); + + uvec2 mask = mask_buf.data[uv_id.x]; + vec4 mask0 = unpackUnorm4x8 (mask.x); + vec4 mask1 = unpackUnorm4x8 (mask.y); + + uint idx = uv_id.y * prop.lap_img_width + uv_id.x; + uvec2 lap = lap0_buf_uv.data[idx]; + vec4 lap00 = unpackUnorm4x8 (lap.x); + vec4 lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_uv.data[idx]; + vec4 lap10 = unpackUnorm4x8 (lap.x); + vec4 lap11 = unpackUnorm4x8 (lap.y); + + mask0.yw = mask0.xz; + mask1.yw = mask1.xz; + vec4 lap_blend0 = (lap00 - lap10) * mask0 + lap10; + vec4 lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + uint prev_blend_idx = blend_id.y * prop.prev_blend_img_width + blend_id.x; + vec4 prev_blend0 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx]); + vec4 prev_blend1 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prop.prev_blend_img_width - 1u) ? prev_blend0.zwzw : prev_blend1; + + vec4 inter = (prev_blend0 + vec4 (prev_blend0.zw, prev_blend1.xy)) * 0.5f; + vec4 prev_blend_inter00 = vec4 (prev_blend0.xy, inter.xy); + vec4 prev_blend_inter01 = vec4 (prev_blend0.zw, inter.zw); + + vec4 out0 = prev_blend_inter00 + lap_blend0 * 2.0f - norm_gl; + vec4 out1 = prev_blend_inter01 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + uint out_idx = uv_id.y * prop.out_img_width + prop.out_offset_x + uv_id.x; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); + + idx = (uv_id.y >= (prop.lap_img_height / 2u - 1u)) ? idx : idx + prop.lap_img_width; + lap = lap0_buf_uv.data[idx]; + lap00 = unpackUnorm4x8 (lap.x); + lap01 = unpackUnorm4x8 (lap.y); + + lap = lap1_buf_uv.data[idx]; + lap10 = unpackUnorm4x8 (lap.x); + lap11 = unpackUnorm4x8 (lap.y); + + lap_blend0 = (lap00 - lap10) * mask0 + lap10; + lap_blend1 = (lap01 - lap11) * mask1 + lap11; + + prev_blend_idx = (blend_id.y >= (prop.prev_blend_img_height / 2u - 1u)) ? + prev_blend_idx : prev_blend_idx + prop.prev_blend_img_width; + prev_blend0 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx]); + prev_blend1 = unpackUnorm4x8 (prev_blend_uv.data[prev_blend_idx + 1u]); + prev_blend1 = (blend_id.x == prop.prev_blend_img_width - 1u) ? prev_blend0.zwzw : prev_blend1; + + inter = (prev_blend0 + vec4 (prev_blend0.zw, prev_blend1.xy)) * 0.5f; + vec4 prev_blend_inter10 = vec4 (prev_blend0.xy, inter.xy); + vec4 prev_blend_inter11 = vec4 (prev_blend0.zw, inter.zw); + prev_blend_inter10 = (prev_blend_inter00 + prev_blend_inter10) * 0.5f; + prev_blend_inter11 = (prev_blend_inter01 + prev_blend_inter11) * 0.5f; + + out0 = prev_blend_inter10 + lap_blend0 * 2.0f - norm_gl; + out1 = prev_blend_inter11 + lap_blend1 * 2.0f - norm_gl; + out0 = clamp (out0, 0.0f, 1.0f); + out1 = clamp (out1, 0.0f, 1.0f); + + out_idx += prop.out_img_width; + out_buf_uv.data[out_idx] = uvec2 (packUnorm4x8 (out0), packUnorm4x8 (out1)); +} diff --git a/shaders/spv/shader_reconstruct_pyr.comp.spv b/shaders/spv/shader_reconstruct_pyr.comp.spv new file mode 100644 index 0000000..00ccea9 --- /dev/null +++ b/shaders/spv/shader_reconstruct_pyr.comp.spv @@ -0,0 +1,670 @@ + // 7.8.2870 + 0x07230203,0x00010000,0x00080007,0x00000366,0x00000000,0x00020011,0x00000001,0x0006000b, + 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, + 0x0006000f,0x00000005,0x00000004,0x6e69616d,0x00000000,0x00000015,0x00060010,0x00000004, + 0x00000011,0x00000008,0x00000008,0x00000001,0x00030003,0x00000001,0x00000136,0x00040005, + 0x00000004,0x6e69616d,0x00000000,0x00080005,0x0000000c,0x6f636572,0x7274736e,0x5f746375, + 0x75762879,0x75763b32,0x00003b32,0x00040005,0x0000000a,0x64695f79,0x00000000,0x00050005, + 0x0000000b,0x6e656c62,0x64695f64,0x00000000,0x00080005,0x00000010,0x6f636572,0x7274736e, + 0x5f746375,0x76287675,0x763b3275,0x003b3275,0x00040005,0x0000000e,0x695f7675,0x00000064, + 0x00050005,0x0000000f,0x6e656c62,0x64695f64,0x00000000,0x00040005,0x00000012,0x64695f67, + 0x00000000,0x00080005,0x00000015,0x475f6c67,0x61626f6c,0x766e496c,0x7461636f,0x496e6f69, + 0x00000044,0x00040005,0x00000018,0x64695f79,0x00000000,0x00050005,0x00000025,0x68737550, + 0x736e6f43,0x00007374,0x00070006,0x00000025,0x00000000,0x5f70616c,0x5f676d69,0x74646977, + 0x00000068,0x00070006,0x00000025,0x00000001,0x5f70616c,0x5f676d69,0x67696568,0x00007468, + 0x00070006,0x00000025,0x00000002,0x5f74756f,0x5f676d69,0x74646977,0x00000068,0x00070006, + 0x00000025,0x00000003,0x5f74756f,0x7366666f,0x785f7465,0x00000000,0x00090006,0x00000025, + 0x00000004,0x76657270,0x656c625f,0x695f646e,0x775f676d,0x68746469,0x00000000,0x00090006, + 0x00000025,0x00000005,0x76657270,0x656c625f,0x695f646e,0x685f676d,0x68676965,0x00000074, + 0x00040005,0x00000027,0x706f7270,0x00000000,0x00050005,0x00000030,0x6e656c62,0x64695f64, + 0x00000000,0x00040005,0x00000040,0x61726170,0x0000006d,0x00040005,0x00000042,0x61726170, + 0x0000006d,0x00040005,0x0000004d,0x61726170,0x0000006d,0x00040005,0x0000004f,0x61726170, + 0x0000006d,0x00040005,0x00000052,0x695f7675,0x00000064,0x00040005,0x00000068,0x61726170, + 0x0000006d,0x00040005,0x0000006a,0x61726170,0x0000006d,0x00040005,0x0000007d,0x6b73616d, + 0x00000000,0x00040005,0x0000007f,0x6b73614d,0x00667542,0x00050006,0x0000007f,0x00000000, + 0x61746164,0x00000000,0x00050005,0x00000081,0x6b73616d,0x6675625f,0x00000000,0x00040005, + 0x0000008a,0x6b73616d,0x00000030,0x00040005,0x0000008e,0x6b73616d,0x00000031,0x00030005, + 0x00000092,0x00786469,0x00030005,0x0000009b,0x0070616c,0x00050005,0x0000009d,0x3070614c, + 0x59667542,0x00000000,0x00050006,0x0000009d,0x00000000,0x61746164,0x00000000,0x00050005, + 0x0000009f,0x3070616c,0x6675625f,0x0000795f,0x00040005,0x000000a3,0x3070616c,0x00000030, + 0x00040005,0x000000a7,0x3070616c,0x00000031,0x00050005,0x000000ac,0x3170614c,0x59667542, + 0x00000000,0x00050006,0x000000ac,0x00000000,0x61746164,0x00000000,0x00050005,0x000000ae, + 0x3170616c,0x6675625f,0x0000795f,0x00040005,0x000000b2,0x3170616c,0x00000030,0x00040005, + 0x000000b6,0x3170616c,0x00000031,0x00050005,0x000000ba,0x5f70616c,0x6e656c62,0x00003064, + 0x00050005,0x000000c2,0x5f70616c,0x6e656c62,0x00003164,0x00060005,0x000000ca,0x76657270, + 0x656c625f,0x695f646e,0x00007864,0x00050005,0x000000d3,0x76657270,0x656c625f,0x0030646e, + 0x00060005,0x000000d5,0x76657250,0x6e656c42,0x66754264,0x00000059,0x00050006,0x000000d5, + 0x00000000,0x61746164,0x00000000,0x00060005,0x000000d7,0x76657270,0x656c625f,0x795f646e, + 0x00000000,0x00050005,0x000000dd,0x76657270,0x656c625f,0x0031646e,0x00040005,0x000000f2, + 0x65746e69,0x00000072,0x00070005,0x00000101,0x76657270,0x656c625f,0x695f646e,0x7265746e, + 0x00003030,0x00070005,0x0000010b,0x76657270,0x656c625f,0x695f646e,0x7265746e,0x00003130, + 0x00040005,0x00000116,0x3074756f,0x00000000,0x00040005,0x0000011f,0x3174756f,0x00000000, + 0x00040005,0x00000130,0x5f74756f,0x00786469,0x00040005,0x0000013f,0x4274754f,0x00596675, + 0x00050006,0x0000013f,0x00000000,0x61746164,0x00000000,0x00050005,0x00000141,0x5f74756f, + 0x5f667562,0x00000079,0x00070005,0x000001ab,0x76657270,0x656c625f,0x695f646e,0x7265746e, + 0x00003031,0x00070005,0x000001b5,0x76657270,0x656c625f,0x695f646e,0x7265746e,0x00003131, + 0x00040005,0x00000202,0x6b73616d,0x00000000,0x00040005,0x00000207,0x6b73616d,0x00000030, + 0x00040005,0x0000020b,0x6b73616d,0x00000031,0x00030005,0x0000020f,0x00786469,0x00030005, + 0x00000218,0x0070616c,0x00050005,0x0000021a,0x3070614c,0x55667542,0x00000056,0x00050006, + 0x0000021a,0x00000000,0x61746164,0x00000000,0x00050005,0x0000021c,0x3070616c,0x6675625f, + 0x0076755f,0x00040005,0x00000220,0x3070616c,0x00000030,0x00040005,0x00000224,0x3070616c, + 0x00000031,0x00050005,0x00000229,0x3170614c,0x55667542,0x00000056,0x00050006,0x00000229, + 0x00000000,0x61746164,0x00000000,0x00050005,0x0000022b,0x3170616c,0x6675625f,0x0076755f, + 0x00040005,0x0000022f,0x3170616c,0x00000030,0x00040005,0x00000233,0x3170616c,0x00000031, + 0x00050005,0x00000240,0x5f70616c,0x6e656c62,0x00003064,0x00050005,0x00000248,0x5f70616c, + 0x6e656c62,0x00003164,0x00060005,0x00000250,0x76657270,0x656c625f,0x695f646e,0x00007864, + 0x00050005,0x00000259,0x76657270,0x656c625f,0x0030646e,0x00060005,0x0000025b,0x76657250, + 0x6e656c42,0x66754264,0x00005655,0x00050006,0x0000025b,0x00000000,0x61746164,0x00000000, + 0x00060005,0x0000025d,0x76657270,0x656c625f,0x755f646e,0x00000076,0x00050005,0x00000262, + 0x76657270,0x656c625f,0x0031646e,0x00040005,0x00000276,0x65746e69,0x00000072,0x00070005, + 0x00000283,0x76657270,0x656c625f,0x695f646e,0x7265746e,0x00003030,0x00070005,0x0000028d, + 0x76657270,0x656c625f,0x695f646e,0x7265746e,0x00003130,0x00040005,0x00000297,0x3074756f, + 0x00000000,0x00040005,0x0000029e,0x3174756f,0x00000000,0x00040005,0x000002ad,0x5f74756f, + 0x00786469,0x00050005,0x000002ba,0x4274754f,0x56556675,0x00000000,0x00050006,0x000002ba, + 0x00000000,0x61746164,0x00000000,0x00050005,0x000002bc,0x5f74756f,0x5f667562,0x00007675, + 0x00070005,0x00000329,0x76657270,0x656c625f,0x695f646e,0x7265746e,0x00003031,0x00070005, + 0x00000333,0x76657270,0x656c625f,0x695f646e,0x7265746e,0x00003131,0x00040047,0x00000015, + 0x0000000b,0x0000001c,0x00050048,0x00000025,0x00000000,0x00000023,0x00000000,0x00050048, + 0x00000025,0x00000001,0x00000023,0x00000004,0x00050048,0x00000025,0x00000002,0x00000023, + 0x00000008,0x00050048,0x00000025,0x00000003,0x00000023,0x0000000c,0x00050048,0x00000025, + 0x00000004,0x00000023,0x00000010,0x00050048,0x00000025,0x00000005,0x00000023,0x00000014, + 0x00030047,0x00000025,0x00000002,0x00040047,0x0000007e,0x00000006,0x00000008,0x00040048, + 0x0000007f,0x00000000,0x00000018,0x00050048,0x0000007f,0x00000000,0x00000023,0x00000000, + 0x00030047,0x0000007f,0x00000003,0x00040047,0x00000081,0x00000022,0x00000000,0x00040047, + 0x00000081,0x00000021,0x00000008,0x00040047,0x0000009c,0x00000006,0x00000008,0x00040048, + 0x0000009d,0x00000000,0x00000018,0x00050048,0x0000009d,0x00000000,0x00000023,0x00000000, + 0x00030047,0x0000009d,0x00000003,0x00040047,0x0000009f,0x00000022,0x00000000,0x00040047, + 0x0000009f,0x00000021,0x00000000,0x00040047,0x000000ab,0x00000006,0x00000008,0x00040048, + 0x000000ac,0x00000000,0x00000018,0x00050048,0x000000ac,0x00000000,0x00000023,0x00000000, + 0x00030047,0x000000ac,0x00000003,0x00040047,0x000000ae,0x00000022,0x00000000,0x00040047, + 0x000000ae,0x00000021,0x00000002,0x00040047,0x000000d4,0x00000006,0x00000004,0x00040048, + 0x000000d5,0x00000000,0x00000018,0x00050048,0x000000d5,0x00000000,0x00000023,0x00000000, + 0x00030047,0x000000d5,0x00000003,0x00040047,0x000000d7,0x00000022,0x00000000,0x00040047, + 0x000000d7,0x00000021,0x00000006,0x00040047,0x0000013e,0x00000006,0x00000008,0x00040048, + 0x0000013f,0x00000000,0x00000019,0x00050048,0x0000013f,0x00000000,0x00000023,0x00000000, + 0x00030047,0x0000013f,0x00000003,0x00040047,0x00000141,0x00000022,0x00000000,0x00040047, + 0x00000141,0x00000021,0x00000004,0x00040047,0x00000219,0x00000006,0x00000008,0x00040048, + 0x0000021a,0x00000000,0x00000018,0x00050048,0x0000021a,0x00000000,0x00000023,0x00000000, + 0x00030047,0x0000021a,0x00000003,0x00040047,0x0000021c,0x00000022,0x00000000,0x00040047, + 0x0000021c,0x00000021,0x00000001,0x00040047,0x00000228,0x00000006,0x00000008,0x00040048, + 0x00000229,0x00000000,0x00000018,0x00050048,0x00000229,0x00000000,0x00000023,0x00000000, + 0x00030047,0x00000229,0x00000003,0x00040047,0x0000022b,0x00000022,0x00000000,0x00040047, + 0x0000022b,0x00000021,0x00000003,0x00040047,0x0000025a,0x00000006,0x00000004,0x00040048, + 0x0000025b,0x00000000,0x00000018,0x00050048,0x0000025b,0x00000000,0x00000023,0x00000000, + 0x00030047,0x0000025b,0x00000003,0x00040047,0x0000025d,0x00000022,0x00000000,0x00040047, + 0x0000025d,0x00000021,0x00000007,0x00040047,0x000002b9,0x00000006,0x00000008,0x00040048, + 0x000002ba,0x00000000,0x00000019,0x00050048,0x000002ba,0x00000000,0x00000023,0x00000000, + 0x00030047,0x000002ba,0x00000003,0x00040047,0x000002bc,0x00000022,0x00000000,0x00040047, + 0x000002bc,0x00000021,0x00000005,0x00040047,0x00000365,0x0000000b,0x00000019,0x00020013, + 0x00000002,0x00030021,0x00000003,0x00000002,0x00040015,0x00000006,0x00000020,0x00000000, + 0x00040017,0x00000007,0x00000006,0x00000002,0x00040020,0x00000008,0x00000007,0x00000007, + 0x00050021,0x00000009,0x00000002,0x00000008,0x00000008,0x00040017,0x00000013,0x00000006, + 0x00000003,0x00040020,0x00000014,0x00000001,0x00000013,0x0004003b,0x00000014,0x00000015, + 0x00000001,0x0004002b,0x00000006,0x00000019,0x00000000,0x00040020,0x0000001a,0x00000007, + 0x00000006,0x0004002b,0x00000006,0x0000001d,0x00000001,0x0004002b,0x00000006,0x00000020, + 0x00000004,0x0008001e,0x00000025,0x00000006,0x00000006,0x00000006,0x00000006,0x00000006, + 0x00000006,0x00040020,0x00000026,0x00000009,0x00000025,0x0004003b,0x00000026,0x00000027, + 0x00000009,0x00040015,0x00000028,0x00000020,0x00000001,0x0004002b,0x00000028,0x00000029, + 0x00000000,0x00040020,0x0000002a,0x00000009,0x00000006,0x0004002b,0x00000006,0x00000035, + 0x00000002,0x0004002b,0x00000028,0x0000003a,0x00000004,0x0004002b,0x00000028,0x0000006f, + 0x00000001,0x0004002b,0x00000028,0x00000077,0x00000005,0x0003001d,0x0000007e,0x00000007, + 0x0003001e,0x0000007f,0x0000007e,0x00040020,0x00000080,0x00000002,0x0000007f,0x0004003b, + 0x00000080,0x00000081,0x00000002,0x00040020,0x00000084,0x00000002,0x00000007,0x00030016, + 0x00000087,0x00000020,0x00040017,0x00000088,0x00000087,0x00000004,0x00040020,0x00000089, + 0x00000007,0x00000088,0x0003001d,0x0000009c,0x00000007,0x0003001e,0x0000009d,0x0000009c, + 0x00040020,0x0000009e,0x00000002,0x0000009d,0x0004003b,0x0000009e,0x0000009f,0x00000002, + 0x0003001d,0x000000ab,0x00000007,0x0003001e,0x000000ac,0x000000ab,0x00040020,0x000000ad, + 0x00000002,0x000000ac,0x0004003b,0x000000ad,0x000000ae,0x00000002,0x0003001d,0x000000d4, + 0x00000006,0x0003001e,0x000000d5,0x000000d4,0x00040020,0x000000d6,0x00000002,0x000000d5, + 0x0004003b,0x000000d6,0x000000d7,0x00000002,0x00040020,0x000000d9,0x00000002,0x00000006, + 0x00020014,0x000000e8,0x00040017,0x000000f4,0x00000087,0x00000003,0x00040020,0x000000f7, + 0x00000007,0x00000087,0x0004002b,0x00000087,0x000000ff,0x3f000000,0x0004002b,0x00000006, + 0x00000110,0x00000003,0x0004002b,0x00000087,0x00000119,0x40000000,0x0004002b,0x00000087, + 0x0000011c,0x3f808081,0x0004002b,0x00000087,0x00000127,0x00000000,0x0004002b,0x00000087, + 0x00000128,0x3f800000,0x0004002b,0x00000028,0x00000133,0x00000002,0x0004002b,0x00000028, + 0x00000137,0x00000003,0x0003001d,0x0000013e,0x00000007,0x0003001e,0x0000013f,0x0000013e, + 0x00040020,0x00000140,0x00000002,0x0000013f,0x0004003b,0x00000140,0x00000141,0x00000002, + 0x0003001d,0x00000219,0x00000007,0x0003001e,0x0000021a,0x00000219,0x00040020,0x0000021b, + 0x00000002,0x0000021a,0x0004003b,0x0000021b,0x0000021c,0x00000002,0x0003001d,0x00000228, + 0x00000007,0x0003001e,0x00000229,0x00000228,0x00040020,0x0000022a,0x00000002,0x00000229, + 0x0004003b,0x0000022a,0x0000022b,0x00000002,0x00040017,0x00000237,0x00000087,0x00000002, + 0x0003001d,0x0000025a,0x00000006,0x0003001e,0x0000025b,0x0000025a,0x00040020,0x0000025c, + 0x00000002,0x0000025b,0x0004003b,0x0000025c,0x0000025d,0x00000002,0x0003001d,0x000002b9, + 0x00000007,0x0003001e,0x000002ba,0x000002b9,0x00040020,0x000002bb,0x00000002,0x000002ba, + 0x0004003b,0x000002bb,0x000002bc,0x00000002,0x0004002b,0x00000006,0x00000364,0x00000008, + 0x0006002c,0x00000013,0x00000365,0x00000364,0x00000364,0x0000001d,0x00050036,0x00000002, + 0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x0004003b,0x00000008,0x00000012, + 0x00000007,0x0004003b,0x00000008,0x00000018,0x00000007,0x0004003b,0x00000008,0x00000030, + 0x00000007,0x0004003b,0x00000008,0x00000040,0x00000007,0x0004003b,0x00000008,0x00000042, + 0x00000007,0x0004003b,0x00000008,0x0000004d,0x00000007,0x0004003b,0x00000008,0x0000004f, + 0x00000007,0x0004003b,0x00000008,0x00000052,0x00000007,0x0004003b,0x00000008,0x00000068, + 0x00000007,0x0004003b,0x00000008,0x0000006a,0x00000007,0x0004003d,0x00000013,0x00000016, + 0x00000015,0x0007004f,0x00000007,0x00000017,0x00000016,0x00000016,0x00000000,0x00000001, + 0x0003003e,0x00000012,0x00000017,0x00050041,0x0000001a,0x0000001b,0x00000012,0x00000019, + 0x0004003d,0x00000006,0x0000001c,0x0000001b,0x00050041,0x0000001a,0x0000001e,0x00000012, + 0x0000001d,0x0004003d,0x00000006,0x0000001f,0x0000001e,0x00050084,0x00000006,0x00000021, + 0x0000001f,0x00000020,0x00050050,0x00000007,0x00000022,0x0000001c,0x00000021,0x0003003e, + 0x00000018,0x00000022,0x00050041,0x0000001a,0x00000023,0x00000018,0x00000019,0x0004003d, + 0x00000006,0x00000024,0x00000023,0x00050041,0x0000002a,0x0000002b,0x00000027,0x00000029, + 0x0004003d,0x00000006,0x0000002c,0x0000002b,0x00050082,0x00000006,0x0000002d,0x0000002c, + 0x0000001d,0x0008000c,0x00000006,0x0000002e,0x00000001,0x0000002c,0x00000024,0x00000019, + 0x0000002d,0x00050041,0x0000001a,0x0000002f,0x00000018,0x00000019,0x0003003e,0x0000002f, + 0x0000002e,0x00050041,0x0000001a,0x00000031,0x00000012,0x00000019,0x0004003d,0x00000006, + 0x00000032,0x00000031,0x00050041,0x0000001a,0x00000033,0x00000012,0x0000001d,0x0004003d, + 0x00000006,0x00000034,0x00000033,0x00050084,0x00000006,0x00000036,0x00000034,0x00000035, + 0x00050050,0x00000007,0x00000037,0x00000032,0x00000036,0x0003003e,0x00000030,0x00000037, + 0x00050041,0x0000001a,0x00000038,0x00000030,0x00000019,0x0004003d,0x00000006,0x00000039, + 0x00000038,0x00050041,0x0000002a,0x0000003b,0x00000027,0x0000003a,0x0004003d,0x00000006, + 0x0000003c,0x0000003b,0x00050082,0x00000006,0x0000003d,0x0000003c,0x0000001d,0x0008000c, + 0x00000006,0x0000003e,0x00000001,0x0000002c,0x00000039,0x00000019,0x0000003d,0x00050041, + 0x0000001a,0x0000003f,0x00000030,0x00000019,0x0003003e,0x0000003f,0x0000003e,0x0004003d, + 0x00000007,0x00000041,0x00000018,0x0003003e,0x00000040,0x00000041,0x0004003d,0x00000007, + 0x00000043,0x00000030,0x0003003e,0x00000042,0x00000043,0x00060039,0x00000002,0x00000044, + 0x0000000c,0x00000040,0x00000042,0x00050041,0x0000001a,0x00000045,0x00000018,0x0000001d, + 0x0004003d,0x00000006,0x00000046,0x00000045,0x00050080,0x00000006,0x00000047,0x00000046, + 0x00000035,0x00050041,0x0000001a,0x00000048,0x00000018,0x0000001d,0x0003003e,0x00000048, + 0x00000047,0x00050041,0x0000001a,0x00000049,0x00000030,0x0000001d,0x0004003d,0x00000006, + 0x0000004a,0x00000049,0x00050080,0x00000006,0x0000004b,0x0000004a,0x0000001d,0x00050041, + 0x0000001a,0x0000004c,0x00000030,0x0000001d,0x0003003e,0x0000004c,0x0000004b,0x0004003d, + 0x00000007,0x0000004e,0x00000018,0x0003003e,0x0000004d,0x0000004e,0x0004003d,0x00000007, + 0x00000050,0x00000030,0x0003003e,0x0000004f,0x00000050,0x00060039,0x00000002,0x00000051, + 0x0000000c,0x0000004d,0x0000004f,0x00050041,0x0000001a,0x00000053,0x00000012,0x00000019, + 0x0004003d,0x00000006,0x00000054,0x00000053,0x00050041,0x0000001a,0x00000055,0x00000012, + 0x0000001d,0x0004003d,0x00000006,0x00000056,0x00000055,0x00050084,0x00000006,0x00000057, + 0x00000056,0x00000035,0x00050050,0x00000007,0x00000058,0x00000054,0x00000057,0x0003003e, + 0x00000052,0x00000058,0x00050041,0x0000001a,0x00000059,0x00000052,0x00000019,0x0004003d, + 0x00000006,0x0000005a,0x00000059,0x00050041,0x0000002a,0x0000005b,0x00000027,0x00000029, + 0x0004003d,0x00000006,0x0000005c,0x0000005b,0x00050082,0x00000006,0x0000005d,0x0000005c, + 0x0000001d,0x0008000c,0x00000006,0x0000005e,0x00000001,0x0000002c,0x0000005a,0x00000019, + 0x0000005d,0x00050041,0x0000001a,0x0000005f,0x00000052,0x00000019,0x0003003e,0x0000005f, + 0x0000005e,0x0004003d,0x00000007,0x00000060,0x00000012,0x0003003e,0x00000030,0x00000060, + 0x00050041,0x0000001a,0x00000061,0x00000030,0x00000019,0x0004003d,0x00000006,0x00000062, + 0x00000061,0x00050041,0x0000002a,0x00000063,0x00000027,0x0000003a,0x0004003d,0x00000006, + 0x00000064,0x00000063,0x00050082,0x00000006,0x00000065,0x00000064,0x0000001d,0x0008000c, + 0x00000006,0x00000066,0x00000001,0x0000002c,0x00000062,0x00000019,0x00000065,0x00050041, + 0x0000001a,0x00000067,0x00000030,0x00000019,0x0003003e,0x00000067,0x00000066,0x0004003d, + 0x00000007,0x00000069,0x00000052,0x0003003e,0x00000068,0x00000069,0x0004003d,0x00000007, + 0x0000006b,0x00000030,0x0003003e,0x0000006a,0x0000006b,0x00060039,0x00000002,0x0000006c, + 0x00000010,0x00000068,0x0000006a,0x000100fd,0x00010038,0x00050036,0x00000002,0x0000000c, + 0x00000000,0x00000009,0x00030037,0x00000008,0x0000000a,0x00030037,0x00000008,0x0000000b, + 0x000200f8,0x0000000d,0x0004003b,0x00000008,0x0000007d,0x00000007,0x0004003b,0x00000089, + 0x0000008a,0x00000007,0x0004003b,0x00000089,0x0000008e,0x00000007,0x0004003b,0x0000001a, + 0x00000092,0x00000007,0x0004003b,0x00000008,0x0000009b,0x00000007,0x0004003b,0x00000089, + 0x000000a3,0x00000007,0x0004003b,0x00000089,0x000000a7,0x00000007,0x0004003b,0x00000089, + 0x000000b2,0x00000007,0x0004003b,0x00000089,0x000000b6,0x00000007,0x0004003b,0x00000089, + 0x000000ba,0x00000007,0x0004003b,0x00000089,0x000000c2,0x00000007,0x0004003b,0x0000001a, + 0x000000ca,0x00000007,0x0004003b,0x00000089,0x000000d3,0x00000007,0x0004003b,0x00000089, + 0x000000dd,0x00000007,0x0004003b,0x00000089,0x000000ea,0x00000007,0x0004003b,0x00000089, + 0x000000f2,0x00000007,0x0004003b,0x00000089,0x00000101,0x00000007,0x0004003b,0x00000089, + 0x0000010b,0x00000007,0x0004003b,0x00000089,0x00000116,0x00000007,0x0004003b,0x00000089, + 0x0000011f,0x00000007,0x0004003b,0x0000001a,0x00000130,0x00000007,0x0004003b,0x0000001a, + 0x0000014f,0x00000007,0x0004003b,0x0000001a,0x0000017f,0x00000007,0x0004003b,0x00000089, + 0x00000198,0x00000007,0x0004003b,0x00000089,0x000001ab,0x00000007,0x0004003b,0x00000089, + 0x000001b5,0x00000007,0x0004003b,0x0000001a,0x000001e1,0x00000007,0x00050041,0x0000001a, + 0x0000006d,0x0000000a,0x0000001d,0x0004003d,0x00000006,0x0000006e,0x0000006d,0x00050041, + 0x0000002a,0x00000070,0x00000027,0x0000006f,0x0004003d,0x00000006,0x00000071,0x00000070, + 0x00050082,0x00000006,0x00000072,0x00000071,0x0000001d,0x0008000c,0x00000006,0x00000073, + 0x00000001,0x0000002c,0x0000006e,0x00000019,0x00000072,0x00050041,0x0000001a,0x00000074, + 0x0000000a,0x0000001d,0x0003003e,0x00000074,0x00000073,0x00050041,0x0000001a,0x00000075, + 0x0000000b,0x0000001d,0x0004003d,0x00000006,0x00000076,0x00000075,0x00050041,0x0000002a, + 0x00000078,0x00000027,0x00000077,0x0004003d,0x00000006,0x00000079,0x00000078,0x00050082, + 0x00000006,0x0000007a,0x00000079,0x00000035,0x0008000c,0x00000006,0x0000007b,0x00000001, + 0x0000002c,0x00000076,0x00000019,0x0000007a,0x00050041,0x0000001a,0x0000007c,0x0000000b, + 0x0000001d,0x0003003e,0x0000007c,0x0000007b,0x00050041,0x0000001a,0x00000082,0x0000000a, + 0x00000019,0x0004003d,0x00000006,0x00000083,0x00000082,0x00060041,0x00000084,0x00000085, + 0x00000081,0x00000029,0x00000083,0x0004003d,0x00000007,0x00000086,0x00000085,0x0003003e, + 0x0000007d,0x00000086,0x00050041,0x0000001a,0x0000008b,0x0000007d,0x00000019,0x0004003d, + 0x00000006,0x0000008c,0x0000008b,0x0006000c,0x00000088,0x0000008d,0x00000001,0x00000040, + 0x0000008c,0x0003003e,0x0000008a,0x0000008d,0x00050041,0x0000001a,0x0000008f,0x0000007d, + 0x0000001d,0x0004003d,0x00000006,0x00000090,0x0000008f,0x0006000c,0x00000088,0x00000091, + 0x00000001,0x00000040,0x00000090,0x0003003e,0x0000008e,0x00000091,0x00050041,0x0000001a, + 0x00000093,0x0000000a,0x0000001d,0x0004003d,0x00000006,0x00000094,0x00000093,0x00050041, + 0x0000002a,0x00000095,0x00000027,0x00000029,0x0004003d,0x00000006,0x00000096,0x00000095, + 0x00050084,0x00000006,0x00000097,0x00000094,0x00000096,0x00050041,0x0000001a,0x00000098, + 0x0000000a,0x00000019,0x0004003d,0x00000006,0x00000099,0x00000098,0x00050080,0x00000006, + 0x0000009a,0x00000097,0x00000099,0x0003003e,0x00000092,0x0000009a,0x0004003d,0x00000006, + 0x000000a0,0x00000092,0x00060041,0x00000084,0x000000a1,0x0000009f,0x00000029,0x000000a0, + 0x0004003d,0x00000007,0x000000a2,0x000000a1,0x0003003e,0x0000009b,0x000000a2,0x00050041, + 0x0000001a,0x000000a4,0x0000009b,0x00000019,0x0004003d,0x00000006,0x000000a5,0x000000a4, + 0x0006000c,0x00000088,0x000000a6,0x00000001,0x00000040,0x000000a5,0x0003003e,0x000000a3, + 0x000000a6,0x00050041,0x0000001a,0x000000a8,0x0000009b,0x0000001d,0x0004003d,0x00000006, + 0x000000a9,0x000000a8,0x0006000c,0x00000088,0x000000aa,0x00000001,0x00000040,0x000000a9, + 0x0003003e,0x000000a7,0x000000aa,0x0004003d,0x00000006,0x000000af,0x00000092,0x00060041, + 0x00000084,0x000000b0,0x000000ae,0x00000029,0x000000af,0x0004003d,0x00000007,0x000000b1, + 0x000000b0,0x0003003e,0x0000009b,0x000000b1,0x00050041,0x0000001a,0x000000b3,0x0000009b, + 0x00000019,0x0004003d,0x00000006,0x000000b4,0x000000b3,0x0006000c,0x00000088,0x000000b5, + 0x00000001,0x00000040,0x000000b4,0x0003003e,0x000000b2,0x000000b5,0x00050041,0x0000001a, + 0x000000b7,0x0000009b,0x0000001d,0x0004003d,0x00000006,0x000000b8,0x000000b7,0x0006000c, + 0x00000088,0x000000b9,0x00000001,0x00000040,0x000000b8,0x0003003e,0x000000b6,0x000000b9, + 0x0004003d,0x00000088,0x000000bb,0x000000a3,0x0004003d,0x00000088,0x000000bc,0x000000b2, + 0x00050083,0x00000088,0x000000bd,0x000000bb,0x000000bc,0x0004003d,0x00000088,0x000000be, + 0x0000008a,0x00050085,0x00000088,0x000000bf,0x000000bd,0x000000be,0x0004003d,0x00000088, + 0x000000c0,0x000000b2,0x00050081,0x00000088,0x000000c1,0x000000bf,0x000000c0,0x0003003e, + 0x000000ba,0x000000c1,0x0004003d,0x00000088,0x000000c3,0x000000a7,0x0004003d,0x00000088, + 0x000000c4,0x000000b6,0x00050083,0x00000088,0x000000c5,0x000000c3,0x000000c4,0x0004003d, + 0x00000088,0x000000c6,0x0000008e,0x00050085,0x00000088,0x000000c7,0x000000c5,0x000000c6, + 0x0004003d,0x00000088,0x000000c8,0x000000b6,0x00050081,0x00000088,0x000000c9,0x000000c7, + 0x000000c8,0x0003003e,0x000000c2,0x000000c9,0x00050041,0x0000001a,0x000000cb,0x0000000b, + 0x0000001d,0x0004003d,0x00000006,0x000000cc,0x000000cb,0x00050041,0x0000002a,0x000000cd, + 0x00000027,0x0000003a,0x0004003d,0x00000006,0x000000ce,0x000000cd,0x00050084,0x00000006, + 0x000000cf,0x000000cc,0x000000ce,0x00050041,0x0000001a,0x000000d0,0x0000000b,0x00000019, + 0x0004003d,0x00000006,0x000000d1,0x000000d0,0x00050080,0x00000006,0x000000d2,0x000000cf, + 0x000000d1,0x0003003e,0x000000ca,0x000000d2,0x0004003d,0x00000006,0x000000d8,0x000000ca, + 0x00060041,0x000000d9,0x000000da,0x000000d7,0x00000029,0x000000d8,0x0004003d,0x00000006, + 0x000000db,0x000000da,0x0006000c,0x00000088,0x000000dc,0x00000001,0x00000040,0x000000db, + 0x0003003e,0x000000d3,0x000000dc,0x0004003d,0x00000006,0x000000de,0x000000ca,0x00050080, + 0x00000006,0x000000df,0x000000de,0x0000001d,0x00060041,0x000000d9,0x000000e0,0x000000d7, + 0x00000029,0x000000df,0x0004003d,0x00000006,0x000000e1,0x000000e0,0x0006000c,0x00000088, + 0x000000e2,0x00000001,0x00000040,0x000000e1,0x0003003e,0x000000dd,0x000000e2,0x00050041, + 0x0000001a,0x000000e3,0x0000000b,0x00000019,0x0004003d,0x00000006,0x000000e4,0x000000e3, + 0x00050041,0x0000002a,0x000000e5,0x00000027,0x0000003a,0x0004003d,0x00000006,0x000000e6, + 0x000000e5,0x00050082,0x00000006,0x000000e7,0x000000e6,0x0000001d,0x000500aa,0x000000e8, + 0x000000e9,0x000000e4,0x000000e7,0x000300f7,0x000000ec,0x00000000,0x000400fa,0x000000e9, + 0x000000eb,0x000000ef,0x000200f8,0x000000eb,0x0004003d,0x00000088,0x000000ed,0x000000d3, + 0x0009004f,0x00000088,0x000000ee,0x000000ed,0x000000ed,0x00000003,0x00000003,0x00000003, + 0x00000003,0x0003003e,0x000000ea,0x000000ee,0x000200f9,0x000000ec,0x000200f8,0x000000ef, + 0x0004003d,0x00000088,0x000000f0,0x000000dd,0x0003003e,0x000000ea,0x000000f0,0x000200f9, + 0x000000ec,0x000200f8,0x000000ec,0x0004003d,0x00000088,0x000000f1,0x000000ea,0x0003003e, + 0x000000dd,0x000000f1,0x0004003d,0x00000088,0x000000f3,0x000000d3,0x0004003d,0x00000088, + 0x000000f5,0x000000d3,0x0008004f,0x000000f4,0x000000f6,0x000000f5,0x000000f5,0x00000001, + 0x00000002,0x00000003,0x00050041,0x000000f7,0x000000f8,0x000000dd,0x00000019,0x0004003d, + 0x00000087,0x000000f9,0x000000f8,0x00050051,0x00000087,0x000000fa,0x000000f6,0x00000000, + 0x00050051,0x00000087,0x000000fb,0x000000f6,0x00000001,0x00050051,0x00000087,0x000000fc, + 0x000000f6,0x00000002,0x00070050,0x00000088,0x000000fd,0x000000fa,0x000000fb,0x000000fc, + 0x000000f9,0x00050081,0x00000088,0x000000fe,0x000000f3,0x000000fd,0x0005008e,0x00000088, + 0x00000100,0x000000fe,0x000000ff,0x0003003e,0x000000f2,0x00000100,0x00050041,0x000000f7, + 0x00000102,0x000000d3,0x00000019,0x0004003d,0x00000087,0x00000103,0x00000102,0x00050041, + 0x000000f7,0x00000104,0x000000f2,0x00000019,0x0004003d,0x00000087,0x00000105,0x00000104, + 0x00050041,0x000000f7,0x00000106,0x000000d3,0x0000001d,0x0004003d,0x00000087,0x00000107, + 0x00000106,0x00050041,0x000000f7,0x00000108,0x000000f2,0x0000001d,0x0004003d,0x00000087, + 0x00000109,0x00000108,0x00070050,0x00000088,0x0000010a,0x00000103,0x00000105,0x00000107, + 0x00000109,0x0003003e,0x00000101,0x0000010a,0x00050041,0x000000f7,0x0000010c,0x000000d3, + 0x00000035,0x0004003d,0x00000087,0x0000010d,0x0000010c,0x00050041,0x000000f7,0x0000010e, + 0x000000f2,0x00000035,0x0004003d,0x00000087,0x0000010f,0x0000010e,0x00050041,0x000000f7, + 0x00000111,0x000000d3,0x00000110,0x0004003d,0x00000087,0x00000112,0x00000111,0x00050041, + 0x000000f7,0x00000113,0x000000f2,0x00000110,0x0004003d,0x00000087,0x00000114,0x00000113, + 0x00070050,0x00000088,0x00000115,0x0000010d,0x0000010f,0x00000112,0x00000114,0x0003003e, + 0x0000010b,0x00000115,0x0004003d,0x00000088,0x00000117,0x00000101,0x0004003d,0x00000088, + 0x00000118,0x000000ba,0x0005008e,0x00000088,0x0000011a,0x00000118,0x00000119,0x00050081, + 0x00000088,0x0000011b,0x00000117,0x0000011a,0x00070050,0x00000088,0x0000011d,0x0000011c, + 0x0000011c,0x0000011c,0x0000011c,0x00050083,0x00000088,0x0000011e,0x0000011b,0x0000011d, + 0x0003003e,0x00000116,0x0000011e,0x0004003d,0x00000088,0x00000120,0x0000010b,0x0004003d, + 0x00000088,0x00000121,0x000000c2,0x0005008e,0x00000088,0x00000122,0x00000121,0x00000119, + 0x00050081,0x00000088,0x00000123,0x00000120,0x00000122,0x00070050,0x00000088,0x00000124, + 0x0000011c,0x0000011c,0x0000011c,0x0000011c,0x00050083,0x00000088,0x00000125,0x00000123, + 0x00000124,0x0003003e,0x0000011f,0x00000125,0x0004003d,0x00000088,0x00000126,0x00000116, + 0x00070050,0x00000088,0x00000129,0x00000127,0x00000127,0x00000127,0x00000127,0x00070050, + 0x00000088,0x0000012a,0x00000128,0x00000128,0x00000128,0x00000128,0x0008000c,0x00000088, + 0x0000012b,0x00000001,0x0000002b,0x00000126,0x00000129,0x0000012a,0x0003003e,0x00000116, + 0x0000012b,0x0004003d,0x00000088,0x0000012c,0x0000011f,0x00070050,0x00000088,0x0000012d, + 0x00000127,0x00000127,0x00000127,0x00000127,0x00070050,0x00000088,0x0000012e,0x00000128, + 0x00000128,0x00000128,0x00000128,0x0008000c,0x00000088,0x0000012f,0x00000001,0x0000002b, + 0x0000012c,0x0000012d,0x0000012e,0x0003003e,0x0000011f,0x0000012f,0x00050041,0x0000001a, + 0x00000131,0x0000000a,0x0000001d,0x0004003d,0x00000006,0x00000132,0x00000131,0x00050041, + 0x0000002a,0x00000134,0x00000027,0x00000133,0x0004003d,0x00000006,0x00000135,0x00000134, + 0x00050084,0x00000006,0x00000136,0x00000132,0x00000135,0x00050041,0x0000002a,0x00000138, + 0x00000027,0x00000137,0x0004003d,0x00000006,0x00000139,0x00000138,0x00050080,0x00000006, + 0x0000013a,0x00000136,0x00000139,0x00050041,0x0000001a,0x0000013b,0x0000000a,0x00000019, + 0x0004003d,0x00000006,0x0000013c,0x0000013b,0x00050080,0x00000006,0x0000013d,0x0000013a, + 0x0000013c,0x0003003e,0x00000130,0x0000013d,0x0004003d,0x00000006,0x00000142,0x00000130, + 0x0004003d,0x00000088,0x00000143,0x00000116,0x0006000c,0x00000006,0x00000144,0x00000001, + 0x00000037,0x00000143,0x0004003d,0x00000088,0x00000145,0x0000011f,0x0006000c,0x00000006, + 0x00000146,0x00000001,0x00000037,0x00000145,0x00050050,0x00000007,0x00000147,0x00000144, + 0x00000146,0x00060041,0x00000084,0x00000148,0x00000141,0x00000029,0x00000142,0x0003003e, + 0x00000148,0x00000147,0x00050041,0x0000001a,0x00000149,0x0000000a,0x0000001d,0x0004003d, + 0x00000006,0x0000014a,0x00000149,0x00050041,0x0000002a,0x0000014b,0x00000027,0x0000006f, + 0x0004003d,0x00000006,0x0000014c,0x0000014b,0x00050082,0x00000006,0x0000014d,0x0000014c, + 0x0000001d,0x000500ae,0x000000e8,0x0000014e,0x0000014a,0x0000014d,0x000300f7,0x00000151, + 0x00000000,0x000400fa,0x0000014e,0x00000150,0x00000153,0x000200f8,0x00000150,0x0004003d, + 0x00000006,0x00000152,0x00000092,0x0003003e,0x0000014f,0x00000152,0x000200f9,0x00000151, + 0x000200f8,0x00000153,0x0004003d,0x00000006,0x00000154,0x00000092,0x00050041,0x0000002a, + 0x00000155,0x00000027,0x00000029,0x0004003d,0x00000006,0x00000156,0x00000155,0x00050080, + 0x00000006,0x00000157,0x00000154,0x00000156,0x0003003e,0x0000014f,0x00000157,0x000200f9, + 0x00000151,0x000200f8,0x00000151,0x0004003d,0x00000006,0x00000158,0x0000014f,0x0003003e, + 0x00000092,0x00000158,0x0004003d,0x00000006,0x00000159,0x00000092,0x00060041,0x00000084, + 0x0000015a,0x0000009f,0x00000029,0x00000159,0x0004003d,0x00000007,0x0000015b,0x0000015a, + 0x0003003e,0x0000009b,0x0000015b,0x00050041,0x0000001a,0x0000015c,0x0000009b,0x00000019, + 0x0004003d,0x00000006,0x0000015d,0x0000015c,0x0006000c,0x00000088,0x0000015e,0x00000001, + 0x00000040,0x0000015d,0x0003003e,0x000000a3,0x0000015e,0x00050041,0x0000001a,0x0000015f, + 0x0000009b,0x0000001d,0x0004003d,0x00000006,0x00000160,0x0000015f,0x0006000c,0x00000088, + 0x00000161,0x00000001,0x00000040,0x00000160,0x0003003e,0x000000a7,0x00000161,0x0004003d, + 0x00000006,0x00000162,0x00000092,0x00060041,0x00000084,0x00000163,0x000000ae,0x00000029, + 0x00000162,0x0004003d,0x00000007,0x00000164,0x00000163,0x0003003e,0x0000009b,0x00000164, + 0x00050041,0x0000001a,0x00000165,0x0000009b,0x00000019,0x0004003d,0x00000006,0x00000166, + 0x00000165,0x0006000c,0x00000088,0x00000167,0x00000001,0x00000040,0x00000166,0x0003003e, + 0x000000b2,0x00000167,0x00050041,0x0000001a,0x00000168,0x0000009b,0x0000001d,0x0004003d, + 0x00000006,0x00000169,0x00000168,0x0006000c,0x00000088,0x0000016a,0x00000001,0x00000040, + 0x00000169,0x0003003e,0x000000b6,0x0000016a,0x0004003d,0x00000088,0x0000016b,0x000000a3, + 0x0004003d,0x00000088,0x0000016c,0x000000b2,0x00050083,0x00000088,0x0000016d,0x0000016b, + 0x0000016c,0x0004003d,0x00000088,0x0000016e,0x0000008a,0x00050085,0x00000088,0x0000016f, + 0x0000016d,0x0000016e,0x0004003d,0x00000088,0x00000170,0x000000b2,0x00050081,0x00000088, + 0x00000171,0x0000016f,0x00000170,0x0003003e,0x000000ba,0x00000171,0x0004003d,0x00000088, + 0x00000172,0x000000a7,0x0004003d,0x00000088,0x00000173,0x000000b6,0x00050083,0x00000088, + 0x00000174,0x00000172,0x00000173,0x0004003d,0x00000088,0x00000175,0x0000008e,0x00050085, + 0x00000088,0x00000176,0x00000174,0x00000175,0x0004003d,0x00000088,0x00000177,0x000000b6, + 0x00050081,0x00000088,0x00000178,0x00000176,0x00000177,0x0003003e,0x000000c2,0x00000178, + 0x00050041,0x0000001a,0x00000179,0x0000000b,0x0000001d,0x0004003d,0x00000006,0x0000017a, + 0x00000179,0x00050041,0x0000002a,0x0000017b,0x00000027,0x00000077,0x0004003d,0x00000006, + 0x0000017c,0x0000017b,0x00050082,0x00000006,0x0000017d,0x0000017c,0x0000001d,0x000500ae, + 0x000000e8,0x0000017e,0x0000017a,0x0000017d,0x000300f7,0x00000181,0x00000000,0x000400fa, + 0x0000017e,0x00000180,0x00000183,0x000200f8,0x00000180,0x0004003d,0x00000006,0x00000182, + 0x000000ca,0x0003003e,0x0000017f,0x00000182,0x000200f9,0x00000181,0x000200f8,0x00000183, + 0x0004003d,0x00000006,0x00000184,0x000000ca,0x00050041,0x0000002a,0x00000185,0x00000027, + 0x0000003a,0x0004003d,0x00000006,0x00000186,0x00000185,0x00050080,0x00000006,0x00000187, + 0x00000184,0x00000186,0x0003003e,0x0000017f,0x00000187,0x000200f9,0x00000181,0x000200f8, + 0x00000181,0x0004003d,0x00000006,0x00000188,0x0000017f,0x0003003e,0x000000ca,0x00000188, + 0x0004003d,0x00000006,0x00000189,0x000000ca,0x00060041,0x000000d9,0x0000018a,0x000000d7, + 0x00000029,0x00000189,0x0004003d,0x00000006,0x0000018b,0x0000018a,0x0006000c,0x00000088, + 0x0000018c,0x00000001,0x00000040,0x0000018b,0x0003003e,0x000000d3,0x0000018c,0x0004003d, + 0x00000006,0x0000018d,0x000000ca,0x00050080,0x00000006,0x0000018e,0x0000018d,0x0000001d, + 0x00060041,0x000000d9,0x0000018f,0x000000d7,0x00000029,0x0000018e,0x0004003d,0x00000006, + 0x00000190,0x0000018f,0x0006000c,0x00000088,0x00000191,0x00000001,0x00000040,0x00000190, + 0x0003003e,0x000000dd,0x00000191,0x00050041,0x0000001a,0x00000192,0x0000000b,0x00000019, + 0x0004003d,0x00000006,0x00000193,0x00000192,0x00050041,0x0000002a,0x00000194,0x00000027, + 0x0000003a,0x0004003d,0x00000006,0x00000195,0x00000194,0x00050082,0x00000006,0x00000196, + 0x00000195,0x0000001d,0x000500aa,0x000000e8,0x00000197,0x00000193,0x00000196,0x000300f7, + 0x0000019a,0x00000000,0x000400fa,0x00000197,0x00000199,0x0000019d,0x000200f8,0x00000199, + 0x0004003d,0x00000088,0x0000019b,0x000000d3,0x0009004f,0x00000088,0x0000019c,0x0000019b, + 0x0000019b,0x00000003,0x00000003,0x00000003,0x00000003,0x0003003e,0x00000198,0x0000019c, + 0x000200f9,0x0000019a,0x000200f8,0x0000019d,0x0004003d,0x00000088,0x0000019e,0x000000dd, + 0x0003003e,0x00000198,0x0000019e,0x000200f9,0x0000019a,0x000200f8,0x0000019a,0x0004003d, + 0x00000088,0x0000019f,0x00000198,0x0003003e,0x000000dd,0x0000019f,0x0004003d,0x00000088, + 0x000001a0,0x000000d3,0x0004003d,0x00000088,0x000001a1,0x000000d3,0x0008004f,0x000000f4, + 0x000001a2,0x000001a1,0x000001a1,0x00000001,0x00000002,0x00000003,0x00050041,0x000000f7, + 0x000001a3,0x000000dd,0x00000019,0x0004003d,0x00000087,0x000001a4,0x000001a3,0x00050051, + 0x00000087,0x000001a5,0x000001a2,0x00000000,0x00050051,0x00000087,0x000001a6,0x000001a2, + 0x00000001,0x00050051,0x00000087,0x000001a7,0x000001a2,0x00000002,0x00070050,0x00000088, + 0x000001a8,0x000001a5,0x000001a6,0x000001a7,0x000001a4,0x00050081,0x00000088,0x000001a9, + 0x000001a0,0x000001a8,0x0005008e,0x00000088,0x000001aa,0x000001a9,0x000000ff,0x0003003e, + 0x000000f2,0x000001aa,0x00050041,0x000000f7,0x000001ac,0x000000d3,0x00000019,0x0004003d, + 0x00000087,0x000001ad,0x000001ac,0x00050041,0x000000f7,0x000001ae,0x000000f2,0x00000019, + 0x0004003d,0x00000087,0x000001af,0x000001ae,0x00050041,0x000000f7,0x000001b0,0x000000d3, + 0x0000001d,0x0004003d,0x00000087,0x000001b1,0x000001b0,0x00050041,0x000000f7,0x000001b2, + 0x000000f2,0x0000001d,0x0004003d,0x00000087,0x000001b3,0x000001b2,0x00070050,0x00000088, + 0x000001b4,0x000001ad,0x000001af,0x000001b1,0x000001b3,0x0003003e,0x000001ab,0x000001b4, + 0x00050041,0x000000f7,0x000001b6,0x000000d3,0x00000035,0x0004003d,0x00000087,0x000001b7, + 0x000001b6,0x00050041,0x000000f7,0x000001b8,0x000000f2,0x00000035,0x0004003d,0x00000087, + 0x000001b9,0x000001b8,0x00050041,0x000000f7,0x000001ba,0x000000d3,0x00000110,0x0004003d, + 0x00000087,0x000001bb,0x000001ba,0x00050041,0x000000f7,0x000001bc,0x000000f2,0x00000110, + 0x0004003d,0x00000087,0x000001bd,0x000001bc,0x00070050,0x00000088,0x000001be,0x000001b7, + 0x000001b9,0x000001bb,0x000001bd,0x0003003e,0x000001b5,0x000001be,0x0004003d,0x00000088, + 0x000001bf,0x00000101,0x0004003d,0x00000088,0x000001c0,0x000001ab,0x00050081,0x00000088, + 0x000001c1,0x000001bf,0x000001c0,0x0005008e,0x00000088,0x000001c2,0x000001c1,0x000000ff, + 0x0003003e,0x000001ab,0x000001c2,0x0004003d,0x00000088,0x000001c3,0x0000010b,0x0004003d, + 0x00000088,0x000001c4,0x000001b5,0x00050081,0x00000088,0x000001c5,0x000001c3,0x000001c4, + 0x0005008e,0x00000088,0x000001c6,0x000001c5,0x000000ff,0x0003003e,0x000001b5,0x000001c6, + 0x0004003d,0x00000088,0x000001c7,0x000001ab,0x0004003d,0x00000088,0x000001c8,0x000000ba, + 0x0005008e,0x00000088,0x000001c9,0x000001c8,0x00000119,0x00050081,0x00000088,0x000001ca, + 0x000001c7,0x000001c9,0x00070050,0x00000088,0x000001cb,0x0000011c,0x0000011c,0x0000011c, + 0x0000011c,0x00050083,0x00000088,0x000001cc,0x000001ca,0x000001cb,0x0003003e,0x00000116, + 0x000001cc,0x0004003d,0x00000088,0x000001cd,0x000001b5,0x0004003d,0x00000088,0x000001ce, + 0x000000c2,0x0005008e,0x00000088,0x000001cf,0x000001ce,0x00000119,0x00050081,0x00000088, + 0x000001d0,0x000001cd,0x000001cf,0x00070050,0x00000088,0x000001d1,0x0000011c,0x0000011c, + 0x0000011c,0x0000011c,0x00050083,0x00000088,0x000001d2,0x000001d0,0x000001d1,0x0003003e, + 0x0000011f,0x000001d2,0x0004003d,0x00000088,0x000001d3,0x00000116,0x00070050,0x00000088, + 0x000001d4,0x00000127,0x00000127,0x00000127,0x00000127,0x00070050,0x00000088,0x000001d5, + 0x00000128,0x00000128,0x00000128,0x00000128,0x0008000c,0x00000088,0x000001d6,0x00000001, + 0x0000002b,0x000001d3,0x000001d4,0x000001d5,0x0003003e,0x00000116,0x000001d6,0x0004003d, + 0x00000088,0x000001d7,0x0000011f,0x00070050,0x00000088,0x000001d8,0x00000127,0x00000127, + 0x00000127,0x00000127,0x00070050,0x00000088,0x000001d9,0x00000128,0x00000128,0x00000128, + 0x00000128,0x0008000c,0x00000088,0x000001da,0x00000001,0x0000002b,0x000001d7,0x000001d8, + 0x000001d9,0x0003003e,0x0000011f,0x000001da,0x00050041,0x0000001a,0x000001db,0x0000000a, + 0x0000001d,0x0004003d,0x00000006,0x000001dc,0x000001db,0x00050041,0x0000002a,0x000001dd, + 0x00000027,0x0000006f,0x0004003d,0x00000006,0x000001de,0x000001dd,0x00050082,0x00000006, + 0x000001df,0x000001de,0x0000001d,0x000500ae,0x000000e8,0x000001e0,0x000001dc,0x000001df, + 0x000300f7,0x000001e3,0x00000000,0x000400fa,0x000001e0,0x000001e2,0x000001e5,0x000200f8, + 0x000001e2,0x0004003d,0x00000006,0x000001e4,0x00000130,0x0003003e,0x000001e1,0x000001e4, + 0x000200f9,0x000001e3,0x000200f8,0x000001e5,0x0004003d,0x00000006,0x000001e6,0x00000130, + 0x00050041,0x0000002a,0x000001e7,0x00000027,0x00000133,0x0004003d,0x00000006,0x000001e8, + 0x000001e7,0x00050080,0x00000006,0x000001e9,0x000001e6,0x000001e8,0x0003003e,0x000001e1, + 0x000001e9,0x000200f9,0x000001e3,0x000200f8,0x000001e3,0x0004003d,0x00000006,0x000001ea, + 0x000001e1,0x0003003e,0x00000130,0x000001ea,0x0004003d,0x00000006,0x000001eb,0x00000130, + 0x0004003d,0x00000088,0x000001ec,0x00000116,0x0006000c,0x00000006,0x000001ed,0x00000001, + 0x00000037,0x000001ec,0x0004003d,0x00000088,0x000001ee,0x0000011f,0x0006000c,0x00000006, + 0x000001ef,0x00000001,0x00000037,0x000001ee,0x00050050,0x00000007,0x000001f0,0x000001ed, + 0x000001ef,0x00060041,0x00000084,0x000001f1,0x00000141,0x00000029,0x000001eb,0x0003003e, + 0x000001f1,0x000001f0,0x000100fd,0x00010038,0x00050036,0x00000002,0x00000010,0x00000000, + 0x00000009,0x00030037,0x00000008,0x0000000e,0x00030037,0x00000008,0x0000000f,0x000200f8, + 0x00000011,0x0004003b,0x00000008,0x00000202,0x00000007,0x0004003b,0x00000089,0x00000207, + 0x00000007,0x0004003b,0x00000089,0x0000020b,0x00000007,0x0004003b,0x0000001a,0x0000020f, + 0x00000007,0x0004003b,0x00000008,0x00000218,0x00000007,0x0004003b,0x00000089,0x00000220, + 0x00000007,0x0004003b,0x00000089,0x00000224,0x00000007,0x0004003b,0x00000089,0x0000022f, + 0x00000007,0x0004003b,0x00000089,0x00000233,0x00000007,0x0004003b,0x00000089,0x00000240, + 0x00000007,0x0004003b,0x00000089,0x00000248,0x00000007,0x0004003b,0x0000001a,0x00000250, + 0x00000007,0x0004003b,0x00000089,0x00000259,0x00000007,0x0004003b,0x00000089,0x00000262, + 0x00000007,0x0004003b,0x00000089,0x0000026e,0x00000007,0x0004003b,0x00000089,0x00000276, + 0x00000007,0x0004003b,0x00000089,0x00000283,0x00000007,0x0004003b,0x00000089,0x0000028d, + 0x00000007,0x0004003b,0x00000089,0x00000297,0x00000007,0x0004003b,0x00000089,0x0000029e, + 0x00000007,0x0004003b,0x0000001a,0x000002ad,0x00000007,0x0004003b,0x0000001a,0x000002cb, + 0x00000007,0x0004003b,0x0000001a,0x000002fc,0x00000007,0x0004003b,0x00000089,0x00000315, + 0x00000007,0x0004003b,0x00000089,0x00000329,0x00000007,0x0004003b,0x00000089,0x00000333, + 0x00000007,0x00050041,0x0000001a,0x000001f2,0x0000000e,0x0000001d,0x0004003d,0x00000006, + 0x000001f3,0x000001f2,0x00050041,0x0000002a,0x000001f4,0x00000027,0x0000006f,0x0004003d, + 0x00000006,0x000001f5,0x000001f4,0x00050086,0x00000006,0x000001f6,0x000001f5,0x00000035, + 0x00050082,0x00000006,0x000001f7,0x000001f6,0x00000035,0x0008000c,0x00000006,0x000001f8, + 0x00000001,0x0000002c,0x000001f3,0x00000019,0x000001f7,0x00050041,0x0000001a,0x000001f9, + 0x0000000e,0x0000001d,0x0003003e,0x000001f9,0x000001f8,0x00050041,0x0000001a,0x000001fa, + 0x0000000f,0x0000001d,0x0004003d,0x00000006,0x000001fb,0x000001fa,0x00050041,0x0000002a, + 0x000001fc,0x00000027,0x00000077,0x0004003d,0x00000006,0x000001fd,0x000001fc,0x00050086, + 0x00000006,0x000001fe,0x000001fd,0x00000035,0x00050082,0x00000006,0x000001ff,0x000001fe, + 0x0000001d,0x0008000c,0x00000006,0x00000200,0x00000001,0x0000002c,0x000001fb,0x00000019, + 0x000001ff,0x00050041,0x0000001a,0x00000201,0x0000000f,0x0000001d,0x0003003e,0x00000201, + 0x00000200,0x00050041,0x0000001a,0x00000203,0x0000000e,0x00000019,0x0004003d,0x00000006, + 0x00000204,0x00000203,0x00060041,0x00000084,0x00000205,0x00000081,0x00000029,0x00000204, + 0x0004003d,0x00000007,0x00000206,0x00000205,0x0003003e,0x00000202,0x00000206,0x00050041, + 0x0000001a,0x00000208,0x00000202,0x00000019,0x0004003d,0x00000006,0x00000209,0x00000208, + 0x0006000c,0x00000088,0x0000020a,0x00000001,0x00000040,0x00000209,0x0003003e,0x00000207, + 0x0000020a,0x00050041,0x0000001a,0x0000020c,0x00000202,0x0000001d,0x0004003d,0x00000006, + 0x0000020d,0x0000020c,0x0006000c,0x00000088,0x0000020e,0x00000001,0x00000040,0x0000020d, + 0x0003003e,0x0000020b,0x0000020e,0x00050041,0x0000001a,0x00000210,0x0000000e,0x0000001d, + 0x0004003d,0x00000006,0x00000211,0x00000210,0x00050041,0x0000002a,0x00000212,0x00000027, + 0x00000029,0x0004003d,0x00000006,0x00000213,0x00000212,0x00050084,0x00000006,0x00000214, + 0x00000211,0x00000213,0x00050041,0x0000001a,0x00000215,0x0000000e,0x00000019,0x0004003d, + 0x00000006,0x00000216,0x00000215,0x00050080,0x00000006,0x00000217,0x00000214,0x00000216, + 0x0003003e,0x0000020f,0x00000217,0x0004003d,0x00000006,0x0000021d,0x0000020f,0x00060041, + 0x00000084,0x0000021e,0x0000021c,0x00000029,0x0000021d,0x0004003d,0x00000007,0x0000021f, + 0x0000021e,0x0003003e,0x00000218,0x0000021f,0x00050041,0x0000001a,0x00000221,0x00000218, + 0x00000019,0x0004003d,0x00000006,0x00000222,0x00000221,0x0006000c,0x00000088,0x00000223, + 0x00000001,0x00000040,0x00000222,0x0003003e,0x00000220,0x00000223,0x00050041,0x0000001a, + 0x00000225,0x00000218,0x0000001d,0x0004003d,0x00000006,0x00000226,0x00000225,0x0006000c, + 0x00000088,0x00000227,0x00000001,0x00000040,0x00000226,0x0003003e,0x00000224,0x00000227, + 0x0004003d,0x00000006,0x0000022c,0x0000020f,0x00060041,0x00000084,0x0000022d,0x0000022b, + 0x00000029,0x0000022c,0x0004003d,0x00000007,0x0000022e,0x0000022d,0x0003003e,0x00000218, + 0x0000022e,0x00050041,0x0000001a,0x00000230,0x00000218,0x00000019,0x0004003d,0x00000006, + 0x00000231,0x00000230,0x0006000c,0x00000088,0x00000232,0x00000001,0x00000040,0x00000231, + 0x0003003e,0x0000022f,0x00000232,0x00050041,0x0000001a,0x00000234,0x00000218,0x0000001d, + 0x0004003d,0x00000006,0x00000235,0x00000234,0x0006000c,0x00000088,0x00000236,0x00000001, + 0x00000040,0x00000235,0x0003003e,0x00000233,0x00000236,0x0004003d,0x00000088,0x00000238, + 0x00000207,0x0007004f,0x00000237,0x00000239,0x00000238,0x00000238,0x00000000,0x00000002, + 0x0004003d,0x00000088,0x0000023a,0x00000207,0x0009004f,0x00000088,0x0000023b,0x0000023a, + 0x00000239,0x00000000,0x00000004,0x00000002,0x00000005,0x0003003e,0x00000207,0x0000023b, + 0x0004003d,0x00000088,0x0000023c,0x0000020b,0x0007004f,0x00000237,0x0000023d,0x0000023c, + 0x0000023c,0x00000000,0x00000002,0x0004003d,0x00000088,0x0000023e,0x0000020b,0x0009004f, + 0x00000088,0x0000023f,0x0000023e,0x0000023d,0x00000000,0x00000004,0x00000002,0x00000005, + 0x0003003e,0x0000020b,0x0000023f,0x0004003d,0x00000088,0x00000241,0x00000220,0x0004003d, + 0x00000088,0x00000242,0x0000022f,0x00050083,0x00000088,0x00000243,0x00000241,0x00000242, + 0x0004003d,0x00000088,0x00000244,0x00000207,0x00050085,0x00000088,0x00000245,0x00000243, + 0x00000244,0x0004003d,0x00000088,0x00000246,0x0000022f,0x00050081,0x00000088,0x00000247, + 0x00000245,0x00000246,0x0003003e,0x00000240,0x00000247,0x0004003d,0x00000088,0x00000249, + 0x00000224,0x0004003d,0x00000088,0x0000024a,0x00000233,0x00050083,0x00000088,0x0000024b, + 0x00000249,0x0000024a,0x0004003d,0x00000088,0x0000024c,0x0000020b,0x00050085,0x00000088, + 0x0000024d,0x0000024b,0x0000024c,0x0004003d,0x00000088,0x0000024e,0x00000233,0x00050081, + 0x00000088,0x0000024f,0x0000024d,0x0000024e,0x0003003e,0x00000248,0x0000024f,0x00050041, + 0x0000001a,0x00000251,0x0000000f,0x0000001d,0x0004003d,0x00000006,0x00000252,0x00000251, + 0x00050041,0x0000002a,0x00000253,0x00000027,0x0000003a,0x0004003d,0x00000006,0x00000254, + 0x00000253,0x00050084,0x00000006,0x00000255,0x00000252,0x00000254,0x00050041,0x0000001a, + 0x00000256,0x0000000f,0x00000019,0x0004003d,0x00000006,0x00000257,0x00000256,0x00050080, + 0x00000006,0x00000258,0x00000255,0x00000257,0x0003003e,0x00000250,0x00000258,0x0004003d, + 0x00000006,0x0000025e,0x00000250,0x00060041,0x000000d9,0x0000025f,0x0000025d,0x00000029, + 0x0000025e,0x0004003d,0x00000006,0x00000260,0x0000025f,0x0006000c,0x00000088,0x00000261, + 0x00000001,0x00000040,0x00000260,0x0003003e,0x00000259,0x00000261,0x0004003d,0x00000006, + 0x00000263,0x00000250,0x00050080,0x00000006,0x00000264,0x00000263,0x0000001d,0x00060041, + 0x000000d9,0x00000265,0x0000025d,0x00000029,0x00000264,0x0004003d,0x00000006,0x00000266, + 0x00000265,0x0006000c,0x00000088,0x00000267,0x00000001,0x00000040,0x00000266,0x0003003e, + 0x00000262,0x00000267,0x00050041,0x0000001a,0x00000268,0x0000000f,0x00000019,0x0004003d, + 0x00000006,0x00000269,0x00000268,0x00050041,0x0000002a,0x0000026a,0x00000027,0x0000003a, + 0x0004003d,0x00000006,0x0000026b,0x0000026a,0x00050082,0x00000006,0x0000026c,0x0000026b, + 0x0000001d,0x000500aa,0x000000e8,0x0000026d,0x00000269,0x0000026c,0x000300f7,0x00000270, + 0x00000000,0x000400fa,0x0000026d,0x0000026f,0x00000273,0x000200f8,0x0000026f,0x0004003d, + 0x00000088,0x00000271,0x00000259,0x0009004f,0x00000088,0x00000272,0x00000271,0x00000271, + 0x00000002,0x00000003,0x00000002,0x00000003,0x0003003e,0x0000026e,0x00000272,0x000200f9, + 0x00000270,0x000200f8,0x00000273,0x0004003d,0x00000088,0x00000274,0x00000262,0x0003003e, + 0x0000026e,0x00000274,0x000200f9,0x00000270,0x000200f8,0x00000270,0x0004003d,0x00000088, + 0x00000275,0x0000026e,0x0003003e,0x00000262,0x00000275,0x0004003d,0x00000088,0x00000277, + 0x00000259,0x0004003d,0x00000088,0x00000278,0x00000259,0x0007004f,0x00000237,0x00000279, + 0x00000278,0x00000278,0x00000002,0x00000003,0x0004003d,0x00000088,0x0000027a,0x00000262, + 0x0007004f,0x00000237,0x0000027b,0x0000027a,0x0000027a,0x00000000,0x00000001,0x00050051, + 0x00000087,0x0000027c,0x00000279,0x00000000,0x00050051,0x00000087,0x0000027d,0x00000279, + 0x00000001,0x00050051,0x00000087,0x0000027e,0x0000027b,0x00000000,0x00050051,0x00000087, + 0x0000027f,0x0000027b,0x00000001,0x00070050,0x00000088,0x00000280,0x0000027c,0x0000027d, + 0x0000027e,0x0000027f,0x00050081,0x00000088,0x00000281,0x00000277,0x00000280,0x0005008e, + 0x00000088,0x00000282,0x00000281,0x000000ff,0x0003003e,0x00000276,0x00000282,0x0004003d, + 0x00000088,0x00000284,0x00000259,0x0007004f,0x00000237,0x00000285,0x00000284,0x00000284, + 0x00000000,0x00000001,0x0004003d,0x00000088,0x00000286,0x00000276,0x0007004f,0x00000237, + 0x00000287,0x00000286,0x00000286,0x00000000,0x00000001,0x00050051,0x00000087,0x00000288, + 0x00000285,0x00000000,0x00050051,0x00000087,0x00000289,0x00000285,0x00000001,0x00050051, + 0x00000087,0x0000028a,0x00000287,0x00000000,0x00050051,0x00000087,0x0000028b,0x00000287, + 0x00000001,0x00070050,0x00000088,0x0000028c,0x00000288,0x00000289,0x0000028a,0x0000028b, + 0x0003003e,0x00000283,0x0000028c,0x0004003d,0x00000088,0x0000028e,0x00000259,0x0007004f, + 0x00000237,0x0000028f,0x0000028e,0x0000028e,0x00000002,0x00000003,0x0004003d,0x00000088, + 0x00000290,0x00000276,0x0007004f,0x00000237,0x00000291,0x00000290,0x00000290,0x00000002, + 0x00000003,0x00050051,0x00000087,0x00000292,0x0000028f,0x00000000,0x00050051,0x00000087, + 0x00000293,0x0000028f,0x00000001,0x00050051,0x00000087,0x00000294,0x00000291,0x00000000, + 0x00050051,0x00000087,0x00000295,0x00000291,0x00000001,0x00070050,0x00000088,0x00000296, + 0x00000292,0x00000293,0x00000294,0x00000295,0x0003003e,0x0000028d,0x00000296,0x0004003d, + 0x00000088,0x00000298,0x00000283,0x0004003d,0x00000088,0x00000299,0x00000240,0x0005008e, + 0x00000088,0x0000029a,0x00000299,0x00000119,0x00050081,0x00000088,0x0000029b,0x00000298, + 0x0000029a,0x00070050,0x00000088,0x0000029c,0x0000011c,0x0000011c,0x0000011c,0x0000011c, + 0x00050083,0x00000088,0x0000029d,0x0000029b,0x0000029c,0x0003003e,0x00000297,0x0000029d, + 0x0004003d,0x00000088,0x0000029f,0x0000028d,0x0004003d,0x00000088,0x000002a0,0x00000248, + 0x0005008e,0x00000088,0x000002a1,0x000002a0,0x00000119,0x00050081,0x00000088,0x000002a2, + 0x0000029f,0x000002a1,0x00070050,0x00000088,0x000002a3,0x0000011c,0x0000011c,0x0000011c, + 0x0000011c,0x00050083,0x00000088,0x000002a4,0x000002a2,0x000002a3,0x0003003e,0x0000029e, + 0x000002a4,0x0004003d,0x00000088,0x000002a5,0x00000297,0x00070050,0x00000088,0x000002a6, + 0x00000127,0x00000127,0x00000127,0x00000127,0x00070050,0x00000088,0x000002a7,0x00000128, + 0x00000128,0x00000128,0x00000128,0x0008000c,0x00000088,0x000002a8,0x00000001,0x0000002b, + 0x000002a5,0x000002a6,0x000002a7,0x0003003e,0x00000297,0x000002a8,0x0004003d,0x00000088, + 0x000002a9,0x0000029e,0x00070050,0x00000088,0x000002aa,0x00000127,0x00000127,0x00000127, + 0x00000127,0x00070050,0x00000088,0x000002ab,0x00000128,0x00000128,0x00000128,0x00000128, + 0x0008000c,0x00000088,0x000002ac,0x00000001,0x0000002b,0x000002a9,0x000002aa,0x000002ab, + 0x0003003e,0x0000029e,0x000002ac,0x00050041,0x0000001a,0x000002ae,0x0000000e,0x0000001d, + 0x0004003d,0x00000006,0x000002af,0x000002ae,0x00050041,0x0000002a,0x000002b0,0x00000027, + 0x00000133,0x0004003d,0x00000006,0x000002b1,0x000002b0,0x00050084,0x00000006,0x000002b2, + 0x000002af,0x000002b1,0x00050041,0x0000002a,0x000002b3,0x00000027,0x00000137,0x0004003d, + 0x00000006,0x000002b4,0x000002b3,0x00050080,0x00000006,0x000002b5,0x000002b2,0x000002b4, + 0x00050041,0x0000001a,0x000002b6,0x0000000e,0x00000019,0x0004003d,0x00000006,0x000002b7, + 0x000002b6,0x00050080,0x00000006,0x000002b8,0x000002b5,0x000002b7,0x0003003e,0x000002ad, + 0x000002b8,0x0004003d,0x00000006,0x000002bd,0x000002ad,0x0004003d,0x00000088,0x000002be, + 0x00000297,0x0006000c,0x00000006,0x000002bf,0x00000001,0x00000037,0x000002be,0x0004003d, + 0x00000088,0x000002c0,0x0000029e,0x0006000c,0x00000006,0x000002c1,0x00000001,0x00000037, + 0x000002c0,0x00050050,0x00000007,0x000002c2,0x000002bf,0x000002c1,0x00060041,0x00000084, + 0x000002c3,0x000002bc,0x00000029,0x000002bd,0x0003003e,0x000002c3,0x000002c2,0x00050041, + 0x0000001a,0x000002c4,0x0000000e,0x0000001d,0x0004003d,0x00000006,0x000002c5,0x000002c4, + 0x00050041,0x0000002a,0x000002c6,0x00000027,0x0000006f,0x0004003d,0x00000006,0x000002c7, + 0x000002c6,0x00050086,0x00000006,0x000002c8,0x000002c7,0x00000035,0x00050082,0x00000006, + 0x000002c9,0x000002c8,0x0000001d,0x000500ae,0x000000e8,0x000002ca,0x000002c5,0x000002c9, + 0x000300f7,0x000002cd,0x00000000,0x000400fa,0x000002ca,0x000002cc,0x000002cf,0x000200f8, + 0x000002cc,0x0004003d,0x00000006,0x000002ce,0x0000020f,0x0003003e,0x000002cb,0x000002ce, + 0x000200f9,0x000002cd,0x000200f8,0x000002cf,0x0004003d,0x00000006,0x000002d0,0x0000020f, + 0x00050041,0x0000002a,0x000002d1,0x00000027,0x00000029,0x0004003d,0x00000006,0x000002d2, + 0x000002d1,0x00050080,0x00000006,0x000002d3,0x000002d0,0x000002d2,0x0003003e,0x000002cb, + 0x000002d3,0x000200f9,0x000002cd,0x000200f8,0x000002cd,0x0004003d,0x00000006,0x000002d4, + 0x000002cb,0x0003003e,0x0000020f,0x000002d4,0x0004003d,0x00000006,0x000002d5,0x0000020f, + 0x00060041,0x00000084,0x000002d6,0x0000021c,0x00000029,0x000002d5,0x0004003d,0x00000007, + 0x000002d7,0x000002d6,0x0003003e,0x00000218,0x000002d7,0x00050041,0x0000001a,0x000002d8, + 0x00000218,0x00000019,0x0004003d,0x00000006,0x000002d9,0x000002d8,0x0006000c,0x00000088, + 0x000002da,0x00000001,0x00000040,0x000002d9,0x0003003e,0x00000220,0x000002da,0x00050041, + 0x0000001a,0x000002db,0x00000218,0x0000001d,0x0004003d,0x00000006,0x000002dc,0x000002db, + 0x0006000c,0x00000088,0x000002dd,0x00000001,0x00000040,0x000002dc,0x0003003e,0x00000224, + 0x000002dd,0x0004003d,0x00000006,0x000002de,0x0000020f,0x00060041,0x00000084,0x000002df, + 0x0000022b,0x00000029,0x000002de,0x0004003d,0x00000007,0x000002e0,0x000002df,0x0003003e, + 0x00000218,0x000002e0,0x00050041,0x0000001a,0x000002e1,0x00000218,0x00000019,0x0004003d, + 0x00000006,0x000002e2,0x000002e1,0x0006000c,0x00000088,0x000002e3,0x00000001,0x00000040, + 0x000002e2,0x0003003e,0x0000022f,0x000002e3,0x00050041,0x0000001a,0x000002e4,0x00000218, + 0x0000001d,0x0004003d,0x00000006,0x000002e5,0x000002e4,0x0006000c,0x00000088,0x000002e6, + 0x00000001,0x00000040,0x000002e5,0x0003003e,0x00000233,0x000002e6,0x0004003d,0x00000088, + 0x000002e7,0x00000220,0x0004003d,0x00000088,0x000002e8,0x0000022f,0x00050083,0x00000088, + 0x000002e9,0x000002e7,0x000002e8,0x0004003d,0x00000088,0x000002ea,0x00000207,0x00050085, + 0x00000088,0x000002eb,0x000002e9,0x000002ea,0x0004003d,0x00000088,0x000002ec,0x0000022f, + 0x00050081,0x00000088,0x000002ed,0x000002eb,0x000002ec,0x0003003e,0x00000240,0x000002ed, + 0x0004003d,0x00000088,0x000002ee,0x00000224,0x0004003d,0x00000088,0x000002ef,0x00000233, + 0x00050083,0x00000088,0x000002f0,0x000002ee,0x000002ef,0x0004003d,0x00000088,0x000002f1, + 0x0000020b,0x00050085,0x00000088,0x000002f2,0x000002f0,0x000002f1,0x0004003d,0x00000088, + 0x000002f3,0x00000233,0x00050081,0x00000088,0x000002f4,0x000002f2,0x000002f3,0x0003003e, + 0x00000248,0x000002f4,0x00050041,0x0000001a,0x000002f5,0x0000000f,0x0000001d,0x0004003d, + 0x00000006,0x000002f6,0x000002f5,0x00050041,0x0000002a,0x000002f7,0x00000027,0x00000077, + 0x0004003d,0x00000006,0x000002f8,0x000002f7,0x00050086,0x00000006,0x000002f9,0x000002f8, + 0x00000035,0x00050082,0x00000006,0x000002fa,0x000002f9,0x0000001d,0x000500ae,0x000000e8, + 0x000002fb,0x000002f6,0x000002fa,0x000300f7,0x000002fe,0x00000000,0x000400fa,0x000002fb, + 0x000002fd,0x00000300,0x000200f8,0x000002fd,0x0004003d,0x00000006,0x000002ff,0x00000250, + 0x0003003e,0x000002fc,0x000002ff,0x000200f9,0x000002fe,0x000200f8,0x00000300,0x0004003d, + 0x00000006,0x00000301,0x00000250,0x00050041,0x0000002a,0x00000302,0x00000027,0x0000003a, + 0x0004003d,0x00000006,0x00000303,0x00000302,0x00050080,0x00000006,0x00000304,0x00000301, + 0x00000303,0x0003003e,0x000002fc,0x00000304,0x000200f9,0x000002fe,0x000200f8,0x000002fe, + 0x0004003d,0x00000006,0x00000305,0x000002fc,0x0003003e,0x00000250,0x00000305,0x0004003d, + 0x00000006,0x00000306,0x00000250,0x00060041,0x000000d9,0x00000307,0x0000025d,0x00000029, + 0x00000306,0x0004003d,0x00000006,0x00000308,0x00000307,0x0006000c,0x00000088,0x00000309, + 0x00000001,0x00000040,0x00000308,0x0003003e,0x00000259,0x00000309,0x0004003d,0x00000006, + 0x0000030a,0x00000250,0x00050080,0x00000006,0x0000030b,0x0000030a,0x0000001d,0x00060041, + 0x000000d9,0x0000030c,0x0000025d,0x00000029,0x0000030b,0x0004003d,0x00000006,0x0000030d, + 0x0000030c,0x0006000c,0x00000088,0x0000030e,0x00000001,0x00000040,0x0000030d,0x0003003e, + 0x00000262,0x0000030e,0x00050041,0x0000001a,0x0000030f,0x0000000f,0x00000019,0x0004003d, + 0x00000006,0x00000310,0x0000030f,0x00050041,0x0000002a,0x00000311,0x00000027,0x0000003a, + 0x0004003d,0x00000006,0x00000312,0x00000311,0x00050082,0x00000006,0x00000313,0x00000312, + 0x0000001d,0x000500aa,0x000000e8,0x00000314,0x00000310,0x00000313,0x000300f7,0x00000317, + 0x00000000,0x000400fa,0x00000314,0x00000316,0x0000031a,0x000200f8,0x00000316,0x0004003d, + 0x00000088,0x00000318,0x00000259,0x0009004f,0x00000088,0x00000319,0x00000318,0x00000318, + 0x00000002,0x00000003,0x00000002,0x00000003,0x0003003e,0x00000315,0x00000319,0x000200f9, + 0x00000317,0x000200f8,0x0000031a,0x0004003d,0x00000088,0x0000031b,0x00000262,0x0003003e, + 0x00000315,0x0000031b,0x000200f9,0x00000317,0x000200f8,0x00000317,0x0004003d,0x00000088, + 0x0000031c,0x00000315,0x0003003e,0x00000262,0x0000031c,0x0004003d,0x00000088,0x0000031d, + 0x00000259,0x0004003d,0x00000088,0x0000031e,0x00000259,0x0007004f,0x00000237,0x0000031f, + 0x0000031e,0x0000031e,0x00000002,0x00000003,0x0004003d,0x00000088,0x00000320,0x00000262, + 0x0007004f,0x00000237,0x00000321,0x00000320,0x00000320,0x00000000,0x00000001,0x00050051, + 0x00000087,0x00000322,0x0000031f,0x00000000,0x00050051,0x00000087,0x00000323,0x0000031f, + 0x00000001,0x00050051,0x00000087,0x00000324,0x00000321,0x00000000,0x00050051,0x00000087, + 0x00000325,0x00000321,0x00000001,0x00070050,0x00000088,0x00000326,0x00000322,0x00000323, + 0x00000324,0x00000325,0x00050081,0x00000088,0x00000327,0x0000031d,0x00000326,0x0005008e, + 0x00000088,0x00000328,0x00000327,0x000000ff,0x0003003e,0x00000276,0x00000328,0x0004003d, + 0x00000088,0x0000032a,0x00000259,0x0007004f,0x00000237,0x0000032b,0x0000032a,0x0000032a, + 0x00000000,0x00000001,0x0004003d,0x00000088,0x0000032c,0x00000276,0x0007004f,0x00000237, + 0x0000032d,0x0000032c,0x0000032c,0x00000000,0x00000001,0x00050051,0x00000087,0x0000032e, + 0x0000032b,0x00000000,0x00050051,0x00000087,0x0000032f,0x0000032b,0x00000001,0x00050051, + 0x00000087,0x00000330,0x0000032d,0x00000000,0x00050051,0x00000087,0x00000331,0x0000032d, + 0x00000001,0x00070050,0x00000088,0x00000332,0x0000032e,0x0000032f,0x00000330,0x00000331, + 0x0003003e,0x00000329,0x00000332,0x0004003d,0x00000088,0x00000334,0x00000259,0x0007004f, + 0x00000237,0x00000335,0x00000334,0x00000334,0x00000002,0x00000003,0x0004003d,0x00000088, + 0x00000336,0x00000276,0x0007004f,0x00000237,0x00000337,0x00000336,0x00000336,0x00000002, + 0x00000003,0x00050051,0x00000087,0x00000338,0x00000335,0x00000000,0x00050051,0x00000087, + 0x00000339,0x00000335,0x00000001,0x00050051,0x00000087,0x0000033a,0x00000337,0x00000000, + 0x00050051,0x00000087,0x0000033b,0x00000337,0x00000001,0x00070050,0x00000088,0x0000033c, + 0x00000338,0x00000339,0x0000033a,0x0000033b,0x0003003e,0x00000333,0x0000033c,0x0004003d, + 0x00000088,0x0000033d,0x00000283,0x0004003d,0x00000088,0x0000033e,0x00000329,0x00050081, + 0x00000088,0x0000033f,0x0000033d,0x0000033e,0x0005008e,0x00000088,0x00000340,0x0000033f, + 0x000000ff,0x0003003e,0x00000329,0x00000340,0x0004003d,0x00000088,0x00000341,0x0000028d, + 0x0004003d,0x00000088,0x00000342,0x00000333,0x00050081,0x00000088,0x00000343,0x00000341, + 0x00000342,0x0005008e,0x00000088,0x00000344,0x00000343,0x000000ff,0x0003003e,0x00000333, + 0x00000344,0x0004003d,0x00000088,0x00000345,0x00000329,0x0004003d,0x00000088,0x00000346, + 0x00000240,0x0005008e,0x00000088,0x00000347,0x00000346,0x00000119,0x00050081,0x00000088, + 0x00000348,0x00000345,0x00000347,0x00070050,0x00000088,0x00000349,0x0000011c,0x0000011c, + 0x0000011c,0x0000011c,0x00050083,0x00000088,0x0000034a,0x00000348,0x00000349,0x0003003e, + 0x00000297,0x0000034a,0x0004003d,0x00000088,0x0000034b,0x00000333,0x0004003d,0x00000088, + 0x0000034c,0x00000248,0x0005008e,0x00000088,0x0000034d,0x0000034c,0x00000119,0x00050081, + 0x00000088,0x0000034e,0x0000034b,0x0000034d,0x00070050,0x00000088,0x0000034f,0x0000011c, + 0x0000011c,0x0000011c,0x0000011c,0x00050083,0x00000088,0x00000350,0x0000034e,0x0000034f, + 0x0003003e,0x0000029e,0x00000350,0x0004003d,0x00000088,0x00000351,0x00000297,0x00070050, + 0x00000088,0x00000352,0x00000127,0x00000127,0x00000127,0x00000127,0x00070050,0x00000088, + 0x00000353,0x00000128,0x00000128,0x00000128,0x00000128,0x0008000c,0x00000088,0x00000354, + 0x00000001,0x0000002b,0x00000351,0x00000352,0x00000353,0x0003003e,0x00000297,0x00000354, + 0x0004003d,0x00000088,0x00000355,0x0000029e,0x00070050,0x00000088,0x00000356,0x00000127, + 0x00000127,0x00000127,0x00000127,0x00070050,0x00000088,0x00000357,0x00000128,0x00000128, + 0x00000128,0x00000128,0x0008000c,0x00000088,0x00000358,0x00000001,0x0000002b,0x00000355, + 0x00000356,0x00000357,0x0003003e,0x0000029e,0x00000358,0x00050041,0x0000002a,0x00000359, + 0x00000027,0x00000133,0x0004003d,0x00000006,0x0000035a,0x00000359,0x0004003d,0x00000006, + 0x0000035b,0x000002ad,0x00050080,0x00000006,0x0000035c,0x0000035b,0x0000035a,0x0003003e, + 0x000002ad,0x0000035c,0x0004003d,0x00000006,0x0000035d,0x000002ad,0x0004003d,0x00000088, + 0x0000035e,0x00000297,0x0006000c,0x00000006,0x0000035f,0x00000001,0x00000037,0x0000035e, + 0x0004003d,0x00000088,0x00000360,0x0000029e,0x0006000c,0x00000006,0x00000361,0x00000001, + 0x00000037,0x00000360,0x00050050,0x00000007,0x00000362,0x0000035f,0x00000361,0x00060041, + 0x00000084,0x00000363,0x000002bc,0x00000029,0x0000035d,0x0003003e,0x00000363,0x00000362, + 0x000100fd,0x00010038 diff --git a/tests/.gitignore b/tests/.gitignore index 61440c7..0c8a72d 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -7,3 +7,7 @@ test-image-stitching test-pipe-manager test-video-stabilization test-soft-image +test-gles-handler +test-render-surround-view +test-surround-view +test-vk-handler diff --git a/tests/Makefile.am b/tests/Makefile.am index 6e68880..eb27a9e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,126 +1,253 @@ -XCORE_DIR = $(top_srcdir)/xcore -MODULES_DIR = $(top_srcdir)/modules +noinst_PROGRAMS = \ + test-soft-image \ + test-surround-view \ + test-device-manager \ + $(NULL) -TEST_BASE_CXXFLAGS = $(XCAM_CXXFLAGS) -if HAVE_LIBDRM -TEST_BASE_CXXFLAGS += $(LIBDRM_CFLAGS) $(LIBDRM_LIBS) +if HAVE_LIBCL +noinst_PROGRAMS += \ + test-cl-image \ + test-image-blend \ + test-pipe-manager \ + test-binary-kernel \ + test-image-stitching \ + test-video-stabilization \ + $(NULL) endif -if USE_LOCAL_ATOMISP -TEST_BASE_CXXFLAGS += -I$(top_srcdir)/ext/atomisp +if HAVE_GLES +noinst_PROGRAMS += \ + test-gles-handler \ + $(NULL) endif -TEST_BASE_CXXFLAGS += \ - -I$(XCORE_DIR) \ - -I$(MODULES_DIR) \ - $(NULL) - -TEST_BASE_LA = \ - $(NULL) - -noinst_PROGRAMS = \ - test-device-manager \ - test-soft-image \ - $(NULL) - -if ENABLE_IA_AIQ +if HAVE_VULKAN noinst_PROGRAMS += \ - test-poll-thread \ - $(NULL) + test-vk-handler \ + $(NULL) endif -if HAVE_LIBCL +if ENABLE_RENDER noinst_PROGRAMS += \ - test-cl-image \ - test-binary-kernel \ - test-pipe-manager \ - test-image-blend \ - test-image-stitching \ - test-video-stabilization \ - $(NULL) + test-render-surround-view \ + $(NULL) +endif -TEST_BASE_LA += $(top_builddir)/modules/ocl/libxcam_ocl.la +if ENABLE_DNN +noinst_PROGRAMS += \ + test-dnn-inference \ + $(NULL) +endif if HAVE_OPENCV noinst_PROGRAMS += \ - test-image-deblurring \ - $(NULL) - -TEST_BASE_CXXFLAGS += $(OPENCV_CFLAGS) -TEST_BASE_LA += $(OPENCV_LIBS) -endif + test-image-deblurring \ + $(NULL) endif -TEST_BASE_LA += \ - $(top_builddir)/xcore/libxcam_core.la \ - $(NULL) +TEST_BASE_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + $(NULL) -test_device_manager_SOURCES = test-device-manager.cpp -test_device_manager_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_device_manager_LDADD = $(TEST_BASE_LA) +TEST_BASE_LA = \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL) -if ENABLE_IA_AIQ -ISP_LA = $(top_builddir)/modules/isp/libxcam_isp.la +if HAVE_OPENCV +XCAM_OCV_CFLAGS = $(OPENCV_CFLAGS) +XCAM_OCV_LIBS = $(OPENCV_LIBS) +XCAM_OCV_LA = $(top_builddir)/modules/ocv/libxcam_ocv.la +endif -test_device_manager_LDADD += $(ISP_LA) +if HAVE_LIBDRM +TEST_DRM_CFLAGS = $(LIBDRM_CFLAGS) +TEST_DRM_LIBS = \ + -ldrm_intel \ + $(LIBDRM_LIBS) \ + $(NULL) +endif -test_poll_thread_SOURCES = test-poll-thread.cpp -test_poll_thread_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_poll_thread_LDADD = \ - $(TEST_BASE_LA) $(ISP_LA) \ - $(NULL) +test_device_manager_SOURCES = test-device-manager.cpp +test_device_manager_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(TEST_DRM_CFLAGS) \ + $(NULL) +test_device_manager_LDADD = \ + $(TEST_BASE_LA) \ + $(TEST_DRM_LIBS) \ + $(NULL) +if USE_LOCAL_ATOMISP +test_device_manager_CXXFLAGS += -I$(top_srcdir)/ext/atomisp +endif +if ENABLE_IA_AIQ +test_device_manager_LDADD += $(top_builddir)/modules/isp/libxcam_isp.la endif if HAVE_LIBCL +test_device_manager_LDADD += $(top_builddir)/modules/ocl/libxcam_ocl.la + +TEST_OCL_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(TEST_DRM_CFLAGS) \ + $(NULL) + +TEST_OCL_LDADD = \ + $(TEST_BASE_LA) \ + $(TEST_DRM_LIBS) \ + $(top_builddir)/modules/ocl/libxcam_ocl.la \ + $(NULL) + test_cl_image_SOURCES = test-cl-image.cpp -test_cl_image_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_cl_image_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) +test_cl_image_CXXFLAGS = $(TEST_OCL_CXXFLAGS) +test_cl_image_LDADD = $(TEST_OCL_LDADD) test_binary_kernel_SOURCES = test-binary-kernel.cpp -test_binary_kernel_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_binary_kernel_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) +test_binary_kernel_CXXFLAGS = $(TEST_OCL_CXXFLAGS) +test_binary_kernel_LDADD = $(TEST_OCL_LDADD) test_pipe_manager_SOURCES = test-pipe-manager.cpp -test_pipe_manager_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_pipe_manager_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) +test_pipe_manager_CXXFLAGS = $(TEST_OCL_CXXFLAGS) +test_pipe_manager_LDADD = $(TEST_OCL_LDADD) test_image_blend_SOURCES = test-image-blend.cpp -test_image_blend_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_image_blend_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) +test_image_blend_CXXFLAGS = $(TEST_OCL_CXXFLAGS) +test_image_blend_LDADD = $(TEST_OCL_LDADD) test_image_stitching_SOURCES = test-image-stitching.cpp -test_image_stitching_CXXFLAGS = $(TEST_BASE_CXXFLAGS) +test_image_stitching_CXXFLAGS = \ + $(TEST_OCL_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) test_image_stitching_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) + $(TEST_OCL_LDADD) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(NULL) test_video_stabilization_SOURCES = test-video-stabilization.cpp -test_video_stabilization_CXXFLAGS = $(TEST_BASE_CXXFLAGS) +test_video_stabilization_CXXFLAGS = \ + $(TEST_OCL_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) test_video_stabilization_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) + $(TEST_OCL_LDADD) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(NULL) +endif if HAVE_OPENCV test_image_deblurring_SOURCES = test-image-deblurring.cpp -test_image_deblurring_CXXFLAGS = $(TEST_BASE_CXXFLAGS) - $(NULL) +test_image_deblurring_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) test_image_deblurring_LDADD = \ - $(TEST_BASE_LA) \ - $(NULL) -endif + $(TEST_BASE_LA) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(NULL) endif +TEST_SOFT_LA = $(top_builddir)/modules/soft/libxcam_soft.la + test_soft_image_SOURCES = test-soft-image.cpp -test_soft_image_CXXFLAGS = $(TEST_BASE_CXXFLAGS) -test_soft_image_LDADD = \ - $(top_builddir)/modules/soft/libxcam_soft.la \ - $(TEST_BASE_LA) \ - $(NULL) +test_soft_image_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) +test_soft_image_LDADD = \ + $(TEST_BASE_LA) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(TEST_SOFT_LA) \ + $(NULL) + +if HAVE_GLES +TEST_GLES_LA = $(top_builddir)/modules/gles/libxcam_gles.la +endif +if HAVE_VULKAN +TEST_VK_LA = $(top_builddir)/modules/vulkan/libxcam_vulkan.la +endif + +test_surround_view_SOURCES = test-surround-view.cpp +test_surround_view_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) +test_surround_view_LDADD = \ + $(TEST_BASE_LA) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(TEST_SOFT_LA) \ + $(TEST_GLES_LA) \ + $(TEST_VK_LA) \ + $(NULL) + +if HAVE_VULKAN +test_vk_handler_SOURCES = test-vk-handler.cpp +test_vk_handler_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(LIBVULKAN_CFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) +test_vk_handler_LDADD = \ + $(TEST_BASE_LA) \ + $(LIBVULKAN_LIBS) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(TEST_VK_LA) \ + $(NULL) +endif + +if HAVE_GLES +test_gles_handler_SOURCES = test-gles-handler.cpp +test_gles_handler_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) +test_gles_handler_LDADD = \ + $(TEST_BASE_LA) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(TEST_GLES_LA) \ + $(NULL) +endif + +if ENABLE_RENDER +TEST_RENDER_LA = $(top_builddir)/modules/render/libxcam_render.la + +test_render_surround_view_SOURCES = test-render-surround-view.cpp +test_render_surround_view_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + $(XCAM_OCV_CFLAGS) \ + $(NULL) +test_render_surround_view_LDADD = \ + $(TEST_BASE_LA) \ + $(XCAM_OCV_LIBS) \ + $(XCAM_OCV_LA) \ + $(TEST_SOFT_LA) \ + $(TEST_GLES_LA) \ + $(TEST_VK_LA) \ + $(TEST_RENDER_LA) \ + $(NULL) +endif + +if ENABLE_DNN +TEST_DNN_INFERENCE_LA = $(top_builddir)/modules/dnn/libxcam_dnn.la + +test_dnn_inference_SOURCES = test-dnn-inference.cpp +test_dnn_inference_CXXFLAGS = \ + $(TEST_BASE_CXXFLAGS) \ + -I$(OPENVINO_IE_INC_PATH)/include \ + -I$(OPENVINO_IE_INC_PATH)/src/extension \ + $(NULL) + +test_dnn_inference_LDADD = \ + $(TEST_BASE_LA) \ + $(TEST_DNN_INFERENCE_LA) \ + $(NULL) +endif + diff --git a/tests/test-cl-image.cpp b/tests/test-cl-image.cpp index 19000b5..a986d5d 100644 --- a/tests/test-cl-image.cpp +++ b/tests/test-cl-image.cpp @@ -175,7 +175,6 @@ int main (int argc, char *argv[]) SmartPtr<CLImageHandler> image_handler; VideoBufferInfo input_buf_info; SmartPtr<CLContext> context; - SmartPtr<BufferPool> buf_pool; int opt = 0; CLCscType csc_type = CL_CSC_TYPE_RGBATONV12; bool enable_bnr = false; @@ -409,6 +408,7 @@ int main (int argc, char *argv[]) SmartPtr<CLNewWaveletDenoiseImageHandler> wavelet = image_handler.dynamic_cast_ptr<CLNewWaveletDenoiseImageHandler> (); XCAM_ASSERT (wavelet.ptr ()); XCam3aResultWaveletNoiseReduction wavelet_config; + xcam_mem_clear (wavelet_config); wavelet_config.threshold[0] = 0.2; wavelet_config.threshold[1] = 0.5; wavelet_config.decomposition_levels = 4; @@ -497,7 +497,8 @@ int main (int argc, char *argv[]) input_buf_info.init (input_format, width, height); - buf_pool = new CLVideoBufferPool (); + SmartPtr<BufferPool> buf_pool = new CLVideoBufferPool (); + XCAM_ASSERT (buf_pool.ptr ()); image_handler->set_pool_type (CLImageHandler::CLVideoPoolType); buf_pool->set_video_info (input_buf_info); if (!buf_pool->reserve (6)) { @@ -541,14 +542,6 @@ int main (int argc, char *argv[]) XCAM_LOG_INFO ("processed %d buffers successfully", buf_count); if (enable_psnr) { - buf_pool = new CLVideoBufferPool (); - XCAM_ASSERT (buf_pool.ptr ()); - buf_pool->set_video_info (input_buf_info); - if (!buf_pool->reserve (6)) { - XCAM_LOG_ERROR ("init buffer pool failed"); - return -1; - } - psnr_ref = buf_pool->get_buffer (buf_pool); XCAM_ASSERT (psnr_ref.ptr ()); diff --git a/tests/test-device-manager.cpp b/tests/test-device-manager.cpp index f299d46..1be70f5 100644 --- a/tests/test-device-manager.cpp +++ b/tests/test-device-manager.cpp @@ -32,7 +32,7 @@ #include "isp/isp_image_processor.h" #include "isp/isp_poll_thread.h" #include "isp/x3a_analyzer_aiq.h" -#include "x3a_analyze_tuner.h" +#include "isp/iq/x3a_analyze_tuner.h" #include "dynamic_analyzer_loader.h" #include "isp/hybrid_analyzer_loader.h" #endif @@ -328,8 +328,6 @@ int main (int argc, char *argv[]) bool have_cl_processor = false; SmartPtr<SmartAnalyzer> smart_analyzer; bool have_cl_post_processor = true; - SmartPtr<CL3aImageProcessor> cl_processor; - SmartPtr<CLPostImageProcessor> cl_post_processor; uint32_t tnr_type = CL_TNR_DISABLE; uint32_t denoise_type = 0; uint8_t tnr_level = 0; @@ -817,7 +815,7 @@ int main (int argc, char *argv[]) #endif #if HAVE_LIBCL if (have_cl_processor) { - cl_processor = new CL3aImageProcessor (); + SmartPtr<CL3aImageProcessor> cl_processor = new CL3aImageProcessor (); cl_processor->set_stats_callback(device_manager); cl_processor->set_denoise (denoise_type); cl_processor->set_capture_stage (capture_stage); @@ -837,7 +835,7 @@ int main (int argc, char *argv[]) } if (have_cl_post_processor) { - cl_post_processor = new CLPostImageProcessor (); + SmartPtr<CLPostImageProcessor> cl_post_processor = new CLPostImageProcessor (); cl_post_processor->set_stats_callback (device_manager); cl_post_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode)defog_type); diff --git a/tests/test-dnn-inference.cpp b/tests/test-dnn-inference.cpp new file mode 100644 index 0000000..d07e27c --- /dev/null +++ b/tests/test-dnn-inference.cpp @@ -0,0 +1,497 @@ +/* + * test-dnn-inference.cpp - test dnn inference sample + * + * Copyright (c) 2019 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: Zong Wei <wei.zong@intel.com> + * + */ + +#include <fstream> +#include <random> +#include <string> +#include <vector> +#include <time.h> + +#include <xcam_std.h> +#include "test_common.h" + +#include <dnn/dnn_inference_engine.h> +#include <dnn/dnn_object_detection.h> + +using namespace XCam; +using namespace InferenceEngine; + +class Color { + +public: + Color (uint8_t r, uint8_t g, uint8_t b) { + _red = r; + _green = g; + _blue = b; + } + +public: + uint8_t _red; + uint8_t _green; + uint8_t _blue; +}; + +static void add_rectangles ( + uint8_t *data, uint32_t width, uint32_t height, + std::vector<int> rectangles, std::vector<int> classes, int thickness = 1) +{ + std::vector<Color> colors = { + // colors to be used for bounding boxes + Color ( 128, 64, 128 ), + Color ( 232, 35, 244 ), + Color ( 70, 70, 70 ), + Color ( 156, 102, 102 ), + Color ( 153, 153, 190 ), + Color ( 153, 153, 153 ), + Color ( 30, 170, 250 ), + Color ( 0, 220, 220 ), + Color ( 35, 142, 107 ), + Color ( 152, 251, 152 ), + Color ( 180, 130, 70 ), + Color ( 60, 20, 220 ), + Color ( 0, 0, 255 ), + Color ( 142, 0, 0 ), + Color ( 70, 0, 0 ), + Color ( 100, 60, 0 ), + Color ( 90, 0, 0 ), + Color ( 230, 0, 0 ), + Color ( 32, 11, 119 ), + Color ( 0, 74, 111 ), + Color ( 81, 0, 81 ) + }; + if (rectangles.size() % 4 != 0 || rectangles.size() / 4 != classes.size()) { + return; + } + + for (size_t i = 0; i < classes.size(); i++) { + int x = rectangles.at(i * 4); + int y = rectangles.at(i * 4 + 1); + int w = rectangles.at(i * 4 + 2); + int h = rectangles.at(i * 4 + 3); + + int cls = classes.at(i) % colors.size(); // color of a bounding box line + + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w < 0) w = 0; + if (h < 0) h = 0; + + if (static_cast<std::size_t>(x) >= width) { + x = width - 1; + w = 0; + thickness = 1; + } + if (static_cast<std::size_t>(y) >= height) { + y = height - 1; + h = 0; + thickness = 1; + } + + if (static_cast<std::size_t>(x + w) >= width) { + w = width - x - 1; + } + if (static_cast<std::size_t>(y + h) >= height) { + h = height - y - 1; + } + + thickness = std::min(std::min(thickness, w / 2 + 1), h / 2 + 1); + + size_t shift_first; + size_t shift_second; + for (int t = 0; t < thickness; t++) { + shift_first = (y + t) * width * 3; + shift_second = (y + h - t) * width * 3; + for (int ii = x; ii < x + w + 1; ii++) { + data[shift_first + ii * 3] = colors.at(cls)._red; + data[shift_first + ii * 3 + 1] = colors.at(cls)._green; + data[shift_first + ii * 3 + 2] = colors.at(cls)._blue; + data[shift_second + ii * 3] = colors.at(cls)._red; + data[shift_second + ii * 3 + 1] = colors.at(cls)._green; + data[shift_second + ii * 3 + 2] = colors.at(cls)._blue; + } + } + + for (int t = 0; t < thickness; t++) { + shift_first = (x + t) * 3; + shift_second = (x + w - t) * 3; + for (int ii = y; ii < y + h + 1; ii++) { + data[shift_first + ii * width * 3] = colors.at(cls)._red; + data[shift_first + ii * width * 3 + 1] = colors.at(cls)._green; + data[shift_first + ii * width * 3 + 2] = colors.at(cls)._blue; + data[shift_second + ii * width * 3] = colors.at(cls)._red; + data[shift_second + ii * width * 3 + 1] = colors.at(cls)._green; + data[shift_second + ii * width * 3 + 2] = colors.at(cls)._blue; + } + } + } +} + +static bool write_output_bmp (std::string name, unsigned char *data, uint32_t width, uint32_t height) +{ + std::ofstream out_file; + out_file.open (name, std::ofstream::binary); + if (!out_file.is_open ()) { + return false; + } + + unsigned char file[14] = { + 'B', 'M', // magic + 0, 0, 0, 0, // size in bytes + 0, 0, // app data + 0, 0, // app data + 40 + 14, 0, 0, 0 // start of data offset + }; + unsigned char info[40] = { + 40, 0, 0, 0, // info hd size + 0, 0, 0, 0, // width + 0, 0, 0, 0, // height + 1, 0, // number color planes + 24, 0, // bits per pixel + 0, 0, 0, 0, // compression is none + 0, 0, 0, 0, // image bits size + 0x13, 0x0B, 0, 0, // horz resolution in pixel / m + 0x13, 0x0B, 0, 0, // vert resolution (0x03C3 = 96 dpi, 0x0B13 = 72 dpi) + 0, 0, 0, 0, // #colors in palette + 0, 0, 0, 0, // #important colors + }; + + if (height > (size_t)std::numeric_limits<int32_t>::max || + width > (size_t)std::numeric_limits<int32_t>::max) { + XCAM_LOG_ERROR ("File size is too big: %dx%d", height, width); + return false; + } + + int pad_size = static_cast<int>(4 - (width * 3) % 4) % 4; + int size_data = static_cast<int>(width * height * 3 + height * pad_size); + int size_all = size_data + sizeof(file) + sizeof(info); + + file[2] = (unsigned char)(size_all); + file[3] = (unsigned char)(size_all >> 8); + file[4] = (unsigned char)(size_all >> 16); + file[5] = (unsigned char)(size_all >> 24); + + info[4] = (unsigned char)(width); + info[5] = (unsigned char)(width >> 8); + info[6] = (unsigned char)(width >> 16); + info[7] = (unsigned char)(width >> 24); + + int32_t negative_height = -(int32_t)height; + info[8] = (unsigned char)(negative_height); + info[9] = (unsigned char)(negative_height >> 8); + info[10] = (unsigned char)(negative_height >> 16); + info[11] = (unsigned char)(negative_height >> 24); + + info[20] = (unsigned char)(size_data); + info[21] = (unsigned char)(size_data >> 8); + info[22] = (unsigned char)(size_data >> 16); + info[23] = (unsigned char)(size_data >> 24); + + out_file.write(reinterpret_cast<char *>(file), sizeof(file)); + out_file.write(reinterpret_cast<char *>(info), sizeof(info)); + + unsigned char pad[3] = { 0, 0, 0 }; + + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + unsigned char pixel[3]; + pixel[0] = data[y * width * 3 + x * 3]; + pixel[1] = data[y * width * 3 + x * 3 + 1]; + pixel[2] = data[y * width * 3 + x * 3 + 2]; + + out_file.write(reinterpret_cast<char *>(pixel), 3); + } + out_file.write(reinterpret_cast<char *>(pad), pad_size); + } + return true; +} + +static void usage (const char* arg0) +{ + printf ("Usage:\n" + "%s --plugin PATH --input filename --model-name xx.xml ...\n" + "\t--plugin plugin path\n" + "\t--target-dev target device, default: DnnInferDeviceCPU\n" + "\t--ext-path extension path\n" + "\t--model-file model file name\n" + "\t--input input image \n" + "\t--save save output image \n" + "\t--help usage\n", + arg0); +} + +int main (int argc, char *argv[]) +{ + const struct option long_opts[] = { + {"plugin", required_argument, NULL, 'p'}, + {"target-dev", required_argument, NULL, 'd'}, + {"ext-path", required_argument, NULL, 'x'}, + {"model-file", required_argument, NULL, 'm'}, + {"input", required_argument, NULL, 'i'}, + {"save", required_argument, NULL, 's'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}, + }; + + // --------------------------- 0. Get inference engine configurations ----------------------------------------------------------- + XCAM_LOG_DEBUG ("0. Get inference engine configurations"); + + DnnInferConfig infer_config; + infer_config.target_id = DnnInferDeviceCPU; + + char* ext_path = NULL; + char* input_image = NULL; + bool save_output = true; + + int opt = -1; + while ((opt = getopt_long (argc, argv, "", long_opts, NULL)) != -1) { + switch (opt) { + case 'p': + XCAM_ASSERT (optarg); + infer_config.plugin_path = optarg; + break; + case 'd': + XCAM_ASSERT (optarg); + infer_config.target_id = (DnnInferTargetDeviceType)(atoi (optarg)); + if (!strcasecmp (optarg, "CPU")) { + infer_config.target_id = DnnInferDeviceCPU; + } else if (!strcasecmp (optarg, "GPU")) { + infer_config.target_id = DnnInferDeviceGPU; + } else if (!strcasecmp (optarg, "FPGA")) { + infer_config.target_id = DnnInferDeviceFPGA; + } else if (!strcasecmp (optarg, "Myriad")) { + infer_config.target_id = DnnInferDeviceMyriad; + } else { + XCAM_LOG_ERROR ("target device unknown type: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 'x': + XCAM_ASSERT (optarg); + ext_path = optarg; + break; + case 'm': + XCAM_ASSERT (optarg); + infer_config.model_filename = optarg; + break; + case 'i': + XCAM_ASSERT (optarg); + input_image = optarg; + break; + case 's': + XCAM_ASSERT (optarg); + save_output = (strcasecmp (optarg, "false") == 0 ? false : true); + break; + case 'h': + usage (argv[0]); + return 0; + default: + XCAM_LOG_ERROR ("getopt_long return unknown value: %c", opt); + usage (argv[0]); + return -1; + } + } + + XCAM_LOG_DEBUG ("targetDevice: %d", infer_config.target_id ); + if (DnnInferDeviceCPU == infer_config.target_id) { + infer_config.cpu_ext_path = ext_path; + XCAM_LOG_DEBUG ("CPU Extension loaded: %s", infer_config.cpu_ext_path); + } else if (DnnInferDeviceGPU == infer_config.target_id) { + infer_config.cldnn_ext_path = ext_path; + XCAM_LOG_DEBUG ("GPU Extension loaded: %s", infer_config.cldnn_ext_path); + } + + if (optind < argc || argc < 2) { + XCAM_LOG_ERROR ("unknown option %s", argv[optind]); + usage (argv[0]); + return -1; + } + + printf ("plugin path:\t\t%s\n", (infer_config.plugin_path != NULL) ? infer_config.plugin_path : "NULL"); + printf ("target device id:\t\t%d\n", infer_config.target_id); + printf ("extention path:\t\t%s\n", (ext_path != NULL) ? ext_path : "NULL"); + printf ("input image:\t\t%s\n", (input_image != NULL) ? input_image : "NULL"); + printf ("model file name:\t\t%s\n", (infer_config.model_filename != NULL) ? infer_config.model_filename : "NULL"); + + // --------------------------- 1. Set input image file names ----------------------------------------------------------- + XCAM_LOG_DEBUG ("1. Set input image file names"); + std::vector<std::string> images; + if (NULL != input_image) { + images.push_back (input_image); + } + + if (images.empty()) { + XCAM_LOG_ERROR ("No suitable images were found!"); + return -1; + } + + // --------------------------- 2. create inference engine -------------------------------------------------- + XCAM_LOG_DEBUG ("2. Create inference engine"); + infer_config.perf_counter = 0; + + SmartPtr<DnnInferenceEngine> infer_engine = new DnnObjectDetection (infer_config); + + DnnInferenceEngineInfo infer_info; + CHECK ( + infer_engine->get_info (infer_info, DnnInferInfoEngine), + "get inference engine info failed!"); + XCAM_LOG_DEBUG ("Inference Engine version: %d.%d", infer_info.major, infer_info.minor); + + CHECK ( + infer_engine->get_info (infer_info, DnnInferInfoPlugin), + "get inference engine info failed!"); + XCAM_LOG_DEBUG ("Inference Engine plugin discription: %s", infer_info.desc); + XCAM_LOG_DEBUG ("Inference Engine plugin version: %d.%d", infer_info.major, infer_info.minor); + + CHECK ( + infer_engine->get_info (infer_info, DnnInferInfoNetwork), + "get inference engine info failed!"); + XCAM_LOG_DEBUG ("Inference Engine network name: %s", infer_info.name); + XCAM_LOG_DEBUG ("Inference Engine network discription: %s", infer_info.desc); + XCAM_LOG_DEBUG ("Inference Engine network version: %d.%d", infer_info.major, infer_info.minor); + + // --------------------------- 3. Get model input infos -------------------------------------------------- + XCAM_LOG_DEBUG ("3. Get/Set model input infos"); + CHECK ( + infer_engine->get_model_input_info (infer_config.input_infos), + "get model input info failed!"); + + XCAM_LOG_DEBUG ("Input info :"); + for (uint32_t i = 0; i < infer_config.input_infos.numbers; i++) { + infer_config.input_infos.data_type[i] = DnnInferDataTypeImage; + CHECK ( + infer_engine->set_input_presion (i, DnnInferPrecisionU8), + "set input presion failed!"); + XCAM_LOG_DEBUG ("Idx %d : [%d X %d X %d] , [%d %d %d], batch size = %d", i, + infer_config.input_infos.width[i], infer_config.input_infos.height[i], infer_config.input_infos.channels[i], + infer_config.input_infos.precision[i], infer_config.input_infos.layout[i], infer_config.input_infos.data_type[i], + infer_config.input_infos.batch_size); + } + + // --------------------------- 4. Get model output infos ------------------------------------------------- + XCAM_LOG_DEBUG ("4. Get/Set model output infos"); + CHECK ( + infer_engine->get_model_output_info (infer_config.output_infos), + "get model output info failed!"); + XCAM_LOG_DEBUG ("Output info (numbers %d) :", infer_config.output_infos.numbers); + + for (uint32_t i = 0; i < infer_config.output_infos.numbers; i++) { + CHECK ( + infer_engine->set_output_presion (i, DnnInferPrecisionFP32), + "set output presion failed!"); + XCAM_LOG_DEBUG ("Idx %d : [%d X %d X %d] , [%d %d %d], batch size = %d", i, + infer_config.output_infos.width[i], infer_config.output_infos.height[i], infer_config.output_infos.channels[i], + infer_config.output_infos.precision[i], infer_config.output_infos.layout[i], infer_config.output_infos.data_type[i], + infer_config.output_infos.batch_size); + } + + // --------------------------- 5. load inference model ------------------------------------------------- + XCAM_LOG_DEBUG ("5. load inference model"); + CHECK ( + infer_engine->load_model (infer_config), + "load model failed!"); + + // --------------------------- 6. Set inference data -------------------------------------------------------- + XCAM_LOG_DEBUG ("6. Set inference data"); + CHECK ( + infer_engine->set_inference_data (images), + "set inference data failed!"); + + // --------------------------- 7. Do inference --------------------------------------------------------- + XCAM_LOG_DEBUG ("7. Start inference iterations"); + if (infer_engine->ready_to_start ()) { + CHECK ( + infer_engine->start (), + "inference failed!"); + } + + FPS_CALCULATION (inference_engine, XCAM_OBJ_DUR_FRAME_NUM); + + // --------------------------- 8. Process inference results ------------------------------------------------------- + XCAM_LOG_DEBUG ("Processing inference results"); + + size_t batch_size = infer_engine->get_output_size (); + if (batch_size != images.size ()) { + XCAM_LOG_DEBUG ( "Number of images: %d ", images.size ()); + batch_size = std::min(batch_size, images.size ()); + XCAM_LOG_DEBUG ( "Number of images to be processed is: %d ", batch_size); + } + + uint32_t blob_size = 0; + float* result_ptr = NULL; + std::vector<std::vector<int> > boxes(batch_size); + std::vector<std::vector<int> > classes(batch_size); + + for (uint32_t batch_idx = 0; batch_idx < batch_size; batch_idx ++) { + result_ptr = (float*)infer_engine->get_inference_results (batch_idx, blob_size); + if (NULL == result_ptr) { + continue; + } + + int image_width = infer_engine->get_input_image_width (); + int image_height = infer_engine->get_input_image_height (); + int max_proposal_count = infer_config.output_infos.channels[batch_idx]; + int object_size = infer_config.output_infos.object_size[batch_idx]; + + for (int32_t cur_proposal = 0; cur_proposal < max_proposal_count; cur_proposal++) { + float image_id = result_ptr[cur_proposal * object_size + 0]; + if (image_id < 0) { + break; + } + + float label = result_ptr[cur_proposal * object_size + 1]; + float confidence = result_ptr[cur_proposal * object_size + 2]; + float xmin = result_ptr[cur_proposal * object_size + 3] * image_width; + float ymin = result_ptr[cur_proposal * object_size + 4] * image_height; + float xmax = result_ptr[cur_proposal * object_size + 5] * image_width; + float ymax = result_ptr[cur_proposal * object_size + 6] * image_height; + + if (confidence > 0.5) { + classes[image_id].push_back(static_cast<int>(label)); + boxes[image_id].push_back(static_cast<int>(xmin)); + boxes[image_id].push_back(static_cast<int>(ymin)); + boxes[image_id].push_back(static_cast<int>(xmax - xmin)); + boxes[image_id].push_back(static_cast<int>(ymax - ymin)); + + XCAM_LOG_DEBUG ("Proposal:%d label:%d confidence:%f", cur_proposal, (int)label, confidence); + XCAM_LOG_DEBUG ("Boxes[%f] {%d, %d, %d, %d}", + image_id, (int)xmin, (int)ymin, (int)xmax, (int)ymax); + } + } + + if (save_output) { + std::shared_ptr<unsigned char> orig_image = infer_engine->read_inference_image (images[batch_idx]); + add_rectangles (orig_image.get (), + image_width, image_height, + boxes[batch_idx], classes[batch_idx]); + + const std::string image_path = images[batch_idx] + "_out_" + std::to_string (batch_idx) + ".bmp"; + if (write_output_bmp (image_path, orig_image.get (), image_width, image_height)) { + XCAM_LOG_DEBUG ("Image %s created!", image_path.c_str ()); + } else { + XCAM_LOG_ERROR ("Can't create image file: %s", image_path.c_str ()); + } + } + } + + XCAM_LOG_DEBUG ("Execution successful"); + return 0; +} diff --git a/tests/test-gles-handler.cpp b/tests/test-gles-handler.cpp new file mode 100644 index 0000000..acafa00 --- /dev/null +++ b/tests/test-gles-handler.cpp @@ -0,0 +1,313 @@ +/* + * 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 <yinhangx.liu@intel.com> + */ + +#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; +} diff --git a/tests/test-image-blend.cpp b/tests/test-image-blend.cpp index a00236f..c355a49 100644 --- a/tests/test-image-blend.cpp +++ b/tests/test-image-blend.cpp @@ -27,6 +27,7 @@ #include <ocl/cl_blender.h> #include <image_file_handle.h> #include <ocl/cl_geo_map_handler.h> +#include <ocl/cl_video_buffer.h> #if HAVE_LIBDRM #include <drm_display.h> #endif @@ -165,7 +166,6 @@ int main (int argc, char *argv[]) SmartPtr<CLBlender> blender; VideoBufferInfo input_buf_info0, input_buf_info1, output_buf_info; SmartPtr<CLContext> context; - SmartPtr<BufferPool> buf_pool0, buf_pool1; ImageFileHandle file_in0, file_in1, file_out; SmartPtr<VideoBuffer> input0, input1; SmartPtr<VideoBuffer> output_buf; @@ -227,7 +227,7 @@ int main (int argc, char *argv[]) break; case 'h': usage (argv[0]); - return -1; + return 0; default: printf ("getopt_long return unknown value:%c\n", opt); usage (argv[0]); @@ -259,13 +259,14 @@ int main (int argc, char *argv[]) input_buf_info0.init (input_format, input_width0, input_height); input_buf_info1.init (input_format, input_width1, input_height); output_buf_info.init (input_format, output_width, output_height); + #if (ENABLE_DMA_TEST) && (HAVE_LIBDRM) SmartPtr<DrmDisplay> display = DrmDisplay::instance (); - buf_pool0 = new DrmBoBufferPool (display); - buf_pool1 = new DrmBoBufferPool (display); + SmartPtr<BufferPool> buf_pool0 = new DrmBoBufferPool (display); + SmartPtr<BufferPool> buf_pool1 = new DrmBoBufferPool (display); #else - buf_pool0 = new CLVideoBufferPool (); - buf_pool1 = new CLVideoBufferPool (); + SmartPtr<BufferPool> buf_pool0 = new CLVideoBufferPool (); + SmartPtr<BufferPool> buf_pool1 = new CLVideoBufferPool (); #endif XCAM_ASSERT (buf_pool0.ptr () && buf_pool1.ptr ()); buf_pool0->set_video_info (input_buf_info0); diff --git a/tests/test-image-deblurring.cpp b/tests/test-image-deblurring.cpp index bc681b2..bfc9d88 100644 --- a/tests/test-image-deblurring.cpp +++ b/tests/test-image-deblurring.cpp @@ -25,9 +25,9 @@ #include <unistd.h> #include <getopt.h> #include <image_file_handle.h> -#include <ocl/cv_image_sharp.h> -#include <ocl/cv_wiener_filter.h> -#include <ocl/cv_image_deblurring.h> +#include "ocv/cv_image_sharp.h" +#include "ocv/cv_wiener_filter.h" +#include "ocv/cv_image_deblurring.h" #include <opencv2/opencv.hpp> #include <opencv2/core/ocl.hpp> @@ -58,7 +58,7 @@ static void non_blind_deblurring (cv::Mat &input_image, cv::Mat &output_image) { SmartPtr<CVWienerFilter> wiener_filter = new CVWienerFilter (); - cv::cvtColor (input_image, input_image, CV_BGR2GRAY); + cv::cvtColor (input_image, input_image, cv::COLOR_BGR2GRAY); // use simple motion blur kernel int kernel_size = 13; cv::Mat kernel = cv::Mat::zeros (kernel_size, kernel_size, CV_32FC1); @@ -115,7 +115,7 @@ int main (int argc, char *argv[]) break; case 'H': usage (argv[0]); - return -1; + return 0; default: printf ("getopt_long return unknown value:%c\n", opt); usage (argv[0]); @@ -144,12 +144,12 @@ int main (int argc, char *argv[]) printf ("----------------------\n"); SmartPtr<CVImageSharp> sharp = new CVImageSharp (); - cv::Mat input_image = cv::imread (file_in_name, CV_LOAD_IMAGE_COLOR); + cv::Mat input_image = cv::imread (file_in_name, cv::IMREAD_COLOR); cv::Mat output_image; if (input_image.empty ()) { XCAM_LOG_ERROR ("input file read error"); - return 0; + return -1; } if (blind) { @@ -166,5 +166,7 @@ int main (int argc, char *argv[]) cv::imwrite (file_out_name, output_image); } XCAM_ASSERT (output_sharp > input_sharp); + + return 0; } diff --git a/tests/test-image-stitching.cpp b/tests/test-image-stitching.cpp index ddd765f..0062f90 100644 --- a/tests/test-image-stitching.cpp +++ b/tests/test-image-stitching.cpp @@ -31,12 +31,16 @@ #include <ocl/cl_image_360_stitch.h> #include <ocl/cl_utils.h> #if HAVE_OPENCV -#include <ocl/cv_base_class.h> +#include "ocv/cv_utils.h" #endif #define XCAM_TEST_STITCH_DEBUG 0 #define XCAM_ALIGNED_WIDTH 16 +#if HAVE_OPENCV +#define FOURCC_X264 cv::VideoWriter::fourcc ('X', '2', '6', '4') +#endif + #define CHECK_ACCESS(fliename) \ if (access (fliename, F_OK) != 0) { \ XCAM_LOG_ERROR ("%s not found", fliename); \ @@ -59,31 +63,28 @@ parse_calibration_params ( ExtrinsicParameter extrinsic_param[], int fisheye_num) { + static const char *instrinsic_names[] = { + "intrinsic_camera_front.txt", "intrinsic_camera_right.txt", + "intrinsic_camera_rear.txt", "intrinsic_camera_left.txt" + }; + static const char *exstrinsic_names[] = { + "extrinsic_camera_front.txt", "extrinsic_camera_right.txt", + "extrinsic_camera_rear.txt", "extrinsic_camera_left.txt" + }; + + std::string fisheye_config_path = FISHEYE_CONFIG_PATH; + const char *env = std::getenv (FISHEYE_CONFIG_ENV_VAR); + if (env) + fisheye_config_path.assign (env, strlen (env)); + XCAM_LOG_INFO ("calibration config path:%s", fisheye_config_path.c_str ()); + CalibrationParser calib_parser; + XCAM_ASSERT (fisheye_num <= 4); char intrinsic_path[1024], extrinsic_path[1024]; for(int index = 0; index < fisheye_num; index++) { - switch (index) { - case 0: - strncpy (intrinsic_path, "./calib_params/intrinsic_camera_front.txt", 1023); - strncpy (extrinsic_path, "./calib_params/extrinsic_camera_front.txt", 1023); - break; - case 1: - strncpy (intrinsic_path, "./calib_params/intrinsic_camera_right.txt", 1023); - strncpy (extrinsic_path, "./calib_params/extrinsic_camera_right.txt", 1023); - break; - case 2: - strncpy (intrinsic_path, "./calib_params/intrinsic_camera_rear.txt", 1023); - strncpy (extrinsic_path, "./calib_params/extrinsic_camera_rear.txt", 1023); - break; - case 3: - strncpy (intrinsic_path, "./calib_params/intrinsic_camera_left.txt", 1023); - strncpy (extrinsic_path, "./calib_params/extrinsic_camera_left.txt", 1023); - break; - default: - XCAM_LOG_ERROR ("bowl view only support 4-camera mode"); - return false; - } + snprintf (intrinsic_path, 1023, "%s/%s", fisheye_config_path.c_str (), instrinsic_names[index]); + snprintf (extrinsic_path, 1023, "%s/%s", fisheye_config_path.c_str (), exstrinsic_names[index]); CHECK_ACCESS (intrinsic_path); CHECK_ACCESS (extrinsic_path); @@ -148,11 +149,13 @@ void usage(const char* arg0) "\t--enable-fisheyemap optional, enable fisheye map, default: no\n" "\t--enable-lsc optional, enable lens shading correction, default: no\n" #if HAVE_OPENCV - "\t--fm-ocl optional, enable ocl for feature match, select from [true/false], default: false\n" + "\t--fm optional, enable or disable feature match, default: true\n" #endif "\t--fisheye-num optional, the number of fisheye lens, default: 2\n" "\t--all-in-one optional, all fisheye in one image, select from [true/false], default: true\n" "\t--save optional, save file or not, select from [true/false], default: true\n" + "\t--save-top-view optional, save top view videos. default: no\n" + "\t--save-free-view optional, save rectified(free) view videos. default: no\n" "\t--framerate optional, framerate of saved video, default: 30.0\n" "\t--loop optional, how many loops need to run for performance test, default: 1\n" "\t--help usage\n", @@ -186,19 +189,21 @@ int main (int argc, char *argv[]) bool enable_seam = false; bool enable_fisheye_map = false; bool enable_lsc = false; +#if HAVE_OPENCV + bool need_fm = true; +#endif CLBlenderScaleMode scale_mode = CLBlenderScaleLocal; StitchResMode res_mode = StitchRes1080P; - SurroundMode surround_mode = BowlView; + SurroundMode surround_mode = SphereView; IntrinsicParameter intrinsic_param[XCAM_STITCH_FISHEYE_MAX_NUM]; ExtrinsicParameter extrinsic_param[XCAM_STITCH_FISHEYE_MAX_NUM]; -#if HAVE_OPENCV - bool fm_ocl = false; -#endif int fisheye_num = 2; bool all_in_one = true; bool need_save_output = true; + bool save_top_view = false; + bool save_free_view = false; double framerate = 30.0; const char *file_in_name[XCAM_STITCH_FISHEYE_MAX_NUM] = {NULL}; @@ -222,11 +227,13 @@ int main (int argc, char *argv[]) {"enable-fisheyemap", no_argument, NULL, 'F'}, {"enable-lsc", no_argument, NULL, 'L'}, #if HAVE_OPENCV - {"fm-ocl", required_argument, NULL, 'O'}, + {"fm", required_argument, NULL, 'm'}, #endif {"fisheye-num", required_argument, NULL, 'N'}, {"all-in-one", required_argument, NULL, 'A'}, {"save", required_argument, NULL, 's'}, + {"save-top-view", no_argument, NULL, 't'}, + {"save-free-view", no_argument, NULL, 'v'}, {"framerate", required_argument, NULL, 'f'}, {"loop", required_argument, NULL, 'l'}, {"help", no_argument, NULL, 'e'}, @@ -299,8 +306,8 @@ int main (int argc, char *argv[]) enable_lsc = true; break; #if HAVE_OPENCV - case 'O': - fm_ocl = (strcasecmp (optarg, "true") == 0 ? true : false); + case 'm': + need_fm = (strcasecmp (optarg, "false") == 0 ? false : true); break; #endif case 'N': @@ -316,6 +323,12 @@ int main (int argc, char *argv[]) case 's': need_save_output = (strcasecmp (optarg, "false") == 0 ? false : true); break; + case 't': + save_top_view = true; + break; + case 'v': + save_free_view = true; + break; case 'f': framerate = atof(optarg); break; @@ -324,7 +337,7 @@ int main (int argc, char *argv[]) break; case 'e': usage (argv[0]); - return -1; + return 0; default: XCAM_LOG_ERROR ("getopt_long return unknown value:%c", opt); usage (argv[0]); @@ -351,8 +364,8 @@ int main (int argc, char *argv[]) } } - if (!file_out_name) { - XCAM_LOG_ERROR ("output path is NULL"); + if (!file_out_name && need_save_output) { + XCAM_LOG_ERROR ("output path is NULL, video can't be saved"); return -1; } @@ -365,7 +378,7 @@ int main (int argc, char *argv[]) #if !HAVE_OPENCV if (need_save_output) { - XCAM_LOG_WARNING ("non-OpenCV mode, can't save video"); + XCAM_LOG_WARNING ("non-OpenCV mode, can't save video to file:%s", XCAM_STR (file_out_name)); need_save_output = false; } #endif @@ -377,7 +390,7 @@ int main (int argc, char *argv[]) for (int i = 0; i < input_count; i++) printf ("input file %d:\t\t%s\n", i, file_in_name[i]); } - printf ("output file:\t\t%s\n", file_out_name); + printf ("output file:\t\t%s\n", XCAM_STR (file_out_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); @@ -391,11 +404,13 @@ int main (int argc, char *argv[]) printf ("fisheye map:\t\t%s\n", enable_fisheye_map ? "true" : "false"); printf ("shading correction:\t%s\n", enable_lsc ? "true" : "false"); #if HAVE_OPENCV - printf ("feature match ocl:\t%s\n", fm_ocl ? "true" : "false"); + printf ("feature match:\t\t%s\n", need_fm ? "true" : "false"); #endif printf ("fisheye number:\t\t%d\n", fisheye_num); printf ("all in one:\t\t%s\n", all_in_one ? "true" : "false"); printf ("save file:\t\t%s\n", need_save_output ? "true" : "false"); + printf ("save top-view file:\t%s\n", save_top_view ? top_view_filename : "NO"); + printf ("save free-view file:\t%s\n", save_free_view ? rectified_view_filename : "NO"); printf ("framerate:\t\t%.3lf\n", framerate); printf ("loop count:\t\t%d\n", loop); printf ("-----------------------------------\n"); @@ -407,13 +422,16 @@ int main (int argc, char *argv[]) res_mode, fisheye_num, all_in_one).dynamic_cast_ptr<CLImage360Stitch> (); XCAM_ASSERT (image_360.ptr ()); image_360->set_output_size (output_width, output_height); + image_360->set_pool_type (CLImageHandler::CLVideoPoolType); #if HAVE_OPENCV - image_360->set_feature_match_ocl (fm_ocl); + image_360->set_feature_match (need_fm); #endif - image_360->set_pool_type (CLImageHandler::CLVideoPoolType); if (surround_mode == BowlView) { - parse_calibration_params (intrinsic_param, extrinsic_param, fisheye_num); + if (!parse_calibration_params (intrinsic_param, extrinsic_param, fisheye_num)) { + XCAM_LOG_ERROR ("parse calibration data failed in surround view."); + return -1; + } for (int i = 0; i < fisheye_num; i++) { image_360->set_fisheye_intrinsic (intrinsic_param[i], i); @@ -426,13 +444,15 @@ int main (int argc, char *argv[]) top_view_buf_info.init (input_format, top_view_width, top_view_height); rectified_view_buf_info.init (input_format, rectified_view_width, rectified_view_height); for (int i = 0; i < input_count; i++) { - buf_pool[i] = new CLVideoBufferPool (); - XCAM_ASSERT (buf_pool[i].ptr ()); - buf_pool[i]->set_video_info (input_buf_info); - if (!buf_pool[i]->reserve (6)) { + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + XCAM_ASSERT (pool.ptr ()); + pool->set_video_info (input_buf_info); + if (!pool->reserve (6)) { XCAM_LOG_ERROR ("init buffer pool failed"); return -1; } + + buf_pool[i] = pool; } SmartPtr<BufferPool> top_view_pool = new CLVideoBufferPool (); @@ -464,19 +484,21 @@ int main (int argc, char *argv[]) cv::VideoWriter rectified_view_writer; if (need_save_output) { cv::Size dst_size = cv::Size (output_width, output_height); - if (!writer.open (file_out_name, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { + if (!writer.open (file_out_name, FOURCC_X264, framerate, dst_size)) { XCAM_LOG_ERROR ("open file %s failed", file_out_name); return -1; } - - dst_size = cv::Size (top_view_width, top_view_height); - if (!top_view_writer.open (top_view_filename, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { + } + if (save_top_view) { + cv::Size dst_size = cv::Size (top_view_width, top_view_height); + if (!top_view_writer.open (top_view_filename, FOURCC_X264, framerate, dst_size)) { XCAM_LOG_ERROR ("open file %s failed", top_view_filename); return -1; } - - dst_size = cv::Size (rectified_view_width, rectified_view_height); - if (!rectified_view_writer.open (rectified_view_filename, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { + } + if (save_free_view) { + cv::Size dst_size = cv::Size (rectified_view_width, rectified_view_height); + if (!rectified_view_writer.open (rectified_view_filename, FOURCC_X264, framerate, dst_size)) { XCAM_LOG_ERROR ("open file %s failed", rectified_view_filename); return -1; } @@ -484,13 +506,15 @@ int main (int argc, char *argv[]) #endif SmartPtr<VideoBuffer> pre_buf, cur_buf; -#if (HAVE_OPENCV) && (XCAM_TEST_STITCH_DEBUG) + int frame_id = 0; +#if (HAVE_OPENCV) +#if XCAM_TEST_STITCH_DEBUG SmartPtr<VideoBuffer> input_bufs[XCAM_STITCH_FISHEYE_MAX_NUM]; #endif - int frame_id = 0; std::vector<PointFloat2> top_view_map_table; std::vector<PointFloat2> rectified_view_map_table; float rectified_start_angle = -45.0f, rectified_end_angle = 45.0f; +#endif while (loop--) { for (int i = 0; i < input_count; i++) { @@ -532,24 +556,29 @@ int main (int argc, char *argv[]) cv::Mat out_mat; convert_to_mat (output_buf, out_mat); writer.write (out_mat); + } - BowlDataConfig config = image_360->get_fisheye_bowl_config (); + BowlDataConfig config = image_360->get_fisheye_bowl_config (); + if (save_top_view) { cv::Mat top_view_mat; sample_generate_top_view (output_buf, top_view_buf, config, top_view_map_table); convert_to_mat (top_view_buf, top_view_mat); top_view_writer.write (top_view_mat); - + } + if (save_free_view) { cv::Mat rectified_view_mat; sample_generate_rectified_view (output_buf, rectified_view_buf, config, rectified_start_angle, rectified_end_angle, rectified_view_map_table); convert_to_mat (rectified_view_buf, rectified_view_mat); rectified_view_writer.write (rectified_view_mat); + } #if XCAM_TEST_STITCH_DEBUG - dbg_write_image (context, image_360, input_bufs, output_buf, top_view_buf, rectified_view_buf, - all_in_one, fisheye_num, input_count); + dbg_write_image (context, image_360, input_bufs, output_buf, top_view_buf, rectified_view_buf, + all_in_one, fisheye_num, input_count); #endif - } else + + if (!(need_save_output || save_top_view || save_free_view)) #endif ensure_gpu_buffer_done (output_buf); diff --git a/tests/test-pipe-manager.cpp b/tests/test-pipe-manager.cpp index 280bfdc..1389699 100644 --- a/tests/test-pipe-manager.cpp +++ b/tests/test-pipe-manager.cpp @@ -199,8 +199,6 @@ int main (int argc, char *argv[]) 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; @@ -400,7 +398,7 @@ int main (int argc, char *argv[]) pipe_manager->set_smart_analyzer (smart_analyzer); } - cl_post_processor = new CLPostImageProcessor (); + SmartPtr<CLPostImageProcessor> 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); @@ -416,7 +414,7 @@ int main (int argc, char *argv[]) pipe_manager->add_image_processor (cl_post_processor); buf_info.init (pixel_format, image_width, image_height); - buf_pool = new CLVideoBufferPool (); + SmartPtr<BufferPool> 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"); diff --git a/tests/test-render-surround-view.cpp b/tests/test-render-surround-view.cpp new file mode 100644 index 0000000..9142d4d --- /dev/null +++ b/tests/test-render-surround-view.cpp @@ -0,0 +1,688 @@ +/* + * test-render-surround-view.cpp - test render surround view + * + * 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: Zong Wei <wei.zong@intel.com> + */ + +#include "test_common.h" +#include "test_stream.h" +#include <interface/geo_mapper.h> +#include <interface/stitcher.h> +#include <calibration_parser.h> +#include <soft/soft_video_buf_allocator.h> +#if HAVE_GLES +#include <gles/gl_video_buffer.h> +#include <gles/egl/egl_base.h> +#endif +#if HAVE_VULKAN +#include <vulkan/vk_device.h> +#endif + +#include <render/render_osg_viewer.h> +#include <render/render_osg_model.h> +#include <render/render_osg_shader.h> + +using namespace XCam; + +#define CAR_MODEL_NAME "Suv.osgb" + +enum SVModule { + SVModuleNone = 0, + SVModuleSoft, + SVModuleGLES, + SVModuleVulkan +}; + +static const char *instrinsic_names[] = { + "intrinsic_camera_front.txt", + "intrinsic_camera_right.txt", + "intrinsic_camera_rear.txt", + "intrinsic_camera_left.txt" +}; + +static const char *exstrinsic_names[] = { + "extrinsic_camera_front.txt", + "extrinsic_camera_right.txt", + "extrinsic_camera_rear.txt", + "extrinsic_camera_left.txt" +}; + +static const float viewpoints_range[] = {64.0f, 160.0f, 64.0f, 160.0f}; + +static const char VtxShaderCar[] = "" + "precision highp float; \n" + "uniform mat4 osg_ModelViewProjectionMatrix; \n" + "uniform mat4 osg_ModelViewMatrix; \n" + "uniform mat3 osg_NormalMatrix; \n" + "attribute vec3 osg_Normal; \n" + "attribute vec4 osg_Color; \n" + "attribute vec4 osg_Vertex; \n" + "varying vec4 v_color; \n" + "varying float diffuseLight; \n" + "varying float specLight; \n" + "attribute vec2 osg_MultiTexCoord0; \n" + "varying vec2 texCoord0; \n" + "void main() \n" + "{ \n" + " vec4 light = vec4(0.0,100.0, 100.0, 1.0); \n" + " vec4 lightColorSpec = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorDiffuse = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorAmbient = vec4(0.3, 0.3, .3, 1.0); \n" + " vec4 carColorAmbient = vec4(0.0, 0.0, 1.0, 1.0); \n" + " vec4 carColorDiffuse = vec4(0.0, 0.0, 1.0, 1.0); \n" + " vec4 carColorSpec = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec3 tnorm = normalize(osg_NormalMatrix * osg_Normal); \n" + " vec4 eye = osg_ModelViewMatrix * osg_Vertex; \n" + " vec3 s = normalize(vec3(light - eye)); \n" + " vec3 v = normalize(-eye.xyz); \n" + " vec3 r = reflect(-s, tnorm); \n" + " diffuseLight = max(0.0, dot( s, tnorm)); \n" + " specLight = 0.0; \n" + " if(diffuseLight > 0.0) \n" + " { \n" + " specLight = pow(max(0.0, dot(r,v)), 10.0); \n" + " } \n" + " texCoord0 = osg_MultiTexCoord0; \n" + " v_color = (specLight * lightColorSpec * carColorSpec) + (carColorDiffuse * lightColorDiffuse * diffuseLight) + lightColorAmbient * carColorAmbient; \n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n" + "} \n"; + +static const char FrgShaderCar[] = "" + "precision highp float; \n" + "varying vec4 v_color; \n" + "varying float diffuseLight; \n" + "varying float specLight; \n" + "uniform sampler2D textureWheel; \n" + "varying vec2 texCoord0; \n" + "void main() \n" + "{ \n" + " vec4 lightColorSpec = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorDiffuse = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorAmbient = vec4(0.3, 0.3, .3, 1.0); \n" + " vec4 base = texture2D(textureWheel, texCoord0.st); \n" + " gl_FragColor = (specLight * lightColorSpec * base) + (base * lightColorDiffuse * diffuseLight) + lightColorAmbient * base ; \n" + "} \n"; + +class SVStream + : public Stream +{ +public: + explicit SVStream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); + virtual ~SVStream () {} + + void set_module (SVModule module) { + XCAM_ASSERT (module != SVModuleNone); + _module = module; + } + +#if HAVE_VULKAN + void set_vk_device (SmartPtr<VKDevice> &device) { + XCAM_ASSERT (device.ptr ()); + _vk_dev = device; + } + SmartPtr<VKDevice> &get_vk_device () { + return _vk_dev; + } +#endif + + virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count); + +private: + XCAM_DEAD_COPY (SVStream); + +private: + SVModule _module; +#if HAVE_VULKAN + SmartPtr<VKDevice> _vk_dev; +#endif +}; +typedef std::vector<SmartPtr<SVStream>> SVStreams; + +SVStream::SVStream (const char *file_name, uint32_t width, uint32_t height) + : Stream (file_name, width, height) + , _module (SVModuleNone) +{ +} + +XCamReturn +SVStream::create_buf_pool (const VideoBufferInfo &info, uint32_t count) +{ + XCAM_FAIL_RETURN ( + ERROR, _module != SVModuleNone, XCAM_RETURN_ERROR_PARAM, + "invalid module, please set module first"); + + SmartPtr<BufferPool> pool; + if (_module == SVModuleSoft) { + pool = new SoftVideoBufAllocator (info); + } else if (_module == SVModuleGLES) { +#if HAVE_GLES + pool = new GLVideoBufferPool (info); +#endif + } else if (_module == SVModuleVulkan) { +#if HAVE_VULKAN + XCAM_ASSERT (_vk_dev.ptr ()); + pool = create_vk_buffer_pool (_vk_dev); + XCAM_ASSERT (pool.ptr ()); + pool->set_video_info (info); +#endif + } + XCAM_ASSERT (pool.ptr ()); + + if (!pool->reserve (count)) { + XCAM_LOG_ERROR ("create buffer pool failed"); + pool.release (); + return XCAM_RETURN_ERROR_MEM; + } + + set_buf_pool (pool); + return XCAM_RETURN_NO_ERROR; +} + +static SmartPtr<Stitcher> +create_stitcher (const SmartPtr<SVStream> &stitch, SVModule module) +{ + SmartPtr<Stitcher> stitcher; + + if (module == SVModuleSoft) { + stitcher = Stitcher::create_soft_stitcher (); + } else if (module == SVModuleGLES) { +#if HAVE_GLES + stitcher = Stitcher::create_gl_stitcher (); +#endif + } else if (module == SVModuleVulkan) { +#if HAVE_VULKAN + SmartPtr<VKDevice> dev = stitch->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + stitcher = Stitcher::create_vk_stitcher (dev); +#else + XCAM_UNUSED (stitch); +#endif + } + XCAM_ASSERT (stitcher.ptr ()); + + return stitcher; +} + +static int +parse_camera_info (const char *path, uint32_t idx, CameraInfo &info, uint32_t camera_count) +{ + XCAM_ASSERT (path); + + char intrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + char extrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + snprintf (intrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, instrinsic_names[idx]); + snprintf (extrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, exstrinsic_names[idx]); + + CalibrationParser parser; + CHECK ( + parser.parse_intrinsic_file (intrinsic_path, info.calibration.intrinsic), + "parse intrinsic params(%s) failed.", intrinsic_path); + + CHECK ( + parser.parse_extrinsic_file (extrinsic_path, info.calibration.extrinsic), + "parse extrinsic params(%s) failed.", extrinsic_path); + info.calibration.extrinsic.trans_x += TEST_CAMERA_POSITION_OFFSET_X; + + info.angle_range = viewpoints_range[idx]; + info.round_angle_start = (idx * 360.0f / camera_count) - info.angle_range / 2.0f; + return 0; +} + +void +get_bowl_model ( + const SmartPtr<Stitcher> &stitcher, + BowlModel::VertexMap &vertices, + BowlModel::PointMap &points, + BowlModel::IndexVector &indices, + float &a, + float &b, + float &c, + float resRatio, + uint32_t image_width, + uint32_t image_height) +{ + uint32_t res_width = image_width * resRatio; + uint32_t res_height = image_height * resRatio; + + BowlDataConfig bowl = stitcher->get_bowl_config(); + bowl.angle_start = 0.0f; + bowl.angle_end = 360.0f; + + a = bowl.a; + b = bowl.b; + c = bowl.c; + + BowlModel bowl_model(bowl, image_width, image_height); + + bowl_model.get_bowlview_vertex_model( + vertices, + points, + indices, + res_width, + res_height); +} + +static SmartPtr<RenderOsgModel> +create_surround_view_model ( + const SmartPtr<Stitcher> &stitcher, + uint32_t texture_width, + uint32_t texture_height) +{ + SmartPtr<RenderOsgModel> svm_model = new RenderOsgModel ("svm model", texture_width, texture_height); + + svm_model->setup_shader_program ("SVM", osg::Shader::VERTEX, VtxShaderProjectNV12Texture); + svm_model->setup_shader_program ("SVM", osg::Shader::FRAGMENT, FrgShaderProjectNV12Texture); + + BowlModel::VertexMap vertices; + BowlModel::PointMap points; + BowlModel::IndexVector indices; + + float a = 0; + float b = 0; + float c = 0; + float res_ratio = 0.3; + float scaling = 1000.0f; + + get_bowl_model (stitcher, vertices, points, indices, + a, b, c, res_ratio, texture_width, texture_height ); + + svm_model->setup_vertex_model (vertices, points, indices, a / scaling, b / scaling, c / scaling); + + return svm_model; +} + +static SmartPtr<RenderOsgModel> +create_car_model (const char *name) +{ + std::string car_name; + if (NULL != name) { + car_name = std::string (name); + } else { + car_name = std::string (CAR_MODEL_NAME); + } + std::string car_model_path = FISHEYE_CONFIG_PATH + car_name; + + const char *env_path = std::getenv (FISHEYE_CONFIG_ENV_VAR); + if (env_path) { + car_model_path.clear (); + car_model_path = std::string (env_path) + car_name; + } + + SmartPtr<RenderOsgModel> car_model = new RenderOsgModel (car_model_path.c_str(), true); + + car_model->setup_shader_program ("Car", osg::Shader::VERTEX, VtxShaderCar); + car_model->setup_shader_program ("Car", osg::Shader::FRAGMENT, FrgShaderCar); + + float translation_x = -0.3f; + float translation_y = 0.0f; + float translation_z = 0.0f; + float rotation_x = 0.0f; + float rotation_y = 0.0f; + float rotation_z = 1.0f; + float rotation_degrees = -180.0; + + car_model->setup_model_matrix ( + translation_x, + translation_y, + translation_z, + rotation_x, + rotation_y, + rotation_z, + rotation_degrees); + + return car_model; +} + +static int +run_stitcher ( + const SmartPtr<Stitcher> &stitcher, + const SmartPtr<RenderOsgModel> &model, + const SVStreams &ins, + const SVStreams &outs) +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + + Mutex mutex; + + VideoBufferList in_buffers; + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK (ins[i]->rewind (), "rewind buffer from file(%s) failed", ins[i]->get_file_name ()); + } + + do { + in_buffers.clear (); + + for (uint32_t i = 0; i < ins.size (); ++i) { + ret = ins[i]->read_buf(); + if (ret == XCAM_RETURN_BYPASS) + break; + CHECK (ret, "read buffer from file(%s) failed.", ins[i]->get_file_name ()); + in_buffers.push_back (ins[i]->get_buf ()); + } + if (ret == XCAM_RETURN_BYPASS) { + XCAM_LOG_DEBUG ("XCAM_RETURN_BYPASS \n"); + break; + } + + { + SmartLock locker (mutex); + CHECK ( + stitcher->stitch_buffers (in_buffers, outs[0]->get_buf ()), + "stitch buffer failed."); + } + + model->update_texture (outs[0]->get_buf ()); + + FPS_CALCULATION (render surround view, XCAM_OBJ_DUR_FRAME_NUM); + } while (true); + + return 0; +} + +static void usage(const char* arg0) +{ + printf ("Usage:\n" + "%s --module MODULE --input0 input.nv12 --input1 input1.nv12 --input2 input2.nv12 ...\n" + "\t--module processing module, selected from: soft, gles, vulkan\n" + "\t-- read calibration files from exported path $FISHEYE_CONFIG_PATH\n" + "\t--input0 input image(NV12)\n" + "\t--input1 input image(NV12)\n" + "\t--input2 input image(NV12)\n" + "\t--input3 input image(NV12)\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: 1920\n" + "\t--out-h optional, output height, default: 640\n" + "\t--scale-mode optional, scaling mode for geometric mapping,\n" + "\t select from [singleconst/dualconst/dualcurve], default: singleconst\n" + "\t--fm-mode optional, feature match mode,\n" +#if HAVE_OPENCV + "\t select from [none/default/cluster/capi], default: none\n" +#else + "\t select from [none], default: none\n" +#endif + "\t--car optional, car model name\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 = 1920; + uint32_t output_height = 640; + + SVStreams ins; + SVStreams outs; + PUSH_STREAM (SVStream, outs, NULL); + + const char *car_name = NULL; + + SVModule module = SVModuleGLES; + GeoMapScaleMode scale_mode = ScaleSingleConst; + FeatureMatchMode fm_mode = FMNone; + + int loop = 1; + + const struct option long_opts[] = { + {"module", required_argument, NULL, 'm'}, + {"input0", required_argument, NULL, 'i'}, + {"input1", required_argument, NULL, 'j'}, + {"input2", required_argument, NULL, 'k'}, + {"input3", required_argument, NULL, 'l'}, + {"in-w", required_argument, NULL, 'w'}, + {"in-h", required_argument, NULL, 'h'}, + {"out-w", required_argument, NULL, 'W'}, + {"out-h", required_argument, NULL, 'H'}, + {"scale-mode", required_argument, NULL, 'S'}, + {"fm-mode", required_argument, NULL, 'F'}, + {"car", required_argument, NULL, 'c'}, + {"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 'm': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "soft")) { + module = SVModuleSoft; + } else if (!strcasecmp (optarg, "gles")) { + module = SVModuleGLES; + } else if (!strcasecmp (optarg, "vulkan")) { + module = SVModuleVulkan; + } + break; + case 'i': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'j': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'k': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'l': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'w': + XCAM_ASSERT (optarg); + input_width = (uint32_t)atoi(optarg); + break; + case 'h': + XCAM_ASSERT (optarg); + input_height = (uint32_t)atoi(optarg); + break; + case 'W': + XCAM_ASSERT (optarg); + output_width = (uint32_t)atoi(optarg); + break; + case 'H': + XCAM_ASSERT (optarg); + output_height = (uint32_t)atoi(optarg); + break; + case 'S': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "singleconst")) + scale_mode = ScaleSingleConst; + else if (!strcasecmp (optarg, "dualconst")) + scale_mode = ScaleDualConst; + else if (!strcasecmp (optarg, "dualcurve")) + scale_mode = ScaleDualCurve; + else { + XCAM_LOG_ERROR ("GeoMapScaleMode unknown mode: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 'F': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "none")) + fm_mode = FMNone; +#if HAVE_OPENCV + else if (!strcasecmp (optarg, "default")) + fm_mode = FMDefault; + else if (!strcasecmp (optarg, "cluster")) + fm_mode = FMCluster; + else if (!strcasecmp (optarg, "capi")) + fm_mode = FMCapi; +#endif + else { + XCAM_LOG_ERROR ("unsupported feature match mode: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 'c': + XCAM_ASSERT (optarg); + car_name = optarg; + 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; + } + + CHECK_EXP (ins.size () == 4, "surrond view needs 4 input streams"); + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK_EXP (ins[i].ptr (), "input stream is NULL, index:%d", i); + CHECK_EXP (strlen (ins[i]->get_file_name ()), "input file name was not set, index:%d", i); + } + + CHECK_EXP (outs.size () == 1 && outs[0].ptr (), "surrond view needs 1 output stream"); + + for (uint32_t i = 0; i < ins.size (); ++i) { + printf ("input%d file:\t\t%s\n", i, ins[i]->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 ("scaling mode:\t\t%s\n", (scale_mode == ScaleSingleConst) ? "singleconst" : + ((scale_mode == ScaleDualConst) ? "dualconst" : "dualcurve")); + printf ("feature match:\t\t%s\n", (fm_mode == FMNone) ? "none" : + ((fm_mode == FMDefault ) ? "default" : ((fm_mode == FMCluster) ? "cluster" : "capi"))); + printf ("car model name:\t\t%s\n", car_name != NULL ? car_name : "Not specified, use default model"); + printf ("loop count:\t\t%d\n", loop); + +#if HAVE_GLES + SmartPtr<EGLBase> egl; + if (module == SVModuleGLES) { + egl = new EGLBase (); + XCAM_ASSERT (egl.ptr ()); + XCAM_FAIL_RETURN (ERROR, egl->init (), -1, "init EGL failed"); + } +#else + if (module == SVModuleGLES) { + XCAM_LOG_ERROR ("GLES module is unsupported"); + return -1; + } +#endif + + if (module == SVModuleVulkan) { +#if HAVE_VULKAN + scale_mode = ScaleSingleConst; + if (scale_mode != ScaleSingleConst) { + XCAM_LOG_ERROR ("vulkan module only support singleconst scale mode currently"); + return -1; + } + + SmartPtr<VKDevice> vk_dev = VKDevice::default_device (); + for (uint32_t i = 0; i < ins.size (); ++i) { + ins[i]->set_vk_device (vk_dev); + } + XCAM_ASSERT (outs[0].ptr ()); + outs[0]->set_vk_device (vk_dev); +#else + XCAM_LOG_ERROR ("vulkan module is unsupported"); + return -1; +#endif + } + + 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_module (module); + ins[i]->set_buf_size (input_width, input_height); + CHECK (ins[i]->create_buf_pool (in_info, 6), "create buffer pool failed"); + CHECK (ins[i]->open_reader ("rb"), "open input file(%s) failed", ins[i]->get_file_name ()); + } + + outs[0]->set_buf_size (output_width, output_height); + + SmartPtr<Stitcher> stitcher = create_stitcher (outs[0], module); + XCAM_ASSERT (stitcher.ptr ()); + + CameraInfo cam_info[4]; + std::string fisheye_config_path = FISHEYE_CONFIG_PATH; + const char *env = std::getenv (FISHEYE_CONFIG_ENV_VAR); + if (env) + fisheye_config_path.assign (env, strlen (env)); + XCAM_LOG_INFO ("calibration config path:%s", fisheye_config_path.c_str ()); + + uint32_t camera_count = ins.size (); + for (uint32_t i = 0; i < camera_count; ++i) { + if (parse_camera_info (fisheye_config_path.c_str (), i, cam_info[i], camera_count) != 0) { + XCAM_LOG_ERROR ("parse fisheye dewarp info(idx:%d) failed.", i); + return -1; + } + } + + PointFloat3 bowl_coord_offset; + centralize_bowl_coord_from_cameras ( + cam_info[0].calibration.extrinsic, cam_info[1].calibration.extrinsic, + cam_info[2].calibration.extrinsic, cam_info[3].calibration.extrinsic, + bowl_coord_offset); + + stitcher->set_camera_num (camera_count); + for (uint32_t i = 0; i < camera_count; ++i) { + stitcher->set_camera_info (i, cam_info[i]); + } + + BowlDataConfig bowl; + bowl.wall_height = 1800.0f; + bowl.ground_length = 3000.0f; + bowl.angle_start = 0.0f; + bowl.angle_end = 360.0f; + stitcher->set_bowl_config (bowl); + stitcher->set_output_size (output_width, output_height); + stitcher->set_scale_mode (scale_mode); + stitcher->set_fm_mode (fm_mode); + + SmartPtr<RenderOsgViewer> render = new RenderOsgViewer (); + + SmartPtr<RenderOsgModel> sv_model = create_surround_view_model (stitcher, output_width, output_height); + render->add_model (sv_model); + + SmartPtr<RenderOsgModel> car_model = create_car_model (car_name); + render->add_model (car_model); + + render->validate_model_groups (); + + render->start_render (); + + while (loop--) { + CHECK_EXP ( + run_stitcher (stitcher, sv_model, ins, outs) == 0, + "run stitcher failed"); + } + + render->stop_render (); + + return 0; +} diff --git a/tests/test-soft-image.cpp b/tests/test-soft-image.cpp index 578de8e..d9d9493 100644 --- a/tests/test-soft-image.cpp +++ b/tests/test-soft-image.cpp @@ -20,31 +20,10 @@ #include "test_common.h" #include "test_inline.h" -#include <buffer_pool.h> -#include <image_handler.h> -#include <image_file_handle.h> +#include "test_stream.h" #include <soft/soft_video_buf_allocator.h> #include <interface/blender.h> #include <interface/geo_mapper.h> -#include <interface/stitcher.h> -#include <calibration_parser.h> -#include <string> - -#if (!defined(ANDROID) && (HAVE_OPENCV)) -#include <ocl/cv_base_class.h> -#endif - -#define XCAM_TEST_SOFT_IMAGE_DEBUG 0 - -#if (!defined(ANDROID) && (HAVE_OPENCV)) -#define XCAM_TEST_OPENCV 1 -#else -#define XCAM_TEST_OPENCV 0 -#endif - -#define XCAM_TEST_MAX_STR_SIZE 1024 - -#define FISHEYE_CONFIG_PATH "./" #define MAP_WIDTH 3 #define MAP_HEIGHT 4 @@ -59,484 +38,58 @@ static PointFloat2 map_table[MAP_HEIGHT * MAP_WIDTH] = { using namespace XCam; enum SoftType { - SoftTypeNone = 0, + SoftTypeNone = 0, SoftTypeBlender, - SoftTypeRemap, - SoftTypeStitch, + SoftTypeRemap }; -#define RUN_N(statement, loop, msg, ...) \ - for (int i = 0; i < loop; ++i) { \ - CHECK (statement, msg, ## __VA_ARGS__); \ - FPS_CALCULATION (soft-image, XCAM_OBJ_DUR_FRAME_NUM); \ - } - -#define ADD_ENELEMT(elements, file_name) \ - { \ - SmartPtr<SoftElement> element = new SoftElement (file_name); \ - elements.push_back (element); \ - } - -#if XCAM_TEST_OPENCV -const static cv::Scalar color = cv::Scalar (0, 0, 255); -const static int fontFace = cv::FONT_HERSHEY_COMPLEX; -#endif - -class SoftElement { +class SoftStream + : public Stream +{ public: - explicit SoftElement (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); - ~SoftElement (); + explicit SoftStream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); + virtual ~SoftStream () {} - void set_buf_size (uint32_t width, uint32_t height); - uint32_t get_width () const { - return _width; - } - uint32_t get_height () const { - return _height; - } - - const char *get_file_name () const { - return _file_name; - } - - SmartPtr<VideoBuffer> &get_buf () { - return _buf; - } - - XCamReturn open_file (const char *option); - XCamReturn close_file (); - XCamReturn rewind_file (); - - XCamReturn read_buf (); - XCamReturn write_buf (); - - XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count); - -#if XCAM_TEST_OPENCV - XCamReturn cv_open_writer (); - void cv_write_image (char *img_name, char *frame_str, char *idx_str = NULL); -#endif + virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count); private: - char *_file_name; - uint32_t _width; - uint32_t _height; - SmartPtr<VideoBuffer> _buf; - - ImageFileHandle _file; - SmartPtr<BufferPool> _pool; -#if XCAM_TEST_OPENCV - cv::VideoWriter _writer; -#endif + XCAM_DEAD_COPY (SoftStream); }; +typedef std::vector<SmartPtr<SoftStream>> SoftStreams; -typedef std::vector<SmartPtr<SoftElement>> SoftElements; - -SoftElement::SoftElement (const char *file_name, uint32_t width, uint32_t height) - : _file_name (NULL) - , _width (width) - , _height (height) +SoftStream::SoftStream (const char *file_name, uint32_t width, uint32_t height) + : Stream (file_name, width, height) { - if (file_name) - _file_name = strndup (file_name, XCAM_TEST_MAX_STR_SIZE); -} - -SoftElement::~SoftElement () -{ - _file.close (); - - if (_file_name) - xcam_free (_file_name); -} - -void -SoftElement::set_buf_size (uint32_t width, uint32_t height) -{ - _width = width; - _height = height; -} - -XCamReturn -SoftElement::open_file (const char *option) -{ - if (_file.open (_file_name, option) != XCAM_RETURN_NO_ERROR) { - XCAM_LOG_ERROR ("open %s failed.", _file_name); - return XCAM_RETURN_ERROR_FILE; - } - - return XCAM_RETURN_NO_ERROR; } XCamReturn -SoftElement::close_file () +SoftStream::create_buf_pool (const VideoBufferInfo &info, uint32_t count) { - return _file.close (); -} - -XCamReturn -SoftElement::rewind_file () -{ - return _file.rewind (); -} + SmartPtr<BufferPool> pool = new SoftVideoBufAllocator (); + XCAM_ASSERT (pool.ptr ()); -XCamReturn -SoftElement::create_buf_pool (const VideoBufferInfo &info, uint32_t count) -{ - _pool = new SoftVideoBufAllocator (); - _pool->set_video_info (info); - if (!_pool->reserve (count)) { + pool->set_video_info (info); + 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; } -XCamReturn -SoftElement::read_buf () -{ - _buf = _pool->get_buffer (_pool); - XCAM_ASSERT (_buf.ptr ()); - - return _file.read_buf (_buf); -} - -XCamReturn -SoftElement::write_buf () { - return _file.write_buf (_buf); -} - -#if XCAM_TEST_OPENCV -XCamReturn -SoftElement::cv_open_writer () -{ - XCAM_FAIL_RETURN ( - ERROR, - _width && _height, - XCAM_RETURN_ERROR_PARAM, - "invalid size width:%d height:%d", _width, _height); - - cv::Size frame_size = cv::Size (_width, _height); - if (!_writer.open (_file_name, CV_FOURCC('X', '2', '6', '4'), 30, frame_size)) { - XCAM_LOG_ERROR ("open file %s failed", _file_name); - return XCAM_RETURN_ERROR_FILE; - } - - return XCAM_RETURN_NO_ERROR; -} - -void -SoftElement::cv_write_image (char *img_name, char *frame_str, char *idx_str) -{ - cv::Mat mat; - -#if XCAM_TEST_SOFT_IMAGE_DEBUG - convert_to_mat (_buf, mat); - - cv::putText (mat, frame_str, cv::Point(20, 50), fontFace, 2.0, color, 2, 8, false); - if(idx_str) - cv::putText (mat, idx_str, cv::Point(20, 110), fontFace, 2.0, color, 2, 8, false); - - cv::imwrite (img_name, mat); -#else - XCAM_UNUSED (img_name); - XCAM_UNUSED (frame_str); - XCAM_UNUSED (idx_str); -#endif - - if (_writer.isOpened ()) { - if (mat.empty()) - convert_to_mat (_buf, mat); - - _writer.write (mat); - } -} -#endif - -static int -parse_camera_info (const char *path, uint32_t idx, CameraInfo &info, uint32_t camera_count) -{ - static const char *instrinsic_names[] = { - "intrinsic_camera_front.txt", "intrinsic_camera_right.txt", - "intrinsic_camera_rear.txt", "intrinsic_camera_left.txt" - }; - static const char *exstrinsic_names[] = { - "extrinsic_camera_front.txt", "extrinsic_camera_right.txt", - "extrinsic_camera_rear.txt", "extrinsic_camera_left.txt" - }; - static const float viewpoints_range[] = {64.0f, 160.0f, 64.0f, 160.0f}; - - char intrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - char extrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - snprintf (intrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, instrinsic_names[idx]); - snprintf (extrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, exstrinsic_names[idx]); - - CalibrationParser parser; - CHECK ( - parser.parse_intrinsic_file (intrinsic_path, info.calibration.intrinsic), - "parse intrinsic params (%s)failed.", intrinsic_path); - - CHECK ( - parser.parse_extrinsic_file (extrinsic_path, info.calibration.extrinsic), - "parse extrinsic params (%s)failed.", extrinsic_path); - info.calibration.extrinsic.trans_x += TEST_CAMERA_POSITION_OFFSET_X; - - info.angle_range = viewpoints_range[idx]; - info.round_angle_start = (idx * 360.0f / camera_count) - info.angle_range / 2.0f; - return 0; -} - -static void -combine_name (const char *orig_name, const char *embedded_str, char *new_name) -{ - const char *dir_delimiter = std::strrchr (orig_name, '/'); - - if (dir_delimiter) { - std::string path (orig_name, dir_delimiter - orig_name + 1); - XCAM_ASSERT (path.c_str ()); - snprintf (new_name, XCAM_TEST_MAX_STR_SIZE, "%s%s_%s", path.c_str (), embedded_str, dir_delimiter + 1); - } else { - snprintf (new_name, XCAM_TEST_MAX_STR_SIZE, "%s_%s", embedded_str, orig_name); - } -} - -static void -add_element (SoftElements &elements, const char *element_name, uint32_t width, uint32_t height) -{ - char file_name[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - combine_name (elements[0]->get_file_name (), element_name, file_name); - - SmartPtr<SoftElement> element = new SoftElement (file_name, width, height); - elements.push_back (element); -} - -static XCamReturn -elements_open_file (const SoftElements &elements, const char *option, const bool &nv12_output) -{ - XCamReturn ret = XCAM_RETURN_NO_ERROR; - - for (uint32_t i = 0; i < elements.size (); ++i) { - if (nv12_output) - ret = elements[i]->open_file (option); -#if XCAM_TEST_OPENCV - else - ret = elements[i]->cv_open_writer (); -#endif - - if (ret != XCAM_RETURN_NO_ERROR) { - XCAM_LOG_ERROR ("open file(%s) failed", elements[i]->get_file_name ()); - break; - } - } - - return ret; -} - -static XCamReturn -remap_topview_buf ( - BowlModel &model, - const SmartPtr<VideoBuffer> &buf, - SmartPtr<VideoBuffer> &topview_buf, - uint32_t topview_width, uint32_t topview_height) -{ - BowlModel::PointMap points; - - uint32_t lut_w = topview_width / 4, lut_h = topview_height / 4; - float length_mm = 0.0f, width_mm = 0.0f; - - model.get_max_topview_area_mm (length_mm, width_mm); - XCAM_LOG_INFO ("Max Topview Area (L%.2fmm, W%.2fmm)", length_mm, width_mm); - - model.get_topview_rect_map (points, lut_w, lut_h); - SmartPtr<GeoMapper> mapper = GeoMapper::create_soft_geo_mapper (); - XCAM_ASSERT (mapper.ptr ()); - mapper->set_output_size (topview_width, topview_height); - mapper->set_lookup_table (points.data (), lut_w, lut_h); - - XCamReturn ret = mapper->remap (buf, topview_buf); - if (ret != XCAM_RETURN_NO_ERROR) { - XCAM_LOG_ERROR ("remap stitched image to topview failed."); - return ret; - } - -#if 0 - BowlModel::VertexMap bowl_vertices; - BowlModel::PointMap bowl_points; - uint32_t bowl_lut_w = 15, bowl_lut_h = 10; - model.get_bowlview_vertex_map (bowl_vertices, bowl_points, bowl_lut_w, bowl_lut_h); - for (uint32_t i = 0; i < bowl_lut_h; ++i) { - for (uint32_t j = 0; j < bowl_lut_w; ++j) - { - PointFloat3 &vetex = bowl_vertices[i * bowl_lut_w + j]; - printf ("(%4.0f, %4.0f, %4.0f), ", vetex.x, vetex.y, vetex.z ); - } - printf ("\n"); - } -#endif - - return XCAM_RETURN_NO_ERROR; -} - -static void -write_image (const SoftElements &ins, const SoftElements &outs, const bool &nv12_output) { - if (nv12_output) { - for (uint32_t i = 0; i < outs.size (); ++i) - outs[i]->write_buf (); - } -#if XCAM_TEST_OPENCV - else { - static uint32_t frame_num = 0; - char img_name[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - char frame_str[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - std::snprintf (frame_str, XCAM_TEST_MAX_STR_SIZE, "frame:%d", frame_num); - - char idx_str[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - for (uint32_t i = 0; i < ins.size (); ++i) { - std::snprintf (idx_str, XCAM_TEST_MAX_STR_SIZE, "idx:%d", i); - std::snprintf (img_name, XCAM_TEST_MAX_STR_SIZE, "orig_fisheye_%d_%d.jpg", frame_num, i); - ins[i]->cv_write_image (img_name, frame_str, idx_str); - } - - for (uint32_t i = 0; i < outs.size (); ++i) { - std::snprintf (img_name, XCAM_TEST_MAX_STR_SIZE, "%s_%d.jpg", outs[i]->get_file_name (), frame_num); - outs[i]->cv_write_image (img_name, frame_str); - } - frame_num++; - } -#endif -} - -static XCamReturn -ensure_output_format (const char *file_name, const SoftType &type, bool &nv12_output) -{ - char suffix[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; - const char *ptr = std::strrchr (file_name, '.'); - std::snprintf (suffix, XCAM_TEST_MAX_STR_SIZE, "%s", ptr + 1); - if (!strcasecmp (suffix, "mp4")) { -#if XCAM_TEST_OPENCV - if (type != SoftTypeStitch) { - XCAM_LOG_ERROR ("only stitch type supports MP4 output format"); - return XCAM_RETURN_ERROR_PARAM; - } - nv12_output = false; -#else - XCAM_LOG_ERROR ("only supports NV12 output format"); - return XCAM_RETURN_ERROR_PARAM; -#endif - } - - return XCAM_RETURN_NO_ERROR; -} - -static bool -check_element (const SoftElements &elements, const uint32_t &idx) -{ - if (idx >= elements.size ()) - return false; - - if (!elements[idx].ptr()) { - XCAM_LOG_ERROR ("SoftElement(idx:%d) ptr is NULL", idx); - return false; - } - - XCAM_FAIL_RETURN ( - ERROR, - elements[idx]->get_width () && elements[idx]->get_height (), - false, - "SoftElement(idx:%d): invalid parameters width:%d height:%d", - idx, elements[idx]->get_width (), elements[idx]->get_height ()); - - return true; -} - -static XCamReturn -check_elements (const SoftElements &elements) -{ - for (uint32_t i = 0; i < elements.size (); ++i) { - XCAM_FAIL_RETURN ( - ERROR, - check_element (elements, i), - XCAM_RETURN_ERROR_PARAM, - "invalid SoftElement index:%d\n", i); - } - - return XCAM_RETURN_NO_ERROR; -} - -static XCamReturn -run_topview (const SmartPtr<Stitcher> &stitcher, const SoftElements &outs) -{ - BowlModel bowl_model (stitcher->get_bowl_config (), outs[0]->get_width (), outs[0]->get_height ()); - return remap_topview_buf (bowl_model, outs[0]->get_buf (), outs[1]->get_buf (), - outs[1]->get_width (), outs[1]->get_height ()); -} - -static int -run_stitcher ( - const SmartPtr<Stitcher> &stitcher, - const SoftElements &ins, const SoftElements &outs, - bool nv12_output, bool save_output, int loop) -{ - XCamReturn ret = XCAM_RETURN_NO_ERROR; - CHECK (check_elements (ins), "invalid input elements"); - CHECK (check_elements (outs), "invalid output elements"); - - VideoBufferList in_buffers; - while (loop--) { - for (uint32_t i = 0; i < ins.size (); ++i) { - CHECK (ins[i]->rewind_file (), "rewind buffer from file(%s) failed", ins[i]->get_file_name ()); - } - - do { - in_buffers.clear (); - - for (uint32_t i = 0; i < ins.size (); ++i) { - ret = ins[i]->read_buf(); - if (ret == XCAM_RETURN_BYPASS) - break; - CHECK (ret, "read buffer from file(%s) failed.", ins[i]->get_file_name ()); - - in_buffers.push_back (ins[i]->get_buf ()); - } - if (ret == XCAM_RETURN_BYPASS) - break; - - CHECK ( - stitcher->stitch_buffers (in_buffers, outs[0]->get_buf ()), - "stitch buffer failed."); - - if (save_output) { - if (check_element (outs, 1)) { - CHECK (run_topview (stitcher, outs), "run topview failed"); - } - - write_image (ins, outs, nv12_output); - } - - FPS_CALCULATION (soft - stitcher, XCAM_OBJ_DUR_FRAME_NUM); - } while (true); - } - - return 0; -} - static void usage(const char* arg0) { printf ("Usage:\n" - "%s --type TYPE--input0 file0 --input1 file1 --output file\n" - "\t--type processing type, selected from: blend, remap, stitch, ...\n" - "\t-- [stitch]: read calibration files from exported path $FISHEYE_CONFIG_PATH\n" + "%s --type TYPE --input0 input.nv12 --input1 input1.nv12 --output output.nv12 ...\n" + "\t--type processing type, selected from: blend, remap\n" "\t--input0 input image(NV12)\n" "\t--input1 input image(NV12)\n" - "\t--input2 input image(NV12)\n" - "\t--input3 input image(NV12)\n" - "\t--output output image(NV12)\n" - "\t--in-w optional, input width, default: 1920\n" - "\t--in-h optional, input height, default: 1080\n" - "\t--out-w optional, output width, default: 1920\n" - "\t--out-h optional, output height, default: 960\n" - "\t--topview-w optional, output width, default: 1280\n" - "\t--topview-h optional, output height, default: 720\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", @@ -545,36 +98,29 @@ static void usage(const char* arg0) int main (int argc, char *argv[]) { - uint32_t input_width = 1920; - uint32_t input_height = 1080; - uint32_t output_width = 1920; //output_height * 2; - uint32_t output_height = 960; //960; - uint32_t topview_width = 1280; - uint32_t topview_height = 720; - SoftType type = SoftTypeNone; + uint32_t input_width = 1280; + uint32_t input_height = 800; + uint32_t output_width = 1280; + uint32_t output_height = 800; - SoftElements ins; - SoftElements outs; + SoftStreams ins; + SoftStreams outs; + SoftType type = SoftTypeNone; int loop = 1; bool save_output = true; - bool nv12_output = true; const struct option long_opts[] = { {"type", required_argument, NULL, 't'}, {"input0", required_argument, NULL, 'i'}, {"input1", required_argument, NULL, 'j'}, - {"input2", required_argument, NULL, 'k'}, - {"input3", required_argument, NULL, 'l'}, {"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'}, - {"topview-w", required_argument, NULL, 'P'}, - {"topview-h", required_argument, NULL, 'V'}, {"save", required_argument, NULL, 's'}, - {"loop", required_argument, NULL, 'L'}, + {"loop", required_argument, NULL, 'l'}, {"help", no_argument, NULL, 'e'}, {NULL, 0, NULL, 0}, }; @@ -588,34 +134,23 @@ int main (int argc, char *argv[]) type = SoftTypeBlender; else if (!strcasecmp (optarg, "remap")) type = SoftTypeRemap; - else if (!strcasecmp (optarg, "stitch")) - type = SoftTypeStitch; else { XCAM_LOG_ERROR ("unknown type:%s", optarg); usage (argv[0]); return -1; } break; - case 'i': XCAM_ASSERT (optarg); - ADD_ENELEMT(ins, optarg); + PUSH_STREAM (SoftStream, ins, optarg); break; case 'j': XCAM_ASSERT (optarg); - ADD_ENELEMT(ins, optarg); - break; - case 'k': - XCAM_ASSERT (optarg); - ADD_ENELEMT(ins, optarg); - break; - case 'l': - XCAM_ASSERT (optarg); - ADD_ENELEMT(ins, optarg); + PUSH_STREAM (SoftStream, ins, optarg); break; case 'o': XCAM_ASSERT (optarg); - ADD_ENELEMT(outs, optarg); + PUSH_STREAM (SoftStream, outs, optarg); break; case 'w': input_width = atoi(optarg); @@ -629,18 +164,15 @@ int main (int argc, char *argv[]) case 'H': output_height = atoi(optarg); break; - case 'P': - topview_width = atoi(optarg); - break; - case 'V': - topview_height = atoi(optarg); - break; case 's': save_output = (strcasecmp (optarg, "false") == 0 ? false : true); break; - case 'L': + 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]); @@ -654,12 +186,6 @@ int main (int argc, char *argv[]) return -1; } - if (SoftTypeNone == type) { - XCAM_LOG_ERROR ("Type was not set"); - usage (argv[0]); - return -1; - } - if (ins.empty () || outs.empty () || !strlen (ins[0]->get_file_name ()) || !strlen (outs[0]->get_file_name ())) { XCAM_LOG_ERROR ("input or output file name was not set"); @@ -675,47 +201,55 @@ int main (int argc, char *argv[]) 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 ("topview width:\t\t%d\n", topview_width); - printf ("topview height:\t\t%d\n", topview_height); printf ("save output:\t\t%s\n", save_output ? "true" : "false"); printf ("loop count:\t\t%d\n", loop); - VideoBufferInfo in_info, out_info; + VideoBufferInfo in_info; in_info.init (V4L2_PIX_FMT_NV12, input_width, input_height); - out_info.init (V4L2_PIX_FMT_NV12, output_width, output_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, 6), "create buffer pool failed"); - CHECK (ins[i]->open_file ("rb"), "open file(%s) failed", ins[i]->get_file_name ()); + CHECK (ins[i]->open_reader ("rb"), "open input file(%s) failed", ins[i]->get_file_name ()); } outs[0]->set_buf_size (output_width, output_height); if (save_output) { - CHECK (ensure_output_format (outs[0]->get_file_name (), type, nv12_output), "unsupported output format"); - if (nv12_output) { - CHECK (outs[0]->open_file ("wb"), "open file(%s) failed", outs[0]->get_file_name ()); - } + 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 SoftTypeBlender: { - CHECK_EXP (ins.size () >= 2, "blender need 2 input files."); + CHECK_EXP (ins.size () == 2, "blender needs 2 input files."); SmartPtr<Blender> blender = Blender::create_soft_blender (); XCAM_ASSERT (blender.ptr ()); blender->set_output_size (output_width, output_height); - Rect merge_window; - merge_window.pos_x = 0; - merge_window.pos_y = 0; - merge_window.width = out_info.width; - merge_window.height = out_info.height; - blender->set_merge_window (merge_window); + + 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 ()); - RUN_N (blender->blend (ins[0]->get_buf (), ins[1]->get_buf (), outs[0]->get_buf ()), loop, "blend buffer failed."); - if (save_output) - outs[0]->write_buf (); + 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 (soft-blend, XCAM_OBJ_DUR_FRAME_NUM); + } break; } case SoftTypeRemap: { @@ -726,64 +260,14 @@ int main (int argc, char *argv[]) //mapper->set_factors ((output_width - 1.0f) / (MAP_WIDTH - 1.0f), (output_height - 1.0f) / (MAP_HEIGHT - 1.0f)); CHECK (ins[0]->read_buf(), "read buffer from file(%s) failed.", ins[0]->get_file_name ()); - RUN_N (mapper->remap (ins[0]->get_buf (), outs[0]->get_buf ()), loop, "remap buffer failed."); - if (save_output) - outs[0]->write_buf (); - break; - } - case SoftTypeStitch: { - CHECK_EXP (ins.size () >= 2 && ins.size () <= 4, "stitcher need at 2~4 input files."); - - uint32_t camera_count = ins.size (); - SmartPtr<Stitcher> stitcher = Stitcher::create_soft_stitcher (); - XCAM_ASSERT (stitcher.ptr ()); - - CameraInfo cam_info[4]; - const char *fisheye_config_path = getenv ("FISHEYE_CONFIG_PATH"); - if (!fisheye_config_path) - fisheye_config_path = FISHEYE_CONFIG_PATH; - - for (uint32_t i = 0; i < camera_count; ++i) { - if (parse_camera_info (fisheye_config_path, i, cam_info[i], camera_count) != 0) { - XCAM_LOG_ERROR ("parse fisheye dewarp info(idx:%d) failed.", i); - return -1; - } - } - - PointFloat3 bowl_coord_offset; - if (camera_count == 4) { - centralize_bowl_coord_from_cameras ( - cam_info[0].calibration.extrinsic, cam_info[1].calibration.extrinsic, - cam_info[2].calibration.extrinsic, cam_info[3].calibration.extrinsic, - bowl_coord_offset); + 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 (soft-remap, XCAM_OBJ_DUR_FRAME_NUM); } - - stitcher->set_camera_num (camera_count); - for (uint32_t i = 0; i < camera_count; ++i) { - stitcher->set_camera_info (i, cam_info[i]); - } - - BowlDataConfig bowl; - bowl.wall_height = 3000.0f; - bowl.ground_length = 2000.0f; - //bowl.a = 5000.0f; - //bowl.b = 3600.0f; - //bowl.c = 3000.0f; - bowl.angle_start = 0.0f; - bowl.angle_end = 360.0f; - stitcher->set_bowl_config (bowl); - stitcher->set_output_size (output_width, output_height); - - if (save_output) { - add_element (outs, "topview", topview_width, topview_height); - elements_open_file (outs, "wb", nv12_output); - } - CHECK_EXP ( - run_stitcher (stitcher, ins, outs, nv12_output, save_output, loop) == 0, - "run stitcher failed."); break; } - default: { XCAM_LOG_ERROR ("unsupported type:%d", type); usage (argv[0]); diff --git a/tests/test-surround-view.cpp b/tests/test-surround-view.cpp new file mode 100644 index 0000000..6d627c3 --- /dev/null +++ b/tests/test-surround-view.cpp @@ -0,0 +1,769 @@ +/* + * test-surround-view.cpp - test surround view + * + * 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 <yinhangx.liu@intel.com> + */ + +#include "test_common.h" +#include "test_stream.h" +#include <interface/geo_mapper.h> +#include <interface/stitcher.h> +#include <calibration_parser.h> +#include <soft/soft_video_buf_allocator.h> +#if HAVE_GLES +#include <gles/gl_video_buffer.h> +#include <gles/egl/egl_base.h> +#endif +#if HAVE_VULKAN +#include <vulkan/vk_device.h> +#endif + +using namespace XCam; + +enum FrameMode { + FrameSingle = 0, + FrameMulti +}; + +enum SVModule { + SVModuleNone = 0, + SVModuleSoft, + SVModuleGLES, + SVModuleVulkan +}; + +enum SVOutIdx { + IdxStitch = 0, + IdxTopView, + IdxCount +}; + +static const char *instrinsic_names[] = { + "intrinsic_camera_front.txt", + "intrinsic_camera_right.txt", + "intrinsic_camera_rear.txt", + "intrinsic_camera_left.txt" +}; + +static const char *exstrinsic_names[] = { + "extrinsic_camera_front.txt", + "extrinsic_camera_right.txt", + "extrinsic_camera_rear.txt", + "extrinsic_camera_left.txt" +}; + +static const float viewpoints_range[] = {64.0f, 160.0f, 64.0f, 160.0f}; + +class SVStream + : public Stream +{ +public: + explicit SVStream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); + virtual ~SVStream () {} + + void set_module (SVModule module) { + XCAM_ASSERT (module != SVModuleNone); + _module = module; + } + + void set_mapper (const SmartPtr<GeoMapper> &mapper) { + XCAM_ASSERT (mapper.ptr ()); + _mapper = mapper; + } + const SmartPtr<GeoMapper> &get_mapper () { + return _mapper; + } + +#if HAVE_VULKAN + void set_vk_device (SmartPtr<VKDevice> &device) { + XCAM_ASSERT (device.ptr ()); + _vk_dev = device; + } + SmartPtr<VKDevice> &get_vk_device () { + return _vk_dev; + } +#endif + + virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count); + +private: + XCAM_DEAD_COPY (SVStream); + +private: + SVModule _module; + SmartPtr<GeoMapper> _mapper; +#if HAVE_VULKAN + SmartPtr<VKDevice> _vk_dev; +#endif +}; +typedef std::vector<SmartPtr<SVStream>> SVStreams; + +SVStream::SVStream (const char *file_name, uint32_t width, uint32_t height) + : Stream (file_name, width, height) + , _module (SVModuleNone) +{ +} + +XCamReturn +SVStream::create_buf_pool (const VideoBufferInfo &info, uint32_t count) +{ + XCAM_FAIL_RETURN ( + ERROR, _module != SVModuleNone, XCAM_RETURN_ERROR_PARAM, + "invalid module, please set module first"); + + SmartPtr<BufferPool> pool; + if (_module == SVModuleSoft) { + pool = new SoftVideoBufAllocator (info); + } else if (_module == SVModuleGLES) { +#if HAVE_GLES + pool = new GLVideoBufferPool (info); +#endif + } else if (_module == SVModuleVulkan) { +#if HAVE_VULKAN + XCAM_ASSERT (_vk_dev.ptr ()); + pool = create_vk_buffer_pool (_vk_dev); + XCAM_ASSERT (pool.ptr ()); + pool->set_video_info (info); +#endif + } + 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 SmartPtr<Stitcher> +create_stitcher (const SmartPtr<SVStream> &stitch, SVModule module) +{ + SmartPtr<Stitcher> stitcher; + + if (module == SVModuleSoft) { + stitcher = Stitcher::create_soft_stitcher (); + } else if (module == SVModuleGLES) { +#if HAVE_GLES + stitcher = Stitcher::create_gl_stitcher (); +#endif + } else if (module == SVModuleVulkan) { +#if HAVE_VULKAN + SmartPtr<VKDevice> dev = stitch->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + stitcher = Stitcher::create_vk_stitcher (dev); +#else + XCAM_UNUSED (stitch); +#endif + } + XCAM_ASSERT (stitcher.ptr ()); + + return stitcher; +} + +static int +parse_camera_info (const char *path, uint32_t idx, CameraInfo &info, uint32_t camera_count) +{ + XCAM_ASSERT (path); + + char intrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + char extrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + snprintf (intrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, instrinsic_names[idx]); + snprintf (extrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, exstrinsic_names[idx]); + + CalibrationParser parser; + CHECK ( + parser.parse_intrinsic_file (intrinsic_path, info.calibration.intrinsic), + "parse intrinsic params(%s) failed.", intrinsic_path); + + CHECK ( + parser.parse_extrinsic_file (extrinsic_path, info.calibration.extrinsic), + "parse extrinsic params(%s) failed.", extrinsic_path); + info.calibration.extrinsic.trans_x += TEST_CAMERA_POSITION_OFFSET_X; + + info.angle_range = viewpoints_range[idx]; + info.round_angle_start = (idx * 360.0f / camera_count) - info.angle_range / 2.0f; + return 0; +} + +static void +combine_name (const char *orig_name, const char *embedded_str, char *new_name) +{ + const char *dir_delimiter = strrchr (orig_name, '/'); + + if (dir_delimiter) { + std::string path (orig_name, dir_delimiter - orig_name + 1); + XCAM_ASSERT (path.c_str ()); + snprintf (new_name, XCAM_TEST_MAX_STR_SIZE, "%s%s_%s", path.c_str (), embedded_str, dir_delimiter + 1); + } else { + snprintf (new_name, XCAM_TEST_MAX_STR_SIZE, "%s_%s", embedded_str, orig_name); + } +} + +static void +add_stream (SVStreams &streams, const char *stream_name, uint32_t width, uint32_t height) +{ + char file_name[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + combine_name (streams[0]->get_file_name (), stream_name, file_name); + + SmartPtr<SVStream> stream = new SVStream (file_name, width, height); + XCAM_ASSERT (stream.ptr ()); + streams.push_back (stream); +} + +static void +write_in_image (const SVStreams &ins, uint32_t frame_num) +{ +#if (XCAM_TEST_STREAM_DEBUG) && (XCAM_TEST_OPENCV) + char frame_str[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + std::snprintf (frame_str, XCAM_TEST_MAX_STR_SIZE, "frame:%d", frame_num); + + char img_name[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + char idx_str[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + for (uint32_t i = 0; i < ins.size (); ++i) { + std::snprintf (idx_str, XCAM_TEST_MAX_STR_SIZE, "idx:%d", i); + std::snprintf (img_name, XCAM_TEST_MAX_STR_SIZE, "orig_fisheye_%d_%d.jpg", frame_num, i); + ins[i]->debug_write_image (img_name, frame_str, idx_str); + } +#else + XCAM_UNUSED (ins); + XCAM_UNUSED (frame_num); +#endif +} + +static void +write_out_image (const SmartPtr<SVStream> &out, uint32_t frame_num) +{ +#if !XCAM_TEST_STREAM_DEBUG + XCAM_UNUSED (frame_num); + out->write_buf (); +#else + char frame_str[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + std::snprintf (frame_str, XCAM_TEST_MAX_STR_SIZE, "frame:%d", frame_num); + out->write_buf (frame_str); + +#if XCAM_TEST_OPENCV + char img_name[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + std::snprintf (img_name, XCAM_TEST_MAX_STR_SIZE, "%s_%d.jpg", out->get_file_name (), frame_num); + out->debug_write_image (img_name, frame_str); +#endif +#endif +} + +static XCamReturn +create_topview_mapper ( + const SmartPtr<Stitcher> &stitcher, const SmartPtr<SVStream> &stitch, + const SmartPtr<SVStream> &topview, SVModule module) +{ + BowlModel bowl_model (stitcher->get_bowl_config (), stitch->get_width (), stitch->get_height ()); + BowlModel::PointMap points; + + float length_mm = 0.0f, width_mm = 0.0f; + bowl_model.get_max_topview_area_mm (length_mm, width_mm); + XCAM_LOG_INFO ("Max Topview Area (L%.2fmm, W%.2fmm)", length_mm, width_mm); + + bowl_model.get_topview_rect_map (points, topview->get_width (), topview->get_height (), length_mm, width_mm); + SmartPtr<GeoMapper> mapper; + if (module == SVModuleSoft) { + mapper = GeoMapper::create_soft_geo_mapper (); + } else if (module == SVModuleGLES) { +#if HAVE_GLES + mapper = GeoMapper::create_gl_geo_mapper (); +#endif + } else if (module == SVModuleVulkan) { +#if HAVE_VULKAN + SmartPtr<VKDevice> dev = stitch->get_vk_device (); + XCAM_ASSERT (dev.ptr ()); + mapper = GeoMapper::create_vk_geo_mapper (dev, "topview-map"); +#endif + } + XCAM_ASSERT (mapper.ptr ()); + + mapper->set_output_size (topview->get_width (), topview->get_height ()); + mapper->set_lookup_table (points.data (), topview->get_width (), topview->get_height ()); + topview->set_mapper (mapper); + + return XCAM_RETURN_NO_ERROR; +} + +static XCamReturn +remap_topview_buf (const SmartPtr<SVStream> &stitch, const SmartPtr<SVStream> &topview) +{ + const SmartPtr<GeoMapper> mapper = topview->get_mapper(); + XCAM_ASSERT (mapper.ptr ()); + + XCamReturn ret = mapper->remap (stitch->get_buf (), topview->get_buf ()); + if (ret != XCAM_RETURN_NO_ERROR) { + XCAM_LOG_ERROR ("remap stitched image to topview failed."); + return ret; + } + + return XCAM_RETURN_NO_ERROR; +} + +static void +write_image ( + const SVStreams &ins, const SVStreams &outs, bool save_output, bool save_topview) +{ + static uint32_t frame_num = 0; + + write_in_image (ins, frame_num); + + if (save_output) + write_out_image (outs[IdxStitch], frame_num); + + if (save_topview) { + remap_topview_buf (outs[IdxStitch], outs[IdxTopView]); + write_out_image (outs[IdxTopView], frame_num); + } + + frame_num++; +} + +static int +single_frame ( + const SmartPtr<Stitcher> &stitcher, + const SVStreams &ins, const SVStreams &outs, + bool save_output, bool save_topview, int loop) +{ + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK (ins[i]->rewind (), "rewind buffer from file(%s) failed", ins[i]->get_file_name ()); + } + + VideoBufferList in_buffers; + for (uint32_t i = 0; i < ins.size (); ++i) { + XCamReturn ret = ins[i]->read_buf (); + CHECK_EXP (ret == XCAM_RETURN_NO_ERROR, "read buffer from file(%s) failed.", ins[i]->get_file_name ()); + + XCAM_ASSERT (ins[i]->get_buf ().ptr ()); + in_buffers.push_back (ins[i]->get_buf ()); + } + + while (loop--) { + CHECK (stitcher->stitch_buffers (in_buffers, outs[IdxStitch]->get_buf ()), "stitch buffer failed."); + + if (save_output || save_topview) + write_image (ins, outs, save_output, save_topview); + + FPS_CALCULATION (surround-view, XCAM_OBJ_DUR_FRAME_NUM); + } + + return 0; +} + +static int +multi_frame ( + const SmartPtr<Stitcher> &stitcher, + const SVStreams &ins, const SVStreams &outs, + bool save_output, bool save_topview, int loop) +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + + VideoBufferList in_buffers; + while (loop--) { + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK (ins[i]->rewind (), "rewind buffer from file(%s) failed", ins[i]->get_file_name ()); + } + + do { + in_buffers.clear (); + + for (uint32_t i = 0; i < ins.size (); ++i) { + ret = ins[i]->read_buf(); + if (ret == XCAM_RETURN_BYPASS) + break; + CHECK (ret, "read buffer from file(%s) failed.", ins[i]->get_file_name ()); + + in_buffers.push_back (ins[i]->get_buf ()); + } + if (ret == XCAM_RETURN_BYPASS) + break; + + CHECK ( + stitcher->stitch_buffers (in_buffers, outs[IdxStitch]->get_buf ()), + "stitch buffer failed."); + + if (save_output || save_topview) + write_image (ins, outs, save_output, save_topview); + + FPS_CALCULATION (surround-view, XCAM_OBJ_DUR_FRAME_NUM); + } while (true); + } + + return 0; +} + +static int +run_stitcher ( + const SmartPtr<Stitcher> &stitcher, + const SVStreams &ins, const SVStreams &outs, + FrameMode frame_mode, bool save_output, bool save_topview, int loop) +{ + CHECK (check_streams<SVStreams> (ins), "invalid input streams"); + CHECK (check_streams<SVStreams> (outs), "invalid output streams"); + + int ret = -1; + if (frame_mode == FrameSingle) + ret = single_frame (stitcher, ins, outs, save_output, save_topview, loop); + else if (frame_mode == FrameMulti) + ret = multi_frame (stitcher, ins, outs, save_output, save_topview, loop); + else + XCAM_LOG_ERROR ("invalid frame mode: %d", frame_mode); + + return ret; +} + +static void usage(const char* arg0) +{ + printf ("Usage:\n" + "%s --module MODULE --input0 input.nv12 --input1 input1.nv12 --input2 input2.nv12 ...\n" + "\t--module processing module, selected from: soft, gles, vulkan\n" + "\t-- read calibration files from exported path $FISHEYE_CONFIG_PATH\n" + "\t--input0 input image(NV12)\n" + "\t--input1 input image(NV12)\n" + "\t--input2 input image(NV12)\n" + "\t--input3 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: 1920\n" + "\t--out-h optional, output height, default: 640\n" + "\t--topview-w optional, output width, default: 1280\n" + "\t--topview-h optional, output height, default: 720\n" + "\t--scale-mode optional, scaling mode for geometric mapping,\n" + "\t select from [singleconst/dualconst/dualcurve], default: singleconst\n" + "\t--fm-mode optional, feature match mode,\n" +#if HAVE_OPENCV + "\t select from [none/default/cluster/capi], default: none\n" +#else + "\t select from [none], default: none\n" +#endif + "\t--frame-mode optional, times of buffer reading, select from [single/multi], default: multi\n" + "\t--save optional, save file or not, select from [true/false], default: true\n" + "\t--save-topview optional, save top view video, select from [true/false], default: false\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 = 1920; + uint32_t output_height = 640; + uint32_t topview_width = 1280; + uint32_t topview_height = 720; + + SVStreams ins; + SVStreams outs; + + FrameMode frame_mode = FrameMulti; + SVModule module = SVModuleNone; + GeoMapScaleMode scale_mode = ScaleSingleConst; + FeatureMatchMode fm_mode = FMNone; + + int loop = 1; + bool save_output = true; + bool save_topview = false; + + const struct option long_opts[] = { + {"module", required_argument, NULL, 'm'}, + {"input0", required_argument, NULL, 'i'}, + {"input1", required_argument, NULL, 'j'}, + {"input2", required_argument, NULL, 'k'}, + {"input3", required_argument, NULL, 'l'}, + {"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'}, + {"topview-w", required_argument, NULL, 'P'}, + {"topview-h", required_argument, NULL, 'V'}, + {"scale-mode", required_argument, NULL, 'S'}, + {"fm-mode", required_argument, NULL, 'F'}, + {"frame-mode", required_argument, NULL, 'f'}, + {"save", required_argument, NULL, 's'}, + {"save-topview", required_argument, NULL, 't'}, + {"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 'm': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "soft")) + module = SVModuleSoft; + else if (!strcasecmp (optarg, "gles")) { + module = SVModuleGLES; + } else if (!strcasecmp (optarg, "vulkan")) { + module = SVModuleVulkan; + } else { + XCAM_LOG_ERROR ("unknown module:%s", optarg); + usage (argv[0]); + return -1; + } + break; + case 'i': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'j': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'k': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'l': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'o': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, 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 'P': + topview_width = atoi(optarg); + break; + case 'V': + topview_height = atoi(optarg); + break; + case 'S': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "singleconst")) + scale_mode = ScaleSingleConst; + else if (!strcasecmp (optarg, "dualconst")) + scale_mode = ScaleDualConst; + else if (!strcasecmp (optarg, "dualcurve")) + scale_mode = ScaleDualCurve; + else { + XCAM_LOG_ERROR ("GeoMapScaleMode unknown mode: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 'F': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "none")) + fm_mode = FMNone; +#if HAVE_OPENCV + else if (!strcasecmp (optarg, "default")) + fm_mode = FMDefault; + else if (!strcasecmp (optarg, "cluster")) + fm_mode = FMCluster; + else if (!strcasecmp (optarg, "capi")) + fm_mode = FMCapi; +#endif + else { + XCAM_LOG_ERROR ("surround view unsupported feature match mode: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 'f': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "single")) + frame_mode = FrameSingle; + else if (!strcasecmp (optarg, "multi")) + frame_mode = FrameMulti; + else { + XCAM_LOG_ERROR ("FrameMode unknown mode: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 's': + save_output = (strcasecmp (optarg, "false") == 0 ? false : true); + break; + case 't': + save_topview = (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; + } + + CHECK_EXP (ins.size () == 4, "surrond view needs 4 input streams"); + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK_EXP (ins[i].ptr (), "input stream is NULL, index:%d", i); + CHECK_EXP (strlen (ins[i]->get_file_name ()), "input file name was not set, index:%d", i); + } + + CHECK_EXP (outs.size () == 1 && outs[IdxStitch].ptr (), "surrond view needs 1 output stream"); + CHECK_EXP (strlen (outs[IdxStitch]->get_file_name ()), "output file name was not set"); + + 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[IdxStitch]->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 ("topview width:\t\t%d\n", topview_width); + printf ("topview height:\t\t%d\n", topview_height); + printf ("scaling mode:\t\t%s\n", (scale_mode == ScaleSingleConst) ? "singleconst" : + ((scale_mode == ScaleDualConst) ? "dualconst" : "dualcurve")); + printf ("feature match:\t\t%s\n", (fm_mode == FMNone) ? "none" : + ((fm_mode == FMDefault ) ? "default" : ((fm_mode == FMCluster) ? "cluster" : "capi"))); + printf ("frame mode:\t\t%s\n", (frame_mode == FrameSingle) ? "singleframe" : "multiframe"); + printf ("save output:\t\t%s\n", save_output ? "true" : "false"); + printf ("save topview:\t\t%s\n", save_topview ? "true" : "false"); + printf ("loop count:\t\t%d\n", loop); + +#if HAVE_GLES + SmartPtr<EGLBase> egl; + if (module == SVModuleGLES) { + if (scale_mode == ScaleDualCurve) { + XCAM_LOG_ERROR ("GLES module does not support dualcurve scale mode currently"); + return -1; + } + + egl = new EGLBase (); + XCAM_ASSERT (egl.ptr ()); + XCAM_FAIL_RETURN (ERROR, egl->init (), -1, "init EGL failed"); + } +#else + if (module == SVModuleGLES) { + XCAM_LOG_ERROR ("GLES module is unsupported"); + return -1; + } +#endif + + if (module == SVModuleVulkan) { +#if HAVE_VULKAN + if (scale_mode != ScaleSingleConst) { + XCAM_LOG_ERROR ("vulkan module only support singleconst scale mode currently"); + return -1; + } + + SmartPtr<VKDevice> vk_dev = VKDevice::default_device (); + for (uint32_t i = 0; i < ins.size (); ++i) { + ins[i]->set_vk_device (vk_dev); + } + XCAM_ASSERT (outs[IdxStitch].ptr ()); + outs[IdxStitch]->set_vk_device (vk_dev); +#else + XCAM_LOG_ERROR ("vulkan module is unsupported"); + return -1; +#endif + } + + 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_module (module); + ins[i]->set_buf_size (input_width, input_height); + CHECK (ins[i]->create_buf_pool (in_info, 6), "create buffer pool failed"); + CHECK (ins[i]->open_reader ("rb"), "open input file(%s) failed", ins[i]->get_file_name ()); + } + + outs[IdxStitch]->set_buf_size (output_width, output_height); + if (save_output) { + CHECK (outs[IdxStitch]->estimate_file_format (), + "%s: estimate file format failed", outs[IdxStitch]->get_file_name ()); + CHECK (outs[IdxStitch]->open_writer ("wb"), "open output file(%s) failed", outs[IdxStitch]->get_file_name ()); + } + + SmartPtr<Stitcher> stitcher = create_stitcher (outs[IdxStitch], module); + XCAM_ASSERT (stitcher.ptr ()); + + CameraInfo cam_info[4]; + std::string fisheye_config_path = FISHEYE_CONFIG_PATH; + const char *env = std::getenv (FISHEYE_CONFIG_ENV_VAR); + if (env) + fisheye_config_path.assign (env, strlen (env)); + XCAM_LOG_INFO ("calibration config path:%s", fisheye_config_path.c_str ()); + + uint32_t camera_count = ins.size (); + for (uint32_t i = 0; i < camera_count; ++i) { + if (parse_camera_info (fisheye_config_path.c_str (), i, cam_info[i], camera_count) != 0) { + XCAM_LOG_ERROR ("parse fisheye dewarp info(idx:%d) failed.", i); + return -1; + } + } + + PointFloat3 bowl_coord_offset; + centralize_bowl_coord_from_cameras ( + cam_info[0].calibration.extrinsic, cam_info[1].calibration.extrinsic, + cam_info[2].calibration.extrinsic, cam_info[3].calibration.extrinsic, + bowl_coord_offset); + + stitcher->set_camera_num (camera_count); + for (uint32_t i = 0; i < camera_count; ++i) { + stitcher->set_camera_info (i, cam_info[i]); + } + + BowlDataConfig bowl; + bowl.wall_height = 1800.0f; + bowl.ground_length = 3000.0f; + bowl.angle_start = 0.0f; + bowl.angle_end = 360.0f; + stitcher->set_bowl_config (bowl); + stitcher->set_output_size (output_width, output_height); + stitcher->set_scale_mode (scale_mode); + stitcher->set_fm_mode (fm_mode); + + if (save_topview) { + add_stream (outs, "topview", topview_width, topview_height); + XCAM_ASSERT (outs.size () >= IdxCount); + + CHECK (outs[IdxTopView]->estimate_file_format (), + "%s: estimate file format failed", outs[IdxTopView]->get_file_name ()); + CHECK (outs[IdxTopView]->open_writer ("wb"), "open output file(%s) failed", outs[IdxTopView]->get_file_name ()); + + create_topview_mapper (stitcher, outs[IdxStitch], outs[IdxTopView], module); + } + + CHECK_EXP ( + run_stitcher (stitcher, ins, outs, frame_mode, save_output, save_topview, loop) == 0, + "run stitcher failed"); + + return 0; +} diff --git a/tests/test-video-stabilization.cpp b/tests/test-video-stabilization.cpp index 5280467..7885462 100644 --- a/tests/test-video-stabilization.cpp +++ b/tests/test-video-stabilization.cpp @@ -33,7 +33,7 @@ #if HAVE_OPENCV #include <opencv2/opencv.hpp> #include <opencv2/core/ocl.hpp> -#include <ocl/cv_base_class.h> +#include "ocv/cv_utils.h" #endif using namespace XCam; @@ -62,10 +62,7 @@ int main (int argc, char *argv[]) XCamReturn ret = XCAM_RETURN_NO_ERROR; SmartPtr<CLVideoStabilizer> video_stab; - SmartPtr<CLContext> context; - SmartPtr<BufferPool> buf_pool; - VideoBufferInfo input_buf_info; VideoBufferInfo output_buf_info; SmartPtr<VideoBuffer> input_buf; @@ -84,7 +81,6 @@ int main (int argc, char *argv[]) const char *gyro_data = "gyro_data.csv"; bool need_save_output = true; - double framerate = 30.0; int loop = 1; const struct option long_opts[] = { @@ -127,7 +123,7 @@ int main (int argc, char *argv[]) break; case 'H': usage (argv[0]); - return -1; + return 0; default: printf ("getopt_long return unknown value:%c\n", opt); usage (argv[0]); @@ -201,7 +197,7 @@ int main (int argc, char *argv[]) input_buf_info.init (input_format, input_width, input_height); output_buf_info.init (input_format, output_width, output_height); - buf_pool = new CLVideoBufferPool (); + SmartPtr<BufferPool> buf_pool = new CLVideoBufferPool (); XCAM_ASSERT (buf_pool.ptr ()); buf_pool->set_video_info (input_buf_info); if (!buf_pool->reserve (36)) { @@ -216,7 +212,7 @@ int main (int argc, char *argv[]) cv::VideoWriter writer; if (need_save_output) { cv::Size dst_size = cv::Size (output_width, output_height); - if (!writer.open (file_out_name, CV_FOURCC('X', '2', '6', '4'), framerate, dst_size)) { + if (!writer.open (file_out_name, cv::VideoWriter::fourcc ('X', '2', '6', '4'), 30, dst_size)) { XCAM_LOG_ERROR ("open file %s failed", file_out_name); return -1; } diff --git a/tests/test-vk-handler.cpp b/tests/test-vk-handler.cpp new file mode 100644 index 0000000..30941fc --- /dev/null +++ b/tests/test-vk-handler.cpp @@ -0,0 +1,340 @@ +/* + * test_vk_handler.cpp - test vulkan 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: Wind Yuan <feng.yuan@intel.com> + */ + +#include "test_common.h" +#include "test_stream.h" + +#include <vulkan/vk_device.h> +#include <vulkan/vk_copy_handler.h> +#include <vulkan/vk_geomap_handler.h> +#include <interface/blender.h> + +using namespace XCam; + +enum VKType { + VKTypeNone = 0, + VKTypeCopy, + VKTypeRemap, + VKTypeBlender +}; + +class VKStream + : public Stream +{ +public: + explicit VKStream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); + virtual ~VKStream () {} + + void set_vk_device (SmartPtr<VKDevice> &device) { + XCAM_ASSERT (device.ptr ()); + _device = device; + } + + virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count); + +private: + SmartPtr<VKDevice> _device; +}; + +typedef std::vector<SmartPtr<VKStream>> VKStreams; + +VKStream::VKStream (const char *file_name, uint32_t width, uint32_t height) + : Stream (file_name, width, height) +{ +} + +XCamReturn +VKStream::create_buf_pool (const VideoBufferInfo &info, uint32_t count) +{ + XCAM_FAIL_RETURN ( + ERROR, _device.ptr(), XCAM_RETURN_ERROR_PARAM, + "vulkan device id NULL, please set device first"); + + SmartPtr<BufferPool> pool = create_vk_buffer_pool (_device); + XCAM_ASSERT (pool.ptr ()); + + if (!pool->set_video_info (info)) { + XCAM_LOG_ERROR ("set video info failed"); + return XCAM_RETURN_ERROR_UNKNOWN; + } + + 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 +print_help (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); + + printf ("Note:\n" + "Spirv path Setup Env: $" XCAM_VK_SHADER_PATH "\n" + "Generate spirv kernel:\n" + "glslangValidator -V -x -o sample.comp.spv sample.comp.sl\n" + ); +} + +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; + + VKStreams ins; + VKStreams outs; + VKType type = VKTypeNone; + + 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 = VKTypeCopy; + else if (!strcasecmp (optarg, "remap")) + type = VKTypeRemap; + else if (!strcasecmp (optarg, "blend")) + type = VKTypeBlender; + else { + XCAM_LOG_ERROR ("unknown type:%s", optarg); + print_help (argv[0]); + return -1; + } + break; + case 'i': + XCAM_ASSERT (optarg); + PUSH_STREAM (VKStream, ins, optarg); + break; + case 'j': + XCAM_ASSERT (optarg); + PUSH_STREAM (VKStream, ins, optarg); + break; + case 'o': + XCAM_ASSERT (optarg); + PUSH_STREAM (VKStream, 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': + print_help (argv[0]); + return 0; + default: + XCAM_LOG_ERROR ("getopt_long return unknown value:%c", opt); + print_help (argv[0]); + return -1; + } + } + + if (optind < argc || argc < 2) { + XCAM_LOG_ERROR ("unknown option %s", argv[optind]); + print_help (argv[0]); + return -1; + } + + if (ins.empty () || outs.empty ()) { + XCAM_LOG_ERROR ("input or output stream is empty"); + print_help (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<VKDevice> vk_device = VKDevice::default_device (); + XCAM_FAIL_RETURN ( + ERROR, vk_device.ptr(), -1, + "Get default VKDevice failed, please check vulkan environment"); + + 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); + ins[i]->set_vk_device (vk_device); + CHECK (ins[i]->create_buf_pool (in_info, 4), "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 VKTypeCopy: { + SmartPtr<VKCopyHandler> copyer = new VKCopyHandler (vk_device, "vk-copy"); + XCAM_ASSERT (copyer.ptr ()); + + Rect in_area = Rect (0, 0, input_width, input_height); + Rect out_area = Rect (0, 0, output_width, output_height); + XCAM_ASSERT (in_area.width == out_area.width && in_area.height == out_area.height); + 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 (vk-copy, XCAM_OBJ_DUR_FRAME_NUM); + } + break; + } + case VKTypeRemap: { + SmartPtr<VKGeoMapHandler> mapper = new VKGeoMapHandler (vk_device, "vk-remap"); + 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 (vk-remap, XCAM_OBJ_DUR_FRAME_NUM); + } + break; + } + case VKTypeBlender: { + CHECK_EXP (ins.size () == 2, "Error: blender needs 2 input files."); + SmartPtr<Blender> blender = Blender::create_vk_blender (vk_device); + 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 (vk-blend, XCAM_OBJ_DUR_FRAME_NUM); + } + break; + } + default: { + XCAM_LOG_ERROR ("unsupported type:%d", type); + print_help (argv[0]); + return -1; + } + } + + return 0; +} diff --git a/tests/test_common.h b/tests/test_common.h index 9ca75e3..3052a60 100644 --- a/tests/test_common.h +++ b/tests/test_common.h @@ -24,6 +24,7 @@ #include <unistd.h> #include <getopt.h> +#include <string> #define TEST_CAMERA_POSITION_OFFSET_X 2000 @@ -60,6 +61,8 @@ #define DEFAULT_HYBRID_3A_LIB "/usr/lib/xcam/plugins/3a/libxcam_3a_hybrid.so" #define DEFAULT_SMART_ANALYSIS_LIB_DIR "/usr/lib/xcam/plugins/smart" +#define FISHEYE_CONFIG_PATH "./calib_params/" +#define FISHEYE_CONFIG_ENV_VAR "FISHEYE_CONFIG_PATH" #define FPS_CALCULATION(objname, count) XCAM_STATIC_FPS_CALCULATION(objname, count) diff --git a/tests/test_stream.h b/tests/test_stream.h new file mode 100644 index 0000000..6bbaf8a --- /dev/null +++ b/tests/test_stream.h @@ -0,0 +1,333 @@ +/* + * test_stream.h - test stream class + * + * 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 <yinhangx.liu@intel.com> + */ + +#ifndef XCAM_TEST_STREAM_H +#define XCAM_TEST_STREAM_H + +#include <buffer_pool.h> +#include <image_file_handle.h> +#if (!defined(ANDROID) && (HAVE_OPENCV)) +#include "ocv/cv_utils.h" +#endif + +#define XCAM_TEST_STREAM_DEBUG 0 + +#define XCAM_TEST_MAX_STR_SIZE 256 + +#if (!defined(ANDROID) && (HAVE_OPENCV)) +#define XCAM_TEST_OPENCV 1 +#else +#define XCAM_TEST_OPENCV 0 +#endif + +#if XCAM_TEST_OPENCV +const static cv::Scalar color = cv::Scalar (0, 0, 255); +const static int fontFace = cv::FONT_HERSHEY_COMPLEX; +#endif + +namespace XCam { + +enum TestFileFormat { + FileNone, + FileNV12, + FileMP4 +}; + +#define PUSH_STREAM(Type, streams, file_name) \ + { \ + SmartPtr<Type> stream = new Type (file_name); \ + XCAM_ASSERT (stream.ptr ()); \ + streams.push_back (stream); \ + } + +template <typename TType> +XCamReturn check_streams (const TType &streams) +{ + for (uint32_t i = 0; i < streams.size (); ++i) { + if (!streams[i].ptr()) { + XCAM_LOG_ERROR ("streams[%d] ptr is NULL", i); + return XCAM_RETURN_ERROR_PARAM; + } + + XCAM_FAIL_RETURN ( + ERROR, streams[i]->get_width () && streams[i]->get_height (), XCAM_RETURN_ERROR_PARAM, + "streams[%d]: invalid parameters width:%d height:%d, please set buffer size first", + i, streams[i]->get_width (), streams[i]->get_height ()); + } + + return XCAM_RETURN_NO_ERROR; +} + +class Stream { +public: + explicit Stream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); + virtual ~Stream (); + + void set_buf_size (uint32_t width, uint32_t height); + uint32_t get_width () const { + return _width; + } + uint32_t get_height () const { + return _height; + } + SmartPtr<VideoBuffer> &get_buf () { + return _buf; + } + const char *get_file_name () const { + return _file_name; + } + XCamReturn estimate_file_format (); + + XCamReturn open_reader (const char *option); + XCamReturn open_writer (const char *option); + XCamReturn close (); + XCamReturn rewind (); + + XCamReturn read_buf (); + XCamReturn write_buf (char *frame_str = NULL); + virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count) = 0; + +#if XCAM_TEST_OPENCV + void debug_write_image (char *img_name, char *frame_str = NULL, char *idx_str = NULL); +#endif + +protected: + void set_buf_pool (const SmartPtr<BufferPool> &pool) { + _pool = pool; + } + +private: +#if XCAM_TEST_OPENCV + XCamReturn cv_open_writer (); + void cv_write_buf (char *frame_str = NULL); +#endif + +private: + XCAM_DEAD_COPY (Stream); + +private: + char *_file_name; + uint32_t _width; + uint32_t _height; + + SmartPtr<VideoBuffer> _buf; + SmartPtr<BufferPool> _pool; + + ImageFileHandle _file; +#if XCAM_TEST_OPENCV + cv::VideoWriter _writer; +#endif + TestFileFormat _format; +}; + +Stream::Stream (const char *file_name, uint32_t width, uint32_t height) + : _file_name (NULL) + , _width (width) + , _height (height) + , _format (FileNV12) +{ + if (file_name) + _file_name = strndup (file_name, XCAM_TEST_MAX_STR_SIZE); +} + +Stream::~Stream () +{ + _file.close (); + + if (_file_name) { + xcam_free (_file_name); + _file_name = NULL; + } +} + +void +Stream::set_buf_size (uint32_t width, uint32_t height) +{ + _width = width; + _height = height; +} + +XCamReturn +Stream::open_reader (const char *option) +{ + XCAM_FAIL_RETURN ( + ERROR, _format == FileNV12, XCAM_RETURN_ERROR_PARAM, + "stream(%s) only support NV12 input format", _file_name); + + if (_file.open (_file_name, option) != XCAM_RETURN_NO_ERROR) { + XCAM_LOG_ERROR ("stream(%s) open failed", _file_name); + return XCAM_RETURN_ERROR_FILE; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +Stream::open_writer (const char *option) +{ + XCAM_ASSERT (_format != FileNone); + + if (_format == FileNV12) { + if (_file.open (_file_name, option) != XCAM_RETURN_NO_ERROR) { + XCAM_LOG_ERROR ("stream(%s) open failed", _file_name); + return XCAM_RETURN_ERROR_FILE; + } + } else if (_format == FileMP4) { +#if XCAM_TEST_OPENCV + XCamReturn ret = cv_open_writer (); + XCAM_FAIL_RETURN ( + ERROR, ret == XCAM_RETURN_NO_ERROR, ret, "stream(%s) cv open writer failed", _file_name); +#else + XCAM_LOG_ERROR ("stream(%s) unsupported MP4 format without opencv", _file_name); + return XCAM_RETURN_ERROR_PARAM; +#endif + } else { + XCAM_LOG_ERROR ("stream(%s) invalid file format: %d", _file_name, (int)_format); + return XCAM_RETURN_ERROR_PARAM; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +Stream::close () +{ + return _file.close (); +} + +XCamReturn +Stream::rewind () +{ + return _file.rewind (); +} + +XCamReturn +Stream::read_buf () +{ + XCAM_ASSERT (_pool.ptr ()); + + _buf = _pool->get_buffer (_pool); + XCAM_ASSERT (_buf.ptr ()); + + return _file.read_buf (_buf); +} + +XCamReturn +Stream::write_buf (char *frame_str) { + if (_format == FileNV12) { + _file.write_buf (_buf); + } else if (_format == FileMP4) { +#if XCAM_TEST_OPENCV + cv_write_buf (frame_str); +#else + XCAM_UNUSED (frame_str); + XCAM_LOG_ERROR ("stream(%s) unsupported MP4 format without opencv", _file_name); + return XCAM_RETURN_ERROR_PARAM; +#endif + } else { + XCAM_LOG_ERROR ("stream(%s) invalid file format: %d", _file_name, (int)_format); + return XCAM_RETURN_ERROR_PARAM; + } + + return XCAM_RETURN_NO_ERROR; +} + +XCamReturn +Stream::estimate_file_format () +{ + XCAM_ASSERT (get_file_name ()); + + char suffix[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + const char *ptr = strrchr (get_file_name (), '.'); + snprintf (suffix, XCAM_TEST_MAX_STR_SIZE, "%s", ptr + 1); + + if (!strcasecmp (suffix, "nv12")) { + _format = FileNV12; + } else if (!strcasecmp (suffix, "mp4")) { +#if XCAM_TEST_OPENCV + _format = FileMP4; +#else + XCAM_LOG_ERROR ("stream(%s) unsupported MP4 format without opencv", _file_name); + return XCAM_RETURN_ERROR_PARAM; +#endif + } else { + XCAM_LOG_ERROR ("stream(%s) invalid file format: %s", _file_name, suffix); + return XCAM_RETURN_ERROR_PARAM; + } + + return XCAM_RETURN_NO_ERROR; +} + +#if XCAM_TEST_OPENCV +XCamReturn +Stream::cv_open_writer () +{ + XCAM_FAIL_RETURN ( + ERROR, _width && _height, XCAM_RETURN_ERROR_PARAM, + "stream(%s) invalid size width:%d height:%d", _file_name, _width, _height); + + cv::Size frame_size = cv::Size (_width, _height); + if (!_writer.open (_file_name, cv::VideoWriter::fourcc ('X', '2', '6', '4'), 30, frame_size)) { + XCAM_LOG_ERROR ("stream(%s) open file failed", _file_name); + return XCAM_RETURN_ERROR_FILE; + } + + return XCAM_RETURN_NO_ERROR; +} + +void +Stream::cv_write_buf (char *frame_str) +{ + cv::Mat mat; + +#if XCAM_TEST_STREAM_DEBUG + convert_to_mat (_buf, mat); + cv::putText (mat, frame_str, cv::Point(20, 50), fontFace, 2.0, color, 2, 8, false); +#else + XCAM_UNUSED (frame_str); +#endif + + if (_writer.isOpened ()) { + if (mat.empty()) + convert_to_mat (_buf, mat); + + _writer.write (mat); + } +} + +void +Stream::debug_write_image (char *img_name, char *frame_str, char *idx_str) +{ + XCAM_ASSERT (img_name); + + cv::Mat mat; + convert_to_mat (_buf, mat); + + if(frame_str) + cv::putText (mat, frame_str, cv::Point(20, 50), fontFace, 2.0, color, 2, 8, false); + if(idx_str) + cv::putText (mat, idx_str, cv::Point(20, 110), fontFace, 2.0, color, 2, 8, false); + + cv::imwrite (img_name, mat); +} +#endif + +} +#endif // XCAM_TEST_STREAM_H diff --git a/tools/cl-double-quotation.sh b/tools/add-quotation-marks.sh index 5a77a67..3c669f5 100755 --- a/tools/cl-double-quotation.sh +++ b/tools/add-quotation-marks.sh @@ -1,12 +1,12 @@ #! /bin/sh -# Add double quotation marks on cl file, this script will -# be called in top_srcdir/clx_kernel/Makefile.am +# Add double quotation marks on source file +# Usage: add-quotation-marks.sh <src_file> <dst_file> -CL_FILE=$1 -CLX_FILE=$2 +SRC_FILE=$1 +DST_FILE=$2 if [ $# -ne 2 ]; then - echo "Usage: $0 <cl_file> <clx_file>" + echo "Usage: $0 <src_file> <dst_file>" exit 1 fi @@ -32,15 +32,15 @@ gawk ' } } } - ' $CL_FILE > $CLX_FILE.tmp + ' $SRC_FILE > $DST_FILE.tmp ret=$? if [ $ret != 0 ]; then - rm -rf $CLX_FILE.tmp - echo "Add double quotation marks on $CL_FILE failed" + rm -rf $DST_FILE.tmp + echo "Add double quotation marks on $SRC_FILE failed" exit 1 fi -mv $CLX_FILE.tmp $CLX_FILE +mv $DST_FILE.tmp $DST_FILE -echo "Add double quotation marks on $CL_FILE done" +echo "Add double quotation marks on $SRC_FILE done" diff --git a/wrapper/Makefile.am b/wrapper/Makefile.am index 63dbffd..cac6ded 100644 --- a/wrapper/Makefile.am +++ b/wrapper/Makefile.am @@ -1,8 +1,5 @@ - if ENABLE_GST GST_DIR = gstreamer -else -GST_DIR = endif SUBDIRS = $(GST_DIR) diff --git a/wrapper/gstreamer/Makefile.am b/wrapper/gstreamer/Makefile.am index 8a47a6f..cc0f7d8 100644 --- a/wrapper/gstreamer/Makefile.am +++ b/wrapper/gstreamer/Makefile.am @@ -2,135 +2,117 @@ if ENABLE_IA_AIQ SUBDIRS = interface endif -plugin_LTLIBRARIES = \ - libgstxcamsrc.la \ - $(NULL) +plugin_LTLIBRARIES = libgstxcamsrc.la if HAVE_LIBCL -plugin_LTLIBRARIES += \ - libgstxcamfilter.la \ - $(NULL) +plugin_LTLIBRARIES += libgstxcamfilter.la endif -XCORE_DIR = $(top_srcdir)/xcore -MODULES_DIR = $(top_srcdir)/modules - -XCORE_LA = $(top_builddir)/xcore/libxcam_core.la - -if ENABLE_IA_AIQ -XCAM_INTERFACE_DIR = -I$(top_srcdir)/wrapper/gstreamer/interface -XCAM_INTERFACE_LA = $(top_builddir)/wrapper/gstreamer/interface/libgstxcaminterface.la -else -XCAM_INTERFACE_DIR = -XCAM_INTERFACE_LA = -endif +XCAM_GST_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + $(GST_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + -I$(top_srcdir)/wrapper/gstreamer \ + $(NULL) -XCAMGST_CXXFLAGS = $(XCAM_CXXFLAGS) -XCAMGST_LIBS = \ +XCAM_GST_LIBS = \ + $(GST_LIBS) \ + $(GST_VIDEO_LIBS) \ + $(GST_ALLOCATOR_LIBS) \ + $(top_builddir)/xcore/libxcam_core.la \ $(NULL) -if HAVE_LIBDRM -XCAMGST_CXXFLAGS += $(LIBDRM_CFLAGS) -XCAMGST_LIBS += $(LIBDRM_LIBS) +if HAVE_LIBCL +XCAM_GST_LIBS += $(top_builddir)/modules/ocl/libxcam_ocl.la endif -if USE_LOCAL_ATOMISP -XCAMGST_CXXFLAGS += -I$(top_srcdir)/ext/atomisp +if HAVE_LIBDRM +XCAM_GST_CXXFLAGS += $(LIBDRM_CFLAGS) +XCAM_GST_LIBS += $(LIBDRM_LIBS) endif -XCAMGST_CXXFLAGS += \ - -I$(XCORE_DIR) \ - -I$(MODULES_DIR) \ - $(NULL) - # Note: plugindir is set in configure plugindir="$(libdir)/gstreamer-1.0" # sources used to compile this plug-in libgstxcamsrc_la_SOURCES = \ - gstxcambuffermeta.cpp \ - gstxcambufferpool.cpp \ - main_dev_manager.cpp \ - gstxcamsrc.cpp \ + gstxcambuffermeta.cpp \ + gstxcambufferpool.cpp \ + main_dev_manager.cpp \ + gstxcamsrc.cpp \ $(NULL) # compiler and linker flags used to compile this plugin, set in configure.ac +XCAM_SRC_CXXFLAGS = \ + $(XCAM_GST_CXXFLAGS) \ + $(NULL) + +XCAM_SRC_LIBS = \ + $(XCAM_GST_LIBS) \ + $(NULL) + +if USE_LOCAL_ATOMISP +XCAM_SRC_CXXFLAGS += -I$(top_srcdir)/ext/atomisp +endif + +if ENABLE_IA_AIQ +XCAM_SRC_CXXFLAGS += -I$(top_srcdir)/wrapper/gstreamer/interface +XCAM_SRC_LIBS += \ + $(top_builddir)/modules/isp/libxcam_isp.la \ + $(top_builddir)/wrapper/gstreamer/interface/libgstxcaminterface.la \ + $(NULL) +endif + libgstxcamsrc_la_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAMGST_CXXFLAGS) \ - -I$(top_srcdir)/wrapper/gstreamer \ - $(XCAM_INTERFACE_DIR) \ + $(XCAM_SRC_CXXFLAGS) \ $(NULL) -libgstxcamsrc_la_LIBADD = $(XCAMGST_LIBS) \ - $(XCAM_INTERFACE_LA) \ - $(XCORE_LA) $(GST_ALLOCATOR_LIBS) \ - $(GST_VIDEO_LIBS) $(GST_LIBS) \ +libgstxcamsrc_la_LIBADD = \ + $(XCAM_SRC_LIBS) \ $(NULL) libgstxcamsrc_la_LDFLAGS = \ - -module -avoid-version \ - $(PTHREAD_LDFLAGS) $(XCORE_LA) \ + -module -avoid-version \ $(NULL) libgstxcamsrc_la_LIBTOOLFLAGS = --tag=disable-static -if ENABLE_IA_AIQ -ISP_LA = $(top_builddir)/modules/isp/libxcam_isp.la -libgstxcamsrc_la_LIBADD += $(ISP_LA) -libgstxcamsrc_la_LDFLAGS += $(ISP_LA) -endif - if HAVE_LIBCL -OCL_LA = $(top_builddir)/modules/ocl/libxcam_ocl.la - -libgstxcamsrc_la_LIBADD += $(OCL_LA) -libgstxcamsrc_la_LDFLAGS += $(OCL_LA) - libgstxcamfilter_la_SOURCES = \ - gstxcambuffermeta.cpp \ - main_pipe_manager.cpp \ - gstxcamfilter.cpp \ + gstxcambuffermeta.cpp \ + main_pipe_manager.cpp \ + gstxcamfilter.cpp \ $(NULL) libgstxcamfilter_la_CXXFLAGS = \ - $(GST_CFLAGS) $(XCAMGST_CXXFLAGS) \ - -I$(top_srcdir)/wrapper/gstreamer \ + $(XCAM_GST_CXXFLAGS) \ $(NULL) libgstxcamfilter_la_LIBADD = \ - $(XCAMGST_LIBS) \ - $(XCORE_LA) $(OCL_LA) \ - $(GST_ALLOCATOR_LIBS) \ - $(GST_VIDEO_LIBS) \ - $(GST_LIBS) \ + $(XCAM_GST_LIBS) \ $(NULL) libgstxcamfilter_la_LDFLAGS = \ - -module -avoid-version \ - $(XCORE_LA) $(OCL_LA) \ + -module -avoid-version \ $(NULL) libgstxcamfilter_la_LIBTOOLFLAGS = --tag=disable-static endif -# headers we need but don't want installed +# headers we need but do not want installed noinst_HEADERS = \ - gst_xcam_utils.h \ + gst_xcam_utils.h \ + gstxcambufferpool.h \ + gstxcambuffermeta.h \ + main_dev_manager.h \ + gstxcamsrc.h \ $(NULL) -if ENABLE_IA_AIQ -noinst_HEADERS += \ - gstxcambufferpool.h \ - gstxcambuffermeta.h \ - main_dev_manager.h \ - gstxcamsrc.h \ - $(NULL) -endif - if HAVE_LIBCL noinst_HEADERS += \ - gstxcambuffermeta.h \ - main_pipe_manager.h \ - gstxcamfilter.h \ + gstxcambuffermeta.h \ + main_pipe_manager.h \ + gstxcamfilter.h \ $(NULL) endif diff --git a/wrapper/gstreamer/gstxcamfilter.cpp b/wrapper/gstreamer/gstxcamfilter.cpp index 21b38d8..a8cd595 100644 --- a/wrapper/gstreamer/gstxcamfilter.cpp +++ b/wrapper/gstreamer/gstxcamfilter.cpp @@ -42,7 +42,6 @@ using namespace GstXCam; #define DEFAULT_PROP_STITCH_SCALE_MODE CLBlenderScaleLocal #define DEFAULT_PROP_STITCH_FISHEYE_MAP FALSE #define DEFAULT_PROP_STITCH_LSC FALSE -#define DEFAULT_PROP_STITCH_FM_OCL FALSE #define DEFAULT_PROP_STITCH_RES_MODE StitchRes1080P XCAM_BEGIN_DECLARE @@ -61,7 +60,6 @@ enum { PROP_STITCH_SCALE_MODE, PROP_STITCH_FISHEYE_MAP, PROP_STITCH_LSC, - PROP_STITCH_FM_OCL, PROP_STITCH_RES_MODE }; @@ -307,13 +305,6 @@ gst_xcam_filter_class_init (GstXCamFilterClass *class_self) g_param_spec_boolean ("stitch-lsc", "stitch enable lens shading correction", "Enable Lens Shading Correction", DEFAULT_PROP_STITCH_LSC, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); -#if HAVE_OPENCV - g_object_class_install_property ( - gobject_class, PROP_STITCH_FM_OCL, - g_param_spec_boolean ("stitch-fm-ocl", "stitch enable ocl for feature match", "Enable ocl for feature match", - DEFAULT_PROP_STITCH_FM_OCL, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); -#endif - g_object_class_install_property ( gobject_class, PROP_STITCH_RES_MODE, g_param_spec_enum ("stitch-res-mode", "stitch resolution mode", "Stitch Resolution Mode", @@ -355,7 +346,6 @@ gst_xcam_filter_init (GstXCamFilter *xcamfilter) xcamfilter->stitch_enable_seam = DEFAULT_PROP_STITCH_ENABLE_SEAM; xcamfilter->stitch_fisheye_map = DEFAULT_PROP_STITCH_FISHEYE_MAP; xcamfilter->stitch_lsc = DEFAULT_PROP_STITCH_LSC; - xcamfilter->stitch_fm_ocl = DEFAULT_PROP_STITCH_FM_OCL; xcamfilter->stitch_scale_mode = DEFAULT_PROP_STITCH_SCALE_MODE; xcamfilter->stitch_res_mode = DEFAULT_PROP_STITCH_RES_MODE; @@ -363,8 +353,9 @@ gst_xcam_filter_init (GstXCamFilter *xcamfilter) xcamfilter->cached_buf_num = 0; XCAM_CONSTRUCTOR (xcamfilter->pipe_manager, SmartPtr<MainPipeManager>); - xcamfilter->pipe_manager = new MainPipeManager; - XCAM_ASSERT (xcamfilter->pipe_manager.ptr ()); + SmartPtr<MainPipeManager> pipe_manager = new MainPipeManager; + XCAM_ASSERT (pipe_manager.ptr ()); + xcamfilter->pipe_manager = pipe_manager; } static void @@ -423,11 +414,6 @@ gst_xcam_filter_set_property (GObject *object, guint prop_id, const GValue *valu case PROP_STITCH_LSC: xcamfilter->stitch_lsc = g_value_get_boolean (value); break; -#if HAVE_OPENCV - case PROP_STITCH_FM_OCL: - xcamfilter->stitch_fm_ocl = g_value_get_boolean (value); - break; -#endif case PROP_STITCH_RES_MODE: xcamfilter->stitch_res_mode = (StitchResMode) g_value_get_enum (value); break; @@ -479,11 +465,6 @@ gst_xcam_filter_get_property (GObject *object, guint prop_id, GValue *value, GPa case PROP_STITCH_LSC: g_value_set_boolean (value, xcamfilter->stitch_lsc); break; -#if HAVE_OPENCV - case PROP_STITCH_FM_OCL: - g_value_set_boolean (value, xcamfilter->stitch_fm_ocl); - break; -#endif case PROP_STITCH_RES_MODE: g_value_set_enum (value, xcamfilter->stitch_res_mode); break; @@ -508,7 +489,6 @@ gst_xcam_filter_start (GstBaseTransform *trans) SmartPtr<MainPipeManager> pipe_manager = xcamfilter->pipe_manager; SmartPtr<SmartAnalyzer> smart_analyzer; - SmartPtr<CLPostImageProcessor> image_processor; SmartHandlerList smart_handlers = SmartAnalyzerLoader::load_smart_handlers (DEFAULT_SMART_ANALYSIS_LIB_DIR); if (!smart_handlers.empty ()) { @@ -530,7 +510,7 @@ gst_xcam_filter_start (GstBaseTransform *trans) } } - image_processor = new CLPostImageProcessor (); + SmartPtr<CLPostImageProcessor> image_processor = new CLPostImageProcessor (); XCAM_ASSERT (image_processor.ptr ()); image_processor->set_stats_callback (pipe_manager); image_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode) xcamfilter->defog_mode); @@ -571,8 +551,10 @@ gst_xcam_filter_start (GstBaseTransform *trans) pipe_manager->add_image_processor (image_processor); pipe_manager->set_image_processor (image_processor); - xcamfilter->buf_pool = new CLVideoBufferPool (); - XCAM_ASSERT (xcamfilter->buf_pool.ptr ()); + SmartPtr<BufferPool> pool = new CLVideoBufferPool (); + XCAM_ASSERT (pool.ptr ()); + xcamfilter->buf_pool = pool; + if (xcamfilter->copy_mode == COPY_MODE_DMA) { XCAM_LOG_WARNING ("CLVideoBuffer doesn't support DMA copy mode, switch to CPU copy mode"); xcamfilter->copy_mode = COPY_MODE_CPU; @@ -735,8 +717,8 @@ gst_xcam_filter_set_caps (GstBaseTransform *trans, GstCaps *incaps, GstCaps *out if (xcamfilter->enable_stitch) { processor->set_image_stitch ( xcamfilter->enable_stitch, xcamfilter->stitch_enable_seam, xcamfilter->stitch_scale_mode, - xcamfilter->stitch_fisheye_map, xcamfilter->stitch_lsc, xcamfilter->stitch_fm_ocl, - GST_VIDEO_INFO_WIDTH (&out_info), GST_VIDEO_INFO_HEIGHT (&out_info), (uint32_t) xcamfilter->stitch_res_mode); + xcamfilter->stitch_fisheye_map, xcamfilter->stitch_lsc, GST_VIDEO_INFO_WIDTH (&out_info), + GST_VIDEO_INFO_HEIGHT (&out_info), (uint32_t) xcamfilter->stitch_res_mode); XCAM_LOG_INFO ("xcamfilter stitch output size width:%d height:%d", GST_VIDEO_INFO_WIDTH (&out_info), GST_VIDEO_INFO_HEIGHT (&out_info)); } @@ -1001,5 +983,5 @@ GST_PLUGIN_DEFINE ( VERSION, GST_LICENSE_UNKNOWN, "libxcamfilter", - "https://github.com/01org/libxcam" + "https://github.com/intel/libxcam" ) diff --git a/wrapper/gstreamer/gstxcamfilter.h b/wrapper/gstreamer/gstxcamfilter.h index fddfed2..bd26aa9 100644 --- a/wrapper/gstreamer/gstxcamfilter.h +++ b/wrapper/gstreamer/gstxcamfilter.h @@ -84,7 +84,6 @@ struct _GstXCamFilter gboolean enable_stitch; gboolean stitch_enable_seam; gboolean stitch_fisheye_map; - gboolean stitch_fm_ocl; gboolean stitch_lsc; XCam::CLBlenderScaleMode stitch_scale_mode; StitchResMode stitch_res_mode; diff --git a/wrapper/gstreamer/gstxcamsrc.cpp b/wrapper/gstreamer/gstxcamsrc.cpp index cb3a6f4..0292c26 100644 --- a/wrapper/gstreamer/gstxcamsrc.cpp +++ b/wrapper/gstreamer/gstxcamsrc.cpp @@ -41,7 +41,7 @@ #include "gstxcaminterface.h" #include "dynamic_analyzer_loader.h" #include "isp/hybrid_analyzer_loader.h" -#include "x3a_analyze_tuner.h" +#include "isp/iq/x3a_analyze_tuner.h" #include "isp/isp_poll_thread.h" #endif #if HAVE_LIBCL @@ -83,6 +83,8 @@ using namespace GstXCam; #define DEFAULT_PROP_IMAGE_PROCESSOR ISP_IMAGE_PROCESSOR #elif HAVE_LIBCL #define DEFAULT_PROP_IMAGE_PROCESSOR CL_IMAGE_PROCESSOR +#else +#define DEFAULT_PROP_IMAGE_PROCESSOR NONE_IMAGE_PROCESSOR #endif #if HAVE_LIBCL #define DEFAULT_PROP_WDR_MODE NONE_WDR @@ -633,8 +635,11 @@ gst_xcam_src_init (GstXCamSrc *xcamsrc) xcamsrc->xcam_video_info.init (DEFAULT_PROP_PIXELFORMAT, DEFAULT_VIDEO_WIDTH, DEFAULT_VIDEO_HEIGHT); xcamsrc->image_processor_type = DEFAULT_PROP_IMAGE_PROCESSOR; xcamsrc->analyzer_type = DEFAULT_PROP_ANALYZER; + XCAM_CONSTRUCTOR (xcamsrc->device_manager, SmartPtr<MainDeviceManager>); - xcamsrc->device_manager = new MainDeviceManager; + SmartPtr<MainDeviceManager> device_manager = new MainDeviceManager; + XCAM_ASSERT (device_manager.ptr ()); + xcamsrc->device_manager = device_manager; } static void @@ -913,11 +918,6 @@ gst_xcam_src_start (GstBaseSrc *src) SmartPtr<ImageProcessor> isp_processor; SmartPtr<IspController> isp_controller; #endif -#if HAVE_LIBCL - SmartPtr<SmartAnalyzer> smart_analyzer; - SmartPtr<CL3aImageProcessor> cl_processor; - SmartPtr<CLPostImageProcessor> cl_post_processor; -#endif SmartPtr<V4l2Device> capture_device; SmartPtr<V4l2SubDevice> event_device; SmartPtr<PollThread> poll_thread; @@ -980,13 +980,15 @@ gst_xcam_src_start (GstBaseSrc *src) XCAM_ASSERT (isp_processor.ptr ()); device_manager->add_image_processor (isp_processor); #endif - cl_processor = new CL3aImageProcessor (); + + SmartPtr<CL3aImageProcessor> cl_processor = new CL3aImageProcessor (); + XCAM_ASSERT (cl_processor.ptr ()); cl_processor->set_stats_callback (device_manager); if(xcamsrc->wdr_mode_type != NONE_WDR) { cl_processor->set_gamma (false); xcamsrc->in_format = V4L2_PIX_FMT_SGRBG12; - cl_processor->set_3a_stats_bits(12); + cl_processor->set_3a_stats_bits (12); setenv ("AIQ_CPF_PATH", "/etc/atomisp/imx185_wdr.cpf", 1); if(xcamsrc->wdr_mode_type == GAUSSIAN_WDR) @@ -1018,7 +1020,8 @@ gst_xcam_src_start (GstBaseSrc *src) } #if HAVE_LIBCL - cl_post_processor = new CLPostImageProcessor (); + SmartPtr<CLPostImageProcessor> cl_post_processor = new CLPostImageProcessor (); + XCAM_ASSERT (cl_post_processor.ptr ()); cl_post_processor->set_stats_callback (device_manager); cl_post_processor->set_defog_mode ((CLPostImageProcessor::CLDefogMode) xcamsrc->defog_mode); @@ -1110,6 +1113,7 @@ gst_xcam_src_start (GstBaseSrc *src) device_manager->set_3a_analyzer (analyzer); #if HAVE_LIBCL + SmartPtr<SmartAnalyzer> smart_analyzer; SmartHandlerList smart_handlers = SmartAnalyzerLoader::load_smart_handlers (DEFAULT_SMART_ANALYSIS_LIB_DIR); if (!smart_handlers.empty ()) { smart_analyzer = new SmartAnalyzer (); @@ -1219,7 +1223,7 @@ translate_format_to_xcam (GstVideoFormat format) case GST_VIDEO_FORMAT_Y42B: return V4L2_PIX_FMT_YUV422P; - //RGB + //RGB case GST_VIDEO_FORMAT_RGBx: return V4L2_PIX_FMT_RGB32; case GST_VIDEO_FORMAT_BGRx: @@ -1733,5 +1737,5 @@ GST_PLUGIN_DEFINE ( VERSION, GST_LICENSE_UNKNOWN, "libxcamsrc", - "https://github.com/01org/libxcam" + "https://github.com/intel/libxcam" ) diff --git a/wrapper/gstreamer/gstxcamsrc.h b/wrapper/gstreamer/gstxcamsrc.h index 8e87e88..4af1926 100644 --- a/wrapper/gstreamer/gstxcamsrc.h +++ b/wrapper/gstreamer/gstxcamsrc.h @@ -42,6 +42,7 @@ XCAM_BEGIN_DECLARE typedef enum { ISP_IMAGE_PROCESSOR = 0, CL_IMAGE_PROCESSOR, + NONE_IMAGE_PROCESSOR, } ImageProcessorType; typedef enum { diff --git a/wrapper/gstreamer/interface/Makefile.am b/wrapper/gstreamer/interface/Makefile.am index 5170426..3b056e0 100644 --- a/wrapper/gstreamer/interface/Makefile.am +++ b/wrapper/gstreamer/interface/Makefile.am @@ -2,20 +2,22 @@ lib_LTLIBRARIES = libgstxcaminterface.la libgstxcaminterface_la_SOURCES = gstxcaminterface.c -libgstxcaminterface_la_CFLAGS = \ - $(GST_CFLAGS) \ - -I$(top_srcdir)/xcore \ - -I$(top_srcdir)/xcore/base \ - $(XCAM_CFLAGS) \ - $(NULL) +libgstxcaminterface_la_CFLAGS = \ + $(XCAM_CFLAGS) \ + $(GST_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/xcore/base \ + $(NULL) libgstxcaminterface_la_LIBADD = \ - $(GST_LIBS) \ - $(NULL) + $(GST_LIBS) \ + $(top_builddir)/xcore/libxcam_core.la \ + $(NULL) libgstxcaminterfaceincludedir = \ - $(includedir)/gstreamer-1.0/gst + $(includedir)/gstreamer-1.0/gst \ + $(NULL) libgstxcaminterfaceinclude_HEADERS = \ - gstxcaminterface.h - + gstxcaminterface.h \ + $(NULL) diff --git a/xcore/Makefile.am b/xcore/Makefile.am index bcadd7c..f901e75 100644 --- a/xcore/Makefile.am +++ b/xcore/Makefile.am @@ -1,146 +1,150 @@ lib_LTLIBRARIES = libxcam_core.la -XCAM_CORE_CXXFLAGS = $(XCAM_CXXFLAGS) +XCAM_CORE_CXXFLAGS = \ + $(XCAM_CXXFLAGS) \ + -pthread \ + $(NULL) + XCAM_CORE_LIBS = \ - -ldl \ - -lpthread \ + -ldl \ $(NULL) xcam_sources = \ - analyzer_loader.cpp \ - smart_analyzer_loader.cpp \ - buffer_pool.cpp \ - calibration_parser.cpp \ - device_manager.cpp \ - pipe_manager.cpp \ - dma_video_buffer.cpp \ - dynamic_analyzer.cpp \ - dynamic_analyzer_loader.cpp \ - smart_analyzer.cpp \ - smart_analysis_handler.cpp \ - smart_buffer_priv.cpp \ - fake_poll_thread.cpp \ - file_handle.cpp \ - handler_interface.cpp \ - image_handler.cpp \ - image_processor.cpp \ - image_projector.cpp \ - image_file_handle.cpp \ - poll_thread.cpp \ - surview_fisheye_dewarp.cpp \ - swapped_buffer.cpp \ - thread_pool.cpp \ - uvc_device.cpp \ - v4l2_buffer_proxy.cpp \ - v4l2_device.cpp \ - video_buffer.cpp \ - worker.cpp \ - xcam_analyzer.cpp \ - x3a_analyzer.cpp \ - x3a_analyzer_manager.cpp \ - x3a_analyzer_simple.cpp \ - x3a_image_process_center.cpp \ - x3a_stats_pool.cpp \ - x3a_result.cpp \ - x3a_result_factory.cpp \ - xcam_common.cpp \ - xcam_buffer.cpp \ - xcam_thread.cpp \ - xcam_utils.cpp \ - interface/feature_match.cpp \ - interface/blender.cpp \ - interface/geo_mapper.cpp \ - interface/stitcher.cpp \ + analyzer_loader.cpp \ + smart_analyzer_loader.cpp \ + buffer_pool.cpp \ + calibration_parser.cpp \ + device_manager.cpp \ + pipe_manager.cpp \ + dma_video_buffer.cpp \ + dynamic_analyzer.cpp \ + dynamic_analyzer_loader.cpp \ + smart_analyzer.cpp \ + smart_analysis_handler.cpp \ + smart_buffer_priv.cpp \ + fake_poll_thread.cpp \ + file_handle.cpp \ + handler_interface.cpp \ + image_handler.cpp \ + image_processor.cpp \ + image_projector.cpp \ + image_file_handle.cpp \ + poll_thread.cpp \ + surview_fisheye_dewarp.cpp \ + swapped_buffer.cpp \ + thread_pool.cpp \ + uvc_device.cpp \ + v4l2_buffer_proxy.cpp \ + v4l2_device.cpp \ + video_buffer.cpp \ + once_map_video_buffer_priv.cpp \ + worker.cpp \ + xcam_analyzer.cpp \ + x3a_analyzer.cpp \ + x3a_analyzer_manager.cpp \ + x3a_analyzer_simple.cpp \ + x3a_image_process_center.cpp \ + x3a_stats_pool.cpp \ + x3a_result.cpp \ + x3a_result_factory.cpp \ + xcam_common.cpp \ + xcam_buffer.cpp \ + xcam_thread.cpp \ + xcam_utils.cpp \ + interface/feature_match.cpp \ + interface/blender.cpp \ + interface/geo_mapper.cpp \ + interface/stitcher.cpp \ $(NULL) if HAVE_LIBDRM XCAM_CORE_CXXFLAGS += $(LIBDRM_CFLAGS) XCAM_CORE_LIBS += \ - -ldrm_intel \ - $(LIBDRM_LIBS) \ + -ldrm_intel \ + $(LIBDRM_LIBS) \ $(NULL) xcam_sources += \ - drm_bo_buffer.cpp \ - drm_display.cpp \ - drm_v4l2_buffer.cpp \ + drm_bo_buffer.cpp \ + drm_display.cpp \ + drm_v4l2_buffer.cpp \ $(NULL) endif libxcam_core_la_CXXFLAGS = \ - $(XCAM_CORE_CXXFLAGS) \ + $(XCAM_CORE_CXXFLAGS) \ $(NULL) libxcam_core_la_SOURCES = \ - $(xcam_sources) \ + $(xcam_sources) \ $(NULL) -libxcam_core_la_LDFLAGS = \ - -no-undefined \ - $(XCAM_LT_LDFLAGS) \ - $(PTHREAD_LDFLAGS) \ +libxcam_core_la_LIBADD = \ + $(XCAM_CORE_LIBS) \ $(NULL) -libxcam_core_la_LIBADD = \ - $(XCAM_CORE_LIBS) \ +libxcam_core_la_LDFLAGS = \ + -no-undefined \ + -pthread \ + $(XCAM_LT_LDFLAGS) \ $(NULL) libxcam_coreincludedir = $(includedir)/xcam nobase_libxcam_coreinclude_HEADERS = \ - base/xcam_3a_result.h \ - base/xcam_3a_types.h \ - base/xcam_3a_description.h \ - base/xcam_buffer.h \ - base/xcam_params.h \ - base/xcam_common.h \ - base/xcam_defs.h \ - base/xcam_smart_description.h \ - base/xcam_smart_result.h \ - calibration_parser.h \ - device_manager.h \ - dma_video_buffer.h \ - file_handle.h \ - pipe_manager.h \ - handler_interface.h \ - image_handler.h \ - image_processor.h \ - image_projector.h \ - image_file_handle.h \ - safe_list.h \ - smartptr.h \ - surview_fisheye_dewarp.h \ - swapped_buffer.h \ - thread_pool.h \ - v4l2_buffer_proxy.h \ - v4l2_device.h \ - video_buffer.h \ - worker.h \ - xcam_analyzer.h \ - x3a_analyzer.h \ - x3a_analyzer_manager.h \ - x3a_event.h \ - x3a_image_process_center.h \ - x3a_result.h \ - xcam_mutex.h \ - xcam_thread.h \ - xcam_std.h \ - xcam_utils.h \ - xcam_obj_debug.h \ - buffer_pool.h \ - meta_data.h \ - vec_mat.h \ - interface/data_types.h \ - interface/feature_match.h \ - interface/blender.h \ - interface/geo_mapper.h \ - interface/stitcher.h \ + base/xcam_3a_result.h \ + base/xcam_3a_types.h \ + base/xcam_3a_description.h \ + base/xcam_buffer.h \ + base/xcam_params.h \ + base/xcam_common.h \ + base/xcam_defs.h \ + base/xcam_smart_description.h \ + base/xcam_smart_result.h \ + calibration_parser.h \ + device_manager.h \ + dma_video_buffer.h \ + file_handle.h \ + pipe_manager.h \ + handler_interface.h \ + image_handler.h \ + image_processor.h \ + image_projector.h \ + image_file_handle.h \ + safe_list.h \ + smartptr.h \ + surview_fisheye_dewarp.h \ + swapped_buffer.h \ + thread_pool.h \ + v4l2_buffer_proxy.h \ + v4l2_device.h \ + video_buffer.h \ + worker.h \ + xcam_analyzer.h \ + x3a_analyzer.h \ + x3a_analyzer_manager.h \ + x3a_event.h \ + x3a_image_process_center.h \ + x3a_result.h \ + xcam_mutex.h \ + xcam_thread.h \ + xcam_std.h \ + xcam_utils.h \ + xcam_obj_debug.h \ + buffer_pool.h \ + meta_data.h \ + vec_mat.h \ + interface/data_types.h \ + interface/feature_match.h \ + interface/blender.h \ + interface/geo_mapper.h \ + interface/stitcher.h \ $(NULL) if HAVE_LIBDRM nobase_libxcam_coreinclude_HEADERS += \ - drm_bo_buffer.h \ - drm_display.h \ - drm_v4l2_buffer.h \ + drm_bo_buffer.h \ + drm_display.h \ + drm_v4l2_buffer.h \ $(NULL) endif diff --git a/xcore/base/xcam_common.h b/xcore/base/xcam_common.h index 46cc6fd..1f16e1e 100644 --- a/xcore/base/xcam_common.h +++ b/xcore/base/xcam_common.h @@ -49,6 +49,8 @@ typedef enum { XCAM_RETURN_ERROR_IOCTL = -8, XCAM_RETURN_ERROR_CL = -9, XCAM_RETURN_ERROR_ORDER = -10, + XCAM_RETURN_ERROR_GLES = -11, + XCAM_RETURN_ERROR_VULKAN = -12, XCAM_RETURN_ERROR_TIMEOUT = -20, diff --git a/xcore/base/xcam_defs.h b/xcore/base/xcam_defs.h index 276644f..77b74a5 100644 --- a/xcore/base/xcam_defs.h +++ b/xcore/base/xcam_defs.h @@ -72,9 +72,17 @@ #define XCAM_FAIL_RETURN(LEVEL, exp, ret, msg, ...) \ if (!(exp)) { \ XCAM_LOG_##LEVEL (msg, ## __VA_ARGS__); \ - return (ret); \ + return ret; \ } +#define XCAM_RETURN_CHECK(LEVEL, exp, msg, ...) \ + do { \ + XCamReturn err_ret = (exp); \ + XCAM_FAIL_RETURN(LEVEL, xcam_ret_is_ok(err_ret), \ + err_ret, msg, ## __VA_ARGS__); \ + } while (0) + + #define XCAM_DEAD_COPY(ClassObj) \ ClassObj (const ClassObj&); \ ClassObj & operator= (const ClassObj&) \ @@ -119,7 +127,10 @@ #define PRIuS "u" #endif -#define PI 3.1415926f -#define degree2radian(degree) ((degree) * PI / 180.0f) +#ifndef XCAM_PI +#define XCAM_PI 3.1415926f +#endif + +#define degree2radian(degree) ((degree) * XCAM_PI / 180.0f) #endif //XCAM_DEFS_H diff --git a/xcore/buffer_pool.h b/xcore/buffer_pool.h index 899cbf0..09bb1da 100644 --- a/xcore/buffer_pool.h +++ b/xcore/buffer_pool.h @@ -67,6 +67,9 @@ protected: SmartPtr<BufferData> &get_buffer_data () { return _data; } + const SmartPtr<BufferData> &get_buffer_data () const { + return _data; + } private: XCAM_DEAD_COPY (BufferProxy); @@ -126,6 +129,9 @@ private: bool _started; }; +class VKDevice; +SmartPtr<BufferPool> create_vk_buffer_pool (const SmartPtr<VKDevice> &dev); + }; #endif //XCAM_BUFFER_POOL_H diff --git a/xcore/drm_bo_buffer.h b/xcore/drm_bo_buffer.h index fa661d3..2a76a43 100644 --- a/xcore/drm_bo_buffer.h +++ b/xcore/drm_bo_buffer.h @@ -94,7 +94,7 @@ class DrmBoBufferPool public: explicit DrmBoBufferPool (SmartPtr<DrmDisplay> &display); - ~DrmBoBufferPool (); + virtual ~DrmBoBufferPool (); // **** MUST be set before set_video_info **** void set_swap_flags (uint32_t flags, uint32_t init_order) { diff --git a/xcore/drm_display.cpp b/xcore/drm_display.cpp index a5c89db..7e41efa 100644 --- a/xcore/drm_display.cpp +++ b/xcore/drm_display.cpp @@ -54,7 +54,11 @@ DrmDisplay::instance () SmartLock lock(_mutex); if (_instance.ptr()) return _instance; - _instance = new DrmDisplay (); + + SmartPtr<DrmDisplay> instance = new DrmDisplay (); + XCAM_ASSERT (instance.ptr ()); + _instance = instance; + return _instance; } diff --git a/xcore/dynamic_analyzer.cpp b/xcore/dynamic_analyzer.cpp index 4ca553a..b0932d1 100644 --- a/xcore/dynamic_analyzer.cpp +++ b/xcore/dynamic_analyzer.cpp @@ -104,7 +104,10 @@ DynamicAnalyzer::create_common_handler () if (_common_handler.ptr()) return _common_handler; - _common_handler = new DynamicCommonHandler (this); + SmartPtr<DynamicCommonHandler> handler = new DynamicCommonHandler (this); + XCAM_ASSERT (handler.ptr ()); + _common_handler = handler; + return _common_handler; } diff --git a/xcore/fake_poll_thread.cpp b/xcore/fake_poll_thread.cpp index 612a697..c15df13 100644 --- a/xcore/fake_poll_thread.cpp +++ b/xcore/fake_poll_thread.cpp @@ -146,8 +146,9 @@ FakePollThread::init_buffer_pool () format.fmt.pix.height, 0, 0, 0); #if HAVE_LIBDRM SmartPtr<DrmDisplay> drm_disp = DrmDisplay::instance (); - _buf_pool = new DrmBoBufferPool (drm_disp); - XCAM_ASSERT (_buf_pool.ptr ()); + SmartPtr<BufferPool> pool = new DrmBoBufferPool (drm_disp); + XCAM_ASSERT (pool.ptr ()); + _buf_pool = pool; if (_buf_pool->set_video_info (info) && _buf_pool->reserve (DEFAULT_FPT_BUF_COUNT)) return XCAM_RETURN_NO_ERROR; diff --git a/xcore/image_file_handle.cpp b/xcore/image_file_handle.cpp index a901b1f..6a9ce68 100644 --- a/xcore/image_file_handle.cpp +++ b/xcore/image_file_handle.cpp @@ -48,6 +48,12 @@ ImageFileHandle::read_buf (const SmartPtr<VideoBuffer> &buf) XCAM_ASSERT (is_valid ()); memory = buf->map (); + + if (NULL == memory) { + XCAM_LOG_ERROR ("ImageFileHandle::read_buf map buffer memory(%p) \n", memory); + buf->unmap (); + return ret; + } for (uint32_t index = 0; index < info.components; index++) { info.get_planar_info (planar, index); uint32_t line_bytes = planar.width * planar.pixel_bytes; diff --git a/xcore/image_handler.cpp b/xcore/image_handler.cpp index 6e47a62..2dabc97 100644 --- a/xcore/image_handler.cpp +++ b/xcore/image_handler.cpp @@ -23,7 +23,10 @@ namespace XCam { ImageHandler::ImageHandler (const char* name) - : _name (NULL) + : _need_configure (true) + , _enable_allocator (true) + , _buf_capacity (XCAM_DEFAULT_HANDLER_BUF_CAP) + , _name (NULL) { if (name) _name = strndup (name, XCAM_MAX_STR_SIZE); @@ -35,21 +38,127 @@ ImageHandler::~ImageHandler() } bool +ImageHandler::set_out_video_info (const VideoBufferInfo &info) +{ + XCAM_ASSERT (info.width && info.height && info.format); + _out_video_info = info; + return true; +} + +bool +ImageHandler::enable_allocator (bool enable, uint32_t buf_count) +{ + + if (enable && !buf_count) { + XCAM_LOG_ERROR ( + "ImageHandler(%s) enable allocator must with buf_count>0", XCAM_STR(get_name ())); + return false; + } + + _enable_allocator = enable; + if (enable) + _buf_capacity = buf_count; + + return true; +} + +bool ImageHandler::set_allocator (const SmartPtr<BufferPool> &allocator) { XCAM_FAIL_RETURN ( ERROR, allocator.ptr (), false, - "softhandler(%s) set allocator(is NULL)", XCAM_STR(get_name ())); + "ImageHandler(%s) set allocator(is NULL)", XCAM_STR(get_name ())); _allocator = allocator; return true; } XCamReturn -ImageHandler::finish () +ImageHandler::configure_rest () { + if (_enable_allocator) { + XCAM_FAIL_RETURN ( + ERROR, _out_video_info.is_valid (), XCAM_RETURN_ERROR_PARAM, + "image_hander(%s) configure reset failed before reserver buffer since out_video_info was not set", + XCAM_STR (get_name ())); + + SmartPtr<BufferPool> allocator = create_allocator (); + XCAM_FAIL_RETURN ( + ERROR, allocator.ptr (), XCAM_RETURN_ERROR_PARAM, + "image_hander(%s) configure reset failed since allocator not created", XCAM_STR (get_name ())); + _allocator = allocator; + XCamReturn ret = reserve_buffers (_out_video_info, _buf_capacity); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "soft_hander(%s) configure resource failed in reserving buffers", XCAM_STR (get_name ())); + } return XCAM_RETURN_NO_ERROR; } +XCamReturn +ImageHandler::execute_buffer (const SmartPtr<ImageHandler::Parameters> ¶m, bool sync) +{ + XCAM_UNUSED (sync); + + XCamReturn ret = XCAM_RETURN_NO_ERROR; + + XCAM_FAIL_RETURN ( + ERROR, param.ptr (), XCAM_RETURN_ERROR_PARAM, + "image_handler(%s) execute buffer failed, params is null", + XCAM_STR (get_name ())); + + if (_need_configure) { + ret = configure_resource (param); + XCAM_FAIL_RETURN ( + WARNING, xcam_ret_is_ok (ret), ret, + "image_handler(%s) configure resource failed", XCAM_STR (get_name ())); + + ret = configure_rest (); + XCAM_FAIL_RETURN ( + WARNING, xcam_ret_is_ok (ret), ret, + "image_handler(%s) configure rest failed", XCAM_STR (get_name ())); + _need_configure = false; + } + + if (!param->out_buf.ptr () && _enable_allocator) { + param->out_buf = get_free_buf (); + XCAM_FAIL_RETURN ( + ERROR, param->out_buf.ptr (), XCAM_RETURN_ERROR_PARAM, + "image_handler:%s execute buffer failed, output buffer failed in allocation.", + XCAM_STR (get_name ())); + } + + ret = start_work (param); + XCAM_FAIL_RETURN ( + ERROR, xcam_ret_is_ok (ret), ret, + "image_handler(%s) execute buffer failed in starting workers", XCAM_STR (get_name ())); + + return ret; +} + +void +ImageHandler::execute_done (const SmartPtr<ImageHandler::Parameters> ¶m, XCamReturn err) +{ + XCAM_ASSERT (param.ptr ()); + + if (err < XCAM_RETURN_NO_ERROR) { + XCAM_LOG_WARNING ( + "image_handler(%s) broken with errno %d", XCAM_STR (get_name ()), (int)err); + return ; + } + + if (err > XCAM_RETURN_NO_ERROR) { + XCAM_LOG_WARNING ( + "image_handler(%s) continued with errno %d", XCAM_STR (get_name ()), (int)err); + } + + execute_status_check (param, err); +} + +XCamReturn +ImageHandler::finish () +{ + return XCAM_RETURN_NO_ERROR; +} XCamReturn ImageHandler::terminate () @@ -72,13 +181,13 @@ ImageHandler::reserve_buffers (const VideoBufferInfo &info, uint32_t count) { XCAM_FAIL_RETURN ( ERROR, _allocator.ptr (), XCAM_RETURN_ERROR_PARAM, - "softhandler(%s) reserve buffers failed, alloctor was not set", XCAM_STR(get_name ())); + "ImageHandler(%s) reserve buffers failed, alloctor was not set", XCAM_STR(get_name ())); _allocator->set_video_info (info); XCAM_FAIL_RETURN ( ERROR, _allocator->reserve (count), XCAM_RETURN_ERROR_MEM, - "softhandler(%s) reserve buffers(%d) failed", XCAM_STR(get_name ()), count); + "ImageHandler(%s) reserve buffers(%d) failed", XCAM_STR(get_name ()), count); return XCAM_RETURN_NO_ERROR; } @@ -88,7 +197,7 @@ ImageHandler::get_free_buf () { XCAM_FAIL_RETURN ( ERROR, _allocator.ptr (), NULL, - "softhandler(%s) get free buffer failed since allocator was not initilized", XCAM_STR(get_name ())); + "ImageHandler(%s) get free buffer failed since allocator was not initilized", XCAM_STR(get_name ())); return _allocator->get_buffer (_allocator); } diff --git a/xcore/image_handler.h b/xcore/image_handler.h index 2c3fba8..80c64f5 100644 --- a/xcore/image_handler.h +++ b/xcore/image_handler.h @@ -37,6 +37,8 @@ _h->mem_func (handler, params, error); } \ } +#define XCAM_DEFAULT_HANDLER_BUF_CAP 4 + namespace XCam { class ImageHandler; @@ -85,14 +87,22 @@ public: const char *get_name () const { return _name; } + bool set_out_video_info (const VideoBufferInfo &info); + bool enable_allocator (bool enable, uint32_t buf_count = XCAM_DEFAULT_HANDLER_BUF_CAP); // virtual functions // execute_buffer params should NOT be const - virtual XCamReturn execute_buffer (const SmartPtr<Parameters> ¶ms, bool sync) = 0; + virtual XCamReturn execute_buffer (const SmartPtr<Parameters> ¶ms, bool sync); + virtual void execute_done (const SmartPtr<ImageHandler::Parameters> ¶m, XCamReturn err); virtual XCamReturn finish (); virtual XCamReturn terminate (); protected: + virtual XCamReturn configure_resource (const SmartPtr<Parameters> ¶m) = 0; + virtual SmartPtr<BufferPool> create_allocator () = 0; + virtual XCamReturn configure_rest (); + virtual XCamReturn start_work (const SmartPtr<Parameters> ¶m) = 0; + virtual void execute_status_check (const SmartPtr<Parameters> ¶ms, const XCamReturn error); bool set_allocator (const SmartPtr<BufferPool> &allocator); @@ -102,12 +112,22 @@ protected: XCamReturn reserve_buffers (const VideoBufferInfo &info, uint32_t count); SmartPtr<VideoBuffer> get_free_buf (); + const VideoBufferInfo &get_out_video_info () { + return _out_video_info; + } + private: XCAM_DEAD_COPY (ImageHandler); +protected: + bool _need_configure; + bool _enable_allocator; + private: SmartPtr<Callback> _callback; + VideoBufferInfo _out_video_info; SmartPtr<BufferPool> _allocator; + uint32_t _buf_capacity; char *_name; }; diff --git a/xcore/image_processor.cpp b/xcore/image_processor.cpp index 928cbcc..f2cdc2d 100644 --- a/xcore/image_processor.cpp +++ b/xcore/image_processor.cpp @@ -144,8 +144,13 @@ ImageProcessor::ImageProcessor (const char* name) if (name) _name = strndup (name, XCAM_MAX_STR_SIZE); - _processor_thread = new ImageProcessorThread (this); - _results_thread = new X3aResultsProcessThread (this); + SmartPtr<ImageProcessorThread> processor_thread = new ImageProcessorThread (this); + XCAM_ASSERT (processor_thread.ptr ()); + _processor_thread = processor_thread; + + SmartPtr<X3aResultsProcessThread> results_thread = new X3aResultsProcessThread (this); + XCAM_ASSERT (results_thread.ptr ()); + _results_thread = results_thread; } ImageProcessor::~ImageProcessor () diff --git a/xcore/interface/blender.h b/xcore/interface/blender.h index 93b5fbe..2d56614 100644 --- a/xcore/interface/blender.h +++ b/xcore/interface/blender.h @@ -30,6 +30,7 @@ namespace XCam { class Blender; +class VKDevice; class Blender { @@ -38,6 +39,8 @@ public: virtual ~Blender (); static SmartPtr<Blender> create_ocl_blender (); static SmartPtr<Blender> create_soft_blender (); + static SmartPtr<Blender> create_gl_blender (); + static SmartPtr<Blender> create_vk_blender (const SmartPtr<VKDevice> &dev); void set_output_size (uint32_t width, uint32_t height); void get_output_size (uint32_t &width, uint32_t &height) const { diff --git a/xcore/interface/data_types.h b/xcore/interface/data_types.h index a4d6f4e..589ec29 100644 --- a/xcore/interface/data_types.h +++ b/xcore/interface/data_types.h @@ -31,6 +31,19 @@ enum SurroundMode { BowlView = 1 }; +enum FeatureMatchMode { + FMNone = 0, + FMDefault, + FMCluster, + FMCapi +}; + +enum GeoMapScaleMode { + ScaleSingleConst = 0, + ScaleDualConst, + ScaleDualCurve +}; + struct Rect { int32_t pos_x, pos_y; int32_t width, height; diff --git a/xcore/interface/feature_match.cpp b/xcore/interface/feature_match.cpp index 4a6a428..1ed625f 100644 --- a/xcore/interface/feature_match.cpp +++ b/xcore/interface/feature_match.cpp @@ -27,7 +27,9 @@ namespace XCam { FeatureMatch::FeatureMatch () : _x_offset (0.0f) + , _y_offset (0.0f) , _mean_offset (0.0f) + , _mean_offset_y (0.0f) , _valid_count (0) , _fm_idx (-1) , _frame_num (0) @@ -35,34 +37,73 @@ FeatureMatch::FeatureMatch () } void -FeatureMatch::set_config (CVFMConfig config) +FeatureMatch::set_fm_index (int idx) +{ + _fm_idx = idx; +} + +void +FeatureMatch::set_config (const FMConfig &config) { _config = config; } -CVFMConfig -FeatureMatch::get_config () +void +FeatureMatch::set_crop_rect (const Rect &left_rect, const Rect &right_rect) { - return _config; + _left_rect = left_rect; + _right_rect = right_rect; } void -FeatureMatch::set_fm_index (int idx) +FeatureMatch::get_crop_rect (Rect &left_rect, Rect &right_rect) { - _fm_idx = idx; + left_rect = _left_rect; + right_rect = _right_rect; } void FeatureMatch::reset_offsets () { _x_offset = 0.0f; + _y_offset = 0.0f; _mean_offset = 0.0f; + _mean_offset_y = 0.0f; +} + +float +FeatureMatch::get_current_left_offset_x () +{ + return _x_offset; +} + +float +FeatureMatch::get_current_left_offset_y () +{ + return _y_offset; +} + +void +FeatureMatch::set_dst_width (int width) +{ + XCAM_UNUSED (width); + + XCAM_LOG_ERROR ("dst width is not supported"); + XCAM_ASSERT (false); +} + +void +FeatureMatch::enable_adjust_crop_area () +{ + XCAM_LOG_ERROR ("adjust crop area is not supported"); + XCAM_ASSERT (false); } bool -FeatureMatch::get_mean_offset (std::vector<float> &offsets, float sum, int &count, float &mean_offset) +FeatureMatch::get_mean_offset ( + const std::vector<float> &offsets, float sum, int &count, float &mean_offset) { - if (count < _config.min_corners) + if (count < _config.min_corners || count <= 0) return false; mean_offset = sum / count; @@ -87,7 +128,7 @@ FeatureMatch::get_mean_offset (std::vector<float> &offsets, float sum, int &coun ++recur_count; } - if (recur_count < _config.min_corners) { + if (recur_count < _config.min_corners || recur_count <= 0) { ret = false; break; } @@ -115,29 +156,4 @@ FeatureMatch::get_mean_offset (std::vector<float> &offsets, float sum, int &coun return ret; } -void -FeatureMatch::adjust_stitch_area (int dst_width, float &x_offset, Rect &stitch0, Rect &stitch1) -{ - if (fabs (x_offset) < 5.0f) - return; - - int last_overlap_width = stitch1.pos_x + stitch1.width + (dst_width - (stitch0.pos_x + stitch0.width)); - // int final_overlap_width = stitch1.pos_x + stitch1.width + (dst_width - (stitch0.pos_x - x_offset + stitch0.width)); - if ((stitch0.pos_x - x_offset + stitch0.width) > dst_width) - x_offset = dst_width - (stitch0.pos_x + stitch0.width); - int final_overlap_width = last_overlap_width + x_offset; - final_overlap_width = XCAM_ALIGN_AROUND (final_overlap_width, 8); - XCAM_ASSERT (final_overlap_width >= _config.sitch_min_width); - int center = final_overlap_width / 2; - XCAM_ASSERT (center >= _config.sitch_min_width / 2); - - stitch1.pos_x = XCAM_ALIGN_AROUND (center - _config.sitch_min_width / 2, 8); - stitch1.width = _config.sitch_min_width; - stitch0.pos_x = dst_width - final_overlap_width + stitch1.pos_x; - stitch0.width = _config.sitch_min_width; - - float delta_offset = final_overlap_width - last_overlap_width; - x_offset -= delta_offset; -} - } diff --git a/xcore/interface/feature_match.h b/xcore/interface/feature_match.h index 06c0b7b..a8dd72b 100644 --- a/xcore/interface/feature_match.h +++ b/xcore/interface/feature_match.h @@ -28,7 +28,7 @@ namespace XCam { -struct CVFMConfig { +struct FMConfig { int sitch_min_width; int min_corners; // number of minimum efficient corners float offset_factor; // last_offset * offset_factor + cur_offset * (1.0f - offset_factor) @@ -38,7 +38,7 @@ struct CVFMConfig { float max_valid_offset_y; // valid maximum offset in vertical direction float max_track_error; // maximum track error - CVFMConfig () + FMConfig () : sitch_min_width (56) , min_corners (8) , offset_factor (0.8f) @@ -56,41 +56,46 @@ public: explicit FeatureMatch (); virtual ~FeatureMatch () {}; - void set_config (CVFMConfig config); - CVFMConfig get_config (); + static SmartPtr<FeatureMatch> create_default_feature_match (); + static SmartPtr<FeatureMatch> create_cluster_feature_match (); + static SmartPtr<FeatureMatch> create_capi_feature_match (); - void set_fm_index (int idx); + virtual void feature_match ( + const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf) = 0; - void reset_offsets (); + void set_fm_index (int idx); + void set_config (const FMConfig &config); - virtual void optical_flow_feature_match ( - const SmartPtr<VideoBuffer> &left_buf, const SmartPtr<VideoBuffer> &right_buf, - Rect &left_crop_rect, Rect &right_crop_rect, int dst_width) = 0; + void set_crop_rect (const Rect &left_rect, const Rect &right_rect); + void get_crop_rect (Rect &left_rect, Rect &right_rect); - float get_current_left_offset_x () const { - return _x_offset; - } + void reset_offsets (); + float get_current_left_offset_x (); + float get_current_left_offset_y (); - virtual void set_ocl (bool use_ocl) = 0; - virtual bool is_ocl_path () = 0; + virtual void set_dst_width (int width); + virtual void enable_adjust_crop_area (); protected: - bool get_mean_offset (std::vector<float> &offsets, float sum, int &count, float &mean_offset); - - void adjust_stitch_area (int dst_width, float &x_offset, Rect &stitch0, Rect &stitch1); + bool get_mean_offset (const std::vector<float> &offsets, float sum, int &count, float &mean_offset); private: XCAM_DEAD_COPY (FeatureMatch); protected: float _x_offset; + float _y_offset; float _mean_offset; + float _mean_offset_y; int _valid_count; - CVFMConfig _config; + FMConfig _config; + + Rect _left_rect; + Rect _right_rect; // debug parameters int _fm_idx; - uint _frame_num; + uint32_t _frame_num; }; } diff --git a/xcore/interface/geo_mapper.h b/xcore/interface/geo_mapper.h index 0ddd495..8a779af 100644 --- a/xcore/interface/geo_mapper.h +++ b/xcore/interface/geo_mapper.h @@ -27,6 +27,8 @@ namespace XCam { +class VKDevice; + class GeoMapper { public: @@ -34,6 +36,8 @@ public: virtual ~GeoMapper (); static SmartPtr<GeoMapper> create_ocl_geo_mapper (); static SmartPtr<GeoMapper> create_soft_geo_mapper (); + static SmartPtr<GeoMapper> create_gl_geo_mapper (); + static SmartPtr<GeoMapper> create_vk_geo_mapper (const SmartPtr<VKDevice> &dev, const char* name); //2D table virtual bool set_lookup_table (const PointFloat2 *data, uint32_t width, uint32_t height) = 0; @@ -53,7 +57,7 @@ public: SmartPtr<VideoBuffer> &out_buf) = 0; protected: - bool auto_calculate_factors (uint32_t lut_w, uint32_t lut_h); + virtual bool auto_calculate_factors (uint32_t lut_w, uint32_t lut_h); private: uint32_t _out_width, _out_height; diff --git a/xcore/interface/stitcher.cpp b/xcore/interface/stitcher.cpp index 70da11f..3b0ed6d 100644 --- a/xcore/interface/stitcher.cpp +++ b/xcore/interface/stitcher.cpp @@ -77,8 +77,7 @@ split_area_by_out ( } Stitcher::Stitcher (uint32_t align_x, uint32_t align_y) - : _is_crop_set (false) - , _alignment_x (align_x) + : _alignment_x (align_x) , _alignment_y (align_y) , _output_width (0) , _output_height (0) @@ -86,7 +85,10 @@ Stitcher::Stitcher (uint32_t align_x, uint32_t align_y) , _camera_num (0) , _is_round_view_set (false) , _is_overlap_set (false) + , _is_crop_set (false) , _is_center_marked (false) + , _scale_mode (ScaleSingleConst) + , _fm_mode (FMNone) { XCAM_ASSERT (align_x >= 1); XCAM_ASSERT (align_y >= 1); @@ -629,7 +631,7 @@ BowlModel::get_stitch_image_vertex_model ( vertices.push_back (PointFloat3(world_pos0.x / _config.a, world_pos0.y / _config.b, world_pos0.z / _config.c)); indeices.push_back (indicator++); - texture_points.push_back (PointFloat2(texture_pos0.x / _bowl_img_width, (_bowl_img_height - texture_pos0.y) / _bowl_img_height)); + texture_points.push_back (PointFloat2(texture_pos0.x / _bowl_img_width, texture_pos0.y / _bowl_img_height)); PointFloat3 world_pos1 = bowl_view_image_to_world ( @@ -637,7 +639,7 @@ BowlModel::get_stitch_image_vertex_model ( vertices.push_back (PointFloat3(world_pos1.x / _config.a, world_pos1.y / _config.b, world_pos1.z / _config.c)); indeices.push_back (indicator++); - texture_points.push_back (PointFloat2(texture_pos1.x / _bowl_img_width, (_bowl_img_height - texture_pos1.y) / _bowl_img_height)); + texture_points.push_back (PointFloat2(texture_pos1.x / _bowl_img_width, texture_pos1.y / _bowl_img_height)); } } return true; diff --git a/xcore/interface/stitcher.h b/xcore/interface/stitcher.h index e38a98e..8987507 100644 --- a/xcore/interface/stitcher.h +++ b/xcore/interface/stitcher.h @@ -70,6 +70,8 @@ struct CameraInfo { float angle_range;; }; +class VKDevice; + class Stitcher { public: @@ -126,6 +128,8 @@ public: virtual ~Stitcher (); static SmartPtr<Stitcher> create_ocl_stitcher (); static SmartPtr<Stitcher> create_soft_stitcher (); + static SmartPtr<Stitcher> create_gl_stitcher (); + static SmartPtr<Stitcher> create_vk_stitcher (const SmartPtr<VKDevice> dev); bool set_bowl_config (const BowlDataConfig &config); const BowlDataConfig &get_bowl_config () { @@ -153,11 +157,25 @@ public: _output_width = width; //XCAM_ALIGN_UP (width, XCAM_BLENDER_ALIGNED_WIDTH); _output_height = height; } - void get_output_size (uint32_t &width, uint32_t &height) const { width = _output_width; height = _output_height; } + + void set_scale_mode (GeoMapScaleMode scale_mode) { + _scale_mode = scale_mode; + } + GeoMapScaleMode get_scale_mode () { + return _scale_mode; + } + + void set_fm_mode (FeatureMatchMode fm_mode) { + _fm_mode = fm_mode; + } + FeatureMatchMode get_fm_mode () { + return _fm_mode; + } + virtual XCamReturn stitch_buffers (const VideoBufferList &in_bufs, SmartPtr<VideoBuffer> &out_buf) = 0; protected: @@ -186,12 +204,6 @@ protected: private: XCAM_DEAD_COPY (Stitcher); -protected: - ImageCropInfo _crop_info[XCAM_STITCH_MAX_CAMERAS]; - bool _is_crop_set; - //update after each feature match - ScaleFactor _scale_factors[XCAM_STITCH_MAX_CAMERAS]; - private: uint32_t _alignment_x, _alignment_y; uint32_t _output_width, _output_height; @@ -205,10 +217,19 @@ private: BowlDataConfig _bowl_config; bool _is_overlap_set; + ImageCropInfo _crop_info[XCAM_STITCH_MAX_CAMERAS]; + bool _is_crop_set; + //auto calculation CenterMark _center_marks[XCAM_STITCH_MAX_CAMERAS]; bool _is_center_marked; CopyAreaArray _copy_areas; + + GeoMapScaleMode _scale_mode; + //update after each feature match + ScaleFactor _scale_factors[XCAM_STITCH_MAX_CAMERAS]; + + FeatureMatchMode _fm_mode; }; class BowlModel { diff --git a/xcore/once_map_video_buffer_priv.cpp b/xcore/once_map_video_buffer_priv.cpp new file mode 100644 index 0000000..1d4793c --- /dev/null +++ b/xcore/once_map_video_buffer_priv.cpp @@ -0,0 +1,97 @@ +/* + * once_map_video_buffer_priv.cpp + * + * Copyright (c) 2017 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: Zong Wei <wei.zong@intel.com> + */ + +#include <xcam_std.h> +#include <video_buffer.h> + +namespace XCam { + +class OnceMapVideoBuffer + : public VideoBuffer +{ +public: + OnceMapVideoBuffer (const VideoBufferInfo &info, uint8_t* buffer); + + virtual ~OnceMapVideoBuffer (); + + virtual uint8_t *map (); + virtual bool unmap (); + virtual int get_fd (); + +private: + + XCAM_DEAD_COPY (OnceMapVideoBuffer); + +private: + uint8_t* _buffer; +}; + +OnceMapVideoBuffer::OnceMapVideoBuffer (const VideoBufferInfo &info, uint8_t* buffer) + : VideoBuffer (info) + , _buffer (buffer) +{ + XCAM_ASSERT (buffer != NULL); +} + +OnceMapVideoBuffer::~OnceMapVideoBuffer () +{ +} + +uint8_t * +OnceMapVideoBuffer::map () +{ + return _buffer; +} + +bool +OnceMapVideoBuffer::unmap () +{ + return true; +} + +int +OnceMapVideoBuffer::get_fd () +{ + XCAM_ASSERT (false && "OnceMapVideoBuffer::get_fd not supported"); + return -1; +} + +SmartPtr<VideoBuffer> +external_buf_to_once_map_buf ( + uint8_t* buf, uint32_t format, + uint32_t width, uint32_t height, + uint32_t aligned_width, uint32_t aligned_height, + uint32_t size) +{ + VideoBufferInfo buf_info; + SmartPtr<OnceMapVideoBuffer> video_buffer; + + XCAM_FAIL_RETURN ( + ERROR, buf, NULL, + "external_buf_to_map_buf failed since buf is NULL"); + + buf_info.init (format, width, height, + aligned_width, aligned_height, size); + video_buffer = new OnceMapVideoBuffer (buf_info, buf); + XCAM_ASSERT (video_buffer.ptr ()); + return video_buffer; +} + +} diff --git a/xcore/poll_thread.cpp b/xcore/poll_thread.cpp index dcb778b..013a543 100644 --- a/xcore/poll_thread.cpp +++ b/xcore/poll_thread.cpp @@ -83,8 +83,13 @@ PollThread::PollThread () : _poll_callback (NULL) , _stats_callback (NULL) { - _event_loop = new EventPollThread(this); - _capture_loop = new CapturePollThread (this); + SmartPtr<EventPollThread> event_loop = new EventPollThread(this); + XCAM_ASSERT (event_loop.ptr ()); + _event_loop = event_loop; + + SmartPtr<CapturePollThread> capture_loop = new CapturePollThread (this); + XCAM_ASSERT (capture_loop.ptr ()); + _capture_loop = capture_loop; XCAM_LOG_DEBUG ("PollThread constructed"); } diff --git a/xcore/surview_fisheye_dewarp.cpp b/xcore/surview_fisheye_dewarp.cpp index 6c0830c..7e45eac 100644 --- a/xcore/surview_fisheye_dewarp.cpp +++ b/xcore/surview_fisheye_dewarp.cpp @@ -60,18 +60,19 @@ SurViewFisheyeDewarp::get_extrinsic_param() } void -SurViewFisheyeDewarp::fisheye_dewarp(MapTable &map_table, uint32_t table_w, uint32_t table_h, uint32_t image_w, uint32_t image_h, const BowlDataConfig &bowl_config) +SurViewFisheyeDewarp::fisheye_dewarp(MapTable &map_table, uint32_t table_w, uint32_t table_h, + uint32_t image_w, uint32_t image_h, const BowlDataConfig &bowl_config) { PointFloat3 world_coord; PointFloat3 cam_coord; PointFloat3 cam_world_coord; PointFloat2 image_coord; - XCAM_LOG_DEBUG ("fisheye-dewarp:\n table(%dx%d), out_size(%dx%d)" - "bowl(start:%.1f, end:%.1f, ground:%.2f, wall:%.2f, a:%.2f, b:%.2f, c:%.2f, center_z:%.2f )", + XCAM_LOG_DEBUG ("fisheye-dewarp:\n table(%dx%d) out_size(%dx%d) " + "bowl(start:%.1f, end:%.1f, ground:%.2f, wall:%.2f, a:%.2f, b:%.2f, c:%.2f, center_z:%.2f)", table_w, table_h, image_w, image_h, bowl_config.angle_start, bowl_config.angle_end, - bowl_config.wall_height, bowl_config.ground_length, + bowl_config.ground_length, bowl_config.wall_height, bowl_config.a, bowl_config.b, bowl_config.c, bowl_config.center_z); float scale_factor_w = (float)image_w / table_w; diff --git a/xcore/surview_fisheye_dewarp.h b/xcore/surview_fisheye_dewarp.h index 571b02a..3754942 100644 --- a/xcore/surview_fisheye_dewarp.h +++ b/xcore/surview_fisheye_dewarp.h @@ -36,7 +36,8 @@ public: explicit SurViewFisheyeDewarp (); virtual ~SurViewFisheyeDewarp (); - void fisheye_dewarp(MapTable &map_table, uint32_t table_w, uint32_t table_h, uint32_t image_w, uint32_t image_h, const BowlDataConfig &bowl_config); + void fisheye_dewarp(MapTable &map_table, uint32_t table_w, uint32_t table_h, + uint32_t image_w, uint32_t image_h, const BowlDataConfig &bowl_config); void set_intrinsic_param(const IntrinsicParameter &intrinsic_param); void set_extrinsic_param(const ExtrinsicParameter &extrinsic_param); diff --git a/xcore/vec_mat.h b/xcore/vec_mat.h index 51add21..eccb52e 100644 --- a/xcore/vec_mat.h +++ b/xcore/vec_mat.h @@ -27,10 +27,6 @@ namespace XCam { -#ifndef PI -#define PI 3.14159265358979323846 -#endif - #ifndef FLT_EPSILON #define FLT_EPSILON 1.19209290e-07F // float #endif @@ -40,11 +36,11 @@ namespace XCam { #endif #ifndef DEGREE_2_RADIANS -#define DEGREE_2_RADIANS(x) (((x) * PI) / 180.0) +#define DEGREE_2_RADIANS(x) (((x) * XCAM_PI) / 180.0) #endif #ifndef RADIANS_2_DEGREE -#define RADIANS_2_DEGREE(x) (((x) * 180.0) / PI) +#define RADIANS_2_DEGREE(x) (((x) * 180.0) / XCAM_PI) #endif #define XCAM_VECT2_OPERATOR_VECT2(op) \ @@ -157,11 +153,11 @@ public: inline bool operator == (const VectorN<T, N>& rhs) const; inline T& operator [] (uint32_t index) { - XCAM_ASSERT(index >= 0 && index < N); + XCAM_ASSERT(index < N); return data[index]; } inline const T& operator [] (uint32_t index) const { - XCAM_ASSERT(index >= 0 && index < N); + XCAM_ASSERT(index < N); return data[index]; } @@ -521,15 +517,11 @@ public: inline void eye (); inline T& at (uint32_t row, uint32_t col) { - XCAM_ASSERT(row >= 0 && row < N); - XCAM_ASSERT(col >= 0 && col < N); - + XCAM_ASSERT(row < N && col < N); return data[row * N + col]; }; inline const T& at (uint32_t row, uint32_t col) const { - XCAM_ASSERT(row >= 0 && row < N); - XCAM_ASSERT(col >= 0 && col < N); - + XCAM_ASSERT(row < N && col < N); return data[row * N + col]; }; diff --git a/xcore/worker.cpp b/xcore/worker.cpp index 6d8a7ab..c4b52d0 100644 --- a/xcore/worker.cpp +++ b/xcore/worker.cpp @@ -25,6 +25,8 @@ namespace XCam { Worker::Worker (const char *name, const SmartPtr<Callback> &cb) : _name (NULL) , _callback (cb) + , _global (1, 1, 1) + , _local (1, 1, 1) { if (name) _name = strndup (name, XCAM_MAX_STR_SIZE); @@ -69,6 +71,31 @@ Worker::status_check (const SmartPtr<Worker::Arguments> &args, const XCamReturn _callback->work_status (this, args, error); } +bool +Worker::set_global_size (const WorkSize &size) +{ + XCAM_FAIL_RETURN ( + ERROR, size.value[0] && size.value[1] && size.value[2], false, + "Worker(%s) set global size(x:%d, y:%d, z:%d) failed.", + XCAM_STR (get_name ()), size.value[0], size.value[1], size.value[2]); + + _global = size; + return true; +} + +bool +Worker::set_local_size (const WorkSize &size) +{ + XCAM_FAIL_RETURN ( + ERROR, size.value[0] && size.value[1] && size.value[2], false, + "Worker(%s) set local size(x:%d, y:%d, z:%d) failed.", + XCAM_STR (get_name ()), size.value[0], size.value[1], size.value[2]); + + _local = size; + return true; +} + + #if ENABLE_FUNC_OBJ bool Worker::set_func_obj (const SmartPtr<FuncObj> &obj) diff --git a/xcore/worker.h b/xcore/worker.h index 16807c1..9a4eec0 100644 --- a/xcore/worker.h +++ b/xcore/worker.h @@ -23,6 +23,8 @@ #include <xcam_std.h> +#define WORK_MAX_DIM 3 + #define ENABLE_FUNC_OBJ 0 #define DECLARE_WORK_CALLBACK(CbClass, Handler, mem_func) \ @@ -38,6 +40,15 @@ namespace XCam { +struct WorkSize { + uint32_t value[WORK_MAX_DIM]; + WorkSize (uint32_t x = 1, uint32_t y = 1, uint32_t z = 1) { + value[0] = x; + value[1] = y; + value[2] = z; + } +}; + class Worker : public RefObj { @@ -82,6 +93,15 @@ public: const char *get_name () const { return _name; } + bool set_global_size (const WorkSize &size); + const WorkSize &get_global_size () const { + return _global; + } + bool set_local_size (const WorkSize &size); + const WorkSize &get_local_size () const { + return _local; + } + #if ENABLE_FUNC_OBJ bool set_func_obj (const SmartPtr<FuncObj> &obj); #endif @@ -99,6 +119,9 @@ private: private: char *_name; SmartPtr<Callback> _callback; + WorkSize _global; + WorkSize _local; + #if ENABLE_FUNC_OBJ SmartPtr<FuncObj> _func_obj; #endif diff --git a/xcore/xcam_analyzer.cpp b/xcore/xcam_analyzer.cpp index 8191a79..13ee457 100644 --- a/xcore/xcam_analyzer.cpp +++ b/xcore/xcam_analyzer.cpp @@ -118,7 +118,9 @@ XAnalyzer::XAnalyzer (const char *name) if (name) _name = strndup (name, XCAM_MAX_STR_SIZE); - _analyzer_thread = new AnalyzerThread (this); + SmartPtr<AnalyzerThread> thread= new AnalyzerThread (this); + XCAM_ASSERT (thread.ptr ()); + _analyzer_thread = thread; } XAnalyzer::~XAnalyzer() diff --git a/xcore/xcam_utils.cpp b/xcore/xcam_utils.cpp index 4393961..246be93 100644 --- a/xcore/xcam_utils.cpp +++ b/xcore/xcam_utils.cpp @@ -32,11 +32,11 @@ transform_bowl_coord_to_image_x ( const float bowl_x, const float bowl_y, const uint32_t img_width) { - float offset_radian = (bowl_x < 0.0f) ? PI : ((bowl_y >= 0.0f) ? 2.0f * PI : 0.0f); - float arctan_radian = (bowl_x != 0.0f) ? atan (-bowl_y / bowl_x) : ((bowl_y >= 0.0f) ? -PI / 2.0f : PI / 2.0f); + float offset_radian = (bowl_x < 0.0f) ? XCAM_PI : ((bowl_y >= 0.0f) ? 2.0f * XCAM_PI : 0.0f); + float arctan_radian = (bowl_x != 0.0f) ? atan (-bowl_y / bowl_x) : ((bowl_y >= 0.0f) ? -XCAM_PI / 2.0f : XCAM_PI / 2.0f); float img_x = arctan_radian + offset_radian; - img_x *= img_width / (2.0f * PI); + img_x *= img_width / (2.0f * XCAM_PI); return XCAM_CLAMP (img_x, 0.0f, img_width - 1.0f); } @@ -95,10 +95,10 @@ PointFloat3 bowl_view_image_to_world ( float b = config.b; float c = config.c; - float wall_image_height = config.wall_height / (float)(config.wall_height + config.ground_length) * (float)img_height; - float ground_image_height = (float)img_height - wall_image_height; + float wall_image_height = config.wall_height / (config.wall_height + config.ground_length) * img_height; + float ground_image_height = img_height - wall_image_height; - float z_step = (float)config.wall_height / wall_image_height; + float z_step = config.wall_height / wall_image_height; float angle_step = fabs(config.angle_end - config.angle_start) / img_width; if(img_pos.y < wall_image_height) { @@ -106,13 +106,13 @@ PointFloat3 bowl_view_image_to_world ( angle = degree2radian (config.angle_start + img_pos.x * angle_step); float r2 = 1 - (world.z - config.center_z) * (world.z - config.center_z) / (c * c); - if(XCAM_DOUBLE_EQUAL_AROUND (angle, PI / 2)) { + if(XCAM_DOUBLE_EQUAL_AROUND (angle, XCAM_PI / 2)) { world.x = 0.0f; world.y = -sqrt(r2 * b * b); - } else if (XCAM_DOUBLE_EQUAL_AROUND (angle, PI * 3 / 2)) { + } else if (XCAM_DOUBLE_EQUAL_AROUND (angle, XCAM_PI * 3 / 2)) { world.x = 0.0f; world.y = sqrt(r2 * b * b); - } else if((angle < PI / 2) || (angle > PI * 3 / 2)) { + } else if((angle < XCAM_PI / 2) || (angle > XCAM_PI * 3 / 2)) { world.x = sqrt(r2 * a * a * b * b / (b * b + a * a * tan(angle) * tan(angle))); world.y = -world.x * tan(angle); } else { @@ -124,7 +124,6 @@ PointFloat3 bowl_view_image_to_world ( b = b * sqrt(1 - config.center_z * config.center_z / (c * c)); float ratio_ab = b / a; - float step_b = config.ground_length / ground_image_height; b = b - (img_pos.y - wall_image_height) * step_b; @@ -132,13 +131,13 @@ PointFloat3 bowl_view_image_to_world ( angle = degree2radian (config.angle_start + img_pos.x * angle_step); - if(XCAM_DOUBLE_EQUAL_AROUND (angle, PI / 2)) { + if(XCAM_DOUBLE_EQUAL_AROUND (angle, XCAM_PI / 2)) { world.x = 0.0f; world.y = -b; - } else if (XCAM_DOUBLE_EQUAL_AROUND (angle, PI * 3 / 2)) { + } else if (XCAM_DOUBLE_EQUAL_AROUND (angle, XCAM_PI * 3 / 2)) { world.x = 0.0f; world.y = b; - } else if((angle < PI / 2) || (angle > PI * 3 / 2)) { + } else if((angle < XCAM_PI / 2) || (angle > XCAM_PI * 3 / 2)) { world.x = a * b / sqrt(b * b + a * a * tan(angle) * tan(angle)); world.y = -world.x * tan(angle); } else { @@ -193,13 +192,13 @@ linear_interpolate_p2 ( if (dist_start == 0) { weight_start = 10000000.0; } else { - weight_start = ((double)dist_sum / dist_start); + weight_start = (dist_sum / dist_start); } if (dist_end == 0) { weight_end = 10000000.0; } else { - weight_end = ((double)dist_sum / dist_end); + weight_end = (dist_sum / dist_end); } value = (value_start * weight_start + value_end * weight_end) / (weight_start + weight_end); @@ -227,36 +226,35 @@ linear_interpolate_p4( double dist_sum = 0; double value = 0; - dist_lt = (double)abs(ref_curr_x - ref_lt_x) + (double)abs(ref_curr_y - ref_lt_y); - dist_rt = (double)abs(ref_curr_x - ref_rt_x) + (double)abs(ref_curr_y - ref_rt_y); - dist_lb = (double)abs(ref_curr_x - ref_lb_x) + (double)abs(ref_curr_y - ref_lb_y); - dist_rb = (double)abs(ref_curr_x - ref_rb_x) + (double)abs(ref_curr_y - ref_rb_y); + dist_lt = abs(ref_curr_x - ref_lt_x) + abs(ref_curr_y - ref_lt_y); + dist_rt = abs(ref_curr_x - ref_rt_x) + abs(ref_curr_y - ref_rt_y); + dist_lb = abs(ref_curr_x - ref_lb_x) + abs(ref_curr_y - ref_lb_y); + dist_rb = abs(ref_curr_x - ref_rb_x) + abs(ref_curr_y - ref_rb_y); dist_sum = dist_lt + dist_rt + dist_lb + dist_rb; if (dist_lt == 0) { weight_lt = 10000000.0; } else { - weight_lt = ((float)dist_sum / dist_lt); + weight_lt = (dist_sum / dist_lt); } if (dist_rt == 0) { weight_rt = 10000000.0; } else { - weight_rt = ((float)dist_sum / dist_rt); + weight_rt = (dist_sum / dist_rt); } if (dist_lb == 0) { weight_lb = 10000000.0; } else { - weight_lb = ((float)dist_sum / dist_lb); + weight_lb = (dist_sum / dist_lb); } if (dist_rb == 0) { weight_rb = 10000000.0; } else { - weight_rb = ((float)dist_sum / dist_rt); + weight_rb = (dist_sum / dist_rt); } - value = (double)floor ( (value_lt * weight_lt + value_rt * weight_rt + - value_lb * weight_lb + value_rb * weight_rb) / - (weight_lt + weight_rt + weight_lb + weight_rb) + 0.5 ); + value = floor ((value_lt * weight_lt + value_rt * weight_rt + value_lb * weight_lb + value_rb * weight_rb) / + (weight_lt + weight_rt + weight_lb + weight_rb) + 0.5); return value; } @@ -272,7 +270,7 @@ get_gauss_table (uint32_t radius, float sigma, std::vector<float> &table, bool n table[radius] = 1.0f; for (i = 0; i < radius; i++) { - dis = ((float)i - radius) * ((float)i - radius); + dis = (i - radius) * (i - radius); table[i] = table[scale - i - 1] = exp(-dis / (2.0f * sigma * sigma)); sum += table[i] * 2.0f; } diff --git a/xcore/xcam_utils.h b/xcore/xcam_utils.h index 492744a..f72efa0 100644 --- a/xcore/xcam_utils.h +++ b/xcore/xcam_utils.h @@ -64,6 +64,13 @@ class VideoBuffer; void dump_buf_perfix_path (const SmartPtr<VideoBuffer> buf, const char *prefix_name); bool dump_video_buf (const SmartPtr<VideoBuffer> buf, const char *file_name); +SmartPtr<VideoBuffer> +external_buf_to_once_map_buf ( + uint8_t* buf, uint32_t format, + uint32_t width, uint32_t height, + uint32_t aligned_width, uint32_t aligned_height, + uint32_t size); + }; #endif //XCAM_UTILS_H |