From a29e37c15d926f776af6cef52a6c8a1f318898ba Mon Sep 17 00:00:00 2001 From: zhanli <719901725@qq.com> Date: Thu, 14 Dec 2023 23:56:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6=E9=83=A8=E5=88=86=E5=B0=8F?= =?UTF-8?q?=E8=BD=A6=E4=B8=8A=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ros_ws/src/pibot_bringup/CMakeLists.txt | 2 +- .../PIBot_ROS/rules/56-orbbec-usb.rules | 63 + .../RK3588/PIBot_ROS/rules/98-pibot-usb.rules | 19 + .../PIBot_ROS/rules/99-realsense-libusb.rules | 76 + Code/RK3588/PIBot_ROS/third_party/build.sh | 18 + .../third_party/create_ap/.gitignore | 2 + .../PIBot_ROS/third_party/create_ap/LICENSE | 23 + .../PIBot_ROS/third_party/create_ap/Makefile | 24 + .../PIBot_ROS/third_party/create_ap/README.md | 98 + .../third_party/create_ap/bash_completion | 168 + .../third_party/create_ap/config_ap.sh | 22 + .../PIBot_ROS/third_party/create_ap/create_ap | 1910 +++ .../third_party/create_ap/create_ap.conf | 28 + .../third_party/create_ap/create_ap.openrc | 11 + .../create_ap/create_ap.service.template | 13 + .../third_party/create_ap/howto/realtek.md | 74 + .../PIBot_ROS/third_party/create_ap/lnxrouter | 2131 +++ .../PIBot_ROS/third_party/iai_kinect2/LICENSE | 201 + .../third_party/iai_kinect2/README.md | 242 + .../iai_kinect2/iai_kinect2/CMakeLists.txt | 4 + .../iai_kinect2/iai_kinect2/package.xml | 22 + .../iai_kinect2/kinect2_bridge/CMakeLists.txt | 144 + .../iai_kinect2/kinect2_bridge/README.md | 171 + .../data/196605135147/calib_color.yaml | 26 + .../data/196605135147/calib_depth.yaml | 2 + .../data/196605135147/calib_ir.yaml | 26 + .../data/196605135147/calib_pose.yaml | 33 + .../data/299150235147/calib_color.yaml | 26 + .../data/299150235147/calib_ir.yaml | 26 + .../data/299150235147/calib_pose.yaml | 33 + .../kinect2_bridge/kinect2_definitions.h | 57 + .../launch/kinect2_bridge.launch | 113 + .../kinect2_bridge/nodelet_plugins.xml | 5 + .../iai_kinect2/kinect2_bridge/package.xml | 39 + .../kinect2_bridge/src/kinect2_bridge.cpp | 1632 ++ .../kinect2_calibration/CMakeLists.txt | 122 + .../iai_kinect2/kinect2_calibration/README.md | 169 + .../kinect2_calibration_definitions.h | 36 + .../kinect2_calibration/package.xml | 37 + .../patterns/chess5x7x0.03.pdf | Bin 0 -> 1059 bytes .../patterns/chess5x7x0.03.svg | 280 + .../patterns/chess7x9x0.025.pdf | Bin 0 -> 1129 bytes .../patterns/chess7x9x0.025.svg | 368 + .../patterns/chess9x11x0.02.pdf | 68 + .../patterns/chess9x11x0.02.svg | 540 + .../convert_calib_pose_to_urdf_format.py | 50 + .../src/kinect2_calibration.cpp | 1400 ++ .../kinect2_registration/CMakeLists.txt | 178 + .../kinect2_registration/README.md | 23 + .../cmake/CheckOpenCLICDLoader.cmake | 21 + .../cmake/FindOpenCL.cmake | 155 + .../cmake/kinect2_registration.cmake.in | 2 + .../include/internal/CL/cl.hpp | 12934 +++++++++++++++ .../kinect2_registration/kinect2_console.h | 65 + .../kinect2_registration.h | 57 + .../kinect2_registration/package.xml | 21 + .../src/depth_registration.cl | 196 + .../src/depth_registration_cpu.cpp | 203 + .../src/depth_registration_cpu.h | 51 + .../src/depth_registration_opencl.cpp | 389 + .../src/depth_registration_opencl.h | 46 + .../src/kinect2_registration.cpp | 101 + .../iai_kinect2/kinect2_viewer/CMakeLists.txt | 126 + .../iai_kinect2/kinect2_viewer/README.md | 44 + .../iai_kinect2/kinect2_viewer/package.xml | 40 + .../iai_kinect2/kinect2_viewer/src/viewer.cpp | 619 + .../third_party/libfreenect2/.gitattributes | 63 + .../libfreenect2/.github/ISSUE_TEMPLATE.md | 24 + .../third_party/libfreenect2/.gitignore | 161 + .../third_party/libfreenect2/APACHE20 | 202 + .../third_party/libfreenect2/CMakeLists.txt | 500 + .../third_party/libfreenect2/CONTRIB | 34 + .../PIBot_ROS/third_party/libfreenect2/GPL2 | 341 + .../third_party/libfreenect2/README.md | 249 + .../cmake_modules/CheckOpenCLICDLoader.cmake | 21 + .../cmake_modules/FindGLFW3.cmake | 75 + .../cmake_modules/FindLibUSB.cmake | 80 + .../cmake_modules/FindOpenCL.cmake | 155 + .../cmake_modules/FindOpenNI2.cmake | 53 + .../cmake_modules/FindTegraJPEG.cmake | 133 + .../cmake_modules/FindTurboJPEG.cmake | 67 + .../cmake_modules/GenerateResources.cmake | 14 + .../SetupLibfreenect2Threading.cmake | 44 + .../libfreenect2/depends/INSTALL-windows.txt | 49 + .../libfreenect2/depends/LICENSES.txt | 287 + .../depends/download_debs_trusty.sh | 31 + .../libfreenect2/depends/install_glfw.sh | 21 + .../libfreenect2/depends/install_libusb.sh | 22 + .../depends/install_libusb_vs2013.cmd | 20 + .../depends/install_libusb_vs2015.cmd | 20 + .../libfreenect2/depends/install_ubuntu.sh | 24 + .../depends/make_release_msvc.cmd | 34 + .../libfreenect2/doc/CMakeLists.txt | 8 + .../libfreenect2/doc/Doxyextra.css | 36 + .../third_party/libfreenect2/doc/Doxyfile.in | 174 + .../third_party/libfreenect2/doc/mainpage.dox | 221 + .../libfreenect2/examples/CMakeLists.txt | 93 + .../libfreenect2/examples/Protonect.cpp | 411 + .../libfreenect2/examples/viewer.cpp | 244 + .../libfreenect2/examples/viewer.h | 288 + .../libfreenect2/freenect2.cmake.in | 10 + .../third_party/libfreenect2/freenect2.pc.in | 11 + .../libfreenect2/freenect2Version.cmake.in | 11 + .../libfreenect2/include/internal/CL/cl.hpp | 12939 ++++++++++++++++ .../include/internal/libfreenect2/allocator.h | 99 + .../libfreenect2/async_packet_processor.h | 157 + .../internal/libfreenect2/data_callback.h | 51 + .../libfreenect2/depth_packet_processor.h | 312 + .../libfreenect2/depth_packet_stream_parser.h | 82 + .../include/internal/libfreenect2/logging.h | 82 + .../internal/libfreenect2/packet_processor.h | 112 + .../internal/libfreenect2/protocol/command.h | 272 + .../protocol/command_transaction.h | 65 + .../internal/libfreenect2/protocol/response.h | 340 + .../libfreenect2/protocol/usb_control.h | 108 + .../include/internal/libfreenect2/resource.h | 41 + .../libfreenect2/rgb_packet_processor.h | 146 + .../libfreenect2/rgb_packet_stream_parser.h | 59 + .../include/internal/libfreenect2/threading.h | 118 + .../internal/libfreenect2/usb/event_loop.h | 57 + .../internal/libfreenect2/usb/transfer_pool.h | 141 + .../include/libfreenect2/color_settings.h | 118 + .../include/libfreenect2/config.h.in | 66 + .../include/libfreenect2/frame_listener.hpp | 109 + .../libfreenect2/frame_listener_impl.h | 86 + .../include/libfreenect2/led_settings.h | 48 + .../include/libfreenect2/libfreenect2.hpp | 370 + .../include/libfreenect2/logger.h | 100 + .../include/libfreenect2/packet_pipeline.h | 161 + .../include/libfreenect2/registration.h | 126 + .../libfreenect2/platform/android/README.md | 42 + .../platform/android/jni/Android.mk | 5 + .../platform/android/jni/Application.mk | 5 + .../platform/android/jni/examples.mk | 16 + .../platform/android/jni/libfreenect2.mk | 50 + .../platform/android/libfreenect2/config.h | 15 + .../platform/linux/udev/90-kinect2.rules | 5 + .../windows/tracing/Readme.tracing.txt | 13 + .../platform/windows/tracing/starttrace.bat | 12 + .../platform/windows/tracing/stoptrace.bat | 6 + .../platform/windows/tracing/timestamp.bat | 56 + .../libfreenect2/src/allocator.cpp | 137 + .../libfreenect2/src/command_transaction.cpp | 146 + .../src/cpu_depth_packet_processor.cpp | 979 ++ .../src/cuda_depth_packet_processor.cu | 966 ++ .../src/cuda_kde_depth_packet_processor.cu | 1419 ++ .../src/depth_packet_processor.cpp | 182 + .../src/depth_packet_stream_parser.cpp | 169 + .../libfreenect2/src/event_loop.cpp | 106 + .../third_party/libfreenect2/src/flextGL.cpp | 279 + .../third_party/libfreenect2/src/flextGL.h | 1463 ++ .../libfreenect2/src/frame_listener_impl.cpp | 194 + .../libfreenect2/src/libfreenect2.cpp | 1650 ++ .../third_party/libfreenect2/src/logging.cpp | 334 + .../src/opencl_depth_packet_processor.cl | 378 + .../src/opencl_depth_packet_processor.cpp | 821 + .../src/opencl_kde_depth_packet_processor.cl | 746 + .../src/opencl_kde_depth_packet_processor.cpp | 885 ++ .../src/opengl_depth_packet_processor.cpp | 986 ++ .../libfreenect2/src/openni2/ColorStream.cpp | 212 + .../libfreenect2/src/openni2/ColorStream.hpp | 67 + .../libfreenect2/src/openni2/DepthStream.cpp | 251 + .../libfreenect2/src/openni2/DepthStream.hpp | 72 + .../libfreenect2/src/openni2/DeviceDriver.cpp | 576 + .../libfreenect2/src/openni2/IrStream.cpp | 103 + .../libfreenect2/src/openni2/IrStream.hpp | 55 + .../libfreenect2/src/openni2/Registration.cpp | 90 + .../libfreenect2/src/openni2/Registration.hpp | 49 + .../libfreenect2/src/openni2/Utility.cpp | 58 + .../libfreenect2/src/openni2/Utility.hpp | 74 + .../libfreenect2/src/openni2/VideoStream.cpp | 292 + .../libfreenect2/src/openni2/VideoStream.hpp | 90 + .../libfreenect2/src/packet_pipeline.cpp | 210 + .../libfreenect2/src/registration.cpp | 405 + .../third_party/libfreenect2/src/resource.cpp | 104 + .../libfreenect2/src/rgb_packet_processor.cpp | 75 + .../src/rgb_packet_stream_parser.cpp | 178 + .../libfreenect2/src/shader/debug.fs | 12 + .../libfreenect2/src/shader/default.vs | 10 + .../libfreenect2/src/shader/filter1.fs | 122 + .../libfreenect2/src/shader/filter2.fs | 130 + .../libfreenect2/src/shader/stage1.fs | 120 + .../libfreenect2/src/shader/stage2.fs | 155 + .../src/tegra_jpeg_rgb_packet_processor.cpp | 304 + .../src/tinythread/tinythread.cpp | 294 + .../libfreenect2/src/tinythread/tinythread.h | 716 + .../libfreenect2/src/transfer_pool.cpp | 289 + .../src/turbo_jpeg_rgb_packet_processor.cpp | 117 + .../libfreenect2/src/usb_control.cpp | 325 + .../src/vaapi_rgb_packet_processor.cpp | 493 + .../src/vt_rgb_packet_processor.cpp | 179 + .../libfreenect2/tools/generate_resources.cpp | 98 + .../libfreenect2/tools/mkcontrib.py | 26 + .../tools/streamer_recorder/CMakeLists.txt | 120 + .../streamer_recorder/PracticalSocket.cpp | 383 + .../tools/streamer_recorder/ProtonectSR.cpp | 534 + .../tools/streamer_recorder/README.md | 82 + .../blender_viewer/blender_viewer.blend | Bin 0 -> 516012 bytes .../blender_viewer/scripts/main.py | 142 + .../include/PracticalSocket.h | 342 + .../tools/streamer_recorder/include/config.h | 34 + .../streamer_recorder/include/msdirent.h | 372 + .../streamer_recorder/include/recorder.h | 85 + .../streamer_recorder/include/streamer.h | 57 + .../tools/streamer_recorder/recorder.cpp | 190 + .../tools/streamer_recorder/streamer.cpp | 74 + .../third_party/libuvc/.gitattributes | 4 + .../PIBot_ROS/third_party/libuvc/.gitignore | 2 + .../PIBot_ROS/third_party/libuvc/.travis.yml | 16 + .../third_party/libuvc/CMakeLists.txt | 214 + .../PIBot_ROS/third_party/libuvc/LICENSE.txt | 31 + .../PIBot_ROS/third_party/libuvc/README.md | 29 + .../libuvc/cameras/isight_imac.txt | 228 + .../libuvc/cameras/isight_macbook.txt | 228 + .../libuvc/cameras/logitech_hd_pro_920.txt | 1817 +++ .../libuvc/cameras/ms_lifecam_show.txt | 767 + .../libuvc/cameras/quickcampro9000.txt | 1543 ++ .../cameras/quickcampro9000_builtin_ctrls.txt | 13 + .../cameras/quickcampro9000_extra_ctrls.txt | 18 + .../third_party/libuvc/changelog.txt | 114 + .../libuvc/cmake/FindJpegPkg.cmake | 82 + .../third_party/libuvc/cmake/FindLibUSB.cmake | 51 + .../libuvc/cmake/FindOpenCVPkg.cmake | 86 + .../PIBot_ROS/third_party/libuvc/doxygen.conf | 2284 +++ .../libuvc/include/libuvc/libuvc.h | 810 + .../libuvc/include/libuvc/libuvc_config.h.in | 22 + .../libuvc/include/libuvc/libuvc_internal.h | 315 + .../third_party/libuvc/include/utlist.h | 490 + .../PIBot_ROS/third_party/libuvc/libuvc.pc.in | 11 + .../third_party/libuvc/libuvcConfig.cmake | 17 + .../third_party/libuvc/src/ctrl-gen.c | 2259 +++ .../third_party/libuvc/src/ctrl-gen.py | 302 + .../PIBot_ROS/third_party/libuvc/src/ctrl.c | 165 + .../PIBot_ROS/third_party/libuvc/src/device.c | 1926 +++ .../PIBot_ROS/third_party/libuvc/src/diag.c | 376 + .../third_party/libuvc/src/example.c | 203 + .../third_party/libuvc/src/frame-mjpeg.c | 222 + .../PIBot_ROS/third_party/libuvc/src/frame.c | 475 + .../PIBot_ROS/third_party/libuvc/src/init.c | 163 + .../PIBot_ROS/third_party/libuvc/src/misc.c | 58 + .../PIBot_ROS/third_party/libuvc/src/stream.c | 1546 ++ .../PIBot_ROS/third_party/libuvc/src/test.c | 153 + .../third_party/libuvc/standard-units.yaml | 518 + Code/RK3588/README.md | 4 +- 244 files changed, 84812 insertions(+), 2 deletions(-) create mode 100644 Code/RK3588/PIBot_ROS/rules/56-orbbec-usb.rules create mode 100644 Code/RK3588/PIBot_ROS/rules/98-pibot-usb.rules create mode 100644 Code/RK3588/PIBot_ROS/rules/99-realsense-libusb.rules create mode 100644 Code/RK3588/PIBot_ROS/third_party/build.sh create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/.gitignore create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/LICENSE create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/Makefile create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/bash_completion create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/config_ap.sh create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.conf create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.openrc create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.service.template create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/howto/realtek.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/create_ap/lnxrouter create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/LICENSE create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/package.xml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_color.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_depth.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_ir.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_pose.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_color.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_ir.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_pose.yaml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/include/kinect2_bridge/kinect2_definitions.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/launch/kinect2_bridge.launch create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/nodelet_plugins.xml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/package.xml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/src/kinect2_bridge.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/include/kinect2_calibration/kinect2_calibration_definitions.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/package.xml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.pdf create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.svg create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.pdf create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.svg create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.pdf create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.svg create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/scripts/convert_calib_pose_to_urdf_format.py create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/src/kinect2_calibration.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/CheckOpenCLICDLoader.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/FindOpenCL.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/kinect2_registration.cmake.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/internal/CL/cl.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_console.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_registration.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/package.xml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration.cl create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/kinect2_registration.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/package.xml create mode 100644 Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/src/viewer.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitattributes create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/.github/ISSUE_TEMPLATE.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitignore create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/APACHE20 create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/CONTRIB create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/GPL2 create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/CheckOpenCLICDLoader.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindGLFW3.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindLibUSB.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenCL.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenNI2.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTegraJPEG.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTurboJPEG.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/GenerateResources.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/SetupLibfreenect2Threading.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/INSTALL-windows.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/LICENSES.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/download_debs_trusty.sh create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_glfw.sh create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb.sh create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2013.cmd create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2015.cmd create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_ubuntu.sh create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/make_release_msvc.cmd create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyextra.css create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyfile.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/mainpage.dox create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/Protonect.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.cmake.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.pc.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2Version.cmake.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/CL/cl.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/allocator.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/async_packet_processor.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/data_callback.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_processor.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_stream_parser.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/logging.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/packet_processor.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command_transaction.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/response.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/usb_control.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/resource.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_processor.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_stream_parser.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/threading.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/event_loop.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/transfer_pool.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/color_settings.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/config.h.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener_impl.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/led_settings.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/libfreenect2.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/logger.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/packet_pipeline.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/registration.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Android.mk create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Application.mk create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/examples.mk create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/libfreenect2.mk create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/libfreenect2/config.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/linux/udev/90-kinect2.rules create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/Readme.tracing.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/starttrace.bat create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/stoptrace.bat create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/timestamp.bat create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/allocator.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/command_transaction.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cpu_depth_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_depth_packet_processor.cu create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_kde_depth_packet_processor.cu create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_stream_parser.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/event_loop.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/frame_listener_impl.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/libfreenect2.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/logging.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cl create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cl create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opengl_depth_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DeviceDriver.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.hpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/packet_pipeline.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/registration.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/resource.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_stream_parser.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/debug.fs create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/default.vs create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter1.fs create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter2.fs create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage1.fs create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage2.fs create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tegra_jpeg_rgb_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/transfer_pool.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/turbo_jpeg_rgb_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/usb_control.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vaapi_rgb_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vt_rgb_packet_processor.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/generate_resources.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/mkcontrib.py create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/PracticalSocket.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/ProtonectSR.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/blender_viewer/blender_viewer.blend create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/blender_viewer/scripts/main.py create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/PracticalSocket.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/config.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/msdirent.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/recorder.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/streamer.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/recorder.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/streamer.cpp create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/.gitattributes create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/.gitignore create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/.travis.yml create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/CMakeLists.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/LICENSE.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/README.md create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_imac.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_macbook.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/logitech_hd_pro_920.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/ms_lifecam_show.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_builtin_ctrls.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_extra_ctrls.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/changelog.txt create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindJpegPkg.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindLibUSB.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindOpenCVPkg.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/doxygen.conf create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/include/libuvc/libuvc.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/include/libuvc/libuvc_config.h.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/include/libuvc/libuvc_internal.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/include/utlist.h create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/libuvc.pc.in create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/libuvcConfig.cmake create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/ctrl-gen.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/ctrl-gen.py create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/ctrl.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/device.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/diag.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/example.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/frame-mjpeg.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/frame.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/init.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/misc.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/stream.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/src/test.c create mode 100644 Code/RK3588/PIBot_ROS/third_party/libuvc/standard-units.yaml diff --git a/Code/RK3588/PIBot_ROS/ros_ws/src/pibot_bringup/CMakeLists.txt b/Code/RK3588/PIBot_ROS/ros_ws/src/pibot_bringup/CMakeLists.txt index da55901..03c44dd 100644 --- a/Code/RK3588/PIBot_ROS/ros_ws/src/pibot_bringup/CMakeLists.txt +++ b/Code/RK3588/PIBot_ROS/ros_ws/src/pibot_bringup/CMakeLists.txt @@ -208,7 +208,7 @@ add_executable(pibot_driver src/simple_dataframe_master.cpp # src/serial_transport.cpp src/serial_transport2.cpp - + ) add_dependencies(pibot_driver ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_link_libraries(pibot_driver diff --git a/Code/RK3588/PIBot_ROS/rules/56-orbbec-usb.rules b/Code/RK3588/PIBot_ROS/rules/56-orbbec-usb.rules new file mode 100644 index 0000000..0f6a761 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/rules/56-orbbec-usb.rules @@ -0,0 +1,63 @@ +SUBSYSTEM=="usb", ATTR{idProduct}=="0401", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra" +SUBSYSTEM=="usb", ATTR{idProduct}=="0402", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0403", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_pro" +SUBSYSTEM=="usb", ATTR{idProduct}=="0404", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini" +SUBSYSTEM=="usb", ATTR{idProduct}=="0407", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra_mini_s" +SUBSYSTEM=="usb", ATTR{idProduct}=="0501", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0502", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0504", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0505", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0508", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0509", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="050a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="050b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="050c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="050d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="050e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="050f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0510", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0511", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0512", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0513", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0514", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0515", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0516", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0517", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0518", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0519", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="051a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="051b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="051c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="051d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="051e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="051f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0520", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="0604", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0605", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="super" +SUBSYSTEM=="usb", ATTR{idProduct}=="0606", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="luna" +SUBSYSTEM=="usb", ATTR{idProduct}=="0607", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="ado" +SUBSYSTEM=="usb", ATTR{idProduct}=="0608", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra d-u" +SUBSYSTEM=="usb", ATTR{idProduct}=="0609", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="p2" +SUBSYSTEM=="usb", ATTR{idProduct}=="060a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="alien" +SUBSYSTEM=="usb", ATTR{idProduct}=="060b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="deeyea" +SUBSYSTEM=="usb", ATTR{idProduct}=="060c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astrauvc" +SUBSYSTEM=="usb", ATTR{idProduct}=="060d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astra pro plus" +SUBSYSTEM=="usb", ATTR{idProduct}=="060e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="060f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0610", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0611", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0612", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0613", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0614", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0615", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0616", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0617", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0618", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0619", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="061a", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="061b", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="061c", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="061d", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="061e", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="061f", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" +SUBSYSTEM=="usb", ATTR{idProduct}=="0620", ATTR{idVendor}=="2bc5", MODE:="0666", OWNER:="root", GROUP:="video", SYMLINK+="astradepth" \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/rules/98-pibot-usb.rules b/Code/RK3588/PIBot_ROS/rules/98-pibot-usb.rules new file mode 100644 index 0000000..840185f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/rules/98-pibot-usb.rules @@ -0,0 +1,19 @@ +# set the udev rule , make the device_port be fixed by rplidar +# pibot +KERNEL=="ttyACM*", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0042", MODE:="0777", SYMLINK+="pibot" +KERNEL=="ttyACM*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE:="0777", SYMLINK+="pibot" +KERNEL=="ttyACM*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d4", MODE:="0777", SYMLINK+="pibot" + +KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE:="0777", SYMLINK+="pibot" +KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE:="0777", SYMLINK+="pibot" +KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="PIBOT USB to UART Bridge Controller", MODE:="0777", SYMLINK+="pibot" + +# rplidar +KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="CP2102 USB to UART Bridge Controller", MODE:="0777", SYMLINK+="rplidar" +KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="CP2102N USB to UART Bridge Controller", MODE:="0777", SYMLINK+="rplidar" +KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="CP2102 USB to UART Bridge", MODE:="0777", SYMLINK+="rplidar" + +# ydlidar +KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{product}=="CP2102 USB to UART Bridge Controller", MODE:="0666", GROUP:="dialout", SYMLINK+="ydlidar" +KERNEL=="ttyACM*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE:="0666", GROUP:="dialout", SYMLINK+="ydlidar" +KERNEL=="ttyUSB*", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE:="0666", GROUP:="dialout", SYMLINK+="ydlidar" diff --git a/Code/RK3588/PIBot_ROS/rules/99-realsense-libusb.rules b/Code/RK3588/PIBot_ROS/rules/99-realsense-libusb.rules new file mode 100644 index 0000000..f2c2a9e --- /dev/null +++ b/Code/RK3588/PIBot_ROS/rules/99-realsense-libusb.rules @@ -0,0 +1,76 @@ +##Version=1.1## +# Device rules for Intel RealSense devices (R200, F200, SR300 LR200, ZR300, D400, L500, T200) +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0a80", MODE:="0666", GROUP:="plugdev", RUN+="/usr/local/bin/usb-R200-in_udev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0a66", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0aa5", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0abf", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0acb", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad0", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="04b4", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad1", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad2", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad3", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad4", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad5", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad6", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0af2", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0af6", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0afe", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0aff", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b00", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b01", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b03", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b07", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b0c", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b0d", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3a", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3d", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b48", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b49", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b4b", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b4d", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b52", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b5b", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b5c", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b64", MODE:="0666", GROUP:="plugdev" + +# Intel RealSense recovery devices (DFU) +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ab3", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0adb", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0adc", MODE:="0666", GROUP:="plugdev" +SUBSYSTEMS=="usb", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b55", MODE:="0666", GROUP:="plugdev" + +# Intel RealSense devices (Movidius, T265) +SUBSYSTEMS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="8087", ATTRS{idProduct}=="0af3", MODE="0666", GROUP="plugdev" +SUBSYSTEMS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="8087", ATTRS{idProduct}=="0b37", MODE="0666", GROUP="plugdev" +SUBSYSTEMS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="03e7", ATTRS{idProduct}=="2150", MODE="0666", GROUP="plugdev" + +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad5", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor_custom", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad5", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0af2", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0af2", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0afe", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor_custom", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0afe", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0aff", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor_custom", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0aff", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b00", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor_custom", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b00", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b01", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor_custom", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b01", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3a", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3a", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3d", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b3d", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b4b", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b4b", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b4d", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b4d", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b5b", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b5b", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b5c", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b5c", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b64", MODE:="0777", GROUP:="plugdev", RUN+="/bin/sh -c 'chmod -R 0777 /sys/%p'" +DRIVER=="hid_sensor*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0b64", RUN+="/bin/sh -c ' chmod -R 0777 /sys/%p && chmod 0777 /dev/%k'" + +# For products with motion_module, if (kernels is 4.15 and up) and (device name is "accel_3d") wait, in another process, until (enable flag is set to 1 or 200 mSec passed) and then set it to 0. +KERNEL=="iio*", ATTRS{idVendor}=="8086", ATTRS{idProduct}=="0ad5|0afe|0aff|0b00|0b01|0b3a|0b3d|0b64", RUN+="/bin/sh -c '(major=`uname -r | cut -d \".\" -f1` && minor=`uname -r | cut -d \".\" -f2` && (([ $major -eq 4 ] && [ $minor -ge 15 ]) || [ $major -ge 5 ])) && (enamefile=/sys/%p/name && [ `cat $enamefile` = \"accel_3d\" ]) && enfile=/sys/%p/buffer/enable && echo \"COUNTER=0; while [ \$COUNTER -lt 20 ] && grep -q 0 $enfile; do sleep 0.01; COUNTER=\$((COUNTER+1)); done && echo 0 > $enfile\" | at now'" \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/build.sh b/Code/RK3588/PIBot_ROS/third_party/build.sh new file mode 100644 index 0000000..6e51442 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/build.sh @@ -0,0 +1,18 @@ +sudo apt-get install build-essential cmake pkg-config libusb-1.0-0-dev libturbojpeg libjpeg-turbo8-dev libglfw3-dev libopenni2-dev + +if [ ! -d ~/pibot_ros/third_party/libfreenect2/build ]; then + mkdir ~/pibot_ros/third_party/libfreenect2/build +fi +cd ~/pibot_ros/third_party/libfreenect2/build +cmake .. -DENABLE_CXX11=ON +make +sudo make install +sudo cp ../platform/linux/udev/90-kinect2.rules /etc/udev/rules.d/ + +if [ ! -d ~/pibot_ros/third_party/libuvc/build ]; then + mkdir ~/pibot_ros/third_party/libuvc/build +fi +cd ~/pibot_ros/third_party/libuvc/build +cmake .. +make +sudo make install diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/.gitignore b/Code/RK3588/PIBot_ROS/third_party/create_ap/.gitignore new file mode 100644 index 0000000..4de2775 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/.gitignore @@ -0,0 +1,2 @@ +build +create_ap.service \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/LICENSE b/Code/RK3588/PIBot_ROS/third_party/create_ap/LICENSE new file mode 100644 index 0000000..cdea412 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2013, oblique +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/Makefile b/Code/RK3588/PIBot_ROS/third_party/create_ap/Makefile new file mode 100644 index 0000000..5317ea2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/Makefile @@ -0,0 +1,24 @@ +PREFIX=/usr +MANDIR=$(PREFIX)/share/man +BINDIR=$(PREFIX)/bin + +all: + @echo "Run 'make install' for installation." + @echo "Run 'make uninstall' for uninstallation." + +install: + install -Dm755 create_ap $(DESTDIR)$(BINDIR)/create_ap + install -Dm755 lnxrouter $(DESTDIR)$(BINDIR)/lnxrouter + install -Dm644 create_ap.conf $(DESTDIR)/etc/create_ap.conf + [ ! -d /lib/systemd/system ] || install -Dm644 create_ap.service $(DESTDIR)$(PREFIX)/lib/systemd/system/create_ap.service + [ ! -e /sbin/openrc-run ] || install -Dm755 create_ap.openrc $(DESTDIR)/etc/init.d/create_ap + install -Dm644 bash_completion $(DESTDIR)$(PREFIX)/share/bash-completion/completions/create_ap + install -Dm644 README.md $(DESTDIR)$(PREFIX)/share/doc/create_ap/README.md + +uninstall: + rm -f $(DESTDIR)$(BINDIR)/create_ap + rm -f $(DESTDIR)/etc/create_ap.conf + [ ! -f /lib/systemd/system/create_ap.service ] || rm -f $(DESTDIR)$(PREFIX)/lib/systemd/system/create_ap.service + [ ! -e /sbin/openrc-run ] || rm -f $(DESTDIR)/etc/init.d/create_ap + rm -f $(DESTDIR)$(PREFIX)/share/bash-completion/completions/create_ap + rm -f $(DESTDIR)$(PREFIX)/share/doc/create_ap/README.md diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/README.md b/Code/RK3588/PIBot_ROS/third_party/create_ap/README.md new file mode 100644 index 0000000..c5b6e0f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/README.md @@ -0,0 +1,98 @@ +## NOT MAINTAINED + +This project is no longer maintained. + +If you are still interested in this project, checkout the following fork that +also provides GUI: [lakinduakash/linux-wifi-hotspot] + + +## Features +* Create an AP (Access Point) at any channel. +* Choose one of the following encryptions: WPA, WPA2, WPA/WPA2, Open (no encryption). +* Hide your SSID. +* Disable communication between clients (client isolation). +* IEEE 802.11n & 802.11ac support +* Internet sharing methods: NATed or Bridged or None (no Internet sharing). +* Choose the AP Gateway IP (only for 'NATed' and 'None' Internet sharing methods). +* You can create an AP with the same interface you are getting your Internet connection. +* You can pass your SSID and password through pipe or through arguments (see examples). + + +## Dependencies +### General +* bash (to run this script) +* util-linux (for getopt) +* procps or procps-ng +* hostapd +* iproute2 +* iw +* iwconfig (you only need this if 'iw' can not recognize your adapter) +* haveged (optional) + +### For 'NATed' or 'None' Internet sharing method +* dnsmasq +* iptables + + +## Installation +### Generic + git clone https://github.com/oblique/create_ap + cd create_ap + make install + +### ArchLinux + pacman -S create_ap + +### Gentoo + emerge layman + layman -f -a jorgicio + emerge net-wireless/create_ap + +## Examples +### No passphrase (open network): + create_ap wlan0 eth0 MyAccessPoint + +### WPA + WPA2 passphrase: + create_ap wlan0 eth0 MyAccessPoint MyPassPhrase + +### AP without Internet sharing: + create_ap -n wlan0 MyAccessPoint MyPassPhrase + +### Bridged Internet sharing: + create_ap -m bridge wlan0 eth0 MyAccessPoint MyPassPhrase + +### Bridged Internet sharing (pre-configured bridge interface): + create_ap -m bridge wlan0 br0 MyAccessPoint MyPassPhrase + +### Internet sharing from the same WiFi interface: + create_ap wlan0 wlan0 MyAccessPoint MyPassPhrase + +### Choose a different WiFi adapter driver + create_ap --driver rtl871xdrv wlan0 eth0 MyAccessPoint MyPassPhrase + +### No passphrase (open network) using pipe: + echo -e "MyAccessPoint" | create_ap wlan0 eth0 + +### WPA + WPA2 passphrase using pipe: + echo -e "MyAccessPoint\nMyPassPhrase" | create_ap wlan0 eth0 + +### Enable IEEE 802.11n + create_ap --ieee80211n --ht_capab '[HT40+]' wlan0 eth0 MyAccessPoint MyPassPhrase + +### Client Isolation: + create_ap --isolate-clients wlan0 eth0 MyAccessPoint MyPassPhrase + +## Systemd service +Using the persistent [systemd](https://wiki.archlinux.org/index.php/systemd#Basic_systemctl_usage) service +### Start service immediately: + systemctl start create_ap + +### Start on boot: + systemctl enable create_ap + + +## License +FreeBSD + + +[lakinduakash/linux-wifi-hotspot]: https://github.com/lakinduakash/linux-wifi-hotspot diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/bash_completion b/Code/RK3588/PIBot_ROS/third_party/create_ap/bash_completion new file mode 100644 index 0000000..aae0bb2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/bash_completion @@ -0,0 +1,168 @@ +# +# Bash Completion routine for create_ap +# + +_use_filedir() { + if [[ $(type -t _filedir) == "function" ]]; then + _filedir + return 0 + fi + return 1 +} + +_create_ap() { + local awk_cmd=' + ($1 ~ /^-/) { + for (i = 1; i <= NF; i++) { + if ($i ~ /,$/) { + print substr ($i, 0, length ($i)-1) + } + else { + print $i + break + } + } + } + ' + + local cur prev opts + COMPREPLY=() + cur="$2" + prev="$3" + opts=$("$1" --help | awk "$awk_cmd") + + case "$prev" in + -h|--help) + # No Options + ;; + --version) + # No Options + ;; + -c) + # Refer http://en.wikipedia.org/wiki/List_of_WLAN_channels + opts=$( + iw list | grep ' MHz \[[[:digit:]]\+\] ' | + grep -v 'no IR\|disabled' | + sed 's/.*\[\(.*\)\].*/\1/' | sort -n | uniq + ) + ;; + -w) + opts="1 2 1+2" + ;; + -n) + # No Options + ;; + -m) + opts="nat bridge none" + ;; + --psk) + # No Options + ;; + --hidden) + # No Options + ;; + --mac-filter) + # No Options + ;; + --mac-filter-accept) + # No Options + ;; + --ieee80211n) + # No Options + ;; + --ht_capab) + # Refer http://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf + opts=' + [LDPC] [HT40-] [HT40+] [SMPS-STATIC] [SMPS-DYNAMIC] + [GF] [SHORT-GI-20] [SHORT-GI-40] [TX-STBC] + [RX-STBC1] [RX-STBC12] [RX-STBC123] [DELAYED-BA] + [MAX-AMSDU-7935] [DSSS_CCK-40] [40-INTOLERANT] + [LSIG-TXOP-PROT] + ' + ;; + --country) + local reg_file=/usr/lib/crda/regulatory.bin + if command -v regdbdump > /dev/null && [[ -f "$reg_file" ]]; then + local country_awk_cmd=' + ($1 ~ /^country/) { + print substr ($2, 0, length ($2)-1) + } + ' + opts=$(regdbdump "$reg_file" 2>/dev/null | awk "$country_awk_cmd") + else + opts=' + AD AE AF AI AL AM AN AR AS AT AU AW AZ BA BB BD BE + BF BG BH BL BM BN BO BR BS BT BY BZ CA CF CH CI CL + CN CO CR CX CY CZ DE DK DM DO DZ EC EE EG ES ET FI + FM FR GB GD GE GF GH GL GP GR GT GU GY HK HN HR HT + HU ID IE IL IN IR IS IT JM JO JP KE KH KN KP KR KW + KY KZ LB LC LI LK LS LT LU LV MA MC MD ME MF MH MK + MN MO MP MQ MR MT MU MW MX MY NG NI NL NO NP NZ OM + PA PE PF PG PH PK PL PM PR PT PW PY QA RE RO RS RU + RW SA SE SG SI SK SN SR SV SY TC TD TG TH TN TR TT + TW TZ UA UG US UY UZ VC VE VI VN VU WF WS YE YT ZA + ZW 00 + ' + fi + ;; + --freq-band) + opts="2.4 5" + ;; + --driver) + # Refer http://w1.fi/cgit/hostap/tree/src/drivers + # Not going to implement + ;; + --no-virt) + # No Options + ;; + --no-haveged) + # No Options + ;; + --fix-unmanaged) + # No Options + ;; + --mac) + # Not going to implement + ;; + --daemon) + # No Options + ;; + --stop) + local stop_awk_cmd='$1 ~ /^[0-9]+$/' + opts=$("$1" --list-running | awk "$stop_awk_cmd") + ;; + --list-running) + # No Options + ;; + --list-clients) + local clients_awk_cmd='$1 ~ /^[0-9]+$/' + opts=$("$1" --list-running | awk "$clients_awk_cmd") + ;; + --no-dns) + # No Options + ;; + --dhcp-dns) + # Not going to implement + ;; + --mkconfig) + _use_filedir && return 0 + ;; + --config) + _use_filedir && return 0 + ;; + -g) + # Not going to implement + ;; + -d) + # No Options + ;; + *) + ;; + esac + + COMPREPLY=( $(compgen -W "$opts" -- $cur) ) + return 0 +} +complete -F _create_ap create_ap + +# vim: set ft=sh: diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/config_ap.sh b/Code/RK3588/PIBot_ROS/third_party/create_ap/config_ap.sh new file mode 100644 index 0000000..3b49e9a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/config_ap.sh @@ -0,0 +1,22 @@ +#!/bin/bash +sudo apt-get install -y hostapd + +SERIAL_ID=`cat /proc/cpuinfo | grep Serial | awk -F ':' '{print \$2}'` +SHORT_SERIAL_ID=${SERIAL_ID: -8} + +if [ "$SHORT_SERIAL_ID"_X!=""_X ]; then + SHORT_SERIAL_ID=`udevadm info --name=mmcblk0 --query=property | grep ID_SERIAL | awk -F '=' '{print $2}'` +fi + +if [ "$SHORT_SERIAL_ID"_X!=""_X ]; then + SERIAL_ID=`udevadm info --name=sda --query=property | grep ID_SERIAL_SHORT | awk -F '=' '{print \$2}'` + SHORT_SERIAL_ID=${SERIAL_ID: -8} +fi + +cp create_ap.service.template create_ap.service +sed -i "s|SSID|pibot_ap_$SHORT_SERIAL_ID|g" create_ap.service + +sudo make install + +sudo systemctl daemon-reload + diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap new file mode 100644 index 0000000..07fa4f6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap @@ -0,0 +1,1910 @@ +#!/bin/bash + +# general dependencies: +# bash (to run this script) +# util-linux (for getopt) +# procps or procps-ng +# hostapd +# iproute2 +# iw +# iwconfig (you only need this if 'iw' can not recognize your adapter) +# haveged (optional) + +# dependencies for 'nat' or 'none' Internet sharing method +# dnsmasq +# iptables + +VERSION=0.4.6 +PROGNAME="$(basename $0)" + +# make sure that all command outputs are in english +# so we can parse them correctly +export LC_ALL=C + +# all new files and directories must be readable only by root. +# in special cases we must use chmod to give any other permissions. +SCRIPT_UMASK=0077 +umask $SCRIPT_UMASK + +usage() { + echo "Usage: "$PROGNAME" [options] [] [ []]" + echo + echo "Options:" + echo " -h, --help Show this help" + echo " --version Print version number" + echo " -c Channel number (default: 1)" + echo " -w Use 1 for WPA, use 2 for WPA2, use 1+2 for both (default: 1+2)" + echo " -n Disable Internet sharing (if you use this, don't pass" + echo " the argument)" + echo " -m Method for Internet sharing." + echo " Use: 'nat' for NAT (default)" + echo " 'bridge' for bridging" + echo " 'none' for no Internet sharing (equivalent to -n)" + echo " --psk Use 64 hex digits pre-shared-key instead of passphrase" + echo " --hidden Make the Access Point hidden (do not broadcast the SSID)" + echo " --mac-filter Enable MAC address filtering" + echo " --mac-filter-accept Location of MAC address filter list (defaults to /etc/hostapd/hostapd.accept)" + echo " --redirect-to-localhost If -n is set, redirect every web request to localhost (useful for public information networks)" + echo " --hostapd-debug With level between 1 and 2, passes arguments -d or -dd to hostapd for debugging." + echo " --isolate-clients Disable communication between clients" + echo " --ieee80211n Enable IEEE 802.11n (HT)" + echo " --ieee80211ac Enable IEEE 802.11ac (VHT)" + echo " --ht_capab HT capabilities (default: [HT40+])" + echo " --vht_capab VHT capabilities" + echo " --country Set two-letter country code for regularity (example: US)" + echo " --freq-band Set frequency band. Valid inputs: 2.4, 5 (default: 2.4)" + echo " --driver Choose your WiFi adapter driver (default: nl80211)" + echo " --no-virt Do not create virtual interface" + echo " --no-haveged Do not run 'haveged' automatically when needed" + echo " --fix-unmanaged If NetworkManager shows your interface as unmanaged after you" + echo " close create_ap, then use this option to switch your interface" + echo " back to managed" + echo " --mac Set MAC address" + echo " --dhcp-dns Set DNS returned by DHCP" + echo " --daemon Run create_ap in the background" + echo " --pidfile Save daemon PID to file" + echo " --logfile Save daemon messages to file" + echo " --stop Send stop command to an already running create_ap. For an " + echo " you can put the PID of create_ap or the WiFi interface. You can" + echo " get them with --list-running" + echo " --list-running Show the create_ap processes that are already running" + echo " --list-clients List the clients connected to create_ap instance associated with ." + echo " For an you can put the PID of create_ap or the WiFi interface." + echo " If virtual WiFi interface was created, then use that one." + echo " You can get them with --list-running" + echo " --mkconfig Store configs in conf_file" + echo " --config Load configs from conf_file" + echo + echo "Non-Bridging Options:" + echo " --no-dns Disable dnsmasq DNS server" + echo " --no-dnsmasq Disable dnsmasq server completely" + echo " -g IPv4 Gateway for the Access Point (default: 192.168.12.1)" + echo " -d DNS server will take into account /etc/hosts" + echo " -e DNS server will take into account additional hosts file" + echo + echo "Useful informations:" + echo " * If you're not using the --no-virt option, then you can create an AP with the same" + echo " interface you are getting your Internet connection." + echo " * You can pass your SSID and password through pipe or through arguments (see examples)." + echo " * On bridge method if the is not a bridge interface, then" + echo " a bridge interface is created automatically." + echo + echo "Examples:" + echo " "$PROGNAME" wlan0 eth0 MyAccessPoint MyPassPhrase" + echo " echo -e 'MyAccessPoint\nMyPassPhrase' | "$PROGNAME" wlan0 eth0" + echo " "$PROGNAME" wlan0 eth0 MyAccessPoint" + echo " echo 'MyAccessPoint' | "$PROGNAME" wlan0 eth0" + echo " "$PROGNAME" wlan0 wlan0 MyAccessPoint MyPassPhrase" + echo " "$PROGNAME" -n wlan0 MyAccessPoint MyPassPhrase" + echo " "$PROGNAME" -m bridge wlan0 eth0 MyAccessPoint MyPassPhrase" + echo " "$PROGNAME" -m bridge wlan0 br0 MyAccessPoint MyPassPhrase" + echo " "$PROGNAME" --driver rtl871xdrv wlan0 eth0 MyAccessPoint MyPassPhrase" + echo " "$PROGNAME" --daemon wlan0 eth0 MyAccessPoint MyPassPhrase" + echo " "$PROGNAME" --stop wlan0" +} + +# Busybox polyfills +if cp --help 2>&1 | grep -q -- --no-clobber; then + cp_n() { + cp -n "$@" + } +else + cp_n() { + yes n | cp -i "$@" + } +fi + +# on success it echos a non-zero unused FD +# on error it echos 0 +get_avail_fd() { + local x + for x in $(seq 1 $(ulimit -n)); do + if [[ ! -a "/proc/$BASHPID/fd/$x" ]]; then + echo $x + return + fi + done + echo 0 +} + +# lock file for the mutex counter +COUNTER_LOCK_FILE=/tmp/create_ap.$$.lock + +cleanup_lock() { + rm -f $COUNTER_LOCK_FILE +} + +init_lock() { + local LOCK_FILE=/tmp/create_ap.all.lock + + # we initialize only once + [[ $LOCK_FD -ne 0 ]] && return 0 + + LOCK_FD=$(get_avail_fd) + [[ $LOCK_FD -eq 0 ]] && return 1 + + # open/create lock file with write access for all users + # otherwise normal users will not be able to use it. + # to avoid race conditions on creation, we need to + # use umask to set the permissions. + umask 0555 + eval "exec $LOCK_FD>$LOCK_FILE" > /dev/null 2>&1 || return 1 + umask $SCRIPT_UMASK + + # there is a case where lock file was created from a normal + # user. change the owner to root as soon as we can. + [[ $(id -u) -eq 0 ]] && chown 0:0 $LOCK_FILE + + # create mutex counter lock file + echo 0 > $COUNTER_LOCK_FILE + + return $? +} + +# recursive mutex lock for all create_ap processes +mutex_lock() { + local counter_mutex_fd + local counter + + # lock local mutex and read counter + counter_mutex_fd=$(get_avail_fd) + if [[ $counter_mutex_fd -ne 0 ]]; then + eval "exec $counter_mutex_fd<>$COUNTER_LOCK_FILE" + flock $counter_mutex_fd + read -u $counter_mutex_fd counter + else + echo "Failed to lock mutex counter" >&2 + return 1 + fi + + # lock global mutex and increase counter + [[ $counter -eq 0 ]] && flock $LOCK_FD + counter=$(( $counter + 1 )) + + # write counter and unlock local mutex + echo $counter > /proc/$BASHPID/fd/$counter_mutex_fd + eval "exec ${counter_mutex_fd}<&-" + return 0 +} + +# recursive mutex unlock for all create_ap processes +mutex_unlock() { + local counter_mutex_fd + local counter + + # lock local mutex and read counter + counter_mutex_fd=$(get_avail_fd) + if [[ $counter_mutex_fd -ne 0 ]]; then + eval "exec $counter_mutex_fd<>$COUNTER_LOCK_FILE" + flock $counter_mutex_fd + read -u $counter_mutex_fd counter + else + echo "Failed to lock mutex counter" >&2 + return 1 + fi + + # decrease counter and unlock global mutex + if [[ $counter -gt 0 ]]; then + counter=$(( $counter - 1 )) + [[ $counter -eq 0 ]] && flock -u $LOCK_FD + fi + + # write counter and unlock local mutex + echo $counter > /proc/$BASHPID/fd/$counter_mutex_fd + eval "exec ${counter_mutex_fd}<&-" + return 0 +} + +# it takes 2 arguments +# returns: +# 0 if v1 (1st argument) and v2 (2nd argument) are the same +# 1 if v1 is less than v2 +# 2 if v1 is greater than v2 +version_cmp() { + local V1 V2 VN x + [[ ! $1 =~ ^[0-9]+(\.[0-9]+)*$ ]] && die "Wrong version format!" + [[ ! $2 =~ ^[0-9]+(\.[0-9]+)*$ ]] && die "Wrong version format!" + + V1=( $(echo $1 | tr '.' ' ') ) + V2=( $(echo $2 | tr '.' ' ') ) + VN=${#V1[@]} + [[ $VN -lt ${#V2[@]} ]] && VN=${#V2[@]} + + for ((x = 0; x < $VN; x++)); do + [[ ${V1[x]} -lt ${V2[x]} ]] && return 1 + [[ ${V1[x]} -gt ${V2[x]} ]] && return 2 + done + + return 0 +} + +USE_IWCONFIG=0 + +is_interface() { + [[ -z "$1" ]] && return 1 + [[ -d "/sys/class/net/${1}" ]] +} + +is_wifi_interface() { + which iw > /dev/null 2>&1 && iw dev $1 info > /dev/null 2>&1 && return 0 + if which iwconfig > /dev/null 2>&1 && iwconfig $1 > /dev/null 2>&1; then + USE_IWCONFIG=1 + return 0 + fi + return 1 +} + +is_bridge_interface() { + [[ -z "$1" ]] && return 1 + [[ -d "/sys/class/net/${1}/bridge" ]] +} + +get_phy_device() { + local x + for x in /sys/class/ieee80211/*; do + [[ ! -e "$x" ]] && continue + if [[ "${x##*/}" = "$1" ]]; then + echo $1 + return 0 + elif [[ -e "$x/device/net/$1" ]]; then + echo ${x##*/} + return 0 + elif [[ -e "$x/device/net:$1" ]]; then + echo ${x##*/} + return 0 + fi + done + echo "Failed to get phy interface" >&2 + return 1 +} + +get_adapter_info() { + local PHY + PHY=$(get_phy_device "$1") + [[ $? -ne 0 ]] && return 1 + iw phy $PHY info +} + +get_adapter_kernel_module() { + local MODULE + MODULE=$(readlink -f "/sys/class/net/$1/device/driver/module") + echo ${MODULE##*/} +} + +can_be_sta_and_ap() { + # iwconfig does not provide this information, assume false + [[ $USE_IWCONFIG -eq 1 ]] && return 1 + if [[ "$(get_adapter_kernel_module "$1")" == "brcmfmac" ]]; then + echo "WARN: brmfmac driver doesn't work properly with virtual interfaces and" >&2 + echo " it can cause kernel panic. For this reason we disallow virtual" >&2 + echo " interfaces for your adapter." >&2 + echo " For more info: https://github.com/oblique/create_ap/issues/203" >&2 + return 1 + fi + get_adapter_info "$1" | grep -E '{.* managed.* AP.*}' > /dev/null 2>&1 && return 0 + get_adapter_info "$1" | grep -E '{.* AP.* managed.*}' > /dev/null 2>&1 && return 0 + return 1 +} + +can_be_ap() { + # iwconfig does not provide this information, assume true + [[ $USE_IWCONFIG -eq 1 ]] && return 0 + get_adapter_info "$1" | grep -E '\* AP$' > /dev/null 2>&1 && return 0 + return 1 +} + +can_transmit_to_channel() { + local IFACE CHANNEL_NUM CHANNEL_INFO + IFACE=$1 + CHANNEL_NUM=$2 + + if [[ $USE_IWCONFIG -eq 0 ]]; then + if [[ $FREQ_BAND == 2.4 ]]; then + CHANNEL_INFO=$(get_adapter_info ${IFACE} | grep " 24[0-9][0-9] MHz \[${CHANNEL_NUM}\]") + else + CHANNEL_INFO=$(get_adapter_info ${IFACE} | grep " \(49[0-9][0-9]\|5[0-9]\{3\}\) MHz \[${CHANNEL_NUM}\]") + fi + [[ -z "${CHANNEL_INFO}" ]] && return 1 + [[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 1 + [[ "${CHANNEL_INFO}" == *disabled* ]] && return 1 + return 0 + else + CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM}) + CHANNEL_INFO=$(iwlist ${IFACE} channel | grep -E "Channel[[:blank:]]${CHANNEL_NUM}[[:blank:]]?:") + [[ -z "${CHANNEL_INFO}" ]] && return 1 + return 0 + fi +} + +# taken from iw/util.c +ieee80211_frequency_to_channel() { + local FREQ=$1 + if [[ $FREQ -eq 2484 ]]; then + echo 14 + elif [[ $FREQ -lt 2484 ]]; then + echo $(( ($FREQ - 2407) / 5 )) + elif [[ $FREQ -ge 4910 && $FREQ -le 4980 ]]; then + echo $(( ($FREQ - 4000) / 5 )) + elif [[ $FREQ -le 45000 ]]; then + echo $(( ($FREQ - 5000) / 5 )) + elif [[ $FREQ -ge 58320 && $FREQ -le 64800 ]]; then + echo $(( ($FREQ - 56160) / 2160 )) + else + echo 0 + fi +} + +is_5ghz_frequency() { + [[ $1 =~ ^(49[0-9]{2})|(5[0-9]{3})$ ]] +} + +is_wifi_connected() { + if [[ $USE_IWCONFIG -eq 0 ]]; then + iw dev "$1" link 2>&1 | grep -E '^Connected to' > /dev/null 2>&1 && return 0 + else + iwconfig "$1" 2>&1 | grep -E 'Access Point: [0-9a-fA-F]{2}:' > /dev/null 2>&1 && return 0 + fi + return 1 +} + +is_macaddr() { + echo "$1" | grep -E "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$" > /dev/null 2>&1 +} + +is_unicast_macaddr() { + local x + is_macaddr "$1" || return 1 + x=$(echo "$1" | cut -d: -f1) + x=$(printf '%d' "0x${x}") + [[ $(expr $x % 2) -eq 0 ]] +} + +get_macaddr() { + is_interface "$1" || return + cat "/sys/class/net/${1}/address" +} + +get_mtu() { + is_interface "$1" || return + cat "/sys/class/net/${1}/mtu" +} + +alloc_new_iface() { + local prefix=$1 + local i=0 + + mutex_lock + while :; do + if ! is_interface $prefix$i && [[ ! -f $COMMON_CONFDIR/ifaces/$prefix$i ]]; then + mkdir -p $COMMON_CONFDIR/ifaces + touch $COMMON_CONFDIR/ifaces/$prefix$i + echo $prefix$i + mutex_unlock + return + fi + i=$((i + 1)) + done + mutex_unlock +} + +dealloc_iface() { + rm -f $COMMON_CONFDIR/ifaces/$1 +} + +get_all_macaddrs() { + cat /sys/class/net/*/address +} + +get_new_macaddr() { + local OLDMAC NEWMAC LAST_BYTE i + OLDMAC=$(get_macaddr "$1") + LAST_BYTE=$(printf %d 0x${OLDMAC##*:}) + mutex_lock + for i in {1..255}; do + NEWMAC="${OLDMAC%:*}:$(printf %02x $(( ($LAST_BYTE + $i) % 256 )))" + (get_all_macaddrs | grep "$NEWMAC" > /dev/null 2>&1) || break + done + mutex_unlock + echo $NEWMAC +} + +# start haveged when needed +haveged_watchdog() { + local show_warn=1 + while :; do + mutex_lock + if [[ $(cat /proc/sys/kernel/random/entropy_avail) -lt 1000 ]]; then + if ! which haveged > /dev/null 2>&1; then + if [[ $show_warn -eq 1 ]]; then + echo "WARN: Low entropy detected. We recommend you to install \`haveged'" + show_warn=0 + fi + elif ! pidof haveged > /dev/null 2>&1; then + echo "Low entropy detected, starting haveged" + # boost low-entropy + haveged -w 1024 -p $COMMON_CONFDIR/haveged.pid + fi + fi + mutex_unlock + sleep 2 + done +} + +NETWORKMANAGER_CONF=/etc/NetworkManager/NetworkManager.conf +NM_OLDER_VERSION=1 + +networkmanager_exists() { + local NM_VER + which nmcli > /dev/null 2>&1 || return 1 + NM_VER=$(nmcli -v | grep -m1 -oE '[0-9]+(\.[0-9]+)*\.[0-9]+') + version_cmp $NM_VER 0.9.9 + if [[ $? -eq 1 ]]; then + NM_OLDER_VERSION=1 + else + NM_OLDER_VERSION=0 + fi + return 0 +} + +networkmanager_is_running() { + local NMCLI_OUT + networkmanager_exists || return 1 + if [[ $NM_OLDER_VERSION -eq 1 ]]; then + NMCLI_OUT=$(nmcli -t -f RUNNING nm 2>&1 | grep -E '^running$') + else + NMCLI_OUT=$(nmcli -t -f RUNNING g 2>&1 | grep -E '^running$') + fi + [[ -n "$NMCLI_OUT" ]] +} + +networkmanager_knows_iface() { + # check if the interface $1 is known to NetworkManager + # an interface may exist but may not be known to NetworkManager if it is in a different network namespace than NetworkManager + nmcli -t -f DEVICE d 2>&1 | grep -Fxq "$1" +} + +networkmanager_iface_is_unmanaged() { + is_interface "$1" || return 2 + networkmanager_knows_iface "$1" || return 0 + (nmcli -t -f DEVICE,STATE d 2>&1 | grep -E "^$1:unmanaged$" > /dev/null 2>&1) || return 1 +} + +ADDED_UNMANAGED= + +networkmanager_add_unmanaged() { + local MAC UNMANAGED WAS_EMPTY x + networkmanager_exists || return 1 + + [[ -d ${NETWORKMANAGER_CONF%/*} ]] || mkdir -p ${NETWORKMANAGER_CONF%/*} + [[ -f ${NETWORKMANAGER_CONF} ]] || touch ${NETWORKMANAGER_CONF} + + if [[ $NM_OLDER_VERSION -eq 1 ]]; then + if [[ -z "$2" ]]; then + MAC=$(get_macaddr "$1") + else + MAC="$2" + fi + [[ -z "$MAC" ]] && return 1 + fi + + mutex_lock + UNMANAGED=$(grep -m1 -Eo '^unmanaged-devices=[[:alnum:]:;,-]*' /etc/NetworkManager/NetworkManager.conf) + + WAS_EMPTY=0 + [[ -z "$UNMANAGED" ]] && WAS_EMPTY=1 + UNMANAGED=$(echo "$UNMANAGED" | sed 's/unmanaged-devices=//' | tr ';,' ' ') + + # if it exists, do nothing + for x in $UNMANAGED; do + if [[ $x == "mac:${MAC}" ]] || + [[ $NM_OLDER_VERSION -eq 0 && $x == "interface-name:${1}" ]]; then + mutex_unlock + return 2 + fi + done + + if [[ $NM_OLDER_VERSION -eq 1 ]]; then + UNMANAGED="${UNMANAGED} mac:${MAC}" + else + UNMANAGED="${UNMANAGED} interface-name:${1}" + fi + + UNMANAGED=$(echo $UNMANAGED | sed -e 's/^ //') + UNMANAGED="${UNMANAGED// /;}" + UNMANAGED="unmanaged-devices=${UNMANAGED}" + + if ! grep -E '^\[keyfile\]' ${NETWORKMANAGER_CONF} > /dev/null 2>&1; then + echo -e "\n\n[keyfile]\n${UNMANAGED}" >> ${NETWORKMANAGER_CONF} + elif [[ $WAS_EMPTY -eq 1 ]]; then + sed -e "s/^\(\[keyfile\].*\)$/\1\n${UNMANAGED}/" -i ${NETWORKMANAGER_CONF} + else + sed -e "s/^unmanaged-devices=.*/${UNMANAGED}/" -i ${NETWORKMANAGER_CONF} + fi + + ADDED_UNMANAGED="${ADDED_UNMANAGED} ${1} " + mutex_unlock + + local nm_pid=$(pidof NetworkManager) + [[ -n "$nm_pid" ]] && kill -HUP $nm_pid + + return 0 +} + +networkmanager_rm_unmanaged() { + local MAC UNMANAGED + networkmanager_exists || return 1 + [[ ! -f ${NETWORKMANAGER_CONF} ]] && return 1 + + if [[ $NM_OLDER_VERSION -eq 1 ]]; then + if [[ -z "$2" ]]; then + MAC=$(get_macaddr "$1") + else + MAC="$2" + fi + [[ -z "$MAC" ]] && return 1 + fi + + mutex_lock + UNMANAGED=$(grep -m1 -Eo '^unmanaged-devices=[[:alnum:]:;,-]*' /etc/NetworkManager/NetworkManager.conf | sed 's/unmanaged-devices=//' | tr ';,' ' ') + + if [[ -z "$UNMANAGED" ]]; then + mutex_unlock + return 1 + fi + + [[ -n "$MAC" ]] && UNMANAGED=$(echo $UNMANAGED | sed -e "s/mac:${MAC}\( \|$\)//g") + UNMANAGED=$(echo $UNMANAGED | sed -e "s/interface-name:${1}\( \|$\)//g") + UNMANAGED=$(echo $UNMANAGED | sed -e 's/ $//') + + if [[ -z "$UNMANAGED" ]]; then + sed -e "/^unmanaged-devices=.*/d" -i ${NETWORKMANAGER_CONF} + else + UNMANAGED="${UNMANAGED// /;}" + UNMANAGED="unmanaged-devices=${UNMANAGED}" + sed -e "s/^unmanaged-devices=.*/${UNMANAGED}/" -i ${NETWORKMANAGER_CONF} + fi + + ADDED_UNMANAGED="${ADDED_UNMANAGED/ ${1} /}" + mutex_unlock + + local nm_pid=$(pidof NetworkManager) + [[ -n "$nm_pid" ]] && kill -HUP $nm_pid + + return 0 +} + +networkmanager_fix_unmanaged() { + [[ -f ${NETWORKMANAGER_CONF} ]] || return + + mutex_lock + sed -e "/^unmanaged-devices=.*/d" -i ${NETWORKMANAGER_CONF} + mutex_unlock + + local nm_pid=$(pidof NetworkManager) + [[ -n "$nm_pid" ]] && kill -HUP $nm_pid +} + +networkmanager_rm_unmanaged_if_needed() { + [[ $ADDED_UNMANAGED =~ .*\ ${1}\ .* ]] && networkmanager_rm_unmanaged $1 $2 +} + +networkmanager_wait_until_unmanaged() { + local RES + networkmanager_is_running || return 1 + while :; do + networkmanager_iface_is_unmanaged "$1" + RES=$? + [[ $RES -eq 0 ]] && break + [[ $RES -eq 2 ]] && die "Interface '${1}' does not exist. + It's probably renamed by a udev rule." + sleep 1 + done + sleep 2 + return 0 +} + + +CHANNEL=default +GATEWAY=192.168.12.1 +WPA_VERSION=1+2 +ETC_HOSTS=0 +ADDN_HOSTS= +DHCP_DNS=gateway +NO_DNS=0 +NO_DNSMASQ=0 +DNS_PORT= +HIDDEN=0 +MAC_FILTER=0 +MAC_FILTER_ACCEPT=/etc/hostapd/hostapd.accept +ISOLATE_CLIENTS=0 +SHARE_METHOD=nat +IEEE80211N=0 +IEEE80211AC=0 +HT_CAPAB='[HT40+]' +VHT_CAPAB= +DRIVER=nl80211 +NO_VIRT=0 +COUNTRY= +FREQ_BAND=2.4 +NEW_MACADDR= +DAEMONIZE=0 +DAEMON_PIDFILE= +DAEMON_LOGFILE=/dev/null +NO_HAVEGED=0 +USE_PSK=0 + +HOSTAPD_DEBUG_ARGS= +REDIRECT_TO_LOCALHOST=0 + +CONFIG_OPTS=(CHANNEL GATEWAY WPA_VERSION ETC_HOSTS DHCP_DNS NO_DNS NO_DNSMASQ HIDDEN MAC_FILTER MAC_FILTER_ACCEPT ISOLATE_CLIENTS + SHARE_METHOD IEEE80211N IEEE80211AC HT_CAPAB VHT_CAPAB DRIVER NO_VIRT COUNTRY FREQ_BAND + NEW_MACADDR DAEMONIZE DAEMON_PIDFILE DAEMON_LOGFILE NO_HAVEGED WIFI_IFACE INTERNET_IFACE + SSID PASSPHRASE USE_PSK) + +FIX_UNMANAGED=0 +LIST_RUNNING=0 +STOP_ID= +LIST_CLIENTS_ID= + +STORE_CONFIG= +LOAD_CONFIG= + +CONFDIR= +WIFI_IFACE= +VWIFI_IFACE= +INTERNET_IFACE= +BRIDGE_IFACE= +OLD_MACADDR= +IP_ADDRS= +ROUTE_ADDRS= + +HAVEGED_WATCHDOG_PID= + +_cleanup() { + local PID x + + trap "" SIGINT SIGUSR1 SIGUSR2 EXIT + mutex_lock + disown -a + + # kill haveged_watchdog + [[ -n "$HAVEGED_WATCHDOG_PID" ]] && kill $HAVEGED_WATCHDOG_PID + + # kill processes + for x in $CONFDIR/*.pid; do + # even if the $CONFDIR is empty, the for loop will assign + # a value in $x. so we need to check if the value is a file + [[ -f $x ]] && kill -9 $(cat $x) + done + + rm -rf $CONFDIR + + local found=0 + for x in $(list_running_conf); do + if [[ -f $x/nat_internet_iface && $(cat $x/nat_internet_iface) == $INTERNET_IFACE ]]; then + found=1 + break + fi + done + + if [[ $found -eq 0 ]]; then + cp -f $COMMON_CONFDIR/${INTERNET_IFACE}_forwarding \ + /proc/sys/net/ipv4/conf/$INTERNET_IFACE/forwarding + rm -f $COMMON_CONFDIR/${INTERNET_IFACE}_forwarding + fi + + # if we are the last create_ap instance then set back the common values + if ! has_running_instance; then + # kill common processes + for x in $COMMON_CONFDIR/*.pid; do + [[ -f $x ]] && kill -9 $(cat $x) + done + + # set old ip_forward + if [[ -f $COMMON_CONFDIR/ip_forward ]]; then + cp -f $COMMON_CONFDIR/ip_forward /proc/sys/net/ipv4 + rm -f $COMMON_CONFDIR/ip_forward + fi + + # set old bridge-nf-call-iptables + if [[ -f $COMMON_CONFDIR/bridge-nf-call-iptables ]]; then + if [[ -e /proc/sys/net/bridge/bridge-nf-call-iptables ]]; then + cp -f $COMMON_CONFDIR/bridge-nf-call-iptables /proc/sys/net/bridge + fi + rm -f $COMMON_CONFDIR/bridge-nf-call-iptables + fi + + rm -rf $COMMON_CONFDIR + fi + + if [[ "$SHARE_METHOD" != "none" ]]; then + if [[ "$SHARE_METHOD" == "nat" ]]; then + iptables -w -t nat -D POSTROUTING -s ${GATEWAY%.*}.0/24 ! -o ${WIFI_IFACE} -j MASQUERADE + iptables -w -D FORWARD -i ${WIFI_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT + iptables -w -D FORWARD -i ${INTERNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT + elif [[ "$SHARE_METHOD" == "bridge" ]]; then + if ! is_bridge_interface $INTERNET_IFACE; then + ip link set dev $BRIDGE_IFACE down + ip link set dev $INTERNET_IFACE down + ip link set dev $INTERNET_IFACE promisc off + ip link set dev $INTERNET_IFACE nomaster + ip link delete $BRIDGE_IFACE type bridge + ip addr flush $INTERNET_IFACE + ip link set dev $INTERNET_IFACE up + dealloc_iface $BRIDGE_IFACE + + for x in "${IP_ADDRS[@]}"; do + x="${x/inet/}" + x="${x/secondary/}" + x="${x/dynamic/}" + x=$(echo $x | sed 's/\([0-9]\)sec/\1/g') + x="${x/${INTERNET_IFACE}/}" + ip addr add $x dev $INTERNET_IFACE + done + + ip route flush dev $INTERNET_IFACE + + for x in "${ROUTE_ADDRS[@]}"; do + [[ -z "$x" ]] && continue + [[ "$x" == default* ]] && continue + ip route add $x dev $INTERNET_IFACE + done + + for x in "${ROUTE_ADDRS[@]}"; do + [[ -z "$x" ]] && continue + [[ "$x" != default* ]] && continue + ip route add $x dev $INTERNET_IFACE + done + + networkmanager_rm_unmanaged_if_needed $INTERNET_IFACE + fi + fi + fi + + if [[ "$SHARE_METHOD" != "bridge" ]]; then + if [[ $NO_DNS -eq 0 ]]; then + iptables -w -D INPUT -p tcp -m tcp --dport $DNS_PORT -j ACCEPT + iptables -w -D INPUT -p udp -m udp --dport $DNS_PORT -j ACCEPT + iptables -w -t nat -D PREROUTING -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} \ + -p tcp -m tcp --dport 53 -j REDIRECT --to-ports $DNS_PORT + iptables -w -t nat -D PREROUTING -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} \ + -p udp -m udp --dport 53 -j REDIRECT --to-ports $DNS_PORT + fi + iptables -w -D INPUT -p udp -m udp --dport 67 -j ACCEPT + fi + + if [[ $NO_VIRT -eq 0 ]]; then + if [[ -n "$VWIFI_IFACE" ]]; then + ip link set down dev ${VWIFI_IFACE} + ip addr flush ${VWIFI_IFACE} + networkmanager_rm_unmanaged_if_needed ${VWIFI_IFACE} ${OLD_MACADDR} + iw dev ${VWIFI_IFACE} del + dealloc_iface $VWIFI_IFACE + fi + else + ip link set down dev ${WIFI_IFACE} + ip addr flush ${WIFI_IFACE} + if [[ -n "$NEW_MACADDR" ]]; then + ip link set dev ${WIFI_IFACE} address ${OLD_MACADDR} + fi + networkmanager_rm_unmanaged_if_needed ${WIFI_IFACE} ${OLD_MACADDR} + fi + + mutex_unlock + cleanup_lock + + if [[ $RUNNING_AS_DAEMON -eq 1 && -n "$DAEMON_PIDFILE" && -f "$DAEMON_PIDFILE" ]]; then + rm $DAEMON_PIDFILE + fi +} + +cleanup() { + echo + echo -n "Doing cleanup.. " + _cleanup > /dev/null 2>&1 + echo "done" +} + +die() { + [[ -n "$1" ]] && echo -e "\nERROR: $1\n" >&2 + # send die signal to the main process + [[ $BASHPID -ne $$ ]] && kill -USR2 $$ + # we don't need to call cleanup because it's traped on EXIT + exit 1 +} + +clean_exit() { + # send clean_exit signal to the main process + [[ $BASHPID -ne $$ ]] && kill -USR1 $$ + # we don't need to call cleanup because it's traped on EXIT + exit 0 +} + +list_running_conf() { + local x + mutex_lock + for x in /tmp/create_ap.*; do + if [[ -f $x/pid && -f $x/wifi_iface && -d /proc/$(cat $x/pid) ]]; then + echo $x + fi + done + mutex_unlock +} + +list_running() { + local IFACE wifi_iface x + mutex_lock + for x in $(list_running_conf); do + IFACE=${x#*.} + IFACE=${IFACE%%.*} + wifi_iface=$(cat $x/wifi_iface) + + if [[ $IFACE == $wifi_iface ]]; then + echo $(cat $x/pid) $IFACE + else + echo $(cat $x/pid) $IFACE '('$(cat $x/wifi_iface)')' + fi + done + mutex_unlock +} + +get_wifi_iface_from_pid() { + list_running | awk '{print $1 " " $NF}' | tr -d '\(\)' | grep -E "^${1} " | cut -d' ' -f2 +} + +get_pid_from_wifi_iface() { + list_running | awk '{print $1 " " $NF}' | tr -d '\(\)' | grep -E " ${1}$" | cut -d' ' -f1 +} + +get_confdir_from_pid() { + local IFACE x + mutex_lock + for x in $(list_running_conf); do + if [[ $(cat $x/pid) == "$1" ]]; then + echo $x + break + fi + done + mutex_unlock +} + +print_client() { + local line ipaddr hostname + local mac="$1" + + if [[ -f $CONFDIR/dnsmasq.leases ]]; then + line=$(grep " $mac " $CONFDIR/dnsmasq.leases | tail -n 1) + ipaddr=$(echo $line | cut -d' ' -f3) + hostname=$(echo "$line" | cut -d' ' -f4) + fi + + [[ -z "$ipaddr" ]] && ipaddr="*" + [[ -z "$hostname" ]] && hostname="*" + + printf "%-20s %-18s %s\n" "$mac" "$ipaddr" "$hostname" +} + +list_clients() { + local wifi_iface pid + + # If PID is given, get the associated wifi iface + if [[ "$1" =~ ^[1-9][0-9]*$ ]]; then + pid="$1" + wifi_iface=$(get_wifi_iface_from_pid "$pid") + [[ -z "$wifi_iface" ]] && die "'$pid' is not the pid of a running $PROGNAME instance." + fi + + [[ -z "$wifi_iface" ]] && wifi_iface="$1" + is_wifi_interface "$wifi_iface" || die "'$wifi_iface' is not a WiFi interface." + + [[ -z "$pid" ]] && pid=$(get_pid_from_wifi_iface "$wifi_iface") + [[ -z "$pid" ]] && die "'$wifi_iface' is not used from $PROGNAME instance.\n\ + Maybe you need to pass the virtual interface instead.\n\ + Use --list-running to find it out." + [[ -z "$CONFDIR" ]] && CONFDIR=$(get_confdir_from_pid "$pid") + + if [[ $USE_IWCONFIG -eq 0 ]]; then + local awk_cmd='($1 ~ /Station$/) {print $2}' + local client_list=$(iw dev "$wifi_iface" station dump | awk "$awk_cmd") + + if [[ -z "$client_list" ]]; then + echo "No clients connected" + return + fi + + printf "%-20s %-18s %s\n" "MAC" "IP" "Hostname" + + local mac + for mac in $client_list; do + print_client $mac + done + else + die "This option is not supported for the current driver." + fi +} + +has_running_instance() { + local PID x + + mutex_lock + for x in /tmp/create_ap.*; do + if [[ -f $x/pid ]]; then + PID=$(cat $x/pid) + if [[ -d /proc/$PID ]]; then + mutex_unlock + return 0 + fi + fi + done + mutex_lock + + return 1 +} + +is_running_pid() { + list_running | grep -E "^${1} " > /dev/null 2>&1 +} + +send_stop() { + local x + + mutex_lock + # send stop signal to specific pid + if is_running_pid $1; then + kill -USR1 $1 + mutex_unlock + return + fi + + # send stop signal to specific interface + for x in $(list_running | grep -E " \(?${1}( |\)?\$)" | cut -f1 -d' '); do + kill -USR1 $x + done + mutex_unlock +} + +# Storing configs +write_config() { + local i=1 + + if ! eval 'echo -n > "$STORE_CONFIG"' > /dev/null 2>&1; then + echo "ERROR: Unable to create config file $STORE_CONFIG" >&2 + exit 1 + fi + + WIFI_IFACE=$1 + if [[ "$SHARE_METHOD" == "none" ]]; then + SSID="$2" + PASSPHRASE="$3" + else + INTERNET_IFACE="$2" + SSID="$3" + PASSPHRASE="$4" + fi + + for config_opt in "${CONFIG_OPTS[@]}"; do + eval echo $config_opt=\$$config_opt + done >> "$STORE_CONFIG" + + echo -e "Config options written to '$STORE_CONFIG'" + exit 0 +} + +is_config_opt() { + local elem opt="$1" + + for elem in "${CONFIG_OPTS[@]}"; do + if [[ "$elem" == "$opt" ]]; then + return 0 + fi + done + return 1 +} + +# Load options from config file +read_config() { + local opt_name opt_val line + + while read line; do + # Read switches and their values + opt_name="${line%%=*}" + opt_val="${line#*=}" + if is_config_opt "$opt_name" ; then + eval $opt_name="\$opt_val" + else + echo "WARN: Unrecognized configuration entry $opt_name" >&2 + fi + done < "$LOAD_CONFIG" +} + + +ARGS=( "$@" ) + +# Preprocessing for --config before option-parsing starts +for ((i=0; i<$#; i++)); do + if [[ "${ARGS[i]}" = "--config" ]]; then + if [[ -f "${ARGS[i+1]}" ]]; then + LOAD_CONFIG="${ARGS[i+1]}" + read_config + else + echo "ERROR: No config file found at given location" >&2 + exit 1 + fi + break + fi +done + +GETOPT_ARGS=$(getopt -o hc:w:g:de:nm: -l "help","hidden","hostapd-debug:","redirect-to-localhost","mac-filter","mac-filter-accept:","isolate-clients","ieee80211n","ieee80211ac","ht_capab:","vht_capab:","driver:","no-virt","fix-unmanaged","country:","freq-band:","mac:","dhcp-dns:","daemon","pidfile:","logfile:","stop:","list","list-running","list-clients:","version","psk","no-haveged","no-dns","no-dnsmasq","mkconfig:","config:" -n "$PROGNAME" -- "$@") +[[ $? -ne 0 ]] && exit 1 +eval set -- "$GETOPT_ARGS" + +while :; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + --version) + echo $VERSION + exit 0 + ;; + --hidden) + shift + HIDDEN=1 + ;; + --mac-filter) + shift + MAC_FILTER=1 + ;; + --mac-filter-accept) + shift + MAC_FILTER_ACCEPT="$1" + shift + ;; + --isolate-clients) + shift + ISOLATE_CLIENTS=1 + ;; + -c) + shift + CHANNEL="$1" + shift + ;; + -w) + shift + WPA_VERSION="$1" + [[ "$WPA_VERSION" == "2+1" ]] && WPA_VERSION=1+2 + shift + ;; + -g) + shift + GATEWAY="$1" + shift + ;; + -d) + shift + ETC_HOSTS=1 + ;; + -e) + shift + ADDN_HOSTS="$1" + shift + ;; + -n) + shift + SHARE_METHOD=none + ;; + -m) + shift + SHARE_METHOD="$1" + shift + ;; + --ieee80211n) + shift + IEEE80211N=1 + ;; + --ieee80211ac) + shift + IEEE80211AC=1 + ;; + --ht_capab) + shift + HT_CAPAB="$1" + shift + ;; + --vht_capab) + shift + VHT_CAPAB="$1" + shift + ;; + --driver) + shift + DRIVER="$1" + shift + ;; + --no-virt) + shift + NO_VIRT=1 + ;; + --fix-unmanaged) + shift + FIX_UNMANAGED=1 + ;; + --country) + shift + COUNTRY="$1" + shift + ;; + --freq-band) + shift + FREQ_BAND="$1" + shift + ;; + --mac) + shift + NEW_MACADDR="$1" + shift + ;; + --dhcp-dns) + shift + DHCP_DNS="$1" + shift + ;; + --daemon) + shift + DAEMONIZE=1 + ;; + --pidfile) + shift + DAEMON_PIDFILE="$1" + shift + ;; + --logfile) + shift + DAEMON_LOGFILE="$1" + shift + ;; + --stop) + shift + STOP_ID="$1" + shift + ;; + --list) + shift + LIST_RUNNING=1 + echo -e "WARN: --list is deprecated, use --list-running instead.\n" >&2 + ;; + --list-running) + shift + LIST_RUNNING=1 + ;; + --list-clients) + shift + LIST_CLIENTS_ID="$1" + shift + ;; + --no-haveged) + shift + NO_HAVEGED=1 + ;; + --psk) + shift + USE_PSK=1 + ;; + --no-dns) + shift + NO_DNS=1 + ;; + --no-dnsmasq) + shift + NO_DNSMASQ=1 + ;; + --redirect-to-localhost) + shift + REDIRECT_TO_LOCALHOST=1 + ;; + --hostapd-debug) + shift + if [ "x$1" = "x1" ]; then + HOSTAPD_DEBUG_ARGS="-d" + elif [ "x$1" = "x2" ]; then + HOSTAPD_DEBUG_ARGS="-dd" + else + printf "Error: argument for --hostapd-debug expected 1 or 2, got %s\n" "$1" + exit 1 + fi + shift + ;; + --mkconfig) + shift + STORE_CONFIG="$1" + shift + ;; + --config) + shift + shift + ;; + --) + shift + break + ;; + esac +done + +# Load positional args from config file, if needed +if [[ -n "$LOAD_CONFIG" && $# -eq 0 ]]; then + i=0 + # set arguments in order + for x in WIFI_IFACE INTERNET_IFACE SSID PASSPHRASE; do + if eval "[[ -n \"\$${x}\" ]]"; then + eval "set -- \"\${@:1:$i}\" \"\$${x}\"" + ((i++)) + fi + # we unset the variable to avoid any problems later + eval "unset $x" + done +fi + +# Check if required number of positional args are present +if [[ $# -lt 1 && $FIX_UNMANAGED -eq 0 && -z "$STOP_ID" && + $LIST_RUNNING -eq 0 && -z "$LIST_CLIENTS_ID" ]]; then + usage >&2 + exit 1 +fi + +# Set NO_DNS, if dnsmasq is disabled +if [[ $NO_DNSMASQ -eq 1 ]]; then + NO_DNS=1 +fi + +trap "cleanup_lock" EXIT + +if ! init_lock; then + echo "ERROR: Failed to initialize lock" >&2 + exit 1 +fi + +# if the user press ctrl+c or we get USR1 signal +# then run clean_exit() +trap "clean_exit" SIGINT SIGUSR1 +# if we get USR2 signal then run die(). +trap "die" SIGUSR2 + +[[ -n "$STORE_CONFIG" ]] && write_config "$@" + +if [[ $LIST_RUNNING -eq 1 ]]; then + echo -e "List of running $PROGNAME instances:\n" + list_running + exit 0 +fi + +if [[ -n "$LIST_CLIENTS_ID" ]]; then + list_clients "$LIST_CLIENTS_ID" + exit 0 +fi + +if [[ $(id -u) -ne 0 ]]; then + echo "You must run it as root." >&2 + exit 1 +fi + +if [[ -n "$STOP_ID" ]]; then + echo "Trying to kill $PROGNAME instance associated with $STOP_ID..." + send_stop "$STOP_ID" + exit 0 +fi + +if [[ $FIX_UNMANAGED -eq 1 ]]; then + echo "Trying to fix unmanaged status in NetworkManager..." + networkmanager_fix_unmanaged + exit 0 +fi + +if [[ $DAEMONIZE -eq 1 && $RUNNING_AS_DAEMON -eq 0 ]]; then + # Assume we're running underneath a service manager if PIDFILE is set + # and don't clobber it's output with a useless message + if [ -z "$DAEMON_PIDFILE" ]; then + echo "Running as Daemon..." + fi + # run a detached create_ap + RUNNING_AS_DAEMON=1 setsid "$0" "${ARGS[@]}" >>$DAEMON_LOGFILE 2>&1 & + exit 0 +elif [[ $RUNNING_AS_DAEMON -eq 1 && -n "$DAEMON_PIDFILE" ]]; then + echo $$ >$DAEMON_PIDFILE +fi + +if [[ $FREQ_BAND != 2.4 && $FREQ_BAND != 5 ]]; then + echo "ERROR: Invalid frequency band" >&2 + exit 1 +fi + +if [[ $CHANNEL == default ]]; then + if [[ $FREQ_BAND == 2.4 ]]; then + CHANNEL=1 + else + CHANNEL=36 + fi +fi + +if [[ $FREQ_BAND != 5 && $CHANNEL -gt 14 ]]; then + echo "Channel number is greater than 14, assuming 5GHz frequency band" + FREQ_BAND=5 +fi + +WIFI_IFACE=$1 + +if ! is_wifi_interface ${WIFI_IFACE}; then + echo "ERROR: '${WIFI_IFACE}' is not a WiFi interface" >&2 + exit 1 +fi + +if ! can_be_ap ${WIFI_IFACE}; then + echo "ERROR: Your adapter does not support AP (master) mode" >&2 + exit 1 +fi + +if ! can_be_sta_and_ap ${WIFI_IFACE}; then + if is_wifi_connected ${WIFI_IFACE}; then + echo "ERROR: Your adapter can not be a station (i.e. be connected) and an AP at the same time" >&2 + exit 1 + elif [[ $NO_VIRT -eq 0 ]]; then + echo "WARN: Your adapter does not fully support AP virtual interface, enabling --no-virt" >&2 + NO_VIRT=1 + fi +fi + +HOSTAPD=$(which hostapd) + +if [[ ! -x "$HOSTAPD" ]]; then + echo "ERROR: hostapd not found." >&2 + exit 1 +fi + +if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^(8192[cd][ue]|8723a[sue])$ ]]; then + if ! strings "$HOSTAPD" | grep -m1 rtl871xdrv > /dev/null 2>&1; then + echo "ERROR: You need to patch your hostapd with rtl871xdrv patches." >&2 + exit 1 + fi + + if [[ $DRIVER != "rtl871xdrv" ]]; then + echo "WARN: Your adapter needs rtl871xdrv, enabling --driver=rtl871xdrv" >&2 + DRIVER=rtl871xdrv + fi +fi + +if [[ "$SHARE_METHOD" != "nat" && "$SHARE_METHOD" != "bridge" && "$SHARE_METHOD" != "none" ]]; then + echo "ERROR: Wrong Internet sharing method" >&2 + echo + usage >&2 + exit 1 +fi + +if [[ -n "$NEW_MACADDR" ]]; then + if ! is_macaddr "$NEW_MACADDR"; then + echo "ERROR: '${NEW_MACADDR}' is not a valid MAC address" >&2 + exit 1 + fi + + if ! is_unicast_macaddr "$NEW_MACADDR"; then + echo "ERROR: The first byte of MAC address (${NEW_MACADDR}) must be even" >&2 + exit 1 + fi + + if [[ $(get_all_macaddrs | grep -c ${NEW_MACADDR}) -ne 0 ]]; then + echo "WARN: MAC address '${NEW_MACADDR}' already exists. Because of this, you may encounter some problems" >&2 + fi +fi + +if [[ "$SHARE_METHOD" != "none" ]]; then + MIN_REQUIRED_ARGS=2 +else + MIN_REQUIRED_ARGS=1 +fi + +if [[ $# -gt $MIN_REQUIRED_ARGS ]]; then + if [[ "$SHARE_METHOD" != "none" ]]; then + if [[ $# -ne 3 && $# -ne 4 ]]; then + usage >&2 + exit 1 + fi + INTERNET_IFACE="$2" + SSID="$3" + PASSPHRASE="$4" + else + if [[ $# -ne 2 && $# -ne 3 ]]; then + usage >&2 + exit 1 + fi + SSID="$2" + PASSPHRASE="$3" + fi +else + if [[ "$SHARE_METHOD" != "none" ]]; then + if [[ $# -ne 2 ]]; then + usage >&2 + exit 1 + fi + INTERNET_IFACE="$2" + fi + if tty -s; then + while :; do + read -p "SSID: " SSID + if [[ ${#SSID} -lt 1 || ${#SSID} -gt 32 ]]; then + echo "ERROR: Invalid SSID length ${#SSID} (expected 1..32)" >&2 + continue + fi + break + done + while :; do + if [[ $USE_PSK -eq 0 ]]; then + read -p "Passphrase: " -s PASSPHRASE + echo + if [[ ${#PASSPHRASE} -gt 0 && ${#PASSPHRASE} -lt 8 ]] || [[ ${#PASSPHRASE} -gt 63 ]]; then + echo "ERROR: Invalid passphrase length ${#PASSPHRASE} (expected 8..63)" >&2 + continue + fi + read -p "Retype passphrase: " -s PASSPHRASE2 + echo + if [[ "$PASSPHRASE" != "$PASSPHRASE2" ]]; then + echo "Passphrases do not match." + else + break + fi + else + read -p "PSK: " PASSPHRASE + echo + if [[ ${#PASSPHRASE} -gt 0 && ${#PASSPHRASE} -ne 64 ]]; then + echo "ERROR: Invalid pre-shared-key length ${#PASSPHRASE} (expected 64)" >&2 + continue + fi + fi + done + else + read SSID + read PASSPHRASE + fi +fi + +if [[ "$SHARE_METHOD" != "none" ]] && ! is_interface $INTERNET_IFACE; then + echo "ERROR: '${INTERNET_IFACE}' is not an interface" >&2 + exit 1 +fi + +if [[ ${#SSID} -lt 1 || ${#SSID} -gt 32 ]]; then + echo "ERROR: Invalid SSID length ${#SSID} (expected 1..32)" >&2 + exit 1 +fi + +if [[ $USE_PSK -eq 0 ]]; then + if [[ ${#PASSPHRASE} -gt 0 && ${#PASSPHRASE} -lt 8 ]] || [[ ${#PASSPHRASE} -gt 63 ]]; then + echo "ERROR: Invalid passphrase length ${#PASSPHRASE} (expected 8..63)" >&2 + exit 1 + fi +elif [[ ${#PASSPHRASE} -gt 0 && ${#PASSPHRASE} -ne 64 ]]; then + echo "ERROR: Invalid pre-shared-key length ${#PASSPHRASE} (expected 64)" >&2 + exit 1 +fi + +if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^rtl[0-9].*$ ]]; then + if [[ -n "$PASSPHRASE" ]]; then + echo "WARN: Realtek drivers usually have problems with WPA1, enabling -w 2" >&2 + WPA_VERSION=2 + fi + echo "WARN: If AP doesn't work, please read: howto/realtek.md" >&2 +fi + +if [[ $NO_VIRT -eq 1 && "$WIFI_IFACE" == "$INTERNET_IFACE" ]]; then + echo -n "ERROR: You can not share your connection from the same" >&2 + echo " interface if you are using --no-virt option." >&2 + exit 1 +fi + +mutex_lock +trap "cleanup" EXIT +CONFDIR=$(mktemp -d /tmp/create_ap.${WIFI_IFACE}.conf.XXXXXXXX) +echo "Config dir: $CONFDIR" +echo "PID: $$" +echo $$ > $CONFDIR/pid + +# to make --list-running work from any user, we must give read +# permissions to $CONFDIR and $CONFDIR/pid +chmod 755 $CONFDIR +chmod 444 $CONFDIR/pid + +COMMON_CONFDIR=/tmp/create_ap.common.conf +mkdir -p $COMMON_CONFDIR + +if [[ "$SHARE_METHOD" == "nat" ]]; then + echo $INTERNET_IFACE > $CONFDIR/nat_internet_iface + cp_n /proc/sys/net/ipv4/conf/$INTERNET_IFACE/forwarding \ + $COMMON_CONFDIR/${INTERNET_IFACE}_forwarding +fi +cp_n /proc/sys/net/ipv4/ip_forward $COMMON_CONFDIR +if [[ -e /proc/sys/net/bridge/bridge-nf-call-iptables ]]; then + cp_n /proc/sys/net/bridge/bridge-nf-call-iptables $COMMON_CONFDIR +fi +mutex_unlock + +if [[ "$SHARE_METHOD" == "bridge" ]]; then + if is_bridge_interface $INTERNET_IFACE; then + BRIDGE_IFACE=$INTERNET_IFACE + else + BRIDGE_IFACE=$(alloc_new_iface br) + fi +fi + +if [[ $USE_IWCONFIG -eq 0 ]]; then + iw dev ${WIFI_IFACE} set power_save off +fi + +if [[ $NO_VIRT -eq 0 ]]; then + VWIFI_IFACE=$(alloc_new_iface ap) + + # in NetworkManager 0.9.9 and above we can set the interface as unmanaged without + # the need of MAC address, so we set it before we create the virtual interface. + if networkmanager_is_running && [[ $NM_OLDER_VERSION -eq 0 ]]; then + echo -n "Network Manager found, set ${VWIFI_IFACE} as unmanaged device... " + networkmanager_add_unmanaged ${VWIFI_IFACE} + # do not call networkmanager_wait_until_unmanaged because interface does not + # exist yet + echo "DONE" + fi + + if is_wifi_connected ${WIFI_IFACE}; then + WIFI_IFACE_FREQ=$(iw dev ${WIFI_IFACE} link | grep -i freq | awk '{print $2}') + WIFI_IFACE_CHANNEL=$(ieee80211_frequency_to_channel ${WIFI_IFACE_FREQ}) + echo -n "${WIFI_IFACE} is already associated with channel ${WIFI_IFACE_CHANNEL} (${WIFI_IFACE_FREQ} MHz)" + if is_5ghz_frequency $WIFI_IFACE_FREQ; then + FREQ_BAND=5 + else + FREQ_BAND=2.4 + fi + if [[ $WIFI_IFACE_CHANNEL -ne $CHANNEL ]]; then + echo ", fallback to channel ${WIFI_IFACE_CHANNEL}" + CHANNEL=$WIFI_IFACE_CHANNEL + else + echo + fi + fi + + VIRTDIEMSG="Maybe your WiFi adapter does not fully support virtual interfaces. + Try again with --no-virt." + echo -n "Creating a virtual WiFi interface... " + + if iw dev ${WIFI_IFACE} interface add ${VWIFI_IFACE} type __ap; then + # now we can call networkmanager_wait_until_unmanaged + networkmanager_is_running && [[ $NM_OLDER_VERSION -eq 0 ]] && networkmanager_wait_until_unmanaged ${VWIFI_IFACE} + echo "${VWIFI_IFACE} created." + else + VWIFI_IFACE= + die "$VIRTDIEMSG" + fi + OLD_MACADDR=$(get_macaddr ${VWIFI_IFACE}) + if [[ -z "$NEW_MACADDR" && $(get_all_macaddrs | grep -c ${OLD_MACADDR}) -ne 1 ]]; then + NEW_MACADDR=$(get_new_macaddr ${VWIFI_IFACE}) + fi + WIFI_IFACE=${VWIFI_IFACE} +else + OLD_MACADDR=$(get_macaddr ${WIFI_IFACE}) +fi + +mutex_lock +echo $WIFI_IFACE > $CONFDIR/wifi_iface +chmod 444 $CONFDIR/wifi_iface +mutex_unlock + +if [[ -n "$COUNTRY" && $USE_IWCONFIG -eq 0 ]]; then + iw reg set "$COUNTRY" +fi + +can_transmit_to_channel ${WIFI_IFACE} ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz." + +if networkmanager_exists && ! networkmanager_iface_is_unmanaged ${WIFI_IFACE}; then + echo -n "Network Manager found, set ${WIFI_IFACE} as unmanaged device... " + networkmanager_add_unmanaged ${WIFI_IFACE} + + if networkmanager_is_running; then + networkmanager_wait_until_unmanaged ${WIFI_IFACE} + fi + + echo "DONE" +fi + +[[ $HIDDEN -eq 1 ]] && echo "Access Point's SSID is hidden!" + +[[ $MAC_FILTER -eq 1 ]] && echo "MAC address filtering is enabled!" + +[[ $ISOLATE_CLIENTS -eq 1 ]] && echo "Access Point's clients will be isolated!" + +# hostapd config +cat << EOF > $CONFDIR/hostapd.conf +beacon_int=100 +ssid=${SSID} +interface=${WIFI_IFACE} +driver=${DRIVER} +channel=${CHANNEL} +ctrl_interface=$CONFDIR/hostapd_ctrl +ctrl_interface_group=0 +ignore_broadcast_ssid=$HIDDEN +ap_isolate=$ISOLATE_CLIENTS +EOF + +if [[ -n "$COUNTRY" ]]; then + cat << EOF >> $CONFDIR/hostapd.conf +country_code=${COUNTRY} +ieee80211d=1 +EOF +fi + +if [[ $FREQ_BAND == 2.4 ]]; then + echo "hw_mode=g" >> $CONFDIR/hostapd.conf +else + echo "hw_mode=a" >> $CONFDIR/hostapd.conf +fi + +if [[ $MAC_FILTER -eq 1 ]]; then + cat << EOF >> $CONFDIR/hostapd.conf +macaddr_acl=${MAC_FILTER} +accept_mac_file=${MAC_FILTER_ACCEPT} +EOF +fi + +if [[ $IEEE80211N -eq 1 ]]; then + cat << EOF >> $CONFDIR/hostapd.conf +ieee80211n=1 +ht_capab=${HT_CAPAB} +EOF +fi + +if [[ $IEEE80211AC -eq 1 ]]; then + echo "ieee80211ac=1" >> $CONFDIR/hostapd.conf +fi + +if [[ -n "$VHT_CAPAB" ]]; then + echo "vht_capab=${VHT_CAPAB}" >> $CONFDIR/hostapd.conf +fi + +if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]]; then + echo "wmm_enabled=1" >> $CONFDIR/hostapd.conf +fi + +if [[ -n "$PASSPHRASE" ]]; then + [[ "$WPA_VERSION" == "1+2" ]] && WPA_VERSION=3 + if [[ $USE_PSK -eq 0 ]]; then + WPA_KEY_TYPE=passphrase + else + WPA_KEY_TYPE=psk + fi + cat << EOF >> $CONFDIR/hostapd.conf +wpa=${WPA_VERSION} +wpa_${WPA_KEY_TYPE}=${PASSPHRASE} +wpa_key_mgmt=WPA-PSK +wpa_pairwise=TKIP CCMP +rsn_pairwise=CCMP +EOF +fi + +if [[ "$SHARE_METHOD" == "bridge" ]]; then + echo "bridge=${BRIDGE_IFACE}" >> $CONFDIR/hostapd.conf +elif [[ $NO_DNSMASQ -eq 0 ]]; then + # dnsmasq config (dhcp + dns) + DNSMASQ_VER=$(dnsmasq -v | grep -m1 -oE '[0-9]+(\.[0-9]+)*\.[0-9]+') + version_cmp $DNSMASQ_VER 2.63 + if [[ $? -eq 1 ]]; then + DNSMASQ_BIND=bind-interfaces + else + DNSMASQ_BIND=bind-dynamic + fi + if [[ "$DHCP_DNS" == "gateway" ]]; then + DHCP_DNS="$GATEWAY" + fi + cat << EOF > $CONFDIR/dnsmasq.conf +listen-address=${GATEWAY} +${DNSMASQ_BIND} +dhcp-range=${GATEWAY%.*}.1,${GATEWAY%.*}.254,255.255.255.0,24h +dhcp-option-force=option:router,${GATEWAY} +dhcp-option-force=option:dns-server,${DHCP_DNS} +EOF + MTU=$(get_mtu $INTERNET_IFACE) + [[ -n "$MTU" ]] && echo "dhcp-option-force=option:mtu,${MTU}" >> $CONFDIR/dnsmasq.conf + [[ $ETC_HOSTS -eq 0 ]] && echo no-hosts >> $CONFDIR/dnsmasq.conf + [[ -n "$ADDN_HOSTS" ]] && echo "addn-hosts=${ADDN_HOSTS}" >> $CONFDIR/dnsmasq.conf + if [[ "$SHARE_METHOD" == "none" && "$REDIRECT_TO_LOCALHOST" == "1" ]]; then + cat << EOF >> $CONFDIR/dnsmasq.conf +address=/#/$GATEWAY +EOF + fi +fi + +# initialize WiFi interface +if [[ $NO_VIRT -eq 0 && -n "$NEW_MACADDR" ]]; then + ip link set dev ${WIFI_IFACE} address ${NEW_MACADDR} || die "$VIRTDIEMSG" +fi + +ip link set down dev ${WIFI_IFACE} || die "$VIRTDIEMSG" +ip addr flush ${WIFI_IFACE} || die "$VIRTDIEMSG" + +if [[ $NO_VIRT -eq 1 && -n "$NEW_MACADDR" ]]; then + ip link set dev ${WIFI_IFACE} address ${NEW_MACADDR} || die +fi + +if [[ "$SHARE_METHOD" != "bridge" ]]; then + ip link set up dev ${WIFI_IFACE} || die "$VIRTDIEMSG" + ip addr add ${GATEWAY}/24 broadcast ${GATEWAY%.*}.255 dev ${WIFI_IFACE} || die "$VIRTDIEMSG" +fi + +# enable Internet sharing +if [[ "$SHARE_METHOD" != "none" ]]; then + echo "Sharing Internet using method: $SHARE_METHOD" + if [[ "$SHARE_METHOD" == "nat" ]]; then + iptables -w -t nat -I POSTROUTING -s ${GATEWAY%.*}.0/24 ! -o ${WIFI_IFACE} -j MASQUERADE || die + iptables -w -I FORWARD -i ${WIFI_IFACE} -s ${GATEWAY%.*}.0/24 -j ACCEPT || die + iptables -w -I FORWARD -i ${INTERNET_IFACE} -d ${GATEWAY%.*}.0/24 -j ACCEPT || die + echo 1 > /proc/sys/net/ipv4/conf/$INTERNET_IFACE/forwarding || die + echo 1 > /proc/sys/net/ipv4/ip_forward || die + # to enable clients to establish PPTP connections we must + # load nf_nat_pptp module + modprobe nf_nat_pptp > /dev/null 2>&1 + elif [[ "$SHARE_METHOD" == "bridge" ]]; then + # disable iptables rules for bridged interfaces + if [[ -e /proc/sys/net/bridge/bridge-nf-call-iptables ]]; then + echo 0 > /proc/sys/net/bridge/bridge-nf-call-iptables + fi + + # to initialize the bridge interface correctly we need to do the following: + # + # 1) save the IPs and route table of INTERNET_IFACE + # 2) if NetworkManager is running set INTERNET_IFACE as unmanaged + # 3) create BRIDGE_IFACE and attach INTERNET_IFACE to it + # 4) set the previously saved IPs and route table to BRIDGE_IFACE + # + # we need the above because BRIDGE_IFACE is the master interface from now on + # and it must know where is connected, otherwise connection is lost. + if ! is_bridge_interface $INTERNET_IFACE; then + echo -n "Create a bridge interface... " + OLD_IFS="$IFS" + IFS=$'\n' + + IP_ADDRS=( $(ip addr show $INTERNET_IFACE | grep -A 1 -E 'inet[[:blank:]]' | paste - -) ) + ROUTE_ADDRS=( $(ip route show dev $INTERNET_IFACE) ) + + IFS="$OLD_IFS" + + if networkmanager_is_running; then + networkmanager_add_unmanaged $INTERNET_IFACE + networkmanager_wait_until_unmanaged $INTERNET_IFACE + fi + + # create bridge interface + ip link add name $BRIDGE_IFACE type bridge || die + ip link set dev $BRIDGE_IFACE up || die + # set 0ms forward delay + echo -n 0 > /sys/class/net/$BRIDGE_IFACE/bridge/forward_delay + + # attach internet interface to bridge interface + ip link set dev $INTERNET_IFACE promisc on || die + ip link set dev $INTERNET_IFACE up || die + ip link set dev $INTERNET_IFACE master $BRIDGE_IFACE || die + + ip addr flush $INTERNET_IFACE + for x in "${IP_ADDRS[@]}"; do + x="${x/inet/}" + x="${x/secondary/}" + x="${x/dynamic/}" + x=$(echo $x | sed 's/\([0-9]\)sec/\1/g') + x="${x/${INTERNET_IFACE}/}" + ip addr add $x dev $BRIDGE_IFACE || die + done + + # remove any existing entries that were added from 'ip addr add' + ip route flush dev $INTERNET_IFACE + ip route flush dev $BRIDGE_IFACE + + # we must first add the entries that specify the subnets and then the + # gateway entry, otherwise 'ip addr add' will return an error + for x in "${ROUTE_ADDRS[@]}"; do + [[ "$x" == default* ]] && continue + ip route add $x dev $BRIDGE_IFACE || die + done + + for x in "${ROUTE_ADDRS[@]}"; do + [[ "$x" != default* ]] && continue + ip route add $x dev $BRIDGE_IFACE || die + done + + echo "$BRIDGE_IFACE created." + fi + fi +else + echo "No Internet sharing" +fi + +# start dhcp + dns (optional) +if [[ "$SHARE_METHOD" != "bridge" ]]; then + if [[ $NO_DNS -eq 0 ]]; then + DNS_PORT=5353 + iptables -w -I INPUT -p tcp -m tcp --dport $DNS_PORT -j ACCEPT || die + iptables -w -I INPUT -p udp -m udp --dport $DNS_PORT -j ACCEPT || die + iptables -w -t nat -I PREROUTING -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} \ + -p tcp -m tcp --dport 53 -j REDIRECT --to-ports $DNS_PORT || die + iptables -w -t nat -I PREROUTING -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} \ + -p udp -m udp --dport 53 -j REDIRECT --to-ports $DNS_PORT || die + else + DNS_PORT=0 + fi + + if [[ $NO_DNSMASQ -eq 0 ]]; then + iptables -w -I INPUT -p udp -m udp --dport 67 -j ACCEPT || die + + if which complain > /dev/null 2>&1; then + # openSUSE's apparmor does not allow dnsmasq to read files. + # remove restriction. + complain dnsmasq + fi + + umask 0033 + dnsmasq -C $CONFDIR/dnsmasq.conf -x $CONFDIR/dnsmasq.pid -l $CONFDIR/dnsmasq.leases -p $DNS_PORT || die + umask $SCRIPT_UMASK + fi +fi + +# start access point +echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl" + +if [[ $NO_HAVEGED -eq 0 ]]; then + haveged_watchdog & + HAVEGED_WATCHDOG_PID=$! +fi + +# start hostapd (use stdbuf when available for no delayed output in programs that redirect stdout) +STDBUF_PATH=`which stdbuf` +if [ $? -eq 0 ]; then + STDBUF_PATH=$STDBUF_PATH" -oL" +fi +$STDBUF_PATH $HOSTAPD $HOSTAPD_DEBUG_ARGS $CONFDIR/hostapd.conf & +HOSTAPD_PID=$! +echo $HOSTAPD_PID > $CONFDIR/hostapd.pid + +if ! wait $HOSTAPD_PID; then + echo -e "\nError: Failed to run hostapd, maybe a program is interfering." >&2 + if networkmanager_is_running; then + echo "If an error like 'n80211: Could not configure driver mode' was thrown" >&2 + echo "try running the following before starting create_ap:" >&2 + if [[ $NM_OLDER_VERSION -eq 1 ]]; then + echo " nmcli nm wifi off" >&2 + else + echo " nmcli r wifi off" >&2 + fi + echo " rfkill unblock wlan" >&2 + fi + die +fi + +clean_exit + +# Local Variables: +# tab-width: 4 +# indent-tabs-mode: nil +# End: + +# vim: et sts=4 sw=4 diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.conf b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.conf new file mode 100644 index 0000000..9f55f09 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.conf @@ -0,0 +1,28 @@ +CHANNEL=default +GATEWAY=10.0.0.1 +WPA_VERSION=2 +ETC_HOSTS=0 +DHCP_DNS=gateway +NO_DNS=0 +NO_DNSMASQ=0 +HIDDEN=0 +MAC_FILTER=0 +MAC_FILTER_ACCEPT=/etc/hostapd/hostapd.accept +ISOLATE_CLIENTS=0 +SHARE_METHOD=nat +IEEE80211N=0 +IEEE80211AC=0 +HT_CAPAB=[HT40+] +VHT_CAPAB= +DRIVER=nl80211 +NO_VIRT=0 +COUNTRY= +FREQ_BAND=2.4 +NEW_MACADDR= +DAEMONIZE=0 +NO_HAVEGED=0 +WIFI_IFACE=wlan0 +INTERNET_IFACE=eth0 +SSID=MyAccessPoint +PASSPHRASE=12345678 +USE_PSK=0 diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.openrc b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.openrc new file mode 100644 index 0000000..9bb4876 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.openrc @@ -0,0 +1,11 @@ +#!/sbin/openrc-run + +name=$RC_SVCNAME + +cfgfile=/etc/$RC_SVCNAME.conf +pidfile=/run/$RC_SVCNAME.pid + +command=/usr/bin/create_ap +command_args="--config $cfgfile" +command_args_background="--daemon --pidfile $pidfile" +stopsig=USR1 diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.service.template b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.service.template new file mode 100644 index 0000000..347a8a4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/create_ap.service.template @@ -0,0 +1,13 @@ +[Unit] +Description=Create AP Service +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/lnxrouter -n --ap wlan0 SSID -p pibot_ap --no-virt -g 12 +KillSignal=SIGINT +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/howto/realtek.md b/Code/RK3588/PIBot_ROS/third_party/create_ap/howto/realtek.md new file mode 100644 index 0000000..266d818 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/howto/realtek.md @@ -0,0 +1,74 @@ +## Try this first + +If you are facing any problems with Realtek adapters (e.g. Edimax EW-7811Un) +first try to run create_ap with `-w 2` (i.e. use WPA2 only) or use it +without passphrase. If you are still facing any problems or you want to +also use WPA1, then follow the instructions below. + +NOTE: The instructions below are only valid for Realtek adapters with 8192 chipset. + +## Before installation + +If you're using ArchLinux, run: + +``` +pacman -S base-devel linux-headers dkms git +pacman -R hostapd +``` + +If you're using Debian, Ubuntu, or any Debian-based distribution, run: + +``` +apt-get install build-essential linux-headers-generic dkms git +apt-get remove hostapd +apt-get build-dep hostapd +``` + +## Install driver + +The driver in the mainline of Linux kernel doesn't work well with the 8192 adapters. +For this reason you need to install the driver that is provided from Realtek. Their +driver can not be compiled with newer kernels, but since it was an open-source +release under GPL license some people were able to fixed it and make it compile. + +With the following commands you can install a fixed version of Realtek's driver: + +``` +git clone https://github.com/pvaret/rtl8192cu-fixes.git +dkms add rtl8192cu-fixes +dkms install 8192cu/1.9 +cp rtl8192cu-fixes/blacklist-native-rtl8192.conf /etc/modprobe.d +cp rtl8192cu-fixes/8192cu-disable-power-management.conf /etc/modprobe.d +``` + +After installation, unload the previous driver and load the new one, or just reboot. + +## Install hostapd + +Realtek's driver is using an old subsystem which is called `wireless-extensions` +(or `wext`). Hostapd works only with the new subsystem (which is called `nl80211`). +For this reason Realtek wrote a patch for hostapd. You can install it with the +following commands: + +If you have ArchLinux install [hostapd-rtl871xdrv](https://aur.archlinux.org/packages/hostapd-rtl871xdrv) +from AUR or just run: + +``` +yaourt -S hostapd-rtl871xdrv +``` + +If you're using any other distribution, run: + +``` +git clone https://github.com/pritambaral/hostapd-rtl871xdrv.git +wget http://w1.fi/releases/hostapd-2.2.tar.gz +tar zxvf hostapd-2.2.tar.gz +cd hostapd-2.2 +patch -p1 -i ../hostapd-rtl871xdrv/rtlxdrv.patch +cp ../hostapd-rtl871xdrv/driver_* src/drivers +cd hostapd +cp defconfig .config +echo CONFIG_DRIVER_RTW=y >> .config +make +make install +``` diff --git a/Code/RK3588/PIBot_ROS/third_party/create_ap/lnxrouter b/Code/RK3588/PIBot_ROS/third_party/create_ap/lnxrouter new file mode 100644 index 0000000..32d2729 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/create_ap/lnxrouter @@ -0,0 +1,2131 @@ +#!/bin/bash + +VERSION=0.6.3 +PROGNAME="$(basename $0)" + +export LC_ALL=C + +SCRIPT_UMASK=0122 +umask $SCRIPT_UMASK + +phead() { + echo "linux-router $VERSION (https://github.com/garywill/linux-router)" +} +usage() { + phead + cat << EOF +Released under LGPL, with no warranty. Use on your own risk. + +Usage: $PROGNAME + +Options: + -h, --help Show this help + --version Print version number + + -i Interface to make NATed sub-network, + and to provide Internet to + (To create Wifi hotspot use '--ap' instead) + -o Specify an inteface to provide Internet from. + (Note using this with default DNS option may leak + queries to other interfaces) + -n Do not provide Internet (See Notice 1) + --ban-priv Disallow clients to access my private network + + -g This host's IPv4 address in subnet (mask is /24) + (example: '192.168.5.1' or '5' shortly) + -6 Enable IPv6 (NAT) + --no4 Disable IPv4 Internet (not forwarding IPv4) + (See Notice 1). Usually used with '-6' + + --p6 Set IPv6 LAN address prefix (length 64) + (example: 'fd00:0:0:5::' or '5' shortly) + Using this enables '-6' + + --dns || + DNS server's upstream DNS. + Use ',' to seperate multiple servers + (default: use /etc/resolve.conf) + (Note IPv6 addresses need '[]' around) + --no-dns Do not serve DNS + --no-dnsmasq Disable dnsmasq server (DHCP, DNS, RA) + --catch-dns Transparent DNS proxy, redirect packets(TCP/UDP) + whose destination port is 53 to this host + --log-dns Show DNS query log + --dhcp-dns |no + Set IPv4 DNS offered by DHCP (default: this host) + --dhcp-dns6 |no + Set IPv6 DNS offered by DHCP (RA) + (default: this host) + (Note IPv6 addresses need '[]' around) + --hostname DNS server associate this name with this host. + Use '-' to read name from /etc/hostname + -d DNS server will take into account /etc/hosts + -e DNS server will take into account additional + hosts file + + --mac Set MAC address + --random-mac Use random MAC address + + --tp Transparent proxy, + redirect non-LAN TCP and UDP traffic to port. + (usually used with '--dns') + + Wifi hotspot options: + --ap + Create Wifi access point + -p, --password + Wifi password + --qr Show Wifi QR code in terminal + + --hidden Hide access point (not broadcast SSID) + --no-virt Do not create virtual interface + Using this you can't use same wlan interface + for both Internet and AP + -c Channel number (default: 1) + --country Set two-letter country code for regularity + (example: US) + --freq-band Set frequency band: 2.4 or 5 (default: 2.4) + --driver Choose your WiFi adapter driver (default: nl80211) + -w '2' for WPA2, '1' for WPA, '1+2' for both + (default: 2) + --psk Use 64 hex digits pre-shared-key instead of + passphrase + --mac-filter Enable Wifi hotspot MAC address filtering + --mac-filter-accept Location of Wifi hotspot MAC address filter list + (defaults to /etc/hostapd/hostapd.accept) + --hostapd-debug 1 or 2. Passes -d or -dd to hostapd + --isolate-clients Disable wifi communication between clients + + --ieee80211n Enable IEEE 802.11n (HT) + --ieee80211ac Enable IEEE 802.11ac (VHT) + --ht_capab HT capabilities (default: [HT40+]) + --vht_capab VHT capabilities + + --no-haveged Do not run haveged automatically when needed + + Instance managing: + --daemon Run in background + -l, --list-running Show running instances + --lc, --list-clients + List clients of an instance. Or list neighbors of + an interface, even if it isn't handled by us. + (passive mode) + --stop Stop a running instance + For you can use PID or subnet interface name. + You can get them with '--list-running' + + Notice 1: This script assume your host's default policy won't forward + packets, so the script won't explictly ban forwarding in any + mode. In some unexpected case may cause unwanted packets + leakage between 2 networks, which you should be aware of if you + want isolated network + +Examples: + $PROGNAME -i eth1 + $PROGNAME --ap wlan0 MyAccessPoint + $PROGNAME --ap wlan0 MyAccessPoint -p MyPassPhrase + $PROGNAME -i eth1 --tp --dns +EOF +} + +check_empty_option(){ + if [[ "$1" == "" ]]; then + usage + exit 0 + fi +} + + +define_global_variables(){ + # user options + GATEWAY= # IPv4 address for this host + PREFIX6= # IPv6 LAN address prefix for this host + IID6=1 # IPv6 LAN ID for this host + IPV6=0 # enable ipv6 + NO4=0 # no IPv4 Internet + BANLAN=0 # ban clients from accessing private addresses + DHCP_DNS=gateway # which ipv4 DNS the DHCP gives clients + DHCP_DNS6=gateway # which ipv6 DNS the DHCP gives clients + dnsmasq_NO_DNS=0 # disable dns server + NO_DNSMASQ=0 # disable dnsmasq (dns and dhcp) + CATCH_DNS=0 # catch clients 53 port packets + SHOW_DNS_QUERY=0 # log dns + ETC_HOSTS=0 + ADDN_HOSTS= + CONN_IFACE= # which interface user choose to use to create network + INTERNET_IFACE= # which interface to get Internet from + THISHOSTNAME= # this host's name the DNS tells clients + TP_PORT= # transparent proxy port + DNS= # upstream DNS + MAC_USE_RANDOM=0 + NEW_MACADDR= + DAEMONIZE=0 + + # script variables + SUBNET_IFACE= # which interface to create network + SHARE_METHOD=nat + OLD_MACADDR= + + + ##### wifi hotspot + # user options + HIDDEN=0 # hidden wifi hotspot + WIFI_IFACE= + CHANNEL=default + WPA_VERSION=2 + MAC_FILTER=0 + MAC_FILTER_ACCEPT=/etc/hostapd/hostapd.accept + IEEE80211N=0 + IEEE80211AC=0 + HT_CAPAB='[HT40+]' + VHT_CAPAB= + DRIVER=nl80211 + NO_VIRT=0 # not use virtual interface + COUNTRY= + FREQ_BAND=2.4 + NO_HAVEGED=0 + HOSTAPD_DEBUG_ARGS= + USE_PSK=0 + ISOLATE_CLIENTS=0 + QR=0 # show wifi qr + + # script variables + VWIFI_IFACE= # virtual wifi interface name, if created + AP_IFACE= # can be VWIFI_IFACE or WIFI_IFACE + USE_IWCONFIG=0 # some device can't use iw + + ####### + + #-- to deal with info of a running instance. then will exit + LIST_RUNNING=0 + STOP_ID= + LIST_CLIENTS_ID= + + # -- variables for running + CONFDIR= + NM_RUNNING=0 + NM_UNM_LIST= # it's called "list" but for now one interface +} + +parse_user_options(){ + while [[ -n "$1" ]]; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + --version) + echo "$VERSION" + exit 0 + ;; + -i) + shift + CONN_IFACE="$1" + shift + ;; + -o) + shift + INTERNET_IFACE="$1" + shift + echo "" + echo "WARN: Since you're using in this mode, make sure you've read Notice 1" >&2 + echo "" + ;; + -n) + shift + SHARE_METHOD=none + echo "" + echo "WARN: Since you're using in this mode, make sure you've read Notice 1" >&2 + echo "" + ;; + --ban-priv) + shift + BANLAN=1 + ;; + --tp) + shift + TP_PORT="$1" + SHARE_METHOD=redsocks + shift + ;; + + + -g) + shift + GATEWAY="$1" + shift + ;; + -6) + shift + IPV6=1 + ;; + --no4) + shift + NO4=1 + echo "" + echo "WARN: Since you're using in this mode, make sure you've read Notice 1" >&2 + echo "" + ;; + --p6) + shift + PREFIX6="$1" + IPV6=1 + shift + ;; + --mac) + shift + NEW_MACADDR="$1" + shift + ;; + --random-mac) + shift + MAC_USE_RANDOM=1 + ;; + + --dns) + shift + DNS="$1" + shift + ;; + --no-dns) + shift + dnsmasq_NO_DNS=1 + ;; + --no-dnsmasq) + shift + NO_DNSMASQ=1 + ;; + --dhcp-dns) + shift + DHCP_DNS="$1" + shift + ;; + --dhcp-dns6) + shift + DHCP_DNS6="$1" + shift + ;; + --catch-dns) + shift + CATCH_DNS=1 + ;; + --log-dns) + shift + SHOW_DNS_QUERY=1 + ;; + --hostname) + shift + THISHOSTNAME="$1" + shift + ;; + -d) + shift + ETC_HOSTS=1 + ;; + -e) + shift + ADDN_HOSTS="$1" + shift + ;; + + --isolate-clients) + shift + ISOLATE_CLIENTS=1 + ;; + + --ap) + shift + WIFI_IFACE="$1" + shift + SSID="$1" + shift + ;; + -p|--password) + shift + PASSPHRASE="$1" + shift + ;; + --qr) + shift + QR=1 + ;; + + + --hidden) + shift + HIDDEN=1 + ;; + --mac-filter) + shift + MAC_FILTER=1 + ;; + --mac-filter-accept) + shift + MAC_FILTER_ACCEPT="$1" + shift + ;; + + -c) + shift + CHANNEL="$1" + shift + ;; + -w) + shift + WPA_VERSION="$1" + [[ "$WPA_VERSION" == "2+1" ]] && WPA_VERSION=1+2 + shift + ;; + + --ieee80211n) + shift + IEEE80211N=1 + ;; + --ieee80211ac) + shift + IEEE80211AC=1 + ;; + --ht_capab) + shift + HT_CAPAB="$1" + shift + ;; + --vht_capab) + shift + VHT_CAPAB="$1" + shift + ;; + --driver) + shift + DRIVER="$1" + shift + ;; + --no-virt) + shift + NO_VIRT=1 + ;; + + --country) + shift + COUNTRY="$1" + shift + ;; + --freq-band) + shift + FREQ_BAND="$1" + shift + ;; + --no-haveged) + shift + NO_HAVEGED=1 + ;; + --hostapd-debug) + shift + if [ "x$1" = "x1" ]; then + HOSTAPD_DEBUG_ARGS="-d" + elif [ "x$1" = "x2" ]; then + HOSTAPD_DEBUG_ARGS="-dd" + else + printf "Error: argument for --hostapd-debug expected 1 or 2, got %s\n" "$1" + exit 1 + fi + shift + ;; + --psk) + shift + USE_PSK=1 + ;; + + --daemon) + shift + DAEMONIZE=1 + ;; + --stop) + shift + STOP_ID="$1" + shift + ;; + -l|--list-running) + shift + LIST_RUNNING=1 + ;; + --lc|--list-clients) + shift + LIST_CLIENTS_ID="$1" + shift + ;; + + *) + echo "Invalid parameter: $1" 1>&2 + exit 1 + ;; + esac + done +} + + +# seperate ip and port +sep_ip_port() { + # usage: sep_ip_port + # input can be: + # port (ip is 127.0.0.1) + # ipv4 + # [ipv6] + # ipv4:port + # [ipv6]:port + local IP + local PORT + local INPUT + INPUT="$1" + if (echo "$INPUT" | grep '\.' >/dev/null 2>&1) ;then + if (echo "$INPUT" | grep ':' >/dev/null 2>&1) ;then + # ipv4 + port + IP="$(echo $INPUT | cut -d: -f1)" + PORT="$(echo $INPUT | cut -d: -f2)" + else + # ipv4 + IP="$INPUT" + fi + elif (echo "$INPUT" | grep '\]' >/dev/null 2>&1) ;then + if (echo "$INPUT" | grep '\]\:' >/dev/null 2>&1) ;then + # ipv6 + port + IP="$(echo $INPUT | cut -d']' -f1 | cut -d'[' -f2)" + PORT="$(echo $INPUT | cut -d']' -f2 |cut -d: -f2)" + else + # ipv6 + IP="$(echo $INPUT | cut -d']' -f1 | cut -d'[' -f2)" + fi + else + # port + IP='127.0.0.1' + PORT="$INPUT" + fi + printf -v "$2" %s "$IP" + printf -v "$3" %s "$PORT" +} + +#========================= +is_interface() { + [[ -z "$1" ]] && return 1 + [[ -d "/sys/class/net/${1}" ]] +} + +get_interface_phy_device() { # only for wifi interface + local x + for x in /sys/class/ieee80211/*; do + [[ ! -e "$x" ]] && continue + if [[ "${x##*/}" = "$1" ]]; then + echo "$1" + return 0 + elif [[ -e "$x/device/net/$1" ]]; then + echo ${x##*/} + return 0 + elif [[ -e "$x/device/net:$1" ]]; then + echo ${x##*/} + return 0 + fi + done + echo "Failed to get phy interface" >&2 + return 1 +} + +get_adapter_info() { # only for wifi interface + local iPHY + iPHY=$(get_interface_phy_device "$1") + [[ $? -ne 0 ]] && return 1 + iw phy $iPHY info +} + +get_adapter_kernel_module() { + local MODULE + MODULE=$(readlink -f "/sys/class/net/$1/device/driver/module") + echo ${MODULE##*/} +} + +can_be_sta_and_ap() { + # iwconfig does not provide this information, assume false + [[ $USE_IWCONFIG -eq 1 ]] && return 1 + if [[ "$(get_adapter_kernel_module "$1")" == "brcmfmac" ]]; then + echo "WARN: brmfmac driver doesn't work properly with virtual interfaces and" >&2 + echo " it can cause kernel panic. For this reason we disallow virtual" >&2 + echo " interfaces for your adapter." >&2 + echo " For more info: https://github.com/oblique/create_ap/issues/203" >&2 + return 1 + fi + get_adapter_info "$1" | grep -E '{.* managed.* AP.*}' > /dev/null 2>&1 && return 0 + get_adapter_info "$1" | grep -E '{.* AP.* managed.*}' > /dev/null 2>&1 && return 0 + return 1 +} + +can_be_ap() { + # iwconfig does not provide this information, assume true + [[ $USE_IWCONFIG -eq 1 ]] && return 0 + get_adapter_info "$1" | grep -E '\* AP$' > /dev/null 2>&1 && return 0 + return 1 +} + +can_transmit_to_channel() { + local IFACE CHANNEL_NUM CHANNEL_INFO + IFACE=$1 + CHANNEL_NUM=$2 + + if [[ $USE_IWCONFIG -eq 0 ]]; then + if [[ $FREQ_BAND == 2.4 ]]; then + CHANNEL_INFO=$(get_adapter_info ${IFACE} | grep " 24[0-9][0-9] MHz \[${CHANNEL_NUM}\]") + else + CHANNEL_INFO=$(get_adapter_info ${IFACE} | grep " \(49[0-9][0-9]\|5[0-9]\{3\}\) MHz \[${CHANNEL_NUM}\]") + fi + [[ -z "${CHANNEL_INFO}" ]] && return 1 + [[ "${CHANNEL_INFO}" == *no\ IR* ]] && return 1 + [[ "${CHANNEL_INFO}" == *disabled* ]] && return 1 + return 0 + else + CHANNEL_NUM=$(printf '%02d' ${CHANNEL_NUM}) + CHANNEL_INFO=$(iwlist ${IFACE} channel | grep -E "Channel[[:blank:]]${CHANNEL_NUM}[[:blank:]]?:") + [[ -z "${CHANNEL_INFO}" ]] && return 1 + return 0 + fi +} + +# taken from iw/util.c +ieee80211_frequency_to_channel() { + local FREQ=$1 + if [[ $FREQ -eq 2484 ]]; then + echo 14 + elif [[ $FREQ -lt 2484 ]]; then + echo $(( ($FREQ - 2407) / 5 )) + elif [[ $FREQ -ge 4910 && $FREQ -le 4980 ]]; then + echo $(( ($FREQ - 4000) / 5 )) + elif [[ $FREQ -le 45000 ]]; then + echo $(( ($FREQ - 5000) / 5 )) + elif [[ $FREQ -ge 58320 && $FREQ -le 64800 ]]; then + echo $(( ($FREQ - 56160) / 2160 )) + else + echo 0 + fi +} + +is_5ghz_frequency() { + [[ $1 =~ ^(49[0-9]{2})|(5[0-9]{3})$ ]] +} + +is_interface_wifi_connected() { + if [[ $USE_IWCONFIG -eq 0 ]]; then + iw dev "$1" link 2>&1 | grep -E '^Connected to' > /dev/null 2>&1 && return 0 + else + iwconfig "$1" 2>&1 | grep -E 'Access Point: [0-9a-fA-F]{2}:' > /dev/null 2>&1 && return 0 + fi + return 1 +} + + +is_unicast_macaddr() { + local x + x=$(echo "$1" | cut -d: -f1) + x=$(printf '%d' "0x${x}") + [[ $(expr $x % 2) -eq 0 ]] +} + +get_interface_mac() { + is_interface "$1" || return + cat "/sys/class/net/${1}/address" +} + +alloc_new_vface_name() { # only for wifi + local i=0 + local v_iface_name= + while :; do + v_iface_name="x$i${WIFI_IFACE}" + if ! is_interface ${v_iface_name} && [[ ! -f $COMMON_CONFDIR/vfaces/${v_iface_name} ]]; then + mkdir -p $COMMON_CONFDIR/vfaces + touch $COMMON_CONFDIR/vfaces/${v_iface_name} + echo "${v_iface_name}" + return + fi + i=$((i + 1)) + done +} + +dealloc_vface_name() { + rm -f $COMMON_CONFDIR/vfaces/$1 +} + +#====== + +get_all_mac_in_system() { + cat /sys/class/net/*/address +} + +get_new_macaddr_according_to_existing() { + local REALDEV OLDMAC NEWMAC LAST_BYTE i + REALDEV=$1 + OLDMAC=$(get_interface_mac "$REALDEV") + NEWMAC="" + LAST_BYTE=$(printf %d 0x${OLDMAC##*:}) + for i in {10..240}; do + NEWMAC="${OLDMAC%:*}:$(printf %02x $(( ($LAST_BYTE + $i) % 256 )))" + (get_all_mac_in_system | grep "$NEWMAC" > /dev/null 2>&1) || break + done + echo "$NEWMAC" +} + +generate_random_mac() { + local r1 r2 r3 r4 r5 r6 + local RAND_MAC + while :; do + r1=$( printf "%02x" $(($RANDOM%256/4*4)) ) + r2=$( printf "%02x" $(($RANDOM%256)) ) + r3=$( printf "%02x" $(($RANDOM%256)) ) + r4=$( printf "%02x" $(($RANDOM%256)) ) + r5=$( printf "%02x" $(($RANDOM%256)) ) + r6=$( printf "%02x" $(($RANDOM%256)) ) + RAND_MAC="$r1:$r2:$r3:$r4:$r5:$r6" + ( ! ip link | grep "link" | grep $RAND_MAC > /dev/null 2>&1 ) && \ + ( ! ip maddress | grep "link" | grep $RAND_MAC > /dev/null 2>&1 ) && \ + ( ! ip neigh | grep "lladdr $RAND_MAC" > /dev/null 2>&1 ) && \ + ( ! get_all_mac_in_system | grep $RAND_MAC ) && \ + break + done + echo "$RAND_MAC" +} + + +is_ip4_lan_range_available() { # checks 192.168.x.x + ( ip -4 address | grep "inet 192\.168\.$1\." > /dev/null 2>&1 ) && return 1 + ( ip -4 route | grep "^192\.168\.$1\." > /dev/null 2>&1 ) && return 1 + ( ip -4 route get 192.168.$1.0 2>&1 | grep -E "\bvia\b|\bunreachable\b" > /dev/null 2>&1 ) && \ + ( ip -4 route get 192.168.$1.255 2>&1 | grep -E "\bvia\b|\bunreachable\b" > /dev/null 2>&1 ) && return 0 + return 1 +} +is_ip6_lan_range_available() { # checks fdxx:: + ( ip -6 address | grep -i "inet6 fd$1:$2$3:$4$5:$6$7:" > /dev/null 2>&1 ) && return 1 + ( ip -6 route | grep -i "^fd$1:$2$3:$4$5:$6$7:" > /dev/null 2>&1 ) && return 1 + ( ip -6 route get fd$1:$2$3:$4$5:$6$7:: 2>&1 | grep -E "\bvia\b|\bunreachable\b" > /dev/null 2>&1 ) && \ + ( ip -6 route get fd$1:$2$3:$4$5:$6$7:ffff:ffff:ffff:ffff 2>&1 | grep -E "\bvia\b|\bunreachable\b" > /dev/null 2>&1 ) && return 0 + return 1 +} + +generate_random_ip4() { + local random_ip4 + while :; do + random_ip4=$(($RANDOM%256)) + is_ip4_lan_range_available $random_ip4 && break + done + echo "192.168.$random_ip4.1" +} +generate_random_lan_ip6_prefix() { + local r1 r2 r3 r4 r5 r6 r7 + while :; do + r1=$( printf "%x" $(($RANDOM%240+16)) ) + r2=$( printf "%x" $(($RANDOM%240+16)) ) + r3=$( printf "%x" $(($RANDOM%240+16)) ) + r4=$( printf "%x" $(($RANDOM%240+16)) ) + r5=$( printf "%x" $(($RANDOM%240+16)) ) + r6=$( printf "%x" $(($RANDOM%240+16)) ) + r7=$( printf "%x" $(($RANDOM%240+16)) ) + is_ip6_lan_range_available $r1 $r2 $r3 $r4 $r5 $r6 $r7 && break + done + echo "fd$r1:$r2$r3:$r4$r5:$r6$r7::" +} + + + +# start haveged when needed +haveged_watchdog() { + local show_warn=1 + while :; do + if [[ $(cat /proc/sys/kernel/random/entropy_avail) -lt 1000 ]]; then + if ! which haveged > /dev/null 2>&1; then + if [[ $show_warn -eq 1 ]]; then + echo "WARN: Low entropy detected. We recommend you to install \`haveged'" 1>&2 + show_warn=0 + fi + elif ! pidof haveged > /dev/null 2>&1; then # TODO judge zombie ? + echo "Low entropy detected, starting haveged" 1>&2 + # boost low-entropy + haveged -w 1024 -p $COMMON_CONFDIR/haveged.pid + fi + fi + sleep 2 + done +} +pid_watchdog() { + local PID="$1" + local SLEEP="$2" + local ERR_MSG="$3" + local ST + while true + do + if [[ -e "/proc/$PID" ]]; then + ST="$(cat "/proc/$PID/status" | grep "^State:" | awk '{print $2}')" + if [[ "$ST" != 'Z' ]]; then + sleep $SLEEP + continue + fi + fi + die "$ERR_MSG" + done + +} +#======== + + +# only support NetworkManager >= 0.9.9 +is_nm_running() { + if (which nmcli >/dev/null 2>&1 ) && (nmcli -t -f RUNNING g 2>&1 | grep -E '^running$' >/dev/null 2>&1 ) ; then + echo 1 + else + echo 0 + fi +} + +nm_knows() { + (nmcli dev show $1 | grep -E "^GENERAL.STATE:" >/dev/null 2>&1 ) && return 0 # nm sees + return 1 # nm doesn't see this interface +} +nm_get_manage() { # get an interface's managed state + local s + s=$(nmcli dev show $1 | grep -E "^GENERAL.STATE:") || return 2 # no such interface + (echo $s | grep "unmanaged" >/dev/null 2>&1) && return 1 # unmanaged + return 0 # managed +} +nm_set_unmanaged() { + while ! nm_knows $1 ; do # wait for virtual wifi interface seen by NM + sleep 0.5 + done + if nm_get_manage $1 ;then + echo "Set $1 unmanaged by NetworkManager" + nmcli dev set $1 managed no || die "Failed to set $1 unmanaged by NetworkManager" + NM_UNM_LIST=$1 + sleep 1 + fi +} + +nm_set_managed() { + nmcli dev set $1 managed yes + NM_UNM_LIST= +} +nm_restore_manage() { + if [[ $NM_UNM_LIST ]]; then + echo "Restore $NM_UNM_LIST managed by NetworkManager" + nm_set_managed $NM_UNM_LIST + sleep 0.5 + fi +} +#========= +check_iptables() +{ + echo + iptables --version + + if which firewall-cmd > /dev/null 2>&1; then + if [[ "$(firewall-cmd --state)" == "running" ]]; then + echo "firewalld is running ($(firewall-cmd --version))" + #echo "firewalld version " + fi + fi +} +iptables_() +{ + # NETFILTER_XT_MATCH_COMMENT would be a env variable if user wants to disable '-m comment' + if [[ "$NETFILTER_XT_MATCH_COMMENT" == "0" ]]; then + iptables -w $@ + else + iptables -w $@ -m comment --comment "lnxrouter-$$-$SUBNET_IFACE" + fi + return $? +} +ip6tables_() +{ + if [[ "$NETFILTER_XT_MATCH_COMMENT" == "0" ]]; then + ip6tables -w $@ + else + ip6tables -w $@ -m comment --comment "lnxrouter-$$-$SUBNET_IFACE" + fi + return $? +} + +start_nat() { + if [[ $INTERNET_IFACE ]]; then + IPTABLES_NAT_OUT="-o ${INTERNET_IFACE}" + IPTABLES_NAT_IN="-i ${INTERNET_IFACE}" + MASQUERADE_NOTOUT="" + else + MASQUERADE_NOTOUT="! -o ${SUBNET_IFACE}" + fi + echo + echo "iptables: NAT " + if [[ $NO4 -eq 0 ]]; then + iptables_ -v -t nat -I POSTROUTING -s ${GATEWAY%.*}.0/24 $IPTABLES_NAT_OUT $MASQUERADE_NOTOUT ! -d ${GATEWAY%.*}.0/24 -j MASQUERADE || die + iptables_ -v -I FORWARD -i ${SUBNET_IFACE} $IPTABLES_NAT_OUT -s ${GATEWAY%.*}.0/24 -j ACCEPT || die + iptables_ -v -I FORWARD -o ${SUBNET_IFACE} $IPTABLES_NAT_IN -d ${GATEWAY%.*}.0/24 -j ACCEPT || die + fi + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -v -t nat -I POSTROUTING -s ${PREFIX6}/64 $IPTABLES_NAT_OUT $MASQUERADE_NOTOUT ! -d ${PREFIX6}/64 -j MASQUERADE || die + ip6tables_ -v -I FORWARD -i ${SUBNET_IFACE} $IPTABLES_NAT_OUT -s ${PREFIX6}/64 -j ACCEPT || die + ip6tables_ -v -I FORWARD -o ${SUBNET_IFACE} $IPTABLES_NAT_IN -d ${PREFIX6}/64 -j ACCEPT || die + fi +} +stop_nat() { + echo "iptables: stop NAT" + if [[ $NO4 -eq 0 ]]; then + iptables_ -t nat -D POSTROUTING -s ${GATEWAY%.*}.0/24 $IPTABLES_NAT_OUT $MASQUERADE_NOTOUT ! -d ${GATEWAY%.*}.0/24 -j MASQUERADE + iptables_ -D FORWARD -i ${SUBNET_IFACE} $IPTABLES_NAT_OUT -s ${GATEWAY%.*}.0/24 -j ACCEPT + iptables_ -D FORWARD -o ${SUBNET_IFACE} $IPTABLES_NAT_IN -d ${GATEWAY%.*}.0/24 -j ACCEPT + fi + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -t nat -D POSTROUTING -s ${PREFIX6}/64 $IPTABLES_NAT_OUT $MASQUERADE_NOTOUT ! -d ${PREFIX6}/64 -j MASQUERADE + ip6tables_ -D FORWARD -i ${SUBNET_IFACE} $IPTABLES_NAT_OUT -s ${PREFIX6}/64 -j ACCEPT + ip6tables_ -D FORWARD -o ${SUBNET_IFACE} $IPTABLES_NAT_IN -d ${PREFIX6}/64 -j ACCEPT + fi +} + +start_ban_lan() { + echo + echo "iptables: Disallow clients to access LAN" + iptables_ -N BANLAN-f-${SUBNET_IFACE} || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 0.0.0.0/8 -j REJECT || die # TODO: use array + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 10.0.0.0/8 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 100.64.0.0/10 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 127.0.0.0/8 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 169.254.0.0/16 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 172.16.0.0/12 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 192.168.0.0/16 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 224.0.0.0/4 -j REJECT || die + iptables_ -v -I BANLAN-f-${SUBNET_IFACE} -d 255.255.255.255 -j REJECT || die + + iptables_ -I FORWARD -i ${SUBNET_IFACE} -j BANLAN-f-${SUBNET_IFACE} || die + + iptables_ -N BANLAN-i-${SUBNET_IFACE} + #iptables_ -v -I BANLAN-i-${SUBNET_IFACE} -i ${SUBNET_IFACE} -j REJECT || die + iptables_ -v -I BANLAN-i-${SUBNET_IFACE} -i ${SUBNET_IFACE} ! -p icmp -j REJECT || die + # TODO: ipv6 need icmp to function. maybe we can block some unneeded icmp to improve security + + iptables_ -I INPUT -i ${SUBNET_IFACE} -j BANLAN-i-${SUBNET_IFACE} || die + + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -N BANLAN-f-${SUBNET_IFACE} || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d fc00::/7 -j REJECT || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d fe80::/10 -j REJECT || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d ff00::/8 -j REJECT || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d ::1 -j REJECT || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d ::/128 -j REJECT || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d ::ffff:0:0/96 -j REJECT || die + ip6tables_ -v -I BANLAN-f-${SUBNET_IFACE} -d ::ffff:0:0:0/96 -j REJECT || die + + ip6tables_ -I FORWARD -i ${SUBNET_IFACE} -j BANLAN-f-${SUBNET_IFACE} || die + + ip6tables_ -N BANLAN-i-${SUBNET_IFACE} || die + #ip6tables_ -v -I BANLAN-i-${SUBNET_IFACE} -i ${SUBNET_IFACE} -j REJECT || die + ip6tables_ -v -I BANLAN-i-${SUBNET_IFACE} -i ${SUBNET_IFACE} ! -p icmpv6 -j REJECT || die + + ip6tables_ -I INPUT -i ${SUBNET_IFACE} -j BANLAN-i-${SUBNET_IFACE} || die + fi +} +stop_ban_lan() { + echo "iptables: Unban clients' LAN access" + + iptables_ -D FORWARD -i ${SUBNET_IFACE} -j BANLAN-f-${SUBNET_IFACE} + + iptables_ -F BANLAN-f-${SUBNET_IFACE} + iptables_ -X BANLAN-f-${SUBNET_IFACE} + + iptables_ -D INPUT -i ${SUBNET_IFACE} -j BANLAN-i-${SUBNET_IFACE} + + iptables_ -F BANLAN-i-${SUBNET_IFACE} + iptables_ -X BANLAN-i-${SUBNET_IFACE} + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -D FORWARD -i ${SUBNET_IFACE} -j BANLAN-f-${SUBNET_IFACE} + + ip6tables_ -F BANLAN-f-${SUBNET_IFACE} + ip6tables_ -X BANLAN-f-${SUBNET_IFACE} + + ip6tables_ -D INPUT -i ${SUBNET_IFACE} -j BANLAN-i-${SUBNET_IFACE} + + ip6tables_ -F BANLAN-i-${SUBNET_IFACE} + ip6tables_ -X BANLAN-i-${SUBNET_IFACE} + fi +} + +allow_dns_port() { + echo + echo "iptables: allow DNS" + iptables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} -p tcp -m tcp --dport 53 -j ACCEPT || die + iptables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} -p udp -m udp --dport 53 -j ACCEPT || die + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -d ${GATEWAY6} -p tcp -m tcp --dport 53 -j ACCEPT || die + ip6tables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -d ${GATEWAY6} -p udp -m udp --dport 53 -j ACCEPT || die + fi +} +unallow_dns_port() { + echo "iptables: unallow DNS" + iptables_ -D INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} -p tcp -m tcp --dport 53 -j ACCEPT + iptables_ -D INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -d ${GATEWAY} -p udp -m udp --dport 53 -j ACCEPT + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -D INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -d ${GATEWAY6} -p tcp -m tcp --dport 53 -j ACCEPT + ip6tables_ -D INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -d ${GATEWAY6} -p udp -m udp --dport 53 -j ACCEPT + fi +} + +start_catch_dns() { + echo + echo "iptables: redirect all TCP/UDP packet that destination port is 53" + iptables_ -v -t nat -I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY} -p udp -m udp --dport 53 -j REDIRECT --to-ports 53 || die + iptables_ -v -t nat -I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY} -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53 || die + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -v -t nat -I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY6} -p udp -m udp --dport 53 -j REDIRECT --to-ports 53 || die + ip6tables_ -v -t nat -I PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY6} -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53 || die + fi +} +stop_catch_dns() { + echo "iptables: stop redirecting DNS queries" + iptables_ -t nat -D PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY} -p udp -m udp --dport 53 -j REDIRECT --to-ports 53 + iptables_ -t nat -D PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY} -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53 + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -t nat -D PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY6} -p udp -m udp --dport 53 -j REDIRECT --to-ports 53 + ip6tables_ -t nat -D PREROUTING -i ${SUBNET_IFACE} ! -d ${GATEWAY6} -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53 + fi +} + +allow_dhcp() { + echo + echo "iptables: allow dhcp" + iptables_ -v -I INPUT -i ${SUBNET_IFACE} -p udp -m udp --dport 67 -j ACCEPT || die + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -v -I INPUT -i ${SUBNET_IFACE} -p udp -m udp --dport 547 -j ACCEPT || die + fi +} +unallow_dhcp() { + echo "iptables: unallow dhcp" + iptables_ -D INPUT -i ${SUBNET_IFACE} -p udp -m udp --dport 67 -j ACCEPT + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -D INPUT -i ${SUBNET_IFACE} -p udp -m udp --dport 547 -j ACCEPT + fi +} + +# TODO: use 'DNAT' instead of '--to-ports' to support other IP +start_redsocks() { + echo + echo "iptables: transparent proxy non-LAN TCP/UDP traffic to port ${TP_PORT}" + if [[ $NO4 -eq 0 ]]; then + iptables_ -t nat -N REDSOCKS-${SUBNET_IFACE} || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 0.0.0.0/8 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 10.0.0.0/8 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 100.64.0.0/10 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 127.0.0.0/8 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 169.254.0.0/16 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 172.16.0.0/12 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 192.168.0.0/16 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 224.0.0.0/4 -j RETURN || die + iptables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d 255.255.255.255 -j RETURN || die + + iptables_ -v -t nat -A REDSOCKS-${SUBNET_IFACE} -p tcp -j REDIRECT --to-ports ${TP_PORT} || die + iptables_ -v -t nat -A REDSOCKS-${SUBNET_IFACE} -p udp -j REDIRECT --to-ports ${TP_PORT} || die + + iptables_ -v -t nat -I PREROUTING -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j REDSOCKS-${SUBNET_IFACE} || die + + iptables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT || die + iptables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -p udp -m udp --dport ${TP_PORT} -j ACCEPT || die + fi + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -t nat -N REDSOCKS-${SUBNET_IFACE} || die + ip6tables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d fc00::/7 -j RETURN || die + ip6tables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d fe80::/10 -j RETURN || die + ip6tables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d ff00::/8 -j RETURN || die + ip6tables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d ::1 -j RETURN || die + ip6tables_ -t nat -A REDSOCKS-${SUBNET_IFACE} -d :: -j RETURN || die + + ip6tables_ -v -t nat -A REDSOCKS-${SUBNET_IFACE} -p tcp -j REDIRECT --to-ports ${TP_PORT} || die + ip6tables_ -v -t nat -A REDSOCKS-${SUBNET_IFACE} -p udp -j REDIRECT --to-ports ${TP_PORT} || die + + ip6tables_ -v -t nat -I PREROUTING -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -j REDSOCKS-${SUBNET_IFACE} || die + + ip6tables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT || die + ip6tables_ -v -I INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -p udp -m udp --dport ${TP_PORT} -j ACCEPT || die + fi +} +stop_redsocks() { + echo "iptables: stop transparent proxy" + if [[ $NO4 -eq 0 ]]; then + iptables_ -t nat -D PREROUTING -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -j REDSOCKS-${SUBNET_IFACE} + iptables_ -t nat -F REDSOCKS-${SUBNET_IFACE} + iptables_ -t nat -X REDSOCKS-${SUBNET_IFACE} + + iptables_ -D INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT + iptables_ -D INPUT -i ${SUBNET_IFACE} -s ${GATEWAY%.*}.0/24 -p udp -m udp --dport ${TP_PORT} -j ACCEPT + fi + if [[ $IPV6 -eq 1 ]]; then + ip6tables_ -t nat -D PREROUTING -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -j REDSOCKS-${SUBNET_IFACE} + ip6tables_ -t nat -F REDSOCKS-${SUBNET_IFACE} + ip6tables_ -t nat -X REDSOCKS-${SUBNET_IFACE} + + ip6tables_ -D INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -p tcp -m tcp --dport ${TP_PORT} -j ACCEPT + ip6tables_ -D INPUT -i ${SUBNET_IFACE} -s ${PREFIX6}/64 -p udp -m udp --dport ${TP_PORT} -j ACCEPT + fi +} +#--------------------------------------- +backup_ipv6_bits() { + mkdir "$CONFDIR/sys_6_conf_iface" || die "Failed making dir to save interface IPv6 status" + cp "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/disable_ipv6" \ + "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/accept_ra" \ + "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/use_tempaddr" \ + "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/addr_gen_mode" \ + "$CONFDIR/sys_6_conf_iface/" || die "Failed backing up interface ipv6 bits" + + if [[ "$SHARE_METHOD" == 'redsocks' ]] ; then + cp "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/forwarding" \ + "$CONFDIR/sys_6_conf_iface/" || die "Failed backking up interface ipv6 bits" + fi +} +set_ipv6_bits() { + if [[ $IPV6 -eq 1 ]]; then + echo 0 > "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/disable_ipv6" + echo 0 > "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/accept_ra" + echo 0 > "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/use_tempaddr" + echo 0 > "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/addr_gen_mode" + else + echo 1 > "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/disable_ipv6" + fi +} +restore_ipv6_bits() { + if [[ -d "$CONFDIR/sys_6_conf_iface" ]]; then + cp -f "$CONFDIR/sys_6_conf_iface/*" "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/" + fi +} + +set_interface_mac() { + local INTERFACE + local MAC + + INTERFACE=$1 + MAC=$2 + + ip link set dev ${INTERFACE} address ${MAC} +} + +backup_interface_status() { + # virtual wifi interface will be destroyed, so no need to save status + + # backup interface up or down status + (ip link show ${SUBNET_IFACE} |grep -q "state UP") && SUBNET_IFACE_ORIGINAL_UP_STATUS=1 + + # save interface old mac + #if [[ -n "$NEW_MACADDR" ]]; then + OLD_MACADDR=$(get_interface_mac $SUBNET_IFACE) + #echo "Saved ${SUBNET_IFACE} old MAC address ${OLD_MACADDR} into RAM" + #fi + + backup_ipv6_bits + + # TODO : backup ip and others + + # nm managing status is saved when nm_set_unmanaged() +} +restore_interface_status() { + # virtual wifi interface will be destroyed, so no need to restore status + # don't use [[ $VWIFI_IFACE ]] to judge, if creating virtual wifi failed, VWIFI_IFACE is empty + [[ "$WIFI_IFACE" && "$NO_VIRT" -eq 0 ]] && return + + restore_ipv6_bits + + if [[ -n "$OLD_MACADDR" && "$(get_interface_mac $SUBNET_IFACE)" != "$OLD_MACADDR" ]] ; then + echo "Restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR} ..." + set_interface_mac ${SUBNET_IFACE} ${OLD_MACADDR} || echo "Failed restoring ${SUBNET_IFACE} to old MAC address ${OLD_MACADDR}" >&2 + fi + + nm_restore_manage + + [[ $SUBNET_IFACE_ORIGINAL_UP_STATUS -eq 1 ]] && ip link set up dev ${SUBNET_IFACE} && echo "Restore ${SUBNET_IFACE} to link up" +} +#--------------------------------------- + +kill_processes() { # for this instance + #echo "Killing processes" + local x pid + for x in $CONFDIR/*.pid; do + # even if the $CONFDIR is empty, the for loop will assign + # a value in $x. so we need to check if the value is a file + if [[ -f $x ]] && sleep 0.3 && [[ -f $x ]]; then + pid=$(cat $x) + pn=$( ps -p $pid -o comm= ) + #echo "Killing $pid $pn ... " + pkill -P $pid + kill $pid 2>/dev/null && ( echo "Killed $pid $pn" && rm $x ) || echo "Failed to kill $pid $pn, it may have exited" + fi + done +} + +_cleanup() { + local x + + ip addr flush ${SUBNET_IFACE} + + rm -rf $CONFDIR + + ip link set down dev ${SUBNET_IFACE} + + if [[ $VWIFI_IFACE ]]; then # the subnet interface (virtual wifi interface) will be removed + iw dev ${VWIFI_IFACE} del + dealloc_vface_name $VWIFI_IFACE + fi + + restore_interface_status + + if ! has_running_instance; then + echo "Exiting: This is the only running instance" + # kill common processes + for x in $COMMON_CONFDIR/*.pid; do + [[ -f $x ]] && kill -9 $(cat $x) && rm $x + done + + rm -d $COMMON_CONFDIR/vfaces + rm -d $COMMON_CONFDIR + rm -d $TMPDIR + else + echo "Exiting: This is NOT the only running instance" + fi +} + +clean_iptables() { + + if [[ "$SHARE_METHOD" == "nat" ]]; then + stop_nat + elif [[ "$SHARE_METHOD" == "redsocks" ]]; then + stop_redsocks + fi + + if [[ "$DHCP_DNS" == "gateway" || "$DHCP_DNS6" == "gateway" ]]; then + unallow_dns_port + fi + + [[ "$CATCH_DNS" -eq 1 ]] && stop_catch_dns + + + if [[ $NO_DNSMASQ -eq 0 ]]; then + unallow_dhcp + fi + + [[ "$BANLAN" -eq 1 ]] && stop_ban_lan +} + +cleanup() { + trap "" SIGINT SIGUSR1 SIGUSR2 EXIT SIGTERM + echo + echo + echo "Doing cleanup.. " + kill_processes + clean_iptables 2> /dev/null + _cleanup 2> /dev/null + + pgid=$(ps opgid= $$ |awk '{print $1}' ) + kill -15 -$pgid + sleep 1 + echo "Cleaning up done" + #kill -9 -$pgid +} + +# NOTE function die() is designed not to be used before init_trap() executed +die() { # SIGUSR2 + echo "Error occured" + [[ -n "$1" ]] && echo -e "\nERROR: $1\n" >&2 + # send die signal to the main process + [[ $BASHPID -ne $$ ]] && kill -USR2 $$ || cleanup + exit 1 +} + +clean_exit() { # SIGUSR1 + # send clean_exit signal to the main process + [[ $BASHPID -ne $$ ]] && kill -USR1 $$ || cleanup + exit 0 +} + +init_trap(){ + trap "cleanup" EXIT + trap "clean_exit" SIGINT SIGUSR1 SIGTERM + trap "die" SIGUSR2 +} +init_conf_dirs() { + mkdir -p "$TMPDIR" || die "Couldn't make linux-router's temporary dir" + chmod 755 "$TMPDIR" 2>/dev/null + cd "$TMPDIR" || die "Couldn't change directory to linux-router's temporary path" + + CONFDIR="$(mktemp -d $TMPDIR/lnxrouter.${TARGET_IFACE}.conf.XXXXXX)" || die "Instance couldn't make config dir" # config dir for one instance + chmod 755 "$CONFDIR" + #echo "Config dir: $CONFDIR" + echo $$ > "$CONFDIR/pid" + + COMMON_CONFDIR="$TMPDIR/lnxrouter_common.conf" # config dir for all instances + mkdir -p "$COMMON_CONFDIR" +} + +#== functions to deal with running instances + +list_running_conf() { + local x + for x in $TMPDIR/lnxrouter.*; do + if [[ -f $x/pid && -f $x/subn_iface && -d /proc/$(cat $x/pid) ]]; then + echo "$x" + fi + done +} + +list_running() { + local IFACE subn_iface x + for x in $(list_running_conf); do + IFACE=${x#*.} + IFACE=${IFACE%%.*} + subn_iface=$(cat $x/subn_iface) + + if [[ $IFACE == $subn_iface ]]; then + echo $(cat $x/pid) $IFACE + else + echo $(cat $x/pid) $IFACE '('$(cat $x/subn_iface)')' + fi + done +} + +get_subn_iface_from_pid() { + list_running | awk '{print $1 " " $NF}' | tr -d '\(\)' | grep -E "^${1} " | cut -d' ' -f2 +} + +get_pid_from_subn_iface() { + list_running | awk '{print $1 " " $NF}' | tr -d '\(\)' | grep -E " ${1}$" | cut -d' ' -f1 +} + +get_confdir_from_pid() { + local IFACE x + for x in $(list_running_conf); do + if [[ $(cat $x/pid) == "$1" ]]; then + echo "$x" + break + fi + done +} + +#====================================================== + +print_clients_from_leases() { # MAC|IP|HOST|lease + local LEASE_FILE="$1" + local FILEC + local line + local LEASEstr LEASEstamp + + FILEC="$(cat "$LEASE_FILE" | grep -v -E "^duid\b" | sed -r '/^\s*$/d' )" + + # TODO: duid is somewhat related to ipv6. I don't know about it. Not sure excluding it miss some info or not + echo "$FILEC" | while read line + do + #echo aa$line + LEASEstamp="$(echo "$line" | awk '{print $1}')" + MAC="$(echo "$line" | awk '{print $2}')" + IP="$(echo "$line" | awk '{print $3}' | sed 's/\[//g' | sed 's/\]//g')" + HOST="$(echo "$line" | awk '{print $4}' | sed 's/*/?/g' | sed 's/|/_/g' | sed 's/ /_/g' )" + + if [[ -n "$MAC" ]]; then + LEASEstr="$(date -d @${LEASEstamp} +%m-%d_%X)" + + echo "$MAC|$IP|$HOST|lease_$LEASEstr" + fi + done + +} +print_interface_neighbors_via_iproute() { # MAC|IP|_|STATUS + local IFACE=$1 + + local line + + ip n | grep -E "\bdev $IFACE\b" | sed 's/ /|/g' | while read line + do + local MAC IP STATUS + + IP="$(echo $line | awk -F'|' '{print $1}')" + + if [[ "$(echo $line | awk -F'|' '{print $4}')" == "lladdr" ]]; then # has mac + # if has mac, $4="lladdr" and $5=macaddress and $6+=status + MAC="$(echo $line | awk -F'|' '{print $5}')" + STATUS="$(echo $line | awk -F'|' '$1="";$2="";$3="";$4="";$5="";{print}' | awk '{$1=$1;print}'| sed 's/ /,/g')" + else # no mac + # if no mac, $4="" and $5+=status + MAC="?" + STATUS="$(echo $line | awk -F'|' '$1="";$2="";$3="";$4="";{print}' | awk '{$1=$1;print}' | sed 's/ /,/g')" + fi + if [[ -n "$IP" && ( "$MAC" != "?" || "$STATUS" != "FAILED" ) ]]; then + echo "$MAC|$IP|?|$STATUS" + fi + done +} +print_interface_neighbors_via_iw() { # MAC|_|_|signal + local IFACE=$1 + local MAC SIGNAL + iw dev $IFACE station dump | awk '($1 ~ /Station$/) {print $2}' | while read MAC + do + if [[ -n "$MAC" ]]; then + SIGNAL="$(iw dev $IFACE station get $MAC | grep "signal:" | awk '{print $2}')" + echo "${MAC}|?|?|${SIGNAL}_dBm" + fi + done +} + +list_clients() { # passive mode. (use 'arp-scan' or 'netdiscover' if want active mode) + local IFACE pid + local CONFDIR + + local output="" + # If number (PID) is given, get the associated wifi iface + if [[ "$1" =~ ^[1-9][0-9]*$ ]]; then + pid="$1" + IFACE=$(get_subn_iface_from_pid "$pid") + if [[ -z "$IFACE" ]] ; then + echo "'$pid' is not the pid of a running $PROGNAME instance." >&2 + exit 1 + fi + else # non-number given + IFACE="$1" + if ( ! is_interface $IFACE ) ; then + echo "'$IFACE' is not an interface or PID" >&2 + exit 1 + fi + pid=$(get_pid_from_subn_iface "$IFACE") + if [[ -n "$pid" ]] ; then # if this interface is hosted by us + CONFDIR=$(get_confdir_from_pid "$pid") + output="$(print_clients_from_leases "$CONFDIR/dnsmasq.leases" )" + else # this interface NOT hosted by us + echo "Tip: '$IFACE' is not an interface hosted by $PROGNAME" >&2 + fi + fi + output="$(echo "$output" ; print_interface_neighbors_via_iw $IFACE) " + output="$(echo "$output" ; print_interface_neighbors_via_iproute $IFACE)" + + output="$(echo "$output" | sort -k 1 -k 2 -t '|' | uniq | sed -r '/^\s*$/d')" + + echo "$IFACE ($(get_interface_mac $IFACE)) neighbors:" + + local fmt="%-19s%-41s%-20s%s" # string length: MAC 17, ipv4 15, ipv6 39, hostname ? + printf "$fmt\n" "MAC" "IP" "HOSTNAME" "INFO" + + local line + echo "$output"| while read line + do + if [[ -n "$line" ]]; then + echo "$line" | awk -F'|' "{printf \"$fmt\n\",\$1,\$2,\$3,\$4}" + fi + done + # TODO : merge same mac and same ip line +} + +has_running_instance() { + local PID x + + for x in $TMPDIR/lnxrouter.*; do + if [[ -f $x/pid ]]; then + PID=$(cat $x/pid) + if [[ -d /proc/$PID ]]; then + return 0 + fi + fi + done + + return 1 +} + +is_running_pid() { + list_running | grep -E "^${1} " > /dev/null 2>&1 +} + +send_stop() { + local x + + # send stop signal to specific pid + if is_running_pid $1; then + kill -USR1 $1 + return + fi + + # send stop signal to specific interface + for x in $(list_running | grep -E " \(?${1}( |\)?\$)" | cut -f1 -d' '); do + kill -USR1 $x + done +} + + +## ======================================================== +## ======================================================== +# decide linux-router's global temporary path for all instances +# this is different and should be before config-saving dir. The latter is for one instance +decide_tmpdir(){ + local TMPD + if [[ -d /dev/shm ]]; then + TMPD=/dev/shm + elif [[ -d /run/shm ]]; then + TMPD=/run/shm + else + TMPD=/tmp + fi + #TMPDIR=$TMPD/lnxrouter_tmp + echo "$TMPD/lnxrouter_tmp" +} + +#====== + +check_other_functions(){ + if [[ $LIST_RUNNING -eq 1 ]]; then + echo -e "List of running $PROGNAME instances:\n" + list_running + exit 0 + fi + + if [[ -n "$LIST_CLIENTS_ID" ]]; then + list_clients "$LIST_CLIENTS_ID" + exit 0 + fi + + ##### root test ##### NOTE above don't require root ########## + if [[ $(id -u) -ne 0 ]]; then + echo "You must run it as root." >&2 + exit 1 + fi + ###### NOTE below require root ########## + + if [[ -n "$STOP_ID" ]]; then + echo "Trying to kill $PROGNAME instance associated with $STOP_ID..." + send_stop "$STOP_ID" + exit 0 + fi +} + + +daemonizing_check(){ + if [[ $DAEMONIZE -eq 1 && $RUNNING_AS_DAEMON -eq 0 ]]; then + echo "Running as Daemon..." + # run a detached lnxrouter + RUNNING_AS_DAEMON=1 setsid "$0" "${ARGS[@]}" & + exit 0 + fi +} + +#============================ +check_wifi_settings() { + + if ! ( which iw > /dev/null 2>&1 && iw dev $WIFI_IFACE info > /dev/null 2>&1 ); then + echo "WARN: Can't use 'iw' to operate interfce '$WIFI_IFACE', trying 'iwconfig' (not as good as 'iw') ..." >&2 + USE_IWCONFIG=1 + fi + + if [[ $USE_IWCONFIG -eq 1 ]]; then + if ! (which iwconfig > /dev/null 2>&1 && iwconfig $WIFI_IFACE > /dev/null 2>&1); then + echo "ERROR: Can't use 'iwconfig' to operate interfce '$WIFI_IFACE'" >&2 + exit 1 + fi + fi + + if [[ $FREQ_BAND != 2.4 && $FREQ_BAND != 5 ]]; then + echo "ERROR: Invalid frequency band" >&2 + exit 1 + fi + + if [[ $CHANNEL == default ]]; then + if [[ $FREQ_BAND == 2.4 ]]; then + CHANNEL=1 + else + CHANNEL=36 + fi + fi + + if [[ $FREQ_BAND != 5 && $CHANNEL -gt 14 ]]; then + echo "Channel number is greater than 14, assuming 5GHz frequency band" + FREQ_BAND=5 + fi + + if ! can_be_ap ${WIFI_IFACE}; then + echo "ERROR: Your adapter does not support AP (master) mode" >&2 + exit 1 + fi + + if ! can_be_sta_and_ap ${WIFI_IFACE}; then + if is_interface_wifi_connected ${WIFI_IFACE}; then + echo "ERROR: Your adapter can not be a station (i.e. be connected) and an AP at the same time" >&2 + exit 1 + elif [[ $NO_VIRT -eq 0 ]]; then + echo "WARN: Your adapter does not fully support AP virtual interface, enabling --no-virt" >&2 + NO_VIRT=1 + fi + fi + + HOSTAPD=$(which hostapd) + + if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^(8192[cd][ue]|8723a[sue])$ ]]; then + if ! strings "$HOSTAPD" | grep -m1 rtl871xdrv > /dev/null 2>&1; then + echo "ERROR: You need to patch your hostapd with rtl871xdrv patches." >&2 + exit 1 + fi + + if [[ $DRIVER != "rtl871xdrv" ]]; then + echo "WARN: Your adapter needs rtl871xdrv, enabling --driver=rtl871xdrv" >&2 + DRIVER=rtl871xdrv + fi + fi + + if [[ ${#SSID} -lt 1 || ${#SSID} -gt 32 ]]; then + echo "ERROR: Invalid SSID length ${#SSID} (expected 1..32)" >&2 + exit 1 + fi + + if [[ $USE_PSK -eq 0 ]]; then + if [[ ${#PASSPHRASE} -gt 0 && ${#PASSPHRASE} -lt 8 ]] || [[ ${#PASSPHRASE} -gt 63 ]]; then + echo "ERROR: Invalid passphrase length ${#PASSPHRASE} (expected 8..63)" >&2 + exit 1 + fi + elif [[ ${#PASSPHRASE} -gt 0 && ${#PASSPHRASE} -ne 64 ]]; then + echo "ERROR: Invalid pre-shared-key length ${#PASSPHRASE} (expected 64)" >&2 + exit 1 + fi + + if [[ $(get_adapter_kernel_module ${WIFI_IFACE}) =~ ^rtl[0-9].*$ ]]; then + if [[ $WPA_VERSION == '1' || $WPA_VERSION == '1+2' ]]; then + echo "WARN: Realtek drivers usually have problems with WPA1, WPA2 is recommended" >&2 + fi + echo "WARN: If AP doesn't work, read https://github.com/oblique/create_ap/blob/master/howto/realtek.md" >&2 + fi +} + +check_if_new_mac_valid() { + if ! is_unicast_macaddr "$NEW_MACADDR"; then + echo "ERROR: The first byte of MAC address (${NEW_MACADDR}) must be even" >&2 + exit 1 + fi + + if [[ $(get_all_mac_in_system | grep -c ${NEW_MACADDR}) -ne 0 ]]; then + echo "WARN: MAC address '${NEW_MACADDR}' already exists" >&2 + fi +} + +decide_target_interface() { + # TARGET_IFACE is a existing physical interface + if [[ "$CONN_IFACE" ]]; then + echo "$CONN_IFACE" + elif [[ "$WIFI_IFACE" ]]; then + echo "$WIFI_IFACE" + else + echo "No target interface specified" >&2 + return 1 + fi +} + +decide_ip_addresses() { + if [[ ! -n $GATEWAY ]]; then + GATEWAY="$(generate_random_ip4)" + echo "Use random LAN IPv4 address $GATEWAY" + elif [[ ! "$GATEWAY" =~ "." ]]; then + GATEWAY="192.168.${GATEWAY}.1" + fi + + if [[ $IPV6 -eq 1 && ! -n $PREFIX6 ]]; then + PREFIX6="$(generate_random_lan_ip6_prefix)" + echo "Use random LAN IPv6 address ${PREFIX6}${IID6}" + elif [[ ! "$PREFIX6" =~ ":" ]]; then + PREFIX6="fd00:0:0:${PREFIX6}::" + fi + if [[ $IPV6 -eq 1 ]]; then + GATEWAY6="${PREFIX6}${IID6}" + fi +} + +prepare_wifi_interface() { + if [[ $USE_IWCONFIG -eq 0 ]]; then + iw dev ${WIFI_IFACE} set power_save off + fi + + if [[ $NO_VIRT -eq 0 ]]; then + ## Will generate virtual wifi interface + if is_interface_wifi_connected ${WIFI_IFACE}; then + WIFI_IFACE_FREQ=$(iw dev ${WIFI_IFACE} link | grep -i freq | awk '{print $2}') + WIFI_IFACE_CHANNEL=$(ieee80211_frequency_to_channel ${WIFI_IFACE_FREQ}) + echo "${WIFI_IFACE} already in channel ${WIFI_IFACE_CHANNEL} (${WIFI_IFACE_FREQ} MHz)" + if is_5ghz_frequency $WIFI_IFACE_FREQ; then + FREQ_BAND=5 + else + FREQ_BAND=2.4 + fi + if [[ $WIFI_IFACE_CHANNEL -ne $CHANNEL ]]; then + echo "Channel fallback to ${WIFI_IFACE_CHANNEL}" + CHANNEL=$WIFI_IFACE_CHANNEL + else + echo + fi + fi + + echo "Creating a virtual WiFi interface... " + VWIFI_IFACE=$(alloc_new_vface_name) + if iw dev ${WIFI_IFACE} interface add ${VWIFI_IFACE} type __ap; then + # Successfully created virtual wifi interface + # if NM running, it will give the new virtual interface a random MAC. MAC will go back after setting NM unmanaged + sleep 2 + echo "${VWIFI_IFACE} created" + else + VWIFI_IFACE= + die "Failed creating virtual WiFi interface. Maybe your WiFi adapter does not fully support virtual interfaces. Try again with '--no-virt'" + fi + + AP_IFACE=${VWIFI_IFACE} + else # no virtual wifi interface, use wifi device interface itself + AP_IFACE=${WIFI_IFACE} + fi +} + +decide_subnet_interface() { + if [[ $WIFI_IFACE ]]; then + echo "${AP_IFACE}" + else + echo "${TARGET_IFACE}" + fi +} + +dealwith_mac() { + local VMAC + + if [[ -n "$NEW_MACADDR" ]] ; then # user choose to set subnet mac + + echo "Setting ${SUBNET_IFACE} new MAC address ${NEW_MACADDR} ..." + set_interface_mac ${SUBNET_IFACE} ${NEW_MACADDR} || die "Failed setting new MAC address" + + elif [[ $VWIFI_IFACE ]]; then # user didn't choose to set mac, but using virtual wifi interface + + VMAC=$(get_new_macaddr_according_to_existing ${WIFI_IFACE}) + if [[ "$VMAC" ]]; then + echo "Assigning MAC address $VMAC to virtual interface $VWIFI_IFACE according to $WIFI_IFACE ..." + set_interface_mac $VWIFI_IFACE $VMAC + fi + fi +} + +write_hostapd_conf() { + cat <<- EOF > "$CONFDIR/hostapd.conf" + beacon_int=100 + ssid=${SSID} + interface=${AP_IFACE} + driver=${DRIVER} + channel=${CHANNEL} + ctrl_interface=$CONFDIR/hostapd_ctrl + ctrl_interface_group=0 + ignore_broadcast_ssid=$HIDDEN + ap_isolate=$ISOLATE_CLIENTS + EOF + + if [[ -n "$COUNTRY" ]]; then + cat <<- EOF >> "$CONFDIR/hostapd.conf" + country_code=${COUNTRY} + ieee80211d=1 + EOF + fi + + if [[ $FREQ_BAND == 2.4 ]]; then + echo "hw_mode=g" >> "$CONFDIR/hostapd.conf" + else + echo "hw_mode=a" >> "$CONFDIR/hostapd.conf" + fi + + if [[ $MAC_FILTER -eq 1 ]]; then + cat <<- EOF >> "$CONFDIR/hostapd.conf" + macaddr_acl=${MAC_FILTER} + accept_mac_file=${MAC_FILTER_ACCEPT} + EOF + fi + + if [[ $IEEE80211N -eq 1 ]]; then + cat <<- EOF >> "$CONFDIR/hostapd.conf" + ieee80211n=1 + ht_capab=${HT_CAPAB} + EOF + fi + + if [[ $IEEE80211AC -eq 1 ]]; then + echo "ieee80211ac=1" >> "$CONFDIR/hostapd.conf" + fi + + if [[ -n "$VHT_CAPAB" ]]; then + echo "vht_capab=${VHT_CAPAB}" >> "$CONFDIR/hostapd.conf" + fi + + if [[ $IEEE80211N -eq 1 ]] || [[ $IEEE80211AC -eq 1 ]]; then + echo "wmm_enabled=1" >> "$CONFDIR/hostapd.conf" + fi + + if [[ -n "$PASSPHRASE" ]]; then + [[ "$WPA_VERSION" == "1+2" ]] && WPA_VERSION=3 + if [[ $USE_PSK -eq 0 ]]; then + WPA_KEY_TYPE=passphrase + else + WPA_KEY_TYPE=psk + fi + cat <<- EOF >> "$CONFDIR/hostapd.conf" + wpa=${WPA_VERSION} + wpa_${WPA_KEY_TYPE}=${PASSPHRASE} + wpa_key_mgmt=WPA-PSK + wpa_pairwise=CCMP + rsn_pairwise=CCMP + EOF + else + echo "WARN: Wifi is not protected by password" >&2 + fi + chmod 600 "$CONFDIR/hostapd.conf" +} + +write_dnsmasq_conf() { + if grep "^nobody:" /etc/group >/dev/null 2>&1 ; then + NOBODY_GROUP="nobody" + else + NOBODY_GROUP="nogroup" + fi + + mkfifo "$CONFDIR/dnsmasq.log" || die "Failed creating pipe file for dnsmasq" + chown nobody "$CONFDIR/dnsmasq.log" || die "Failed changing dnsmasq log file owner" + cat "$CONFDIR/dnsmasq.log" & + + cat <<- EOF > "$CONFDIR/dnsmasq.conf" + user=nobody + group=$NOBODY_GROUP + bind-dynamic + listen-address=${GATEWAY} + interface=$SUBNET_IFACE + except-interface=lo + no-dhcp-interface=lo + dhcp-range=${GATEWAY%.*}.10,${GATEWAY%.*}.250,255.255.255.0 + dhcp-option-force=option:router,${GATEWAY} + #log-dhcp + log-facility=$CONFDIR/dnsmasq.log + bogus-priv + domain-needed + EOF + # 'log-dhcp'(Extra logging for DHCP) shows too much logs. + # if use '-d', 'log-facility' should = /dev/null + if [[ $SHARE_METHOD == "none" ]]; then + echo "no-resolv" >> "$CONFDIR/dnsmasq.conf" + echo "no-poll" >> "$CONFDIR/dnsmasq.conf" + fi + if [[ "$DHCP_DNS" != "no" ]]; then + if [[ "$DHCP_DNS" == "gateway" ]]; then + dns_offer="$GATEWAY" + else + dns_offer="$DHCP_DNS" + fi + echo "dhcp-option-force=option:dns-server,${dns_offer}" >> "$CONFDIR/dnsmasq.conf" + fi + + if [[ ! "$dnsmasq_NO_DNS" -eq 0 ]]; then + echo "port=0" >> "$CONFDIR/dnsmasq.conf" + fi + + [[ -n "$MTU" ]] && echo "dhcp-option-force=option:mtu,${MTU}" >> "$CONFDIR/dnsmasq.conf" + [[ $ETC_HOSTS -eq 0 ]] && echo no-hosts >> "$CONFDIR/dnsmasq.conf" + [[ -n "$ADDN_HOSTS" ]] && echo "addn-hosts=${ADDN_HOSTS}" >> "$CONFDIR/dnsmasq.conf" + if [[ "$THISHOSTNAME" ]]; then + [[ "$THISHOSTNAME" == "-" ]] && THISHOSTNAME="$(cat /etc/hostname)" + echo "interface-name=$THISHOSTNAME,$SUBNET_IFACE" >> "$CONFDIR/dnsmasq.conf" + fi + if [[ ! "$SHOW_DNS_QUERY" -eq 0 ]]; then + echo log-queries=extra >> "$CONFDIR/dnsmasq.conf" + fi + + if [[ $DNS ]]; then + DNS_count=$(echo "$DNS" | awk -F, '{print NF}') + for (( i=1;i<=DNS_count;i++ )); do + sep_ip_port "$(echo $DNS | cut -d, -f$i)" DNS_IP DNS_PORT + [[ "$DNS_PORT" ]] && DNS_PORT_D="#$DNS_PORT" + echo "server=${DNS_IP}${DNS_PORT_D}" >> "$CONFDIR/dnsmasq.conf" + done + + cat <<- EOF >> "$CONFDIR/dnsmasq.conf" + no-resolv + no-poll + EOF + fi + if [[ $IPV6 -eq 1 ]];then + cat <<- EOF >> "$CONFDIR/dnsmasq.conf" + listen-address=${GATEWAY6} + enable-ra + #quiet-ra + dhcp-range=interface:${SUBNET_IFACE},::,::ffff:ffff:ffff:ffff,constructor:${SUBNET_IFACE},ra-stateless,64 + EOF + if [[ "$DHCP_DNS6" != "no" ]]; then + if [[ "$DHCP_DNS6" == "gateway" ]]; then + dns_offer6="[$GATEWAY6]" + else + dns_offer6="$DHCP_DNS6" + fi + echo "dhcp-option=option6:dns-server,${dns_offer6}" >> "$CONFDIR/dnsmasq.conf" + fi + fi +} + +run_wifi_ap_processes() { + if [[ $NO_HAVEGED -eq 0 ]]; then + haveged_watchdog & + HAVEGED_WATCHDOG_PID=$! + echo "$HAVEGED_WATCHDOG_PID" > "$CONFDIR/haveged_watchdog.pid" + echo + echo "haveged_watchdog PID: $HAVEGED_WATCHDOG_PID" + fi + + # start access point + #echo "hostapd command-line interface: hostapd_cli -p $CONFDIR/hostapd_ctrl" + # start hostapd (use stdbuf when available for no delayed output in programs that redirect stdout) + STDBUF_PATH=`which stdbuf` + if [ $? -eq 0 ]; then + STDBUF_PATH=$STDBUF_PATH" -oL" + fi + echo + echo "Starting hostapd" + + if which complain > /dev/null 2>&1; then + complain hostapd + fi + + # hostapd '-P' works only when use '-B' (run in background) + $STDBUF_PATH hostapd $HOSTAPD_DEBUG_ARGS -P "$CONFDIR/hostapd.pid" "$CONFDIR/hostapd.conf" & + HOSTAPD_PID=$! + echo "$HOSTAPD_PID" > "$CONFDIR/hostapd.pid" + echo "hostapd PID: $HOSTAPD_PID" + #while [[ ! -f $CONFDIR/hostapd.pid ]]; do + # sleep 1 + #done + #echo -n "hostapd PID: " ; cat $CONFDIR/hostapd.pid + pid_watchdog $HOSTAPD_PID 10 "hostapd failed" & + sleep 3 +} + +start_dnsmasq() { + echo + echo "Starting dnsmasq" + + if which complain > /dev/null 2>&1; then + # openSUSE's apparmor does not allow dnsmasq to read files. + # remove restriction. + complain dnsmasq + fi + + # Using '-d'(no daemon) dnsmasq will not turn into 'nobody' + # '-x' works only when no '-d' + dnsmasq -k -C "$CONFDIR/dnsmasq.conf" -x "$CONFDIR/dnsmasq.pid" -l "$CONFDIR/dnsmasq.leases" & + #####DNSMASQ_PID=$! # only when with '-d' + ######echo "dnsmasq PID: $DNSMASQ_PID" # only when with '-d' + i=0; while [[ ! -f "$CONFDIR/dnsmasq.pid" ]]; do + sleep 1 + i=$((i + 1)) + if [[ $i -gt 10 ]]; then die "Couldn't get dnsmasq PID" ; fi + done + DNSMASQ_PID="$(cat "$CONFDIR/dnsmasq.pid" )" + echo "dnsmasq PID: $DNSMASQ_PID" + ######(wait $DNSMASQ_PID ; die "dnsmasq failed") & # wait can't deal with non-child + pid_watchdog $DNSMASQ_PID 9 "dnsmasq failed" & + sleep 2 +} + +check_rfkill_unblock_wifi() { + local PHY + if which rfkill > /dev/null 2>&1 ; then + PHY=$(get_interface_phy_device ${SUBNET_IFACE}) + [[ -n $PHY ]] && rfkill unblock $(rfkill | grep $PHY | awk '{print $1}') >/dev/null 2>&1 + fi +} + +#=========== Above are functions ====================== +#=========== Executing begin ============================== + +# if empty option, show usage and exit +check_empty_option "$@" + +# TODO: are some global variables are still defined in those following code? +define_global_variables + +ARGS=( "$@" ) + +parse_user_options "$@" +# TODO: detect user option conflict + +# check if networkManager running +NM_RUNNING="$(is_nm_running)" + +TMPDIR="$(decide_tmpdir)" + +# if user choose to deal with running instances, will output some info then exit after this +# NOTE above don't require root +check_other_functions +# NOTE below require root + +# if user choose to daemonize, will start new background process and exit this +daemonizing_check + +# check if wifi will work on this system and user settings +[[ $WIFI_IFACE ]] && check_wifi_settings + +[[ -n "$NEW_MACADDR" ]] && check_if_new_mac_valid # check NEW_MACADDR. will exit if not valid + +# checks finished + +## ===== Above don't echo anything if no warning or error==================== +## ======================================================== +phead +echo "PID: $$" + +TARGET_IFACE="$(decide_target_interface)" || exit 1 # judge wired (-i CONN_IFACE) or wireless hotspot (--ap $WIFI_IFACE) +echo "Target interface is ${TARGET_IFACE} ($(get_interface_mac $TARGET_IFACE))" +# TODO: show interface type, device model and pci/usb id (hwdata pci.ids), current driver + +if [[ "$MAC_USE_RANDOM" -eq 1 ]] ; then + NEW_MACADDR="$(generate_random_mac)" + echo "Use random MAC address $NEW_MACADDR" +fi + +decide_ip_addresses # ip 4 & 6 lan addresses + +# if user choose to make DHCP to tell clients to use other DNS, we don't have to serve DNS +[[ $DHCP_DNS != 'gateway' && $DHCP_DNS6 != 'gateway' ]] && dnsmasq_NO_DNS=1 + +#=========================================================== +#==== begin to do some change on config files and system=== + +init_trap +# NOTE function die() is designed not to be used before init_trap() executed + +init_conf_dirs # CONFDIR , COMMON_CONFDIR . make dir + +[[ $WIFI_IFACE ]] && prepare_wifi_interface # this will create virtual ap interface (if needed) and set VWIFI_IFACE and AP_IFACE (if success) + +SUBNET_IFACE="$(decide_subnet_interface)" # SUBNET_IFACE can be TARGET_IFACE (wired) or AP_IFACE (ap) .this is after prepare_wifi_interface() +echo "$SUBNET_IFACE" > "$CONFDIR/subn_iface" + +# if virtual wifi interface, will be destroyed, so only need to save status when not +[[ -z $VWIFI_IFACE ]] && backup_interface_status + +# TODO: should these 2 before calling prepare_wifi_interface ? in check_wifi_settings() ? +# set iw country code +if [[ $WIFI_IFACE && -n "$COUNTRY" && $USE_IWCONFIG -eq 0 ]]; then + iw reg set "$COUNTRY" || die "Failed setting country code" +fi + +# judge channel availability after changing country code +if [[ $WIFI_IFACE ]] ; then + can_transmit_to_channel ${AP_IFACE} ${CHANNEL} || die "Your adapter can not transmit to channel ${CHANNEL}, frequency band ${FREQ_BAND}GHz." +fi + +[[ $WIFI_IFACE ]] && write_hostapd_conf +#=================================================== +#=================================================== + +# set interface unmanaged by networkManager +if [[ $NM_RUNNING -eq 1 ]] && nm_knows $TARGET_IFACE; then # if nm knows target iface, should know subnet iface too. but need to wait until nm finds subnet iface (waiting code is in nm_set_unmanaged() + nm_set_unmanaged ${SUBNET_IFACE} # will write NM_UNM_LIST +fi + +[[ $NO_DNSMASQ -eq 0 ]] && write_dnsmasq_conf +#=========================== + +# initialize subnet interface +# take subnet interface down first +ip link set down dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} down" +# flush old IPs of subnet interface +ip addr flush ${SUBNET_IFACE} || die "Failed flush ${SUBNET_IFACE} IP" + +dealwith_mac # setting MAC should be after setting NM unmanaged + +[[ $WIFI_IFACE ]] && check_rfkill_unblock_wifi + +# bring subnet interface up +ip link set up dev ${SUBNET_IFACE} || die "Failed bringing ${SUBNET_IFACE} up" + +# hostapd , haveged +[[ $WIFI_IFACE ]] && run_wifi_ap_processes + +# add ipv4 address to subnet interface +ip -4 addr add ${GATEWAY}/24 broadcast ${GATEWAY%.*}.255 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv4 address" + +set_ipv6_bits + +# add ipv6 address to subnet interface +if [[ $IPV6 -eq 1 ]] ; then + ip -6 addr add ${GATEWAY6}/64 dev ${SUBNET_IFACE} || die "Failed setting ${SUBNET_IFACE} IPv6 address" +fi + +check_iptables + +# enable Internet sharing +if [[ "$SHARE_METHOD" == "none" ]]; then + + echo "No Internet sharing" + + [[ "$BANLAN" -eq 1 ]] && start_ban_lan + +elif [[ "$SHARE_METHOD" == "nat" ]]; then + + [[ "$INTERNET_IFACE" && "$dnsmasq_NO_DNS" -eq 0 ]] && echo -e "\nWARN: You specified Internet interface but this host is providing local DNS, queries may leak to other interfaces!!!\n" >&2 + + start_nat + + [[ "$BANLAN" -eq 1 ]] && start_ban_lan + + echo 1 > "/proc/sys/net/ipv4/ip_forward" || die "Failed enabling system ipv4 forwarding" + + if [[ $IPV6 -eq 1 ]]; then + echo 1 > "/proc/sys/net/ipv6/conf/all/forwarding" || die "Failed enabling system ipv6 forwarding" + fi + + # to enable clients to establish PPTP connections we must + # load nf_nat_pptp module + modprobe nf_nat_pptp > /dev/null 2>&1 && echo "Loaded kernel module nf_nat_pptp" + +elif [[ "$SHARE_METHOD" == "redsocks" ]]; then + + if [[ $IPV6 -eq 1 ]]; then + echo 1 > "/proc/sys/net/ipv6/conf/$SUBNET_IFACE/forwarding" || die "Failed enabling $SUBNET_IFACE ipv6 forwarding" # to set NA router bit + fi + + [[ "$dnsmasq_NO_DNS" -eq 0 && ! $DNS ]] && echo -e "\nWARN: You are using in transparent proxy mode but this host is providing local DNS, this may cause privacy leak !!!\n" >&2 + + [[ "$BANLAN" -eq 1 ]] && start_ban_lan + + start_redsocks +fi + +# start dhcp + dns (optional) + +# allow dns port input even if we don't run dnsmasq +# user can serve their own dns server +[[ "$DHCP_DNS" == "gateway" || "$DHCP_DNS6" == "gateway" ]] && allow_dns_port + +[[ "$CATCH_DNS" -eq 1 ]] && start_catch_dns + +[[ $NO_DNSMASQ -eq 0 ]] && ( allow_dhcp ; start_dnsmasq ) + +echo +echo "== Setting up completed, now linux-router is working ==" + +#============================================================ +#============================================================ +#============================================================ + +show_qr() { + local T S P H + S="$SSID" + if [[ -n "$PASSPHRASE" ]]; then + T="WPA" + P="$PASSPHRASE" + else + T="nopass" + fi + [[ "$HIDDEN" -eq 1 ]] && H="true" + echo "Scan QR code on phone to connect to WiFi" + qrencode -m 2 -t ANSIUTF8 "WIFI:T:${T};S:${S};P:${P};H:${H};" + echo "Use this command to save QR code to image file:" + echo " qrencode -m 2 -o \"WIFI:T:${T};S:${S};P:${P};H:${H};\"" + echo +} + +[[ "$QR" -eq 1 ]] && show_qr + +# need loop to keep this script running +bash -c "while :; do sleep 8000 ; done " & +KEEP_RUNNING_PID=$! +echo "$KEEP_RUNNING_PID" > "$CONFDIR/keep_running.pid" +wait $KEEP_RUNNING_PID + +clean_exit diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/LICENSE b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/LICENSE new file mode 100644 index 0000000..5c304d1 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/README.md b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/README.md new file mode 100644 index 0000000..f7301fe --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/README.md @@ -0,0 +1,242 @@ +# IAI Kinect2 + +## Maintainer + +- [Thiemo Wiedemeyer](https://ai.uni-bremen.de/team/thiemo_wiedemeyer) <>, [Institute for Artificial Intelligence](http://ai.uni-bremen.de/), University of Bremen + +## Read this first + +Please read this README and the ones of the individual components throughly before asking questions. We get a lot of repeated questions, so when you have a problem, we urge everyone to check the [github issues (including closed ones)](https://github.com/code-iai/iai_kinect2/issues?utf8=%E2%9C%93&q=is%3Aissue). Your issue is very likely discussed there already. + +The goal of this project is to give you a driver and the tools needed to receive data from the Kinect-2 sensor, in a way useful for robotics. You will still need to know how to use ROS to make use of it. Please follow the [ROS tutorials](http://wiki.ros.org/ROS/Tutorials). You will also need to learn how to work with point-clouds, or depth-clouds, or images (computer vision) to do useful things with the data. + +*Note:* ***Please use the GitHub issues*** *for questions and problems regarding the iai_kinect2 package and its components.* ***Do not write emails.*** + +## Table of contents +- [Description](#description) +- [FAQ](#faq) +- [Dependencies](#dependencies) +- [Install](#install) +- [GPU acceleration](#gpu-acceleration) + - [OpenCL with AMD](#opencl-with-amd) + - [OpenCL/CUDA with Nvidia](#openclcuda-with-nvidia) + - [OpenCL with Intel](#opencl-with-intel) +- [Citation](#citation) +- [Screenshots](#screenshots) + +## Description + +This is a collection of tools and libraries for a ROS Interface to the Kinect One (Kinect v2). + +It contains: +- [a calibration tool](kinect2_calibration) for calibrating the IR sensor of the Kinect One to the RGB sensor and the depth measurements +- [a library](kinect2_registration) for depth registration with OpenCL support +- [the bridge](kinect2_bridge) between [libfreenect2](https://github.com/OpenKinect/libfreenect2) and [ROS](http://www.ros.org/) +- [a viewer](kinect2_viewer) for the images / point clouds + +## FAQ + +#### If I have any question or someting is not working, what should I do first? + +First you should look at this FAQ and the [FAQ from libfreenect2](https://github.com/OpenKinect/libfreenect2#faq). +Secondly, look at [issue page from libfreenect2](https://github.com/OpenKinect/libfreenect2/issues) and +the [issue page of iai_kinect2](https://github.com/code-iai/iai_kinect2/issues) for similar issues and solutions. + +#### Point clouds are not being published? + +Point clouds are only published when the launch file is used. Make sure to start kinect2_bridge with `roslaunch kinect2_bridge kinect2_bridge.launch`. + +#### Will it work with OpenCV 3.0 + +Short answer: No. + +Long answer: Yes, it is possible to compile this package with OpenCV 3.0, but it will not work. +This is because cv_bridge is used, which itself is compiled with OpenCV 2.4.x in ROS Indigo/Jade and +linking against both OpenCV versions is not possible. Working support for OpenCV 3.0 might come with a future ROS release. + +#### kinect2_bridge is not working / crashing, what is wrong? + +There are many reasons why `kinect2_bridge` might not working. The first thing to find out whether the problem is related to `kinect2_bridge` or `libfreenect2`. +A good tool for testing is `Protonect`, it is a binary located in `libfreenect2/build/bin/Protonect`. +It uses libfreenect2 directly with a minimal dependency on other libraries, so it is a good tool for the first tests. + +Execute: +- `./Protonect gl` to test OpenGL support. +- `./Protonect cl` to test OpenCL support. +- `./Protonect cpu` to test CPU support. + +Before running `kinect2_bridge` please make sure `Protonect` is working and showing color, depth and ir images. +If some of them are black, than there is a problem not related to `kinect2_bridge` and you should look at the issues from the libfreenect2 GitHub page for help. + +If one of them works, try out the one that worked with `kinect2_bridge`: `rosrun kinect2_bridge kinect2_bridge _depth_method:=`. +You can also change the registration method with `_reg_method:=`. + +#### Protonect works fine, but kinect2_bridge is still not working / crashing. + +If that is the case, you have to make sure that `Protonect` uses the same version of `libfreenect2` as `kinect2_bridge` does. +To do so, run `make` and `sudo make install` in the build folder again. And try out `kinect2_bridge` again. + +```bash +cd libfreenect2/build +make & sudo make install +``` + +Also make sure that you are not using OpenCV 3.0. + +If it is still crashing, compile it in debug and run it with gdb: + +```bash +cd +catkin_make -DCMAKE_BUILD_TYPE="Debug" +cd devel/lib/kinect2_bridge +gdb kinect2_bridge +# inside gdb: run until it crashes and do a backtrace +run +bt +quit +``` + +Open an issue and post the problem description and the output from the backtrace (`bt`). + +#### kinect2_bridge hangs and prints "waiting for clients to connect" + +This is the normal behavior. 'kinect2_bridge' will only process data when clients are connected (ROS nodes listening to at least one of the topics). +This saves CPU and GPU resources. As soon as you start the `kinect_viewer` or `rostopic hz` on one of the topics, processing should start. + +#### rosdep: Cannot locate rosdep definition for [kinect2_bridge] or [kinect2_registration] + +`rosdep` will output errors on not being able to locate `[kinect2_bridge]` and `[kinect2_registration]`. +That is fine because they are all part of the iai_kinect2 package and `rosdep` does not know these packages. + +#### Protonect or kinect2_bridge outputs [TransferPool::submit] failed to submit transfer + +This indicates problems with the USB connection. + +#### I still have an issue, what should I do? + +First of all, check the issue pages on GitHub for similar issues, as they might contain solutions for them. +By default you will only see the open issues, but if you click on `closed` you will the the ones solved. There is also a search field which helps to find similar issues. + +If you found no solution in the issues, feel free to open a new issue for your problem. Please describe your problem in detail and provide error messages and log output. + +## Dependencies + +- ROS Hydro/Indigo +- OpenCV (2.4.x, using the one from the official Ubuntu repositories is recommended) +- PCL (1.7.x, using the one from the official Ubuntu repositories is recommended) +- Eigen (optional, but recommended) +- OpenCL (optional, but recommended) +- [libfreenect2](https://github.com/OpenKinect/libfreenect2) (>= v0.2.0, for stability checkout the latest stable release) + +## Install + +1. Install the ROS. [Instructions for Ubuntu 14.04](http://wiki.ros.org/indigo/Installation/Ubuntu) +2. [Setup your ROS environment](http://wiki.ros.org/ROS/Tutorials/InstallingandConfiguringROSEnvironment) +3. Install [libfreenect2](https://github.com/OpenKinect/libfreenect2): + + Follow [the instructions](https://github.com/OpenKinect/libfreenect2#debianubuntu-1404) and enable C++11 by using `cmake .. -DENABLE_CXX11=ON` instead of `cmake ..`. If you are compiling libfreenect2 with CUDA, use `cmake .. -DENABLE_CXX11=ON -DCUDA_PROPAGATE_HOST_FLAGS=off`. + + If something is not working, check out the latest stable release, for example `git checkout v0.2.0`. + +4. Clone this repository into your catkin workspace, install the dependencies and build it: + + ```bash + cd ~/catkin_ws/src/ + git clone https://github.com/code-iai/iai_kinect2.git + cd iai_kinect2 + rosdep install -r --from-paths . + cd ~/catkin_ws + catkin_make -DCMAKE_BUILD_TYPE="Release" + ``` + + *Note: `rosdep` will output errors on not being able to locate `[kinect2_bridge]` and `[depth_registration]`. + That is fine because they are all part of the iai_kinect2 package and `rosdep` does not know these packages.* + + *Note: If you installed libfreenect2 somewhere else than in `$HOME/freenect2` or a standard location like `/usr/local` + you have to specify the path to it by adding `-Dfreenect2_DIR=path_to_freenect2/lib/cmake/freenect2` to `catkin_make`.* + +5. Connect your sensor and run `kinect2_bridge`: + + ```bash + roslaunch kinect2_bridge kinect2_bridge.launch + ``` + +6. Calibrate your sensor using the `kinect2_calibration`. [Further details](kinect2_calibration#calibrating-the-kinect-one) +7. Add the calibration files to the `kinect2_bridge/data/` folder. [Further details](kinect2_bridge#first-steps) +8. Restart `kinect2_bridge` and view the results using `rosrun kinect2_viewer kinect2_viewer kinect2 sd cloud`. + +## GPU acceleration + +### OpenCL with AMD + +Install the latest version of the AMD Catalyst drivers from https://support.amd.com and follow the instructions. Also install `opencl-headers`. + +```bash +sudo apt-get install opencl-headers +``` + +### OpenCL/CUDA with Nvidia + +Go to [developer.nvidia.com/cuda-downloads](https://developer.nvidia.com/cuda-downloads) and select `linux`, `x86_64`, `Ubuntu`, `14.04`, `deb(network)`. +Download the file and follow the instructions. Also install `nvidia-modprobe` and `opencl-headers`. + +```bash +sudo apt-get install nvidia-modprobe opencl-headers +``` + +You also need to add CUDA paths to the system environment, add these lines to you `~/.bashrc`: + +```bash +export LD_LIBRARY_PATH="/usr/local/cuda/lib64:${LD_LIBRARY_PATH}" +export PATH="/usr/local/cuda/bin:${PATH}" +``` + +A system-wide configuration of the libary path can be created with the following commands: + +```bash +echo "/usr/local/cuda/lib64" | sudo tee /etc/ld.so.conf.d/cuda.conf +sudo ldconfig +``` + +### OpenCL with Intel + +You can either install a binary package from a PPA like [ppa:floe/beignet](https://launchpad.net/~floe/+archive/ubuntu/beignet), or build beignet yourself. +It's recommended to use the binary from the PPA. + +```bash +sudo add-apt-repository ppa:floe/beignet && sudo apt-get update +sudo apt-get install beignet beignet-dev opencl-headers +``` + +## Citation + +If you used `iai_kinect2` for your work, please cite it. + +```tex +@misc{iai_kinect2, + author = {Wiedemeyer, Thiemo}, + title = {{IAI Kinect2}}, + organization = {Institute for Artificial Intelligence}, + address = {University Bremen}, + year = {2014 -- 2015}, + howpublished = {\url{https://github.com/code-iai/iai\_kinect2}}, + note = {Accessed June 12, 2015} +} +``` + +The result should look something similar to this (may depend on the bibliography style used): + +``` +T. Wiedemeyer, “IAI Kinect2,” https://github.com/code-iai/iai_kinect2, +Institute for Artificial Intelligence, University Bremen, 2014 – 2015, +accessed June 12, 2015. +``` + +## Screenshots + +Here are some screenshots from our toolkit: +![color image](http://ai.uni-bremen.de/wiki/_media/software/kinect2_color.jpg) +![depth image](http://ai.uni-bremen.de/wiki/_media/software/kinect2_depth_colored.png) +![point cloud](http://ai.uni-bremen.de/wiki/_media/software/kinect2_cloud.png) +![image viewer](http://ai.uni-bremen.de/wiki/_media/software/kinect2_viewer.png) + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/CMakeLists.txt new file mode 100644 index 0000000..711b290 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 2.8.3) +project(iai_kinect2) +find_package(catkin REQUIRED) +catkin_metapackage() diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/package.xml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/package.xml new file mode 100644 index 0000000..562efc1 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/iai_kinect2/package.xml @@ -0,0 +1,22 @@ + + + iai_kinect2 + 0.0.1 + + The iai_kinect2 metapackage + + + Thiemo Wiedemeyer + Apache 2.0 + + catkin + + kinect2_calibration + kinect2_viewer + kinect2_bridge + kinect2_registration + + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/CMakeLists.txt new file mode 100644 index 0000000..9ffadef --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/CMakeLists.txt @@ -0,0 +1,144 @@ +cmake_minimum_required(VERSION 2.8.3) +project(kinect2_bridge CXX) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBT_USE_DOUBLE_PRECISION -Wall") +# Unused warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuninitialized -Winit-self -Wunused-function -Wunused-label -Wunused-variable -Wunused-but-set-variable -Wunused-but-set-parameter") +# Additional warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Warray-bounds -Wtype-limits -Wreturn-type -Wsequence-point -Wparentheses -Wmissing-braces -Wchar-subscripts -Wswitch -Wwrite-strings -Wenum-compare -Wempty-body -Wlogical-op") + +# Check for c++11 support +INCLUDE(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +IF(COMPILER_SUPPORTS_CXX11) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +ELSEIF(COMPILER_SUPPORTS_CXX0X) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +ELSE() + MESSAGE(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +ENDIF() + +find_package(freenect2 REQUIRED HINTS "$ENV{HOME}/freenect2") + +find_package(catkin REQUIRED COMPONENTS roscpp rostime tf std_msgs sensor_msgs nodelet cv_bridge compressed_depth_image_transport kinect2_registration) + +## System dependencies are found with CMake's conventions +find_package(OpenCV REQUIRED) + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( + INCLUDE_DIRS include +# LIBRARIES kinect2_bridge + CATKIN_DEPENDS kinect2_registration +# DEPENDS system_lib +) + +########### +## Build ## +########### + +# Display additional files in qtcreator +execute_process(COMMAND find ${PROJECT_SOURCE_DIR} -type f OUTPUT_VARIABLE FILES_STRING) +string(REPLACE "\n" ";" FILES_LIST ${FILES_STRING}) +add_custom_target(additional_files_${PROJECT_NAME} + SOURCES + ${FILES_LIST} + ${PROJECT_SOURCE_DIR}/../README.md +) + +include_directories(include + ${catkin_INCLUDE_DIRS} + ${OpenCV_INCLUDE_DIRS} + ${freenect2_INCLUDE_DIRS} + ${kinect2_registration_INCLUDE_DIRS} +) + +if(DEPTH_REG_OPENCL) + add_definitions(-DDEPTH_REG_OPENCL) +endif() +if(DEPTH_REG_CPU) + add_definitions(-DDEPTH_REG_CPU) +endif() +add_definitions(-DK2_CALIB_PATH="${PROJECT_SOURCE_DIR}/data/") + +add_library(kinect2_bridge_nodelet SHARED src/kinect2_bridge.cpp) +target_link_libraries(kinect2_bridge_nodelet + ${catkin_LIBRARIES} + ${OpenCV_LIBRARIES} + ${freenect2_LIBRARY} + ${kinect2_registration_LIBRARY} +) + +add_executable(kinect2_bridge src/kinect2_bridge.cpp) +target_link_libraries(kinect2_bridge + ${catkin_LIBRARIES} + ${OpenCV_LIBRARIES} + ${freenect2_LIBRARY} + ${kinect2_registration_LIBRARY} +) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +install(TARGETS kinect2_bridge kinect2_bridge_nodelet +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +## Mark cpp header files for installation +install(DIRECTORY include/${PROJECT_NAME}/ + DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} + FILES_MATCHING PATTERN "*.h" + PATTERN ".svn" EXCLUDE +) + +## Mark other files for installation (e.g. launch and bag files, etc.) +install(DIRECTORY + launch + # myfile2 + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +) +install(FILES + nodelet_plugins.xml + # myfile2 + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_kinect2_bridge.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/README.md b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/README.md new file mode 100644 index 0000000..9722817 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/README.md @@ -0,0 +1,171 @@ +# Kinect2 Bridge + +## Maintainer + +- [Thiemo Wiedemeyer](https://ai.uni-bremen.de/team/thiemo_wiedemeyer) <>, [Institute for Artificial Intelligence](http://ai.uni-bremen.de/), University of Bremen + +*Note:* ***Please use the GitHub issues*** *for questions and problems regarding the iai_kinect2 package and its components.* ***Do not write emails.*** + +## Description + +This is a bridge between [libfreenect2](https://github.com/OpenKinect/libfreenect2) and ROS. + +### Highlights + +- delivers up to 30 frames per second on non high end hardware +- delivers up to 30 frames per second over gigabit ethernet +- support for compressed image transport +- utilizes multiple cores and uses special OpenCL based implementation of the depth registration + +## Dependencies + +- ROS Hydro/Indigo +- OpenCV +- [libfreenect2](https://github.com/OpenKinect/libfreenect2) + +*for the ROS packages look at the package.xml* + +## First steps + +For the depth registration the camera intrinsic and extrinsic parameters need to be known. The program reads in the values from the `data/` folder. For each new sensor you need to add a sub-folder with the serial number of the device as the folder name. In this folder you need to provide 4 yaml files with the intrinsic and extrinsic parameters. These files can be created by the `kinect2_calibration` tool (or you can copy the files provided in one of the other folders, but results can be sub optimal). The device serial number is shown when `kinect2_bridge` or `Protonect` from libfreenect2 is started, it also appears in `dmesg` when you connect the sensor. [More information on calibration](../kinect2_calibration#calibrating-the-kinect-one). + +When `kinect2_bridge` is running you can use the `kinect2_viewer` to display the images or point cloud: `rosrun kinect2_viewer kinect2_viewer sd image` or `rosrun kinect2_viewer kinect2_viewer sd cloud`. + +## Topics + +### HD Topics + +The images in this topics have a FullHD resolution (1920x1080). + +*Note: For correct registration of the depth image to the color image it is needed to perform a calibration.* + +``` +/kinect2/hd/camera_info +/kinect2/hd/image_color +/kinect2/hd/image_color/compressed +/kinect2/hd/image_color_rect +/kinect2/hd/image_color_rect/compressed +/kinect2/hd/image_depth_rect +/kinect2/hd/image_depth_rect/compressed +/kinect2/hd/image_mono +/kinect2/hd/image_mono/compressed +/kinect2/hd/image_mono_rect +/kinect2/hd/image_mono_rect/compressed +/kinect2/hd/points +``` + +### Quater HD Topics + +The images in this topics have a quarter FullHD resolution (960x540). + +*Note: For correct registration of the depth image to the color image it is needed to perform a calibration.* + +``` +/kinect2/qhd/camera_info +/kinect2/qhd/image_color +/kinect2/qhd/image_color/compressed +/kinect2/qhd/image_color_rect +/kinect2/qhd/image_color_rect/compressed +/kinect2/qhd/image_depth_rect +/kinect2/qhd/image_depth_rect/compressed +/kinect2/qhd/image_mono +/kinect2/qhd/image_mono/compressed +/kinect2/qhd/image_mono_rect +/kinect2/qhd/image_mono_rect/compressed +/kinect2/qhd/points +``` + +### IR/Depth Topics + +This are the raw IR and depth images from the sensor (512x424). + +*Note: The registration of the color image is available without a calibration. Parameters for the registration are provided by the sensor itself.* + +``` +/kinect2/sd/camera_info +/kinect2/sd/image_color_rect +/kinect2/sd/image_color_rect/compressed +/kinect2/sd/image_depth +/kinect2/sd/image_depth/compressed +/kinect2/sd/image_depth_rect +/kinect2/sd/image_depth_rect/compressed +/kinect2/sd/image_ir +/kinect2/sd/image_ir/compressed +/kinect2/sd/image_ir_rect +/kinect2/sd/image_ir_rect/compressed +/kinect2/sd/points +``` + +## Notes + +- Point clouds are only published when the launch file is used. Run `roslaunch kinect2_bridge kinect2_bridge.launch`. +- Images from the same frame have the same timestamp. Using the `message_filters::sync_policies::ExactTime` policy is recommended. + +## Usage + +``` +roslaunch kinect2_bridge kinect2_bridge.launch [options:=value] +base_name:= + default: kinect2 + info: set base name for all topics +sensor:= + default: + info: serial of the sensor to use +fps_limit:= + default: -1.0 + info: limit the frames per second +calib_path:= + default: /home/wiedemeyer/work/src/iai_kinect2/kinect2_bridge/data/ + info: path to the calibration files +use_png:= + default: false + info: Use PNG compression instead of TIFF +jpeg_quality:= + default: 90 + info: JPEG quality level from 0 to 100 +png_level:= + default: 1 + info: PNG compression level from 0 to 9 +depth_method:= + default: cuda + info: Use specific depth processing: default, cpu, opengl, opencl, cuda, clkde, cudakde +depth_device:= + default: -1 + info: openCL device to use for depth processing +reg_method:= + default: opencl + info: Use specific depth registration: default, cpu, opencl +reg_device:= + default: -1 + info: openCL device to use for depth registration +max_depth:= + default: 12.0 + info: max depth value +min_depth:= + default: 0.1 + info: min depth value +queue_size:= + default: 2 + info: queue size of publisher +bilateral_filter:= + default: true + info: enable bilateral filtering of depth images +edge_aware_filter:= + default: true + info: enable edge aware filtering of depth images +publish_tf:= + default: false + info: publish static tf transforms for camera +base_name_tf:= + default: as base_name + info: base name for the tf frames +worker_threads:= + default: 4 + info: number of threads used for processing the images +``` + +## Key bindings + +Terminal: +- `CRTL`+`c`: Quit + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_color.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_color.yaml new file mode 100644 index 0000000..9267859 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_color.yaml @@ -0,0 +1,26 @@ +%YAML:1.0 +cameraMatrix: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1.0599465578241038e+03, 0., 9.5488326677588441e+02, 0., + 1.0539326808799726e+03, 5.2373858291060583e+02, 0., 0., 1. ] +distortionCoefficients: !!opencv-matrix + rows: 1 + cols: 5 + dt: d + data: [ 5.6268441170930321e-02, -7.4199141308694802e-02, + 1.4250797540545752e-03, -1.6951722389720336e-03, + 2.4107681263086548e-02 ] +rotation: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ] +projection: !!opencv-matrix + rows: 4 + cols: 4 + dt: d + data: [ 1.0599465578241038e+03, 0., 9.5488326677588441e+02, 0., 0., + 1.0539326808799726e+03, 5.2373858291060583e+02, 0., 0., 0., 1., + 0., 0., 0., 0., 1. ] diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_depth.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_depth.yaml new file mode 100644 index 0000000..4450cad --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_depth.yaml @@ -0,0 +1,2 @@ +%YAML:1.0 +depthShift: -1.3354238655403018e+01 diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_ir.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_ir.yaml new file mode 100644 index 0000000..1898950 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_ir.yaml @@ -0,0 +1,26 @@ +%YAML:1.0 +cameraMatrix: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 3.6694757270064110e+02, 0., 2.4298551682775121e+02, 0., + 3.6479117165721783e+02, 2.0769853575457685e+02, 0., 0., 1. ] +distortionCoefficients: !!opencv-matrix + rows: 1 + cols: 5 + dt: d + data: [ 9.6558110377123016e-02, -2.8298244017989416e-01, + 1.5889951609432634e-04, -5.0751483524871712e-04, + 1.0523948765859192e-01 ] +rotation: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ] +projection: !!opencv-matrix + rows: 4 + cols: 4 + dt: d + data: [ 3.6694757270064110e+02, 0., 2.4298551682775121e+02, 0., 0., + 3.6479117165721783e+02, 2.0769853575457685e+02, 0., 0., 0., 1., + 0., 0., 0., 0., 1. ] diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_pose.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_pose.yaml new file mode 100644 index 0000000..a022a52 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/196605135147/calib_pose.yaml @@ -0,0 +1,33 @@ +%YAML:1.0 +rotation: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 9.9979883926593693e-01, -1.6871335541758126e-02, + -1.0846153213119176e-02, 1.6891097527572209e-02, + 9.9985583336600126e-01, 1.7330055664057141e-03, + 1.0815351441312036e-02, -1.9158603854556545e-03, + 9.9993967700666042e-01 ] +translation: !!opencv-matrix + rows: 3 + cols: 1 + dt: d + data: [ -5.2052476112081990e-02, -4.6313865353939110e-04, + 8.8806735554907584e-04 ] +essential: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ -2.0009439617717153e-05, -8.8705201686837285e-04, + -4.6464974129998811e-04, 1.4508545338106024e-03, + -1.1470815928716492e-04, 5.2039704036310315e-02, + -4.1617796233292743e-04, -5.2052785649435836e-02, + -9.5230503642644511e-05 ] +fundamental: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ -1.1817221592596941e-08, -5.2697406371005770e-07, + 1.1627629703684574e-05, 8.6173835202613450e-07, + -6.8533918097934840e-08, 1.1146863908955499e-02, + -7.0056301516242358e-04, -3.2237824184460216e-02, 1. ] diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_color.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_color.yaml new file mode 100644 index 0000000..b450500 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_color.yaml @@ -0,0 +1,26 @@ +%YAML:1.0 +cameraMatrix: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1.0660120360637927e+03, 0., 9.4558752751085558e+02, 0., + 1.0688708399911650e+03, 5.2006994012356529e+02, 0., 0., 1. ] +distortionCoefficients: !!opencv-matrix + rows: 1 + cols: 5 + dt: d + data: [ 5.9360108008991816e-02, -6.2758287999836640e-02, + -1.5766859436148536e-03, -1.1502971845708829e-03, + 7.7657531491476016e-03 ] +rotation: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ] +projection: !!opencv-matrix + rows: 4 + cols: 4 + dt: d + data: [ 1.0705899358803581e+03, 0., 9.4912209493857927e+02, 0., 0., + 1.0734714110656350e+03, 5.1739403678512770e+02, 0., 0., 0., 1., + 0., 0., 0., 0., 1. ] diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_ir.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_ir.yaml new file mode 100644 index 0000000..616cd60 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_ir.yaml @@ -0,0 +1,26 @@ +%YAML:1.0 +cameraMatrix: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 3.6638346288148574e+02, 0., 2.5564531890330468e+02, 0., + 3.6714380707081017e+02, 2.0398020160452000e+02, 0., 0., 1. ] +distortionCoefficients: !!opencv-matrix + rows: 1 + cols: 5 + dt: d + data: [ 1.0952761399998089e-01, -3.1461678804886056e-01, + -1.2613602146463686e-03, -7.1815538262097348e-04, + 1.2565382780717374e-01 ] +rotation: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ] +projection: !!opencv-matrix + rows: 4 + cols: 4 + dt: d + data: [ 3.6677544568158339e+02, 0., 2.5556683247282524e+02, 0., 0., + 3.6781383188070873e+02, 2.0379944675671842e+02, 0., 0., 0., 1., + 0., 0., 0., 0., 1. ] diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_pose.yaml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_pose.yaml new file mode 100644 index 0000000..0b29c98 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/data/299150235147/calib_pose.yaml @@ -0,0 +1,33 @@ +%YAML:1.0 +rotation: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 9.9999932279092762e-01, 1.1418659978192800e-03, + -2.2485490683788145e-04, -1.1422648685177200e-03, + 9.9999776014165309e-01, -1.7818368744440499e-03, + 2.2281978425420061e-04, 1.7820925116285419e-03, + 9.9999838724751144e-01 ] +translation: !!opencv-matrix + rows: 3 + cols: 1 + dt: d + data: [ -5.2017152124108991e-02, -2.4045118112262469e-04, + 2.9454469402941368e-04 ] +essential: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 2.8287077589668930e-07, -2.9497254054031309e-04, + -2.3992596273739050e-04, 3.0613494517488655e-04, + 9.3035707847567608e-05, 5.2017002003497723e-02, + 2.9986838371861500e-04, -5.2016761050028761e-02, + 9.2632013130372647e-05 ] +fundamental: !!opencv-matrix + rows: 3 + cols: 3 + dt: d + data: [ 1.9731570930693606e-10, -2.0533114366326771e-07, + -1.9484772545527813e-05, 2.1297242074431652e-07, + 6.4589181747782925e-08, 1.3190795684430680e-02, + 1.1203310138770501e-04, -3.8438663277953075e-02, 1. ] diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/include/kinect2_bridge/kinect2_definitions.h b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/include/kinect2_bridge/kinect2_definitions.h new file mode 100644 index 0000000..0d6f61e --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/include/kinect2_bridge/kinect2_definitions.h @@ -0,0 +1,57 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#pragma once +#ifndef __KINECT2_DEFINITIONS_H__ +#define __KINECT2_DEFINITIONS_H__ + +#include + +#define K2_DEFAULT_NS "kinect2" + +#define K2_TF_LINK "_link" +#define K2_TF_RGB_OPT_FRAME "_rgb_optical_frame" +#define K2_TF_IR_OPT_FRAME "_ir_optical_frame" + +#define K2_TOPIC_HD "/hd" +#define K2_TOPIC_QHD "/qhd" +#define K2_TOPIC_SD "/sd" + +#define K2_TOPIC_IMAGE_RECT "_rect" +#define K2_TOPIC_IMAGE_COLOR "/image_color" +#define K2_TOPIC_IMAGE_MONO "/image_mono" +#define K2_TOPIC_IMAGE_DEPTH "/image_depth" +#define K2_TOPIC_IMAGE_IR "/image_ir" + +#define K2_TOPIC_COMPRESSED "/compressed" +#define K2_TOPIC_INFO "/camera_info" + +#define K2_CALIB_COLOR "calib_color.yaml" +#define K2_CALIB_IR "calib_ir.yaml" +#define K2_CALIB_POSE "calib_pose.yaml" +#define K2_CALIB_DEPTH "calib_depth.yaml" + +#define K2_CALIB_CAMERA_MATRIX "cameraMatrix" +#define K2_CALIB_DISTORTION "distortionCoefficients" +#define K2_CALIB_ROTATION "rotation" +#define K2_CALIB_PROJECTION "projection" +#define K2_CALIB_TRANSLATION "translation" +#define K2_CALIB_ESSENTIAL "essential" +#define K2_CALIB_FUNDAMENTAL "fundamental" +#define K2_CALIB_DEPTH_SHIFT "depthShift" + +#endif //__KINECT2_DEFINITIONS_H__ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/launch/kinect2_bridge.launch b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/launch/kinect2_bridge.launch new file mode 100644 index 0000000..a3807de --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/launch/kinect2_bridge.launch @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/nodelet_plugins.xml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/nodelet_plugins.xml new file mode 100644 index 0000000..ceb5655 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/nodelet_plugins.xml @@ -0,0 +1,5 @@ + + + Kinect2Bridge nodelet + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/package.xml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/package.xml new file mode 100644 index 0000000..8c570a3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/package.xml @@ -0,0 +1,39 @@ + + + kinect2_bridge + 0.0.1 + The kinect2_bridge package + + Thiemo Wiedemeyer + + Apache 2.0 + + catkin + + roscpp + rostime + tf + std_msgs + sensor_msgs + message_filters + compressed_depth_image_transport + kinect2_registration + nodelet + cv_bridge + + message_runtime + roscpp + rostime + tf + std_msgs + sensor_msgs + compressed_depth_image_transport + kinect2_registration + nodelet + depth_image_proc + cv_bridge + + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/src/kinect2_bridge.cpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/src/kinect2_bridge.cpp new file mode 100644 index 0000000..e5f4307 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_bridge/src/kinect2_bridge.cpp @@ -0,0 +1,1632 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#elif defined(__APPLE__) +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +class Kinect2Bridge +{ +private: + std::vector compressionParams; + std::string compression16BitExt, compression16BitString, baseNameTF; + + cv::Size sizeColor, sizeIr, sizeLowRes; + libfreenect2::Frame color; + cv::Mat cameraMatrixColor, distortionColor, cameraMatrixLowRes, cameraMatrixIr, distortionIr, cameraMatrixDepth, distortionDepth; + cv::Mat rotation, translation; + cv::Mat map1Color, map2Color, map1Ir, map2Ir, map1LowRes, map2LowRes; + + std::vector threads; + std::mutex lockIrDepth, lockColor; + std::mutex lockSync, lockPub, lockTime, lockStatus; + std::mutex lockRegLowRes, lockRegHighRes, lockRegSD; + + bool publishTF; + std::thread tfPublisher, mainThread; + + libfreenect2::Freenect2 freenect2; + libfreenect2::Freenect2Device *device; + libfreenect2::SyncMultiFrameListener *listenerColor, *listenerIrDepth; + libfreenect2::PacketPipeline *packetPipeline; + libfreenect2::Registration *registration; + libfreenect2::Freenect2Device::ColorCameraParams colorParams; + libfreenect2::Freenect2Device::IrCameraParams irParams; + + ros::NodeHandle nh, priv_nh; + + DepthRegistration *depthRegLowRes, *depthRegHighRes; + + size_t frameColor, frameIrDepth, pubFrameColor, pubFrameIrDepth; + ros::Time lastColor, lastDepth; + + bool nextColor, nextIrDepth; + double deltaT, depthShift, elapsedTimeColor, elapsedTimeIrDepth; + bool running, deviceActive, clientConnected, isSubscribedColor, isSubscribedDepth; + + enum Image + { + IR_SD = 0, + IR_SD_RECT, + + DEPTH_SD, + DEPTH_SD_RECT, + DEPTH_HD, + DEPTH_QHD, + + COLOR_SD_RECT, + COLOR_HD, + COLOR_HD_RECT, + COLOR_QHD, + COLOR_QHD_RECT, + + MONO_HD, + MONO_HD_RECT, + MONO_QHD, + MONO_QHD_RECT, + + COUNT + }; + + enum Status + { + UNSUBCRIBED = 0, + RAW, + COMPRESSED, + BOTH + }; + + std::vector imagePubs, compressedPubs; + ros::Publisher infoHDPub, infoQHDPub, infoIRPub; + sensor_msgs::CameraInfo infoHD, infoQHD, infoIR; + std::vector status; + +public: + Kinect2Bridge(const ros::NodeHandle &nh = ros::NodeHandle(), const ros::NodeHandle &priv_nh = ros::NodeHandle("~")) + : sizeColor(1920, 1080), sizeIr(512, 424), sizeLowRes(sizeColor.width / 2, sizeColor.height / 2), color(sizeColor.width, sizeColor.height, 4), nh(nh), priv_nh(priv_nh), + frameColor(0), frameIrDepth(0), pubFrameColor(0), pubFrameIrDepth(0), lastColor(0, 0), lastDepth(0, 0), nextColor(false), + nextIrDepth(false), depthShift(0), running(false), deviceActive(false), clientConnected(false) + { + status.resize(COUNT, UNSUBCRIBED); + } + + bool start() + { + if(running) + { + OUT_ERROR("kinect2_bridge is already running!"); + return false; + } + if(!initialize()) + { + OUT_ERROR("Initialization failed!"); + return false; + } + running = true; + + if(publishTF) + { + tfPublisher = std::thread(&Kinect2Bridge::publishStaticTF, this); + } + + for(size_t i = 0; i < threads.size(); ++i) + { + threads[i] = std::thread(&Kinect2Bridge::threadDispatcher, this, i); + } + + mainThread = std::thread(&Kinect2Bridge::main, this); + return true; + } + + void stop() + { + if(!running) + { + OUT_ERROR("kinect2_bridge is not running!"); + return; + } + running = false; + + mainThread.join(); + + for(size_t i = 0; i < threads.size(); ++i) + { + threads[i].join(); + } + + if(publishTF) + { + tfPublisher.join(); + } + + if(deviceActive && !device->stop()) + { + OUT_ERROR("could not stop device!"); + } + + if(!device->close()) + { + OUT_ERROR("could not close device!"); + } + + delete listenerIrDepth; + delete listenerColor; + delete registration; + + delete depthRegLowRes; + delete depthRegHighRes; + + for(size_t i = 0; i < COUNT; ++i) + { + imagePubs[i].shutdown(); + compressedPubs[i].shutdown(); + infoHDPub.shutdown(); + infoQHDPub.shutdown(); + infoIRPub.shutdown(); + } + + nh.shutdown(); + } + +private: + bool initialize() + { + double fps_limit, maxDepth, minDepth; + bool use_png, bilateral_filter, edge_aware_filter; + int32_t jpeg_quality, png_level, queueSize, reg_dev, depth_dev, worker_threads; + std::string depth_method, reg_method, calib_path, sensor, base_name; + + std::string depthDefault = "cpu"; + std::string regDefault = "default"; + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT + depthDefault = "opengl"; +#endif +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + depthDefault = "opencl"; +#endif +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + depthDefault = "cuda"; +#endif +#ifdef DEPTH_REG_OPENCL + regDefault = "opencl"; +#endif + + priv_nh.param("base_name", base_name, std::string(K2_DEFAULT_NS)); + priv_nh.param("sensor", sensor, std::string("")); + priv_nh.param("fps_limit", fps_limit, -1.0); + priv_nh.param("calib_path", calib_path, std::string(K2_CALIB_PATH)); + priv_nh.param("use_png", use_png, false); + priv_nh.param("jpeg_quality", jpeg_quality, 90); + priv_nh.param("png_level", png_level, 1); + priv_nh.param("depth_method", depth_method, depthDefault); + priv_nh.param("depth_device", depth_dev, -1); + priv_nh.param("reg_method", reg_method, regDefault); + priv_nh.param("reg_device", reg_dev, -1); + priv_nh.param("max_depth", maxDepth, 12.0); + priv_nh.param("min_depth", minDepth, 0.1); + priv_nh.param("queue_size", queueSize, 2); + priv_nh.param("bilateral_filter", bilateral_filter, true); + priv_nh.param("edge_aware_filter", edge_aware_filter, true); + priv_nh.param("publish_tf", publishTF, false); + priv_nh.param("base_name_tf", baseNameTF, base_name); + priv_nh.param("worker_threads", worker_threads, 4); + + worker_threads = std::max(1, worker_threads); + threads.resize(worker_threads); + + OUT_INFO("parameter:" << std::endl + << " base_name: " FG_CYAN << base_name << NO_COLOR << std::endl + << " sensor: " FG_CYAN << (sensor.empty() ? "default" : sensor) << NO_COLOR << std::endl + << " fps_limit: " FG_CYAN << fps_limit << NO_COLOR << std::endl + << " calib_path: " FG_CYAN << calib_path << NO_COLOR << std::endl + << " use_png: " FG_CYAN << (use_png ? "true" : "false") << NO_COLOR << std::endl + << " jpeg_quality: " FG_CYAN << jpeg_quality << NO_COLOR << std::endl + << " png_level: " FG_CYAN << png_level << NO_COLOR << std::endl + << " depth_method: " FG_CYAN << depth_method << NO_COLOR << std::endl + << " depth_device: " FG_CYAN << depth_dev << NO_COLOR << std::endl + << " reg_method: " FG_CYAN << reg_method << NO_COLOR << std::endl + << " reg_device: " FG_CYAN << reg_dev << NO_COLOR << std::endl + << " max_depth: " FG_CYAN << maxDepth << NO_COLOR << std::endl + << " min_depth: " FG_CYAN << minDepth << NO_COLOR << std::endl + << " queue_size: " FG_CYAN << queueSize << NO_COLOR << std::endl + << " bilateral_filter: " FG_CYAN << (bilateral_filter ? "true" : "false") << NO_COLOR << std::endl + << "edge_aware_filter: " FG_CYAN << (edge_aware_filter ? "true" : "false") << NO_COLOR << std::endl + << " publish_tf: " FG_CYAN << (publishTF ? "true" : "false") << NO_COLOR << std::endl + << " base_name_tf: " FG_CYAN << baseNameTF << NO_COLOR << std::endl + << " worker_threads: " FG_CYAN << worker_threads << NO_COLOR); + + deltaT = fps_limit > 0 ? 1.0 / fps_limit : 0.0; + + if(calib_path.empty() || calib_path.back() != '/') + { + calib_path += '/'; + } + + initCompression(jpeg_quality, png_level, use_png); + + if(!initPipeline(depth_method, depth_dev)) + { + return false; + } + + if(!initDevice(sensor)) + { + return false; + } + + initConfig(bilateral_filter, edge_aware_filter, minDepth, maxDepth); + + initCalibration(calib_path, sensor); + + if(!initRegistration(reg_method, reg_dev, maxDepth)) + { + if(!device->close()) + { + OUT_ERROR("could not close device!"); + } + delete listenerIrDepth; + delete listenerColor; + return false; + } + + createCameraInfo(); + initTopics(queueSize, base_name); + + return true; + } + + bool initRegistration(const std::string &method, const int32_t device, const double maxDepth) + { + DepthRegistration::Method reg; + + if(method == "default") + { + reg = DepthRegistration::DEFAULT; + } + else if(method == "cpu") + { +#ifdef DEPTH_REG_CPU + reg = DepthRegistration::CPU; +#else + OUT_ERROR("CPU registration is not available!"); + return false; +#endif + } + else if(method == "opencl") + { +#ifdef DEPTH_REG_OPENCL + reg = DepthRegistration::OPENCL; +#else + OUT_ERROR("OpenCL registration is not available!"); + return false; +#endif + } + else + { + OUT_ERROR("Unknown registration method: " << method); + return false; + } + + depthRegLowRes = DepthRegistration::New(reg); + depthRegHighRes = DepthRegistration::New(reg); + + if(!depthRegLowRes->init(cameraMatrixLowRes, sizeLowRes, cameraMatrixDepth, sizeIr, distortionDepth, rotation, translation, 0.5f, maxDepth, device) || + !depthRegHighRes->init(cameraMatrixColor, sizeColor, cameraMatrixDepth, sizeIr, distortionDepth, rotation, translation, 0.5f, maxDepth, device)) + { + delete depthRegLowRes; + delete depthRegHighRes; + return false; + } + + registration = new libfreenect2::Registration(irParams, colorParams); + + return true; + } + + bool initPipeline(const std::string &method, const int32_t device) + { + if(method == "default") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + packetPipeline = new libfreenect2::CudaPacketPipeline(device); +#elif defined(LIBFREENECT2_WITH_OPENCL_SUPPORT) + packetPipeline = new libfreenect2::OpenCLPacketPipeline(device); +#elif defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) + packetPipeline = new libfreenect2::OpenGLPacketPipeline(); +#else + packetPipeline = new libfreenect2::CpuPacketPipeline(); +#endif + } + else if(method == "cpu") + { + packetPipeline = new libfreenect2::CpuPacketPipeline(); + } + else if(method == "cuda") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + packetPipeline = new libfreenect2::CudaPacketPipeline(device); +#else + OUT_ERROR("Cuda depth processing is not available!"); + return false; +#endif + } + else if(method == "opencl") + { +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + packetPipeline = new libfreenect2::OpenCLPacketPipeline(device); +#else + OUT_ERROR("OpenCL depth processing is not available!"); + return false; +#endif + } + else if(method == "opengl") + { +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT + packetPipeline = new libfreenect2::OpenGLPacketPipeline(); +#else + OUT_ERROR("OpenGL depth processing is not available!"); + return false; +#endif + } + else if(method == "clkde") + { +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + packetPipeline = new libfreenect2::OpenCLKdePacketPipeline(device); +#else + OUT_ERROR("OpenCL depth processing is not available!"); + return false; +#endif + } + else if(method == "cudakde") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + packetPipeline = new libfreenect2::CudaKdePacketPipeline(device); +#else + OUT_ERROR("Cuda depth processing is not available!"); + return false; +#endif + } + else + { + OUT_ERROR("Unknown depth processing method: " << method); + return false; + } + + return true; + } + + void initConfig(const bool bilateral_filter, const bool edge_aware_filter, const double minDepth, const double maxDepth) + { + libfreenect2::Freenect2Device::Config config; + config.EnableBilateralFilter = bilateral_filter; + config.EnableEdgeAwareFilter = edge_aware_filter; + config.MinDepth = minDepth; + config.MaxDepth = maxDepth; + device->setConfiguration(config); + } + + void initCompression(const int32_t jpegQuality, const int32_t pngLevel, const bool use_png) + { + compressionParams.resize(7, 0); + compressionParams[0] = CV_IMWRITE_JPEG_QUALITY; + compressionParams[1] = jpegQuality; + compressionParams[2] = CV_IMWRITE_PNG_COMPRESSION; + compressionParams[3] = pngLevel; + compressionParams[4] = CV_IMWRITE_PNG_STRATEGY; + compressionParams[5] = CV_IMWRITE_PNG_STRATEGY_RLE; + compressionParams[6] = 0; + + if(use_png) + { + compression16BitExt = ".png"; + compression16BitString = sensor_msgs::image_encodings::TYPE_16UC1 + "; png compressed"; + } + else + { + compression16BitExt = ".tif"; + compression16BitString = sensor_msgs::image_encodings::TYPE_16UC1 + "; tiff compressed"; + } + } + + void initTopics(const int32_t queueSize, const std::string &base_name) + { + std::vector topics(COUNT); + topics[IR_SD] = K2_TOPIC_SD K2_TOPIC_IMAGE_IR; + topics[IR_SD_RECT] = K2_TOPIC_SD K2_TOPIC_IMAGE_IR K2_TOPIC_IMAGE_RECT; + + topics[DEPTH_SD] = K2_TOPIC_SD K2_TOPIC_IMAGE_DEPTH; + topics[DEPTH_SD_RECT] = K2_TOPIC_SD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + topics[DEPTH_HD] = K2_TOPIC_HD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + topics[DEPTH_QHD] = K2_TOPIC_QHD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + + topics[COLOR_SD_RECT] = K2_TOPIC_SD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + + topics[COLOR_HD] = K2_TOPIC_HD K2_TOPIC_IMAGE_COLOR; + topics[COLOR_HD_RECT] = K2_TOPIC_HD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + topics[COLOR_QHD] = K2_TOPIC_QHD K2_TOPIC_IMAGE_COLOR; + topics[COLOR_QHD_RECT] = K2_TOPIC_QHD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + + topics[MONO_HD] = K2_TOPIC_HD K2_TOPIC_IMAGE_MONO; + topics[MONO_HD_RECT] = K2_TOPIC_HD K2_TOPIC_IMAGE_MONO K2_TOPIC_IMAGE_RECT; + topics[MONO_QHD] = K2_TOPIC_QHD K2_TOPIC_IMAGE_MONO; + topics[MONO_QHD_RECT] = K2_TOPIC_QHD K2_TOPIC_IMAGE_MONO K2_TOPIC_IMAGE_RECT; + + imagePubs.resize(COUNT); + compressedPubs.resize(COUNT); + ros::SubscriberStatusCallback cb = boost::bind(&Kinect2Bridge::callbackStatus, this); + + for(size_t i = 0; i < COUNT; ++i) + { + imagePubs[i] = nh.advertise(base_name + topics[i], queueSize, cb, cb); + compressedPubs[i] = nh.advertise(base_name + topics[i] + K2_TOPIC_COMPRESSED, queueSize, cb, cb); + } + infoHDPub = nh.advertise(base_name + K2_TOPIC_HD + K2_TOPIC_INFO, queueSize, cb, cb); + infoQHDPub = nh.advertise(base_name + K2_TOPIC_QHD + K2_TOPIC_INFO, queueSize, cb, cb); + infoIRPub = nh.advertise(base_name + K2_TOPIC_SD + K2_TOPIC_INFO, queueSize, cb, cb); + } + + bool initDevice(std::string &sensor) + { + bool deviceFound = false; + const int numOfDevs = freenect2.enumerateDevices(); + + if(numOfDevs <= 0) + { + OUT_ERROR("no Kinect2 devices found!"); + delete packetPipeline; + return false; + } + + if(sensor.empty()) + { + sensor = freenect2.getDefaultDeviceSerialNumber(); + } + + OUT_INFO("Kinect2 devices found: "); + for(int i = 0; i < numOfDevs; ++i) + { + const std::string &s = freenect2.getDeviceSerialNumber(i); + deviceFound = deviceFound || s == sensor; + OUT_INFO(" " << i << ": " FG_CYAN << s << (s == sensor ? FG_YELLOW " (selected)" : "") << NO_COLOR); + } + + if(!deviceFound) + { + OUT_ERROR("Device with serial '" << sensor << "' not found!"); + delete packetPipeline; + return false; + } + + device = freenect2.openDevice(sensor, packetPipeline); + + if(device == 0) + { + OUT_INFO("no device connected or failure opening the default one!"); + return false; + } + + listenerColor = new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Color); + listenerIrDepth = new libfreenect2::SyncMultiFrameListener(libfreenect2::Frame::Ir | libfreenect2::Frame::Depth); + + device->setColorFrameListener(listenerColor); + device->setIrAndDepthFrameListener(listenerIrDepth); + + OUT_INFO("starting kinect2"); + if(!device->start()) + { + OUT_ERROR("could not start device!"); + delete listenerIrDepth; + delete listenerColor; + return false; + } + + OUT_INFO("device serial: " FG_CYAN << sensor << NO_COLOR); + OUT_INFO("device firmware: " FG_CYAN << device->getFirmwareVersion() << NO_COLOR); + + colorParams = device->getColorCameraParams(); + irParams = device->getIrCameraParams(); + + if(!device->stop()) + { + OUT_ERROR("could not stop device!"); + delete listenerIrDepth; + delete listenerColor; + return false; + } + + OUT_DEBUG("default ir camera parameters: "); + OUT_DEBUG("fx: " FG_CYAN << irParams.fx << NO_COLOR ", fy: " FG_CYAN << irParams.fy << NO_COLOR ", cx: " FG_CYAN << irParams.cx << NO_COLOR ", cy: " FG_CYAN << irParams.cy << NO_COLOR); + OUT_DEBUG("k1: " FG_CYAN << irParams.k1 << NO_COLOR ", k2: " FG_CYAN << irParams.k2 << NO_COLOR ", p1: " FG_CYAN << irParams.p1 << NO_COLOR ", p2: " FG_CYAN << irParams.p2 << NO_COLOR ", k3: " FG_CYAN << irParams.k3 << NO_COLOR); + + OUT_DEBUG("default color camera parameters: "); + OUT_DEBUG("fx: " FG_CYAN << colorParams.fx << NO_COLOR ", fy: " FG_CYAN << colorParams.fy << NO_COLOR ", cx: " FG_CYAN << colorParams.cx << NO_COLOR ", cy: " FG_CYAN << colorParams.cy << NO_COLOR); + + cameraMatrixColor = cv::Mat::eye(3, 3, CV_64F); + distortionColor = cv::Mat::zeros(1, 5, CV_64F); + + cameraMatrixColor.at(0, 0) = colorParams.fx; + cameraMatrixColor.at(1, 1) = colorParams.fy; + cameraMatrixColor.at(0, 2) = colorParams.cx; + cameraMatrixColor.at(1, 2) = colorParams.cy; + cameraMatrixColor.at(2, 2) = 1; + + cameraMatrixIr = cv::Mat::eye(3, 3, CV_64F); + distortionIr = cv::Mat::zeros(1, 5, CV_64F); + + cameraMatrixIr.at(0, 0) = irParams.fx; + cameraMatrixIr.at(1, 1) = irParams.fy; + cameraMatrixIr.at(0, 2) = irParams.cx; + cameraMatrixIr.at(1, 2) = irParams.cy; + cameraMatrixIr.at(2, 2) = 1; + + distortionIr.at(0, 0) = irParams.k1; + distortionIr.at(0, 1) = irParams.k2; + distortionIr.at(0, 2) = irParams.p1; + distortionIr.at(0, 3) = irParams.p2; + distortionIr.at(0, 4) = irParams.k3; + + cameraMatrixDepth = cameraMatrixIr.clone(); + distortionDepth = distortionIr.clone(); + + rotation = cv::Mat::eye(3, 3, CV_64F); + translation = cv::Mat::zeros(3, 1, CV_64F); + return true; + } + + void initCalibration(const std::string &calib_path, const std::string &sensor) + { + std::string calibPath = calib_path + sensor + '/'; + + struct stat fileStat; + bool calibDirNotFound = stat(calibPath.c_str(), &fileStat) != 0 || !S_ISDIR(fileStat.st_mode); + if(calibDirNotFound || !loadCalibrationFile(calibPath + K2_CALIB_COLOR, cameraMatrixColor, distortionColor)) + { + OUT_WARN("using sensor defaults for color intrinsic parameters."); + } + + if(calibDirNotFound || !loadCalibrationFile(calibPath + K2_CALIB_IR, cameraMatrixDepth, distortionDepth)) + { + OUT_WARN("using sensor defaults for ir intrinsic parameters."); + } + + if(calibDirNotFound || !loadCalibrationPoseFile(calibPath + K2_CALIB_POSE, rotation, translation)) + { + OUT_WARN("using defaults for rotation and translation."); + } + + if(calibDirNotFound || !loadCalibrationDepthFile(calibPath + K2_CALIB_DEPTH, depthShift)) + { + OUT_WARN("using defaults for depth shift."); + depthShift = 0.0; + } + + cameraMatrixLowRes = cameraMatrixColor.clone(); + cameraMatrixLowRes.at(0, 0) /= 2; + cameraMatrixLowRes.at(1, 1) /= 2; + cameraMatrixLowRes.at(0, 2) /= 2; + cameraMatrixLowRes.at(1, 2) /= 2; + + const int mapType = CV_16SC2; + cv::initUndistortRectifyMap(cameraMatrixColor, distortionColor, cv::Mat(), cameraMatrixColor, sizeColor, mapType, map1Color, map2Color); + cv::initUndistortRectifyMap(cameraMatrixIr, distortionIr, cv::Mat(), cameraMatrixIr, sizeIr, mapType, map1Ir, map2Ir); + cv::initUndistortRectifyMap(cameraMatrixColor, distortionColor, cv::Mat(), cameraMatrixLowRes, sizeLowRes, mapType, map1LowRes, map2LowRes); + + OUT_DEBUG("camera parameters used:"); + OUT_DEBUG("camera matrix color:" FG_CYAN << std::endl << cameraMatrixColor << NO_COLOR); + OUT_DEBUG("distortion coefficients color:" FG_CYAN << std::endl << distortionColor << NO_COLOR); + OUT_DEBUG("camera matrix ir:" FG_CYAN << std::endl << cameraMatrixIr << NO_COLOR); + OUT_DEBUG("distortion coefficients ir:" FG_CYAN << std::endl << distortionIr << NO_COLOR); + OUT_DEBUG("camera matrix depth:" FG_CYAN << std::endl << cameraMatrixDepth << NO_COLOR); + OUT_DEBUG("distortion coefficients depth:" FG_CYAN << std::endl << distortionDepth << NO_COLOR); + OUT_DEBUG("rotation:" FG_CYAN << std::endl << rotation << NO_COLOR); + OUT_DEBUG("translation:" FG_CYAN << std::endl << translation << NO_COLOR); + OUT_DEBUG("depth shift:" FG_CYAN << std::endl << depthShift << NO_COLOR); + } + + bool loadCalibrationFile(const std::string &filename, cv::Mat &cameraMatrix, cv::Mat &distortion) const + { + cv::FileStorage fs; + if(fs.open(filename, cv::FileStorage::READ)) + { + fs[K2_CALIB_CAMERA_MATRIX] >> cameraMatrix; + fs[K2_CALIB_DISTORTION] >> distortion; + fs.release(); + } + else + { + OUT_ERROR("can't open calibration file: " << filename); + return false; + } + return true; + } + + bool loadCalibrationPoseFile(const std::string &filename, cv::Mat &rotation, cv::Mat &translation) const + { + cv::FileStorage fs; + if(fs.open(filename, cv::FileStorage::READ)) + { + fs[K2_CALIB_ROTATION] >> rotation; + fs[K2_CALIB_TRANSLATION] >> translation; + fs.release(); + } + else + { + OUT_ERROR("can't open calibration pose file: " << filename); + return false; + } + return true; + } + + bool loadCalibrationDepthFile(const std::string &filename, double &depthShift) const + { + cv::FileStorage fs; + if(fs.open(filename, cv::FileStorage::READ)) + { + fs[K2_CALIB_DEPTH_SHIFT] >> depthShift; + fs.release(); + } + else + { + OUT_ERROR("can't open calibration depth file: " << filename); + return false; + } + return true; + } + + void createCameraInfo() + { + cv::Mat projColor = cv::Mat::zeros(3, 4, CV_64F); + cv::Mat projIr = cv::Mat::zeros(3, 4, CV_64F); + cv::Mat projLowRes = cv::Mat::zeros(3, 4, CV_64F); + + cameraMatrixColor.copyTo(projColor(cv::Rect(0, 0, 3, 3))); + cameraMatrixIr.copyTo(projIr(cv::Rect(0, 0, 3, 3))); + cameraMatrixLowRes.copyTo(projLowRes(cv::Rect(0, 0, 3, 3))); + + createCameraInfo(sizeColor, cameraMatrixColor, distortionColor, cv::Mat::eye(3, 3, CV_64F), projColor, infoHD); + createCameraInfo(sizeIr, cameraMatrixIr, distortionIr, cv::Mat::eye(3, 3, CV_64F), projIr, infoIR); + createCameraInfo(sizeLowRes, cameraMatrixLowRes, distortionColor, cv::Mat::eye(3, 3, CV_64F), projLowRes, infoQHD); + } + + void createCameraInfo(const cv::Size &size, const cv::Mat &cameraMatrix, const cv::Mat &distortion, const cv::Mat &rotation, const cv::Mat &projection, sensor_msgs::CameraInfo &cameraInfo) const + { + cameraInfo.height = size.height; + cameraInfo.width = size.width; + + const double *itC = cameraMatrix.ptr(0, 0); + for(size_t i = 0; i < 9; ++i, ++itC) + { + cameraInfo.K[i] = *itC; + } + + const double *itR = rotation.ptr(0, 0); + for(size_t i = 0; i < 9; ++i, ++itR) + { + cameraInfo.R[i] = *itR; + } + + const double *itP = projection.ptr(0, 0); + for(size_t i = 0; i < 12; ++i, ++itP) + { + cameraInfo.P[i] = *itP; + } + + cameraInfo.distortion_model = "plumb_bob"; + cameraInfo.D.resize(distortion.cols); + const double *itD = distortion.ptr(0, 0); + for(size_t i = 0; i < (size_t)distortion.cols; ++i, ++itD) + { + cameraInfo.D[i] = *itD; + } + } + + void callbackStatus() + { + bool isSubscribedDepth = false; + bool isSubscribedColor = false; + + lockStatus.lock(); + clientConnected = updateStatus(isSubscribedColor, isSubscribedDepth); + bool error = false; + + if(clientConnected && !deviceActive) + { + OUT_INFO("client connected. starting device..."); + if(!device->startStreams(isSubscribedColor, isSubscribedDepth)) + { + OUT_ERROR("could not start device!"); + error = true; + } + else + { + deviceActive = true; + } + } + else if(!clientConnected && deviceActive) + { + OUT_INFO("no clients connected. stopping device..."); + if(!device->stop()) + { + OUT_ERROR("could not stop device!"); + error = true; + } + else + { + deviceActive = false; + } + } + else if(deviceActive && (isSubscribedColor != this->isSubscribedColor || isSubscribedDepth != this->isSubscribedDepth)) + { + if(!device->stop()) + { + OUT_ERROR("could not stop device!"); + error = true; + } + else if(!device->startStreams(isSubscribedColor, isSubscribedDepth)) + { + OUT_ERROR("could not start device!"); + error = true; + deviceActive = false; + } + } + this->isSubscribedColor = isSubscribedColor; + this->isSubscribedDepth = isSubscribedDepth; + lockStatus.unlock(); + + if(error) + { + stop(); + } + } + + bool updateStatus(bool &isSubscribedColor, bool &isSubscribedDepth) + { + isSubscribedDepth = false; + isSubscribedColor = false; + + for(size_t i = 0; i < COUNT; ++i) + { + Status s = UNSUBCRIBED; + if(imagePubs[i].getNumSubscribers() > 0) + { + s = RAW; + } + if(compressedPubs[i].getNumSubscribers() > 0) + { + s = s == RAW ? BOTH : COMPRESSED; + } + + if(i <= COLOR_SD_RECT && s != UNSUBCRIBED) + { + isSubscribedDepth = true; + } + if(i >= COLOR_SD_RECT && s != UNSUBCRIBED) + { + isSubscribedColor = true; + } + + status[i] = s; + } + if(infoHDPub.getNumSubscribers() > 0 || infoQHDPub.getNumSubscribers() > 0) + { + isSubscribedColor = true; + } + if(infoIRPub.getNumSubscribers() > 0) + { + isSubscribedDepth = true; + } + + return isSubscribedColor || isSubscribedDepth; + } + + void main() + { + setThreadName("Controll"); + OUT_INFO("waiting for clients to connect"); + double nextFrame = ros::Time::now().toSec() + deltaT; + double fpsTime = ros::Time::now().toSec(); + size_t oldFrameIrDepth = 0, oldFrameColor = 0; + nextColor = true; + nextIrDepth = true; + + for(; running && ros::ok();) + { + if(!deviceActive) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + fpsTime = ros::Time::now().toSec(); + nextFrame = fpsTime + deltaT; + continue; + } + + double now = ros::Time::now().toSec(); + + if(now - fpsTime >= 3.0) + { + fpsTime = now - fpsTime; + size_t framesIrDepth = frameIrDepth - oldFrameIrDepth; + size_t framesColor = frameColor - oldFrameColor; + oldFrameIrDepth = frameIrDepth; + oldFrameColor = frameColor; + + lockTime.lock(); + double tColor = elapsedTimeColor; + double tDepth = elapsedTimeIrDepth; + elapsedTimeColor = 0; + elapsedTimeIrDepth = 0; + lockTime.unlock(); + + if(isSubscribedDepth) + { + OUT_INFO("depth processing: " FG_YELLOW "~" << (tDepth / framesIrDepth) * 1000 << "ms" NO_COLOR " (~" << framesIrDepth / tDepth << "Hz) publishing rate: " FG_YELLOW "~" << framesIrDepth / fpsTime << "Hz" NO_COLOR); + } + if(isSubscribedColor) + { + OUT_INFO("color processing: " FG_YELLOW "~" << (tColor / framesColor) * 1000 << "ms" NO_COLOR " (~" << framesColor / tColor << "Hz) publishing rate: " FG_YELLOW "~" << framesColor / fpsTime << "Hz" NO_COLOR); + } + fpsTime = now; + } + + if(now >= nextFrame) + { + nextColor = true; + nextIrDepth = true; + nextFrame += deltaT; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + if(!deviceActive) + { + oldFrameIrDepth = frameIrDepth; + oldFrameColor = frameColor; + lockTime.lock(); + elapsedTimeColor = 0; + elapsedTimeIrDepth = 0; + lockTime.unlock(); + continue; + } + } + } + + void threadDispatcher(const size_t id) + { + setThreadName("Worker" + std::to_string(id)); + const size_t checkFirst = id % 2; + bool processedFrame = false; + int oldNice = nice(0); + oldNice = nice(19 - oldNice); + + for(; running && ros::ok();) + { + processedFrame = false; + + for(size_t i = 0; i < 2; ++i) + { + if(i == checkFirst) + { + if(nextIrDepth && lockIrDepth.try_lock()) + { + nextIrDepth = false; + receiveIrDepth(); + processedFrame = true; + } + } + else + { + if(nextColor && lockColor.try_lock()) + { + nextColor = false; + receiveColor(); + processedFrame = true; + } + } + } + + if(!processedFrame) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } + } + + void receiveIrDepth() + { + libfreenect2::FrameMap frames; + cv::Mat depth, ir; + std_msgs::Header header; + std::vector images(COUNT); + std::vector status = this->status; + size_t frame; + + if(!receiveFrames(listenerIrDepth, frames)) + { + lockIrDepth.unlock(); + return; + } + double now = ros::Time::now().toSec(); + + header = createHeader(lastDepth, lastColor); + + libfreenect2::Frame *irFrame = frames[libfreenect2::Frame::Ir]; + libfreenect2::Frame *depthFrame = frames[libfreenect2::Frame::Depth]; + + if(irFrame->status != 0 || depthFrame->status != 0) + { + listenerIrDepth->release(frames); + lockIrDepth.unlock(); + running = false; + OUT_ERROR("failure in depth packet processor from libfreenect2"); + return; + } + if(irFrame->format != libfreenect2::Frame::Float || depthFrame->format != libfreenect2::Frame::Float) + { + listenerIrDepth->release(frames); + lockIrDepth.unlock(); + running = false; + OUT_ERROR("received invalid frame format"); + return; + } + + frame = frameIrDepth++; + + if(status[COLOR_SD_RECT] || status[DEPTH_SD] || status[DEPTH_SD_RECT] || status[DEPTH_QHD] || status[DEPTH_HD]) + { + cv::Mat(depthFrame->height, depthFrame->width, CV_32FC1, depthFrame->data).copyTo(depth); + } + + if(status[IR_SD] || status[IR_SD_RECT]) + { + ir = cv::Mat(irFrame->height, irFrame->width, CV_32FC1, irFrame->data); + ir.convertTo(images[IR_SD], CV_16U); + } + + listenerIrDepth->release(frames); + lockIrDepth.unlock(); + + processIrDepth(depth, images, status); + + publishImages(images, header, status, frame, pubFrameIrDepth, IR_SD, COLOR_HD); + + double elapsed = ros::Time::now().toSec() - now; + lockTime.lock(); + elapsedTimeIrDepth += elapsed; + lockTime.unlock(); + } + + void receiveColor() + { + libfreenect2::FrameMap frames; + std_msgs::Header header; + std::vector images(COUNT); + std::vector status = this->status; + size_t frame; + + if(!receiveFrames(listenerColor, frames)) + { + lockColor.unlock(); + return; + } + double now = ros::Time::now().toSec(); + + header = createHeader(lastColor, lastDepth); + + libfreenect2::Frame *colorFrame = frames[libfreenect2::Frame::Color]; + + if(colorFrame->status != 0) + { + listenerColor->release(frames); + lockIrDepth.unlock(); + running = false; + OUT_ERROR("failure in rgb packet processor from libfreenect2"); + return; + } + if(colorFrame->format != libfreenect2::Frame::BGRX && colorFrame->format != libfreenect2::Frame::RGBX) + { + listenerColor->release(frames); + lockIrDepth.unlock(); + running = false; + OUT_ERROR("received invalid frame format"); + return; + } + + frame = frameColor++; + + cv::Mat color = cv::Mat(colorFrame->height, colorFrame->width, CV_8UC4, colorFrame->data); + if(status[COLOR_SD_RECT]) + { + lockRegSD.lock(); + memcpy(this->color.data, colorFrame->data, sizeColor.width * sizeColor.height * 4); + this->color.format = colorFrame->format; + lockRegSD.unlock(); + } + if(status[COLOR_HD] || status[COLOR_HD_RECT] || status[COLOR_QHD] || status[COLOR_QHD_RECT] || + status[MONO_HD] || status[MONO_HD_RECT] || status[MONO_QHD] || status[MONO_QHD_RECT]) + { + cv::Mat tmp; + cv::flip(color, tmp, 1); + if(colorFrame->format == libfreenect2::Frame::BGRX) + { + cv::cvtColor(tmp, images[COLOR_HD], CV_BGRA2BGR); + } + else + { + cv::cvtColor(tmp, images[COLOR_HD], CV_RGBA2BGR); + } + } + + listenerColor->release(frames); + lockColor.unlock(); + + processColor(images, status); + + publishImages(images, header, status, frame, pubFrameColor, COLOR_HD, COUNT); + + double elapsed = ros::Time::now().toSec() - now; + lockTime.lock(); + elapsedTimeColor += elapsed; + lockTime.unlock(); + } + + bool receiveFrames(libfreenect2::SyncMultiFrameListener *listener, libfreenect2::FrameMap &frames) + { + bool newFrames = false; + for(; !newFrames;) + { +#ifdef LIBFREENECT2_THREADING_STDLIB + newFrames = listener->waitForNewFrame(frames, 1000); +#else + newFrames = true; + listener->waitForNewFrame(frames); +#endif + if(!deviceActive || !running || !ros::ok()) + { + if(newFrames) + { + listener->release(frames); + } + return false; + } + } + return newFrames; + } + + std_msgs::Header createHeader(ros::Time &last, ros::Time &other) + { + ros::Time timestamp = ros::Time::now(); + lockSync.lock(); + if(other.isZero()) + { + last = timestamp; + } + else + { + timestamp = other; + other = ros::Time(0, 0); + } + lockSync.unlock(); + + std_msgs::Header header; + header.seq = 0; + header.stamp = timestamp; + return header; + } + + void processIrDepth(const cv::Mat &depth, std::vector &images, const std::vector &status) + { + // COLOR registered to depth + if(status[COLOR_SD_RECT]) + { + cv::Mat tmp; + libfreenect2::Frame depthFrame(sizeIr.width, sizeIr.height, 4, depth.data); + libfreenect2::Frame undistorted(sizeIr.width, sizeIr.height, 4); + libfreenect2::Frame registered(sizeIr.width, sizeIr.height, 4); + lockRegSD.lock(); + registration->apply(&color, &depthFrame, &undistorted, ®istered); + lockRegSD.unlock(); + cv::flip(cv::Mat(sizeIr, CV_8UC4, registered.data), tmp, 1); + if(color.format == libfreenect2::Frame::BGRX) + { + cv::cvtColor(tmp, images[COLOR_SD_RECT], CV_BGRA2BGR); + } + else + { + cv::cvtColor(tmp, images[COLOR_SD_RECT], CV_RGBA2BGR); + } + } + + // IR + if(status[IR_SD] || status[IR_SD_RECT]) + { + cv::flip(images[IR_SD], images[IR_SD], 1); + } + if(status[IR_SD_RECT]) + { + cv::remap(images[IR_SD], images[IR_SD_RECT], map1Ir, map2Ir, cv::INTER_AREA); + } + + // DEPTH + cv::Mat depthShifted; + if(status[DEPTH_SD]) + { + depth.convertTo(images[DEPTH_SD], CV_16U, 1); + cv::flip(images[DEPTH_SD], images[DEPTH_SD], 1); + } + if(status[DEPTH_SD_RECT] || status[DEPTH_QHD] || status[DEPTH_HD]) + { + depth.convertTo(depthShifted, CV_16U, 1, depthShift); + cv::flip(depthShifted, depthShifted, 1); + } + if(status[DEPTH_SD_RECT]) + { + cv::remap(depthShifted, images[DEPTH_SD_RECT], map1Ir, map2Ir, cv::INTER_NEAREST); + } + if(status[DEPTH_QHD]) + { + lockRegLowRes.lock(); + depthRegLowRes->registerDepth(depthShifted, images[DEPTH_QHD]); + lockRegLowRes.unlock(); + } + if(status[DEPTH_HD]) + { + lockRegHighRes.lock(); + depthRegHighRes->registerDepth(depthShifted, images[DEPTH_HD]); + lockRegHighRes.unlock(); + } + } + + void processColor(std::vector &images, const std::vector &status) + { + // COLOR + if(status[COLOR_HD_RECT] || status[MONO_HD_RECT]) + { + cv::remap(images[COLOR_HD], images[COLOR_HD_RECT], map1Color, map2Color, cv::INTER_AREA); + } + if(status[COLOR_QHD] || status[MONO_QHD]) + { + cv::resize(images[COLOR_HD], images[COLOR_QHD], sizeLowRes, 0, 0, cv::INTER_AREA); + } + if(status[COLOR_QHD_RECT] || status[MONO_QHD_RECT]) + { + cv::remap(images[COLOR_HD], images[COLOR_QHD_RECT], map1LowRes, map2LowRes, cv::INTER_AREA); + } + + // MONO + if(status[MONO_HD]) + { + cv::cvtColor(images[COLOR_HD], images[MONO_HD], CV_BGR2GRAY); + } + if(status[MONO_HD_RECT]) + { + cv::cvtColor(images[COLOR_HD_RECT], images[MONO_HD_RECT], CV_BGR2GRAY); + } + if(status[MONO_QHD]) + { + cv::cvtColor(images[COLOR_QHD], images[MONO_QHD], CV_BGR2GRAY); + } + if(status[MONO_QHD_RECT]) + { + cv::cvtColor(images[COLOR_QHD_RECT], images[MONO_QHD_RECT], CV_BGR2GRAY); + } + } + + void publishImages(const std::vector &images, const std_msgs::Header &header, const std::vector &status, const size_t frame, size_t &pubFrame, const size_t begin, const size_t end) + { + std::vector imageMsgs(COUNT); + std::vector compressedMsgs(COUNT); + sensor_msgs::CameraInfoPtr infoHDMsg, infoQHDMsg, infoIRMsg; + std_msgs::Header _header = header; + + if(begin < COLOR_HD) + { + _header.frame_id = baseNameTF + K2_TF_IR_OPT_FRAME; + + infoIRMsg = sensor_msgs::CameraInfoPtr(new sensor_msgs::CameraInfo); + *infoIRMsg = infoIR; + infoIRMsg->header = _header; + } + else + { + _header.frame_id = baseNameTF + K2_TF_RGB_OPT_FRAME; + + infoHDMsg = sensor_msgs::CameraInfoPtr(new sensor_msgs::CameraInfo); + *infoHDMsg = infoHD; + infoHDMsg->header = _header; + + infoQHDMsg = sensor_msgs::CameraInfoPtr(new sensor_msgs::CameraInfo); + *infoQHDMsg = infoQHD; + infoQHDMsg->header = _header; + + } + + for(size_t i = begin; i < end; ++i) + { + if(i < DEPTH_HD || i == COLOR_SD_RECT) + { + _header.frame_id = baseNameTF + K2_TF_IR_OPT_FRAME; + } + else + { + _header.frame_id = baseNameTF + K2_TF_RGB_OPT_FRAME; + } + + switch(status[i]) + { + case UNSUBCRIBED: + break; + case RAW: + imageMsgs[i] = sensor_msgs::ImagePtr(new sensor_msgs::Image); + createImage(images[i], _header, Image(i), *imageMsgs[i]); + break; + case COMPRESSED: + compressedMsgs[i] = sensor_msgs::CompressedImagePtr(new sensor_msgs::CompressedImage); + createCompressed(images[i], _header, Image(i), *compressedMsgs[i]); + break; + case BOTH: + imageMsgs[i] = sensor_msgs::ImagePtr(new sensor_msgs::Image); + compressedMsgs[i] = sensor_msgs::CompressedImagePtr(new sensor_msgs::CompressedImage); + createImage(images[i], _header, Image(i), *imageMsgs[i]); + createCompressed(images[i], _header, Image(i), *compressedMsgs[i]); + break; + } + } + + while(frame != pubFrame) + { + std::this_thread::sleep_for(std::chrono::microseconds(100)); + } + lockPub.lock(); + for(size_t i = begin; i < end; ++i) + { + switch(status[i]) + { + case UNSUBCRIBED: + break; + case RAW: + imagePubs[i].publish(imageMsgs[i]); + break; + case COMPRESSED: + compressedPubs[i].publish(compressedMsgs[i]); + break; + case BOTH: + imagePubs[i].publish(imageMsgs[i]); + compressedPubs[i].publish(compressedMsgs[i]); + break; + } + } + + if(begin < COLOR_HD) + { + if(infoIRPub.getNumSubscribers() > 0) + { + infoIRPub.publish(infoIRMsg); + } + } + else + { + if(infoHDPub.getNumSubscribers() > 0) + { + infoHDPub.publish(infoHDMsg); + } + if(infoQHDPub.getNumSubscribers() > 0) + { + infoQHDPub.publish(infoQHDMsg); + } + } + + ++pubFrame; + lockPub.unlock(); + } + + void createImage(const cv::Mat &image, const std_msgs::Header &header, const Image type, sensor_msgs::Image &msgImage) const + { + size_t step, size; + step = image.cols * image.elemSize(); + size = image.rows * step; + + switch(type) + { + case IR_SD: + case IR_SD_RECT: + case DEPTH_SD: + case DEPTH_SD_RECT: + case DEPTH_HD: + case DEPTH_QHD: + msgImage.encoding = sensor_msgs::image_encodings::TYPE_16UC1; + break; + case COLOR_SD_RECT: + case COLOR_HD: + case COLOR_HD_RECT: + case COLOR_QHD: + case COLOR_QHD_RECT: + msgImage.encoding = sensor_msgs::image_encodings::BGR8; + break; + case MONO_HD: + case MONO_HD_RECT: + case MONO_QHD: + case MONO_QHD_RECT: + msgImage.encoding = sensor_msgs::image_encodings::TYPE_8UC1; + break; + case COUNT: + return; + } + + msgImage.header = header; + msgImage.height = image.rows; + msgImage.width = image.cols; + msgImage.is_bigendian = false; + msgImage.step = step; + msgImage.data.resize(size); + memcpy(msgImage.data.data(), image.data, size); + } + + void createCompressed(const cv::Mat &image, const std_msgs::Header &header, const Image type, sensor_msgs::CompressedImage &msgImage) const + { + msgImage.header = header; + + switch(type) + { + case IR_SD: + case IR_SD_RECT: + case DEPTH_SD: + case DEPTH_SD_RECT: + case DEPTH_HD: + case DEPTH_QHD: + msgImage.format = compression16BitString; + cv::imencode(compression16BitExt, image, msgImage.data, compressionParams); + break; + case COLOR_SD_RECT: + case COLOR_HD: + case COLOR_HD_RECT: + case COLOR_QHD: + case COLOR_QHD_RECT: + msgImage.format = sensor_msgs::image_encodings::BGR8 + "; jpeg compressed bgr8"; + cv::imencode(".jpg", image, msgImage.data, compressionParams); + break; + case MONO_HD: + case MONO_HD_RECT: + case MONO_QHD: + case MONO_QHD_RECT: + msgImage.format = sensor_msgs::image_encodings::TYPE_8UC1 + "; jpeg compressed "; + cv::imencode(".jpg", image, msgImage.data, compressionParams); + break; + case COUNT: + return; + } + } + + void publishStaticTF() + { + setThreadName("TFPublisher"); + tf::TransformBroadcaster broadcaster; + tf::StampedTransform stColorOpt, stIrOpt; + ros::Time now = ros::Time::now(); + + tf::Matrix3x3 rot(rotation.at(0, 0), rotation.at(0, 1), rotation.at(0, 2), + rotation.at(1, 0), rotation.at(1, 1), rotation.at(1, 2), + rotation.at(2, 0), rotation.at(2, 1), rotation.at(2, 2)); + + tf::Quaternion qZero; + qZero.setRPY(0, 0, 0); + tf::Vector3 trans(translation.at(0), translation.at(1), translation.at(2)); + tf::Vector3 vZero(0, 0, 0); + tf::Transform tIr(rot, trans), tZero(qZero, vZero); + + stColorOpt = tf::StampedTransform(tZero, now, baseNameTF + K2_TF_LINK, baseNameTF + K2_TF_RGB_OPT_FRAME); + stIrOpt = tf::StampedTransform(tIr, now, baseNameTF + K2_TF_RGB_OPT_FRAME, baseNameTF + K2_TF_IR_OPT_FRAME); + + for(; running && ros::ok();) + { + now = ros::Time::now(); + stColorOpt.stamp_ = now; + stIrOpt.stamp_ = now; + + broadcaster.sendTransform(stColorOpt); + broadcaster.sendTransform(stIrOpt); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + + static inline void setThreadName(const std::string &name) + { +#if defined(__linux__) + prctl(PR_SET_NAME, name.c_str()); +#elif defined(__APPLE__) + pthread_setname_np(name.c_str()); +#endif + } +}; + +class Kinect2BridgeNodelet : public nodelet::Nodelet +{ +private: + Kinect2Bridge *pKinect2Bridge; + +public: + Kinect2BridgeNodelet() : Nodelet(), pKinect2Bridge(NULL) + { + } + + ~Kinect2BridgeNodelet() + { + if(pKinect2Bridge) + { + pKinect2Bridge->stop(); + delete pKinect2Bridge; + } + } + + virtual void onInit() + { + pKinect2Bridge = new Kinect2Bridge(getNodeHandle(), getPrivateNodeHandle()); + if(!pKinect2Bridge->start()) + { + delete pKinect2Bridge; + pKinect2Bridge = NULL; + throw nodelet::Exception("Could not start kinect2_bridge!"); + } + } +}; + +#include +PLUGINLIB_EXPORT_CLASS(Kinect2BridgeNodelet, nodelet::Nodelet) + +void helpOption(const std::string &name, const std::string &stype, const std::string &value, const std::string &desc) +{ + std::cout << FG_GREEN "_" << name << NO_COLOR ":=" FG_YELLOW "<" << stype << ">" NO_COLOR << std::endl + << " default: " FG_CYAN << value << NO_COLOR << std::endl + << " info: " << desc << std::endl; +} + +void help(const std::string &path) +{ + std::string depthMethods = "cpu"; + std::string depthDefault = "cpu"; + std::string regMethods = "default"; + std::string regDefault = "default"; + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT + depthMethods += ", opengl"; + depthDefault = "opengl"; +#endif +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + depthMethods += ", opencl"; + depthDefault = "opencl"; +#endif +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + depthMethods += ", cuda"; + depthMethods += ", cudakde"; + depthDefault = "cuda"; +#endif +#ifdef DEPTH_REG_CPU + regMethods += ", cpu"; +#endif +#ifdef DEPTH_REG_OPENCL + regMethods += ", opencl"; + regMethods += ", clkde"; + regDefault = "opencl"; +#endif + + std::cout << path << FG_BLUE " [_options:=value]" << std::endl; + helpOption("base_name", "string", K2_DEFAULT_NS, "set base name for all topics"); + helpOption("sensor", "double", "-1.0", "serial of the sensor to use"); + helpOption("fps_limit", "double", "-1.0", "limit the frames per second"); + helpOption("calib_path", "string", K2_CALIB_PATH, "path to the calibration files"); + helpOption("use_png", "bool", "false", "Use PNG compression instead of TIFF"); + helpOption("jpeg_quality", "int", "90", "JPEG quality level from 0 to 100"); + helpOption("png_level", "int", "1", "PNG compression level from 0 to 9"); + helpOption("depth_method", "string", depthDefault, "Use specific depth processing: " + depthMethods); + helpOption("depth_device", "int", "-1", "openCL device to use for depth processing"); + helpOption("reg_method", "string", regDefault, "Use specific depth registration: " + regMethods); + helpOption("reg_device", "int", "-1", "openCL device to use for depth registration"); + helpOption("max_depth", "double", "12.0", "max depth value"); + helpOption("min_depth", "double", "0.1", "min depth value"); + helpOption("queue_size", "int", "2", "queue size of publisher"); + helpOption("bilateral_filter", "bool", "true", "enable bilateral filtering of depth images"); + helpOption("edge_aware_filter", "bool", "true", "enable edge aware filtering of depth images"); + helpOption("publish_tf", "bool", "false", "publish static tf transforms for camera"); + helpOption("base_name_tf", "string", "as base_name", "base name for the tf frames"); + helpOption("worker_threads", "int", "4", "number of threads used for processing the images"); +} + +int main(int argc, char **argv) +{ +#if EXTENDED_OUTPUT + ROSCONSOLE_AUTOINIT; + if(!getenv("ROSCONSOLE_FORMAT")) + { + ros::console::g_formatter.tokens_.clear(); + ros::console::g_formatter.init("[${severity}] ${message}"); + } +#endif + + ros::init(argc, argv, "kinect2_bridge", ros::init_options::AnonymousName); + + for(int argI = 1; argI < argc; ++argI) + { + std::string arg(argv[argI]); + + if(arg == "--help" || arg == "--h" || arg == "-h" || arg == "-?" || arg == "--?") + { + help(argv[0]); + ros::shutdown(); + return 0; + } + else + { + OUT_ERROR("Unknown argument: " << arg); + return -1; + } + } + + if(!ros::ok()) + { + OUT_ERROR("ros::ok failed!"); + return -1; + } + + Kinect2Bridge kinect2; + if(kinect2.start()) + { + ros::spin(); + + kinect2.stop(); + } + + ros::shutdown(); + return 0; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/CMakeLists.txt new file mode 100644 index 0000000..0ef4dcc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/CMakeLists.txt @@ -0,0 +1,122 @@ +cmake_minimum_required(VERSION 2.8.3) +project(kinect2_calibration CXX) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBT_USE_DOUBLE_PRECISION -Wall") +# Unused warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuninitialized -Winit-self -Wunused-function -Wunused-label -Wunused-variable -Wunused-but-set-variable -Wunused-but-set-parameter") +# Additional warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Warray-bounds -Wtype-limits -Wreturn-type -Wsequence-point -Wparentheses -Wmissing-braces -Wchar-subscripts -Wswitch -Wwrite-strings -Wenum-compare -Wempty-body -Wlogical-op") + +# Check for c++11 support +INCLUDE(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +IF(COMPILER_SUPPORTS_CXX11) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +ELSEIF(COMPILER_SUPPORTS_CXX0X) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +ELSE() + MESSAGE(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +ENDIF() + +find_package(catkin REQUIRED COMPONENTS roscpp rostime std_msgs sensor_msgs message_filters cv_bridge image_transport compressed_image_transport compressed_depth_image_transport kinect2_bridge) + +## System dependencies are found with CMake's conventions +find_package(OpenCV REQUIRED) +find_package(OpenMP) + +if(OPENMP_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +endif() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES kinect2_bridge +# CATKIN_DEPENDS other_catkin_pkg +# DEPENDS system_lib +) + +########### +## Build ## +########### + +# Display additional files in qtcreator +execute_process(COMMAND find ${PROJECT_SOURCE_DIR} -type f OUTPUT_VARIABLE FILES_STRING) +string(REPLACE "\n" ";" FILES_LIST ${FILES_STRING}) +add_custom_target(additional_files_${PROJECT_NAME} + SOURCES + ${FILES_LIST} +) + +include_directories(include + ${catkin_INCLUDE_DIRS} + ${OpenCV_INCLUDE_DIRS} + ${kinect2_bridge_INCLUDE_DIR} +) + +add_executable(kinect2_calibration src/kinect2_calibration.cpp) +target_link_libraries(kinect2_calibration + ${catkin_LIBRARIES} + ${OpenCV_LIBRARIES} +) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +# install(TARGETS kinect2_bridge kinect2_bridge_node +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_kinect2_bridge.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/README.md b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/README.md new file mode 100644 index 0000000..dac99af --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/README.md @@ -0,0 +1,169 @@ +# Kinect2 Calibration + +## Maintainer + +- [Thiemo Wiedemeyer](https://ai.uni-bremen.de/team/thiemo_wiedemeyer) <>, [Institute for Artificial Intelligence](http://ai.uni-bremen.de/), University of Bremen + +*Note:* ***Please use the GitHub issues*** *for questions and problems regarding the iai_kinect2 package and its components.* ***Do not write emails.*** + +## Description + +This tool uses OpenCV to calibrate two cameras to each other. It is specially designed for the Kinect One. It uses chess or circle boards. + +## Dependencies + +- ROS Hydro/Indigo +- OpenCV + +*for the ROS packages look at the package.xml* + +## Usage + +``` +kinect2_calibration [options] + name: 'any string' equals to the kinect2_bridge topic base name + mode: 'record' or 'calibrate' + source: 'color', 'ir', 'sync', 'depth' + board: + 'circlexx' for symmetric circle grid + 'acirclexx' for asymmetric circle grid + 'chessxx' for chessboard pattern + distortion model: 'rational' for using model with 8 instead of 5 coefficients + output path: '-path ' +``` + +## Key bindings + +Windows: +- `ESC`, `q`: Quit +- `SPACE`, `s`: Save the current image for calibration +- `l`: decrease min and max value for IR value rage +- `h`: increase min and max value for IR value rage +- `1`: decrease min value for IR value rage +- `2`: increase min value for IR value rage +- `3`: decrease max value for IR value rage +- `4`: increase max value for IR value rage + +Terminal: +- `CRTL`+`c`: Quit + +## Calibration patterns + +Any chessboard pattern or symmetric or asymmetric circle grid should work. Three different chessboard patterns are located inside the `kinect2_calibration/patterns` folder: +- [chess5x7x0.03.pdf](patterns/chess5x7x0.03.pdf) +- [chess7x9x0.025.pdf](patterns/chess7x9x0.025.pdf) +- [chess9x11x0.02.pdf](patterns/chess9x11x0.02.pdf) + +Other patterns are available at OpenCV: +- [Chessboard pattern](http://docs.opencv.org/2.4.2/_downloads/pattern.png) +- [Asymmetric circle grid](http://docs.opencv.org/2.4.2/_downloads/acircles_pattern.png) + +The standard board is a 7x6 0.108m chessboard from the PR2. But any other board can be specified with as parameter. For example a circle board with 8x7 circles in 0.02m distance between them `rosrun kinect2_calibration kinect2_calibration record color circle8x7x0.02`. + +Recently, to calibrate our sensors, we have used the chess5x7x0.03 pattern, as it can be printed easily on a good laser printer on A4 paper. + + +## Calibrating the Kinect One + +*Recommended preparation:* +- Print your calibration pattern (for the examples, we used chess5x7x0.03) and glue it to a flat object. It is very important that the calibration pattern is very flat. Also, check with a caliper that the distance between the features of the printed pattern is correct. Sometimes printers scale the document, and the calibration won't work. For the mentioned pattern, the distance between intersections of black and white corners should be 3cm exactly. +- Get two tripods, one for holding the calibration pattern, and another one for holding the kinect2 sensor. Ideally, the tripod for the kinect2 will have a ball head, to allow you to move it easily and lock it in place before you take an image. It is very important that the sensor is stable (and the image is clear and not blurred) before you take an image. The tripod will specially help you to make sure that the sensor has not moved between the moment the IR and the RGB images are taken. +- When recording images for all the steps indicated below (RGB, IR, SYNC), start the recording program, then press spacebar to record each image. The calibration pattern should be detected (indicated by color lines overlayed on the calibration pattern), and the image should be clear and stable. +- It is recommended to take images that show the calibration pattern in all areas of the image, and with different orientations of the pattern (tilting the pattern relative to the plane of the image), and at least two distances. So you can easily reach 100 images per calibration set. +- We normally start at a short distance, where the calibration pattern covers most of the image, there we take several pictures tilting the calibration pattern vertically, then horizontally. Imagine a ray coming out of the camera sensor, this makes sure that you have images where the calibration pattern is not perpendicular to that ray. +- Then we move the calibration pattern further away, and for different orientations (tilting) of the pattern, we take many images so that we calibration pattern is present around most of the camera image. For example, at first the calibration pattern is on the left upper corner. Then on the next image on the upper middle, then on the upper right corner. Then some images where the calibration pattern is in the middle vertically, etc... + +*Typical calibration setup* +![kinect2_calibration_setup_small.jpg](https://ai.uni-bremen.de/_media/kinect2_calibration_setup_small.jpg) + +*Detailed steps:* + +0. If you haven't already, start the kinect2_bridge with a low number of frames per second (to make it easy on your CPU): `rosrun kinect2_bridge kinect2_bridge _fps_limit:=2` +1. create a directory for your calibration data files, for example: `mkdir ~/kinect_cal_data; cd ~/kinect_cal_data` +2. Record images for the color camera: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 record color` +3. Calibrate the intrinsics: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 calibrate color` +4. Record images for the ir camera: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 record ir` +5. Calibrate the intrinsics of the ir camera: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 calibrate ir` +6. Record images on both cameras synchronized: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 record sync` +7. Calibrate the extrinsics: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 calibrate sync` +8. Calibrate the depth measurements: `rosrun kinect2_calibration kinect2_calibration chess5x7x0.03 calibrate depth` +9. Find out the serial number of your kinect2 by looking at the first lines printed out by the kinect2_bridge. The line looks like this: + `device serial: 012526541941` +10. Create the calibration results directory in kinect2_bridge/data/$serial: `roscd kinect2_bridge/data; mkdir 012526541941` +11. Copy the following files from your calibration directory (~/kinect_cal_data) into the directory you just created: `calib_color.yaml calib_depth.yaml calib_ir.yaml calib_pose.yaml` +12. Restart the kinect2_bridge and be amazed at the better data. + + + +## Calibration of the depth measurements + +I did some tests on the measured and the computed distance based on the detected chess board. It seems like the Kinect2 (or at least the Kinect2s I am using) has a static offset of around 24 mm. As shown in the following images, one can see, that the difference between measured and computed distance is unrelated to the x and y coordinates of the pixel and also unrelated to the distance. + +![plot.png](http://ai.uni-bremen.de/wiki/_media/software/plot.png) +![plot_x.png](http://ai.uni-bremen.de/wiki/_media/software/plot_x.png) +![plot_y.png](http://ai.uni-bremen.de/wiki/_media/software/plot_y.png) +![plot_xy.png](http://ai.uni-bremen.de/wiki/_media/software/plot_xy.png) + +For the images above ~400 images of a 4x5x0.03 chessboard in different orientations, distances and image positions were used. The code for computing the depth offset is added to the calibration tool. + +### GNUPlot + +The depth calibration creates a file named `plot.dat` inside the calibration folder. This files contains the results of the calibration in 5 columns: x, y, computed depth, measured depth, difference between computed and measured depth. + +- Difference between measured/computed distance + +``` +set xlabel "Measured distance" +set ylabel "Computed distance" +plot 'plot.dat' using 3:4 with dots title "Difference between measured/computed distance" +``` + +- Difference relative to x coordinate + +``` +set xlabel "X" +set ylabel "Distance difference" +plot 'plot.dat' using 1:5 with dots title "Difference relative to X-coordinate" +``` + +- Difference relative to y coordinate + +``` +set xlabel "Y" +set ylabel "Distance difference" +plot 'plot.dat' using 2:5 with dots title "Difference relative to Y-coordinate" +``` + +- Difference relative to XY-coordinate + +``` +set xlabel "X" +set ylabel "Y" +set zlabel "Distance difference" +splot 'plot.dat' using 1:2:5 with dots palette title "Difference relative to XY-coordinate" +``` + +## Example results + +Example calibration results can be found in the directory [kinect2_bridge/data/](../kinect2_bridge/data). + +The following images were made before and after the calibration, using the kinect2 viewer. + - For the superimposed images: `rosrun kinect2_viewer kinect2_viewer hd image` + - For the point cloud images: `rosrun kinect2_viewer kinect2_viewer hd cloud` + - For the superimposed and point cloud images: `rosrun kinect2_viewer kinect2_viewer hd both` + +raw here stands for raw data transmission aka uncompressed. + +Uncalibrated rectified images (depth and RGB superimposed): +![kinect2_cloud_calib](https://ai.uni-bremen.de/_media/kinect2_raw_nocalib.png) + +Calibrated rectified images (depth and RGB superimposed): +![kinect2_cloud_calib](https://ai.uni-bremen.de/_media/kinect2_raw_calib.png) + +Uncalibrated depth cloud: +![kinect2_cloud_calib](https://ai.uni-bremen.de/_media/kinect2_cloud_nocalib.png) + +Calibrated depth cloud: +![kinect2_cloud_calib](https://ai.uni-bremen.de/_media/kinect2_cloud_calib.png) + +Note how the color is now correctly applied on the depth data. This is specially evident around strong edges, like the edge of the white column on the left. diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/include/kinect2_calibration/kinect2_calibration_definitions.h b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/include/kinect2_calibration/kinect2_calibration_definitions.h new file mode 100644 index 0000000..a5cf8c3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/include/kinect2_calibration/kinect2_calibration_definitions.h @@ -0,0 +1,36 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#pragma once +#ifndef __KINECT2_CALIBRATION_DEFINITIONS_H__ +#define __KINECT2_CALIBRATION_DEFINITIONS_H__ + +#define CALIB_FILE_EXT ".png" +#define CALIB_FILE_COLOR "_color" CALIB_FILE_EXT +#define CALIB_FILE_IR "_ir" CALIB_FILE_EXT +#define CALIB_FILE_IR_GREY "_grey_ir" CALIB_FILE_EXT +#define CALIB_FILE_DEPTH "_depth" CALIB_FILE_EXT + +#define CALIB_POINTS_COLOR "_color_points.yaml" +#define CALIB_POINTS_IR "_ir_points.yaml" + +#define CALIB_SYNC "_sync" +#define CALIB_SYNC_COLOR CALIB_SYNC CALIB_FILE_COLOR +#define CALIB_SYNC_IR CALIB_SYNC CALIB_FILE_IR +#define CALIB_SYNC_IR_GREY CALIB_SYNC CALIB_FILE_IR_GREY + +#endif //__KINECT2_CALIBRATION_DEFINITIONS_H__ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/package.xml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/package.xml new file mode 100644 index 0000000..b213152 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/package.xml @@ -0,0 +1,37 @@ + + + kinect2_calibration + 0.0.1 + The kinect2_calibration package + + Thiemo Wiedemeyer + + Apache 2.0 + + catkin + + roscpp + rostime + std_msgs + sensor_msgs + message_filters + image_transport + compressed_image_transport + compressed_depth_image_transport + kinect2_bridge + cv_bridge + + message_runtime + roscpp + rostime + std_msgs + sensor_msgs + message_filters + image_transport + compressed_image_transport + compressed_depth_image_transport + cv_bridge + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.pdf b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e64ca455c68e06b263a4e67d277a5bf5f1f2d917 GIT binary patch literal 1059 zcma)5Uq}=|7>|gIQAnwWsE59!6A$us_wIH*<UAN&Yf#^u1-?| z?azx3Ne@xkOJFZWP+~n5ln_1yQ3ySX2w@M_b4Jk2o_8MBL&LJO^PBm;`Tc(1x1K~S z-lX|-X9F7 zZPRnpdc(l@_x)oH8}B|>)z6_PdThM?=#kCn@Y&-Jo)6!8{B^NsD!xAMT|9j9(capX zyR+B2m*IfEw6Ez#d)2-5j`vqmtNpDtk%r0JbuX;ht5Y3Iv0DF|SI7F7FVy<$u77Bn z*flf%^a~<(dW)*~k|L!tISXx?p~`)^@|P`eMRyi>SBeY45DrT~3QKI%A=R_fO2LuM?gv73~_TNFe5e>VI^mKN!r2@T7Yu`QbE^LpFd#uRRfHW z>I-PWmY@a$Zfum=Tm(BHOI55(7o+)H1-;^JE?Q!o5*!$|ot(Vc94*1!z**kqBxOa# zsTjFznIzd2kw=QElq7Lzo|(h}=}odiqf}68mu-!XOZ2prc7z^jL$b_0FJ)IGFe(y6 zMH_L-pwYw@qoDb;fKP+QA%3c~i9I|A%eYsJY_$ zBL67nI7>6d)S_O_R+YA63XBXQ6+%cY4={8+pu-@PFuhsymKRTK8?Jf{nn zcVK~_Flq;81X}*WnvIHcoM9_VnENlMtT7@e%PJ=+ literal 0 HcmV?d00001 diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.svg b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.svg new file mode 100644 index 0000000..24c7a0b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess5x7x0.03.svg @@ -0,0 +1,280 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.pdf b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.pdf new file mode 100644 index 0000000000000000000000000000000000000000..92dba15513987cd519b2164f45643d72c18cae15 GIT binary patch literal 1129 zcma)6ZAcVB81B!3ECq&9XhI`)aYF9L-R<689Ljm;ol@d)YS5Ro?aiHA*X}txSEo`C zc%_g+A7n;9N`it&iIjdsP!tH!kLXVsNsx(2SP>OLM9u7ZA6P#cmfe|W=6&aVp66w) z;XtrfU`56{wKV>daR46Z2M#h`FW`1SEsnc@lRyy$0Kf&+1cr!w6EcPYsOVA1)YUNt zMo>P?q%R*kdvDDnezm2q^`Yfyxc+%Xb@jETz0)(B2FeCAt3LQLo45^$TzMUA0U0-M^2H%{5P0-#xfcy7unlnZ6fI!x?|3X=1ATOz)wkdC3-FQya@S zj<(yc-#LX)$NC{Ybfe|w$SiBA(k#NbMff%Qc3p4z#la2d=Q_i~&+2P-PHrvf<_5^K zICZk(tDP_7Y}5CzR9+3jNiMhZY3zw;c@Ot*Au)YEPs63tw_=4|@!U|y?U56sX`kn# zW&ZUD_pQBZ7X!8EGGQ{KQc->AmndX+@N}Q9?0F$g=^E2G)P{*{!0V*|8Jx_M1>pQX zAOKF0$(x8tHprVi%X!3n9>BHtBq89!avYjD!!m*zCSf^$T3}R_8}u~TLm(cAlEixK z9>L)TF5b;blHerMeP*m**Dwh-05v@8ZV2hAWKnt9+e|c9aT}=t$(oU*H!D3kxEWxS zGHar={Nz*s9#It-2{q6oSyo&G8hQ#T&;V4MND)WMAlGySj)qz2b~S1cK2(NCzV;NQ zU6ep7O5i8Wh;;;PimW0X2&~{>1z_vKIJu1@G7~V43Tf{D z4=Z@&D!M*fzhB03LXT%t6TggQmkKdy1Y-;j+zg)|KoUiV2x1_INlwyRbO0@nIsSq1 z0+DCsIXh8#1?CipP%AJO@A(UJJBrR>B&!LC%s)b#+6zg^)a8h-V?c>#o2OZe>44f` U`f6YqVUwZT?Pjdj#?~P72Nt|cJpcdz literal 0 HcmV?d00001 diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.svg b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.svg new file mode 100644 index 0000000..9328969 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess7x9x0.025.svg @@ -0,0 +1,368 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.pdf b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.pdf new file mode 100644 index 0000000..cef128b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.pdf @@ -0,0 +1,68 @@ +%PDF-1.5 +% +3 0 obj +<< /Length 4 0 R + /Filter /FlateDecode +>> +stream +x}An E9 9FE;N/uh< AO 2?[ ?c޾kvv5\%J!#Ԃ)soT}JQޑ]=)Jւb8; cv1Y7JfL vB01&j0L &;L9}/ &;LLĘ`HB^@# )}|x1Y^b-պMޓys܇#3jkr䎂1Y&SZVi6bL01&1 3Z7bLc1Tc! +endstream +endobj +4 0 obj + 315 +endobj +2 0 obj +<< + /ExtGState << + /a0 << /CA 1 /ca 1 >> + >> +>> +endobj +5 0 obj +<< /Type /Page + /Parent 1 0 R + /MediaBox [ 0 0 566.929138 680.314941 ] + /Contents 3 0 R + /Group << + /Type /Group + /S /Transparency + /I true + /CS /DeviceRGB + >> + /Resources 2 0 R +>> +endobj +1 0 obj +<< /Type /Pages + /Kids [ 5 0 R ] + /Count 1 +>> +endobj +6 0 obj +<< /Creator (cairo 1.13.1 (http://cairographics.org)) + /Producer (cairo 1.13.1 (http://cairographics.org)) +>> +endobj +7 0 obj +<< /Type /Catalog + /Pages 1 0 R +>> +endobj +xref +0 8 +0000000000 65535 f +0000000729 00000 n +0000000429 00000 n +0000000015 00000 n +0000000407 00000 n +0000000501 00000 n +0000000794 00000 n +0000000921 00000 n +trailer +<< /Size 8 + /Root 7 0 R + /Info 6 0 R +>> +startxref +973 +%%EOF diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.svg b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.svg new file mode 100644 index 0000000..1b9590e --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/patterns/chess9x11x0.02.svg @@ -0,0 +1,540 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/scripts/convert_calib_pose_to_urdf_format.py b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/scripts/convert_calib_pose_to_urdf_format.py new file mode 100644 index 0000000..f1b0ba2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/scripts/convert_calib_pose_to_urdf_format.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import argparse +import numpy as np +import os +import tempfile +import tf +import yaml + +def read_calib_pose(fname): + tmp = tempfile.TemporaryFile() + # we need modify original yaml file because yaml.load(fname) simply will fail + with open(fname, "r") as f: + reader = f.readlines() + for row in reader: + if row[0] == "%": + # remove first line: "%YAML:1.0" + continue + if row.find("!!") != -1: + # remove "!!opencv-matrix" + row = row[:row.find("!!")] + os.linesep + tmp.write(row) + tmp.seek(0) + data = yaml.load(tmp) + return data + +def calc_xyz_rpy(data): + mat = np.resize(data["rotation"]["data"], (3, 3)) + xyz = data["translation"]["data"] + rpy = tf.transformations.euler_from_matrix(mat) + return xyz, rpy + +def print_urdf(xyz, rpy): + print(""" + + + + + + """.format(x=xyz[0], y=xyz[1], z=xyz[2], + roll=rpy[0], pitch=rpy[1], yaw=rpy[2])) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='calculate transform from kinect2_rgb_optical_frame to kinect2_ir_optical_frame') + parser.add_argument('-f', type=str, help='path to calib_pose.yaml', metavar='file', required=True) + args = parser.parse_args() + data = read_calib_pose(args.f) + xyz, rpy = calc_xyz_rpy(data) + print_urdf(xyz, rpy) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/src/kinect2_calibration.cpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/src/kinect2_calibration.cpp new file mode 100644 index 0000000..73d7957 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_calibration/src/kinect2_calibration.cpp @@ -0,0 +1,1400 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + + +enum Mode +{ + RECORD, + CALIBRATE +}; + +enum Source +{ + COLOR, + IR, + SYNC +}; + +class Recorder +{ +private: + const bool circleBoard; + int circleFlags; + + const cv::Size boardDims; + const float boardSize; + const Source mode; + + const std::string path; + const std::string topicColor, topicIr, topicDepth; + std::mutex lock; + + bool update; + bool foundColor, foundIr; + cv::Mat color, ir, irGrey, depth; + + size_t frame; + std::vector params; + + std::vector board; + std::vector pointsColor, pointsIr; + + typedef message_filters::sync_policies::ExactTime ColorIrDepthSyncPolicy; + ros::NodeHandle nh; + ros::AsyncSpinner spinner; + image_transport::ImageTransport it; + image_transport::SubscriberFilter *subImageColor, *subImageIr, *subImageDepth; + message_filters::Synchronizer *sync; + + int minIr, maxIr; + cv::Ptr clahe; + +public: + Recorder(const std::string &path, const std::string &topicColor, const std::string &topicIr, const std::string &topicDepth, + const Source mode, const bool circleBoard, const bool symmetric, const cv::Size &boardDims, const float boardSize) + : circleBoard(circleBoard), boardDims(boardDims), boardSize(boardSize), mode(mode), path(path), topicColor(topicColor), topicIr(topicIr), + topicDepth(topicDepth), update(false), foundColor(false), foundIr(false), frame(0), nh("~"), spinner(0), it(nh), minIr(0), maxIr(0x7FFF) + { + if(symmetric) + { + circleFlags = cv::CALIB_CB_SYMMETRIC_GRID + cv::CALIB_CB_CLUSTERING; + } + else + { + circleFlags = cv::CALIB_CB_ASYMMETRIC_GRID + cv::CALIB_CB_CLUSTERING; + } + + params.push_back(CV_IMWRITE_PNG_COMPRESSION); + params.push_back(9); + + board.resize(boardDims.width * boardDims.height); + if (symmetric) + { + for (size_t r = 0, i = 0; r < (size_t)boardDims.height; ++r) + { + for (size_t c = 0; c < (size_t)boardDims.width; ++c, ++i) + { + board[i] = cv::Point3f(c * boardSize, r * boardSize, 0); + } + } + } + else + { + for (size_t r = 0, i = 0; r < (size_t)boardDims.height; ++r) + { + for (size_t c = 0; c < (size_t)boardDims.width; ++c, ++i) + { + board[i] = cv::Point3f(float((2 * c + r % 2) * boardSize), float(r * boardSize), 0); //for asymmetrical circles + } + } + } + + clahe = cv::createCLAHE(1.5, cv::Size(32, 32)); + } + ~Recorder() + { + } + + void run() + { + startRecord(); + + display(); + + stopRecord(); + } + +private: + void startRecord() + { + OUT_INFO("Controls:" << std::endl + << FG_YELLOW " [ESC, q]" NO_COLOR " - Exit" << std::endl + << FG_YELLOW " [SPACE, s]" NO_COLOR " - Save current frame" << std::endl + << FG_YELLOW " [l]" NO_COLOR " - decrease min and max value for IR value range" << std::endl + << FG_YELLOW " [h]" NO_COLOR " - increase min and max value for IR value range" << std::endl + << FG_YELLOW " [1]" NO_COLOR " - decrease min value for IR value range" << std::endl + << FG_YELLOW " [2]" NO_COLOR " - increase min value for IR value range" << std::endl + << FG_YELLOW " [3]" NO_COLOR " - decrease max value for IR value range" << std::endl + << FG_YELLOW " [4]" NO_COLOR " - increase max value for IR value range"); + + image_transport::TransportHints hints("compressed"); + subImageColor = new image_transport::SubscriberFilter(it, topicColor, 4, hints); + subImageIr = new image_transport::SubscriberFilter(it, topicIr, 4, hints); + subImageDepth = new image_transport::SubscriberFilter(it, topicDepth, 4, hints); + + sync = new message_filters::Synchronizer(ColorIrDepthSyncPolicy(4), *subImageColor, *subImageIr, *subImageDepth); + sync->registerCallback(boost::bind(&Recorder::callback, this, _1, _2, _3)); + + spinner.start(); + } + + void stopRecord() + { + spinner.stop(); + + delete sync; + delete subImageColor; + delete subImageIr; + delete subImageDepth; + } + + void convertIr(const cv::Mat &ir, cv::Mat &grey) + { + const float factor = 255.0f / (maxIr - minIr); + grey.create(ir.rows, ir.cols, CV_8U); + + #pragma omp parallel for + for(size_t r = 0; r < (size_t)ir.rows; ++r) + { + const uint16_t *itI = ir.ptr(r); + uint8_t *itO = grey.ptr(r); + + for(size_t c = 0; c < (size_t)ir.cols; ++c, ++itI, ++itO) + { + *itO = std::min(std::max(*itI - minIr, 0) * factor, 255.0f); + } + } + clahe->apply(grey, grey); + } + + void findMinMax(const cv::Mat &ir, const std::vector &pointsIr) + { + minIr = 0xFFFF; + maxIr = 0; + for(size_t i = 0; i < pointsIr.size(); ++i) + { + const cv::Point2f &p = pointsIr[i]; + cv::Rect roi(std::max(0, (int)p.x - 2), std::max(0, (int)p.y - 2), 9, 9); + roi.width = std::min(roi.width, ir.cols - roi.x); + roi.height = std::min(roi.height, ir.rows - roi.y); + + findMinMax(ir(roi)); + } + } + + void findMinMax(const cv::Mat &ir) + { + for(size_t r = 0; r < (size_t)ir.rows; ++r) + { + const uint16_t *it = ir.ptr(r); + + for(size_t c = 0; c < (size_t)ir.cols; ++c, ++it) + { + minIr = std::min(minIr, (int) * it); + maxIr = std::max(maxIr, (int) * it); + } + } + } + + void callback(const sensor_msgs::Image::ConstPtr imageColor, const sensor_msgs::Image::ConstPtr imageIr, const sensor_msgs::Image::ConstPtr imageDepth) + { + std::vector pointsColor, pointsIr; + cv::Mat color, ir, irGrey, irScaled, depth; + bool foundColor = false; + bool foundIr = false; + + if(mode == COLOR || mode == SYNC) + { + readImage(imageColor, color); + } + if(mode == IR || mode == SYNC) + { + readImage(imageIr, ir); + readImage(imageDepth, depth); + cv::resize(ir, irScaled, cv::Size(), 2.0, 2.0, cv::INTER_CUBIC); + + convertIr(irScaled, irGrey); + } + + if(circleBoard) + { + switch(mode) + { + case COLOR: + foundColor = cv::findCirclesGrid(color, boardDims, pointsColor, circleFlags); + break; + case IR: + foundIr = cv::findCirclesGrid(irGrey, boardDims, pointsIr, circleFlags); + break; + case SYNC: + foundColor = cv::findCirclesGrid(color, boardDims, pointsColor, circleFlags); + foundIr = cv::findCirclesGrid(irGrey, boardDims, pointsIr, circleFlags); + break; + } + } + else + { + const cv::TermCriteria termCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::COUNT, 100, DBL_EPSILON); + switch(mode) + { + case COLOR: + foundColor = cv::findChessboardCorners(color, boardDims, pointsColor, cv::CALIB_CB_FAST_CHECK); + break; + case IR: + foundIr = cv::findChessboardCorners(irGrey, boardDims, pointsIr, cv::CALIB_CB_ADAPTIVE_THRESH); + break; + case SYNC: + foundColor = cv::findChessboardCorners(color, boardDims, pointsColor, cv::CALIB_CB_FAST_CHECK); + foundIr = cv::findChessboardCorners(irGrey, boardDims, pointsIr, cv::CALIB_CB_ADAPTIVE_THRESH); + break; + } + if(foundColor) + { + cv::cornerSubPix(color, pointsColor, cv::Size(11, 11), cv::Size(-1, -1), termCriteria); + } + if(foundIr) + { + cv::cornerSubPix(irGrey, pointsIr, cv::Size(11, 11), cv::Size(-1, -1), termCriteria); + } + } + + if(foundIr) + { + // Update min and max ir value based on checkerboard values + findMinMax(irScaled, pointsIr); + } + + lock.lock(); + this->color = color; + this->ir = ir; + this->irGrey = irGrey; + this->depth = depth; + this->foundColor = foundColor; + this->foundIr = foundIr; + this->pointsColor = pointsColor; + this->pointsIr = pointsIr; + update = true; + lock.unlock(); + } + + void display() + { + std::vector pointsColor, pointsIr; + cv::Mat color, ir, irGrey, depth; + cv::Mat colorDisp, irDisp; + bool foundColor = false; + bool foundIr = false; + bool save = false; + bool running = true; + + std::chrono::milliseconds duration(1); + while(!update && ros::ok()) + { + std::this_thread::sleep_for(duration); + } + + for(; ros::ok() && running;) + { + if(update) + { + lock.lock(); + color = this->color; + ir = this->ir; + irGrey = this->irGrey; + depth = this->depth; + foundColor = this->foundColor; + foundIr = this->foundIr; + pointsColor = this->pointsColor; + pointsIr = this->pointsIr; + update = false; + lock.unlock(); + + if(mode == COLOR || mode == SYNC) + { + cv::cvtColor(color, colorDisp, CV_GRAY2BGR); + cv::drawChessboardCorners(colorDisp, boardDims, pointsColor, foundColor); + //cv::resize(colorDisp, colorDisp, cv::Size(), 0.5, 0.5); + //cv::flip(colorDisp, colorDisp, 1); + } + if(mode == IR || mode == SYNC) + { + cv::cvtColor(irGrey, irDisp, CV_GRAY2BGR); + cv::drawChessboardCorners(irDisp, boardDims, pointsIr, foundIr); + //cv::resize(irDisp, irDisp, cv::Size(), 0.5, 0.5); + //cv::flip(irDisp, irDisp, 1); + } + } + + switch(mode) + { + case COLOR: + cv::imshow("color", colorDisp); + break; + case IR: + cv::imshow("ir", irDisp); + break; + case SYNC: + cv::imshow("color", colorDisp); + cv::imshow("ir", irDisp); + break; + } + + int key = cv::waitKey(10); + switch(key & 0xFF) + { + case ' ': + case 's': + save = true; + break; + case 27: + case 'q': + running = false; + break; + case '1': + minIr = std::max(0, minIr - 100); + break; + case '2': + minIr = std::min(maxIr - 1, minIr + 100); + break; + case '3': + maxIr = std::max(minIr + 1, maxIr - 100); + break; + case '4': + maxIr = std::min(0xFFFF, maxIr + 100); + break; + case 'l': + minIr = std::max(0, minIr - 100); + maxIr = std::max(minIr + 1, maxIr - 100); + break; + case 'h': + maxIr = std::min(0x7FFF, maxIr + 100); + minIr = std::min(maxIr - 1, minIr + 100); + break; + } + + if(save && ((mode == COLOR && foundColor) || (mode == IR && foundIr) || (mode == SYNC && foundColor && foundIr))) + { + store(color, ir, irGrey, depth, pointsColor, pointsIr); + save = false; + } + } + cv::destroyAllWindows(); + cv::waitKey(100); + } + + void readImage(const sensor_msgs::Image::ConstPtr msgImage, cv::Mat &image) const + { + cv_bridge::CvImageConstPtr pCvImage; + pCvImage = cv_bridge::toCvShare(msgImage, msgImage->encoding); + pCvImage->image.copyTo(image); + } + + void store(const cv::Mat &color, const cv::Mat &ir, const cv::Mat &irGrey, const cv::Mat &depth, const std::vector &pointsColor, std::vector &pointsIr) + { + std::ostringstream oss; + oss << std::setfill('0') << std::setw(4) << frame++; + const std::string frameNumber(oss.str()); + OUT_INFO("storing frame: " << frameNumber); + std::string base = path + frameNumber; + + for(size_t i = 0; i < pointsIr.size(); ++i) + { + pointsIr[i].x /= 2.0; + pointsIr[i].y /= 2.0; + } + + if(mode == SYNC) + { + base += CALIB_SYNC; + } + + if(mode == COLOR || mode == SYNC) + { + cv::imwrite(base + CALIB_FILE_COLOR, color, params); + + cv::FileStorage file(base + CALIB_POINTS_COLOR, cv::FileStorage::WRITE); + file << "points" << pointsColor; + } + + if(mode == IR || mode == SYNC) + { + cv::imwrite(base + CALIB_FILE_IR, ir, params); + cv::imwrite(base + CALIB_FILE_IR_GREY, irGrey, params); + cv::imwrite(base + CALIB_FILE_DEPTH, depth, params); + + cv::FileStorage file(base + CALIB_POINTS_IR, cv::FileStorage::WRITE); + file << "points" << pointsIr; + } + } +}; + +class CameraCalibration +{ +private: + const bool circleBoard; + const cv::Size boardDims; + const float boardSize; + const int flags; + + const Source mode; + const std::string path; + + std::vector board; + + std::vector > pointsBoard; + std::vector > pointsColor; + std::vector > pointsIr; + + cv::Size sizeColor; + cv::Size sizeIr; + + cv::Mat cameraMatrixColor, distortionColor, rotationColor, translationColor, projectionColor; + cv::Mat cameraMatrixIr, distortionIr, rotationIr, translationIr, projectionIr; + cv::Mat rotation, translation, essential, fundamental, disparity; + + std::vector rvecsColor, tvecsColor; + std::vector rvecsIr, tvecsIr; + +public: + CameraCalibration(const std::string &path, const Source mode, const bool circleBoard, const bool symmetric, const cv::Size &boardDims, const float boardSize, const bool rational) + : circleBoard(circleBoard), boardDims(boardDims), boardSize(boardSize), flags(rational ? cv::CALIB_RATIONAL_MODEL : 0), mode(mode), path(path), sizeColor(1920, 1080), sizeIr(512, 424) + { + board.resize(boardDims.width * boardDims.height); + if (symmetric) + { + for (size_t r = 0, i = 0; r < (size_t)boardDims.height; ++r) + { + for (size_t c = 0; c < (size_t)boardDims.width; ++c, ++i) + { + board[i] = cv::Point3f(c * boardSize, r * boardSize, 0); + } + } + } + else + { + for (size_t r = 0, i = 0; r < (size_t)boardDims.height; ++r) + { + for (size_t c = 0; c < (size_t)boardDims.width; ++c, ++i) + { + board[i] = cv::Point3f(float((2 * c + r % 2) * boardSize), float(r * boardSize), 0); //for asymmetrical circles + } + } + } + } + + ~CameraCalibration() + { + } + + bool restore() + { + std::vector filesSync; + std::vector filesColor; + std::vector filesIr; + + DIR *dp; + struct dirent *dirp; + size_t posColor, posIr, posSync; + + if((dp = opendir(path.c_str())) == NULL) + { + OUT_ERROR("Error opening: " << path); + return false; + } + + while((dirp = readdir(dp)) != NULL) + { + std::string filename = dirp->d_name; + + if(dirp->d_type != DT_REG) + { + continue; + } + + posSync = filename.rfind(CALIB_SYNC); + posColor = filename.rfind(CALIB_FILE_COLOR); + + if(posSync != std::string::npos) + { + if(posColor != std::string::npos) + { + std::string frameName = filename.substr(0, posColor); + filesSync.push_back(frameName); + filesColor.push_back(frameName); + filesIr.push_back(frameName); + } + continue; + } + + if(posColor != std::string::npos) + { + std::string frameName = filename.substr(0, posColor); + filesColor.push_back(frameName); + continue; + } + + posIr = filename.rfind(CALIB_FILE_IR_GREY); + if(posIr != std::string::npos) + { + std::string frameName = filename.substr(0, posIr); + filesIr.push_back(frameName); + continue; + } + } + closedir(dp); + + std::sort(filesColor.begin(), filesColor.end()); + std::sort(filesIr.begin(), filesIr.end()); + std::sort(filesSync.begin(), filesSync.end()); + + bool ret = true; + switch(mode) + { + case COLOR: + if(filesColor.empty()) + { + OUT_ERROR("no files found!"); + return false; + } + pointsColor.resize(filesColor.size()); + pointsBoard.resize(filesColor.size(), board); + ret = ret && readFiles(filesColor, CALIB_POINTS_COLOR, pointsColor); + break; + case IR: + if(filesIr.empty()) + { + OUT_ERROR("no files found!"); + return false; + } + pointsIr.resize(filesIr.size()); + pointsBoard.resize(filesIr.size(), board); + ret = ret && readFiles(filesIr, CALIB_POINTS_IR, pointsIr); + break; + case SYNC: + if(filesColor.empty() || filesIr.empty()) + { + OUT_ERROR("no files found!"); + return false; + } + pointsColor.resize(filesColor.size()); + pointsIr.resize(filesSync.size()); + pointsColor.resize(filesSync.size()); + pointsBoard.resize(filesSync.size(), board); + ret = ret && readFiles(filesSync, CALIB_POINTS_COLOR, pointsColor); + ret = ret && readFiles(filesSync, CALIB_POINTS_IR, pointsIr); + ret = ret && checkSyncPointsOrder(); + ret = ret && loadCalibration(); + break; + } + return ret; + } + + void calibrate() + { + switch(mode) + { + case COLOR: + calibrateIntrinsics(sizeColor, pointsBoard, pointsColor, cameraMatrixColor, distortionColor, rotationColor, projectionColor, rvecsColor, tvecsColor); + break; + case IR: + calibrateIntrinsics(sizeIr, pointsBoard, pointsIr, cameraMatrixIr, distortionIr, rotationIr, projectionIr, rvecsIr, tvecsIr); + break; + case SYNC: + calibrateExtrinsics(); + break; + } + storeCalibration(); + } + +private: + bool readFiles(const std::vector &files, const std::string &ext, std::vector > &points) const + { + bool ret = true; + #pragma omp parallel for + for(size_t i = 0; i < files.size(); ++i) + { + std::string pointsname = path + files[i] + ext; + + #pragma omp critical + OUT_INFO("restoring file: " << files[i] << ext); + + cv::FileStorage file(pointsname, cv::FileStorage::READ); + if(!file.isOpened()) + { + #pragma omp critical + { + ret = false; + OUT_ERROR("couldn't open file: " << files[i] << ext); + } + } + else + { + file["points"] >> points[i]; + } + } + return ret; + } + + bool checkSyncPointsOrder() + { + if(pointsColor.size() != pointsIr.size()) + { + OUT_ERROR("number of detected color and ir patterns does not match!"); + return false; + } + + for(size_t i = 0; i < pointsColor.size(); ++i) + { + const std::vector &pColor = pointsColor[i]; + const std::vector &pIr = pointsIr[i]; + + if(pColor.front().y > pColor.back().y || pColor.front().x > pColor.back().x) + { + std::reverse(pointsColor[i].begin(), pointsColor[i].end()); + } + + if(pIr.front().y > pIr.back().y || pIr.front().x > pIr.back().x) + { + std::reverse(pointsIr[i].begin(), pointsIr[i].end()); + } + } + return true; + } + + void calibrateIntrinsics(const cv::Size &size, const std::vector > &pointsBoard, const std::vector > &points, + cv::Mat &cameraMatrix, cv::Mat &distortion, cv::Mat &rotation, cv::Mat &projection, std::vector &rvecs, std::vector &tvecs) + { + if(points.empty()) + { + OUT_ERROR("no data for calibration provided!"); + return; + } + const cv::TermCriteria termCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 50, DBL_EPSILON); + double error; + + OUT_INFO("calibrating intrinsics..."); + error = cv::calibrateCamera(pointsBoard, points, size, cameraMatrix, distortion, rvecs, tvecs, flags, termCriteria); + OUT_INFO("re-projection error: " << error << std::endl); + + OUT_INFO("Camera Matrix:" << std::endl << cameraMatrix); + OUT_INFO("Distortion Coeeficients:" << std::endl << distortion << std::endl); + rotation = cv::Mat::eye(3, 3, CV_64F); + projection = cv::Mat::eye(4, 4, CV_64F); + cameraMatrix.copyTo(projection(cv::Rect(0, 0, 3, 3))); + } + + void calibrateExtrinsics() + { + if(pointsColor.size() != pointsIr.size()) + { + OUT_ERROR("number of detected color and ir patterns does not match!"); + return; + } + if(pointsColor.empty() || pointsIr.empty()) + { + OUT_ERROR("no data for calibration provided!"); + return; + } + const cv::TermCriteria termCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 100, DBL_EPSILON); + double error; + + OUT_INFO("Camera Matrix Color:" << std::endl << cameraMatrixColor); + OUT_INFO("Distortion Coeeficients Color:" << std::endl << distortionColor << std::endl); + OUT_INFO("Camera Matrix Ir:" << std::endl << cameraMatrixIr); + OUT_INFO("Distortion Coeeficients Ir:" << std::endl << distortionIr << std::endl); + + OUT_INFO("calibrating Color and Ir extrinsics..."); +#if CV_MAJOR_VERSION == 2 + error = cv::stereoCalibrate(pointsBoard, pointsIr, pointsColor, cameraMatrixIr, distortionIr, cameraMatrixColor, distortionColor, sizeColor, + rotation, translation, essential, fundamental, termCriteria, cv::CALIB_FIX_INTRINSIC); +#elif CV_MAJOR_VERSION == 3 + error = cv::stereoCalibrate(pointsBoard, pointsIr, pointsColor, cameraMatrixIr, distortionIr, cameraMatrixColor, distortionColor, sizeColor, + rotation, translation, essential, fundamental, cv::CALIB_FIX_INTRINSIC, termCriteria); +#endif + OUT_INFO("re-projection error: " << error << std::endl); + + OUT_INFO("Rotation:" << std::endl << rotation); + OUT_INFO("Translation:" << std::endl << translation); + OUT_INFO("Essential:" << std::endl << essential); + OUT_INFO("Fundamental:" << std::endl << fundamental << std::endl); + } + + void storeCalibration() + { + cv::FileStorage fs; + + switch(mode) + { + case SYNC: + fs.open(path + K2_CALIB_POSE, cv::FileStorage::WRITE); + break; + case COLOR: + fs.open(path + K2_CALIB_COLOR, cv::FileStorage::WRITE); + break; + case IR: + fs.open(path + K2_CALIB_IR, cv::FileStorage::WRITE); + break; + } + + if(!fs.isOpened()) + { + OUT_ERROR("couldn't store calibration data!"); + return; + } + + switch(mode) + { + case SYNC: + fs << K2_CALIB_ROTATION << rotation; + fs << K2_CALIB_TRANSLATION << translation; + fs << K2_CALIB_ESSENTIAL << essential; + fs << K2_CALIB_FUNDAMENTAL << fundamental; + break; + case COLOR: + fs << K2_CALIB_CAMERA_MATRIX << cameraMatrixColor; + fs << K2_CALIB_DISTORTION << distortionColor; + fs << K2_CALIB_ROTATION << rotationColor; + fs << K2_CALIB_PROJECTION << projectionColor; + break; + case IR: + fs << K2_CALIB_CAMERA_MATRIX << cameraMatrixIr; + fs << K2_CALIB_DISTORTION << distortionIr; + fs << K2_CALIB_ROTATION << rotationIr; + fs << K2_CALIB_PROJECTION << projectionIr; + break; + } + fs.release(); + } + + bool loadCalibration() + { + cv::FileStorage fs; + + if(fs.open(path + K2_CALIB_COLOR, cv::FileStorage::READ)) + { + fs[K2_CALIB_CAMERA_MATRIX] >> cameraMatrixColor; + fs[K2_CALIB_DISTORTION] >> distortionColor; + fs[K2_CALIB_ROTATION] >> rotationColor; + fs[K2_CALIB_PROJECTION] >> projectionColor; + fs.release(); + } + else + { + OUT_ERROR("couldn't load color calibration data!"); + return false; + } + + if(fs.open(path + K2_CALIB_IR, cv::FileStorage::READ)) + { + fs[K2_CALIB_CAMERA_MATRIX] >> cameraMatrixIr; + fs[K2_CALIB_DISTORTION] >> distortionIr; + fs[K2_CALIB_ROTATION] >> rotationIr; + fs[K2_CALIB_PROJECTION] >> projectionIr; + fs.release(); + } + else + { + OUT_ERROR("couldn't load ir calibration data!"); + return false; + } + + return true; + } +}; + +class DepthCalibration +{ +private: + const std::string path; + + std::vector board; + std::vector > points; + std::vector images; + + cv::Size size; + + cv::Mat cameraMatrix, distortion, rotation, translation; + cv::Mat mapX, mapY; + + double fx, fy, cx, cy; + + std::ofstream plot; + +public: + DepthCalibration(const std::string &path, const bool symmetric, const cv::Size &boardDims, const float boardSize) + : path(path), size(512, 424) + { + board.resize(boardDims.width * boardDims.height); + if (symmetric) + { + for (size_t r = 0, i = 0; r < (size_t)boardDims.height; ++r) + { + for (size_t c = 0; c < (size_t)boardDims.width; ++c, ++i) + { + board[i] = cv::Point3f(c * boardSize, r * boardSize, 0); + } + } + } + else + { + for (size_t r = 0, i = 0; r < (size_t)boardDims.height; ++r) + { + for (size_t c = 0; c < (size_t)boardDims.width; ++c, ++i) + { + board[i] = cv::Point3f(float((2 * c + r % 2) * boardSize), float(r * boardSize), 0); //for asymmetrical circles + } + } + } + } + + ~DepthCalibration() + { + } + + bool restore() + { + std::vector files; + + DIR *dp; + struct dirent *dirp; + size_t pos; + + if((dp = opendir(path.c_str())) == NULL) + { + OUT_ERROR("Error opening: " << path); + return false; + } + + while((dirp = readdir(dp)) != NULL) + { + std::string filename = dirp->d_name; + + if(dirp->d_type != DT_REG) + { + continue; + } + + /*pos = filename.rfind(CALIB_SYNC); + if(pos != std::string::npos) + { + continue; + }*/ + + pos = filename.rfind(CALIB_FILE_IR_GREY); + if(pos != std::string::npos) + { + std::string frameName = filename.substr(0, pos); + files.push_back(frameName); + continue; + } + } + closedir(dp); + + std::sort(files.begin(), files.end()); + + if(files.empty()) + { + OUT_ERROR("no files found!"); + return false; + } + + bool ret = readFiles(files); + ret = ret && loadCalibration(); + + if(ret) + { + cv::initUndistortRectifyMap(cameraMatrix, distortion, cv::Mat(), cameraMatrix, size, CV_32FC1, mapX, mapY); + fx = cameraMatrix.at(0, 0); + fy = cameraMatrix.at(1, 1); + cx = cameraMatrix.at(0, 2); + cy = cameraMatrix.at(1, 2); + } + return ret; + } + + void calibrate() + { + plot.open(path + "plot.dat", std::ios_base::trunc); + if(!plot.is_open()) + { + OUT_ERROR("couldn't open 'plot.dat'!"); + return; + } + if(images.empty()) + { + OUT_ERROR("no images found!"); + return; + } + + plot << "# Columns:" << std::endl + << "# 1: X" << std::endl + << "# 2: Y" << std::endl + << "# 3: computed depth" << std::endl + << "# 4: measured depth" << std::endl + << "# 5: difference between computed and measured depth" << std::endl; + + std::vector depthDists, imageDists; + for(size_t i = 0; i < images.size(); ++i) + { + OUT_INFO("frame: " << images[i]); + plot << "# frame: " << images[i] << std::endl; + + cv::Mat depth, planeNormal, region; + double planeDistance; + cv::Rect roi; + + depth = cv::imread(images[i], cv::IMREAD_ANYDEPTH); + if(depth.empty()) + { + OUT_ERROR("couldn't load image '" << images[i] << "'!"); + return; + } + + cv::remap(depth, depth, mapX, mapY, cv::INTER_NEAREST); + computeROI(depth, points[i], region, roi); + + getPlane(i, planeNormal, planeDistance); + + computePointDists(planeNormal, planeDistance, region, roi, depthDists, imageDists); + } + compareDists(imageDists, depthDists); + } + +private: + void compareDists(const std::vector &imageDists, const std::vector &depthDists) const + { + if(imageDists.size() != depthDists.size()) + { + OUT_ERROR("number of real and computed distance samples does not match!"); + return; + } + if(imageDists.empty() || depthDists.empty()) + { + OUT_ERROR("no distance sample data!"); + return; + } + + double avg = 0, sqavg = 0, var = 0, stddev = 0; + std::vector diffs(imageDists.size()); + + for(size_t i = 0; i < imageDists.size(); ++i) + { + diffs[i] = imageDists[i] - depthDists[i]; + avg += diffs[i]; + sqavg += diffs[i] * diffs[i]; + } + sqavg = sqrt(sqavg / imageDists.size()); + avg /= imageDists.size(); + + for(size_t i = 0; i < imageDists.size(); ++i) + { + const double diff = diffs[i] - avg; + var += diff * diff; + } + var = var / (imageDists.size()); + stddev = sqrt(var); + + std::sort(diffs.begin(), diffs.end()); + OUT_INFO("stats on difference:" << std::endl + << " avg: " << avg << std::endl + << " var: " << var << std::endl + << " stddev: " << stddev << std::endl + << " rms: " << sqavg << std::endl + << " median: " << diffs[diffs.size() / 2]); + + storeCalibration(avg * 1000.0); + } + + void computePointDists(const cv::Mat &normal, const double distance, const cv::Mat ®ion, const cv::Rect &roi, std::vector &depthDists, std::vector &imageDists) + { + for(int r = 0; r < region.rows; ++r) + { + const uint16_t *itD = region.ptr(r); + cv::Point p(roi.x, roi.y + r); + + for(int c = 0; c < region.cols; ++c, ++itD, ++p.x) + { + const double dDist = *itD / 1000.0; + + if(dDist < 0.1) + { + continue; + } + + const double iDist = computeDistance(p, normal, distance); + const double diff = iDist - dDist; + + if(std::abs(diff) > 0.08) + { + continue; + } + depthDists.push_back(dDist); + imageDists.push_back(iDist); + plot << p.x << ' ' << p.y << ' ' << iDist << ' ' << dDist << ' ' << diff << std::endl; + } + } + } + + double computeDistance(const cv::Point &pointImage, const cv::Mat &normal, const double distance) const + { + cv::Mat point = cv::Mat(3, 1, CV_64F); + + point.at(0) = (pointImage.x - cx) / fx; + point.at(1) = (pointImage.y - cy) / fy; + point.at(2) = 1; + + double t = distance / normal.dot(point); + point = point * t; + + return point.at(2); + } + + void getPlane(const size_t index, cv::Mat &normal, double &distance) const + { + cv::Mat rvec, rotation, translation; + //cv::solvePnP(board, points[index], cameraMatrix, distortion, rvec, translation, false, cv::EPNP); +#if CV_MAJOR_VERSION == 2 + cv::solvePnPRansac(board, points[index], cameraMatrix, distortion, rvec, translation, false, 300, 0.05, board.size(), cv::noArray(), cv::ITERATIVE); +#elif CV_MAJOR_VERSION == 3 + cv::solvePnPRansac(board, points[index], cameraMatrix, distortion, rvec, translation, false, 300, 0.05, 0.99, cv::noArray(), cv::SOLVEPNP_ITERATIVE); +#endif + cv::Rodrigues(rvec, rotation); + + normal = cv::Mat(3, 1, CV_64F); + normal.at(0) = 0; + normal.at(1) = 0; + normal.at(2) = 1; + normal = rotation * normal; + distance = normal.dot(translation); + } + + void computeROI(const cv::Mat &depth, const std::vector &points, cv::Mat ®ion, cv::Rect &roi) const + { + std::vector norm; + std::vector undist, hull; + + cv::undistortPoints(points, norm, cameraMatrix, distortion); + undist.reserve(norm.size()); + + for(size_t i = 0; i < norm.size(); ++i) + { + cv::Point p; + p.x = (int)round(norm[i].x * fx + cx); + p.y = (int)round(norm[i].y * fy + cy); + if(p.x >= 0 && p.x < depth.cols && p.y >= 0 && p.y < depth.rows) + { + undist.push_back(p); + } + } + + roi = cv::boundingRect(undist); + + cv::Mat mask = cv::Mat::zeros(depth.rows, depth.cols, CV_8U); + + cv::convexHull(undist, hull); + cv::fillConvexPoly(mask, hull, CV_RGB(255, 255, 255)); + + cv::Mat tmp; + depth.copyTo(tmp, mask); + tmp(roi).copyTo(region); + } + + bool readFiles(const std::vector &files) + { + points.resize(files.size()); + images.resize(files.size()); + bool ret = true; + + #pragma omp parallel for + for(size_t i = 0; i < files.size(); ++i) + { + std::string pointsname = path + files[i] + CALIB_POINTS_IR; + + #pragma omp critical + OUT_INFO("restoring file: " << files[i]); + + cv::FileStorage file(pointsname, cv::FileStorage::READ); + if(!file.isOpened()) + { + #pragma omp critical + { + OUT_ERROR("couldn't read '" << pointsname << "'!"); + ret = false; + } + } + else + { + file["points"] >> points[i]; + file.release(); + images[i] = path + files[i] + CALIB_FILE_DEPTH; + } + } + return ret; + } + + bool loadCalibration() + { + cv::FileStorage fs; + + if(fs.open(path + K2_CALIB_IR, cv::FileStorage::READ)) + { + fs[K2_CALIB_CAMERA_MATRIX] >> cameraMatrix; + fs[K2_CALIB_DISTORTION] >> distortion; + fs.release(); + } + else + { + OUT_ERROR("couldn't read calibration '" << path + K2_CALIB_IR << "'!"); + return false; + } + + return true; + } + + void storeCalibration(const double depthShift) const + { + cv::FileStorage fs; + + if(fs.open(path + K2_CALIB_DEPTH, cv::FileStorage::WRITE)) + { + fs << K2_CALIB_DEPTH_SHIFT << depthShift; + fs.release(); + } + else + { + OUT_ERROR("couldn't store depth calibration!"); + } + } +}; + +void help(const std::string &path) +{ + std::cout << path << FG_BLUE " [options]" << std::endl + << FG_GREEN " name" NO_COLOR ": " FG_YELLOW "'any string'" NO_COLOR " equals to the kinect2_bridge topic base name" << std::endl + << FG_GREEN " mode" NO_COLOR ": " FG_YELLOW "'record'" NO_COLOR " or " FG_YELLOW "'calibrate'" << std::endl + << FG_GREEN " source" NO_COLOR ": " FG_YELLOW "'color'" NO_COLOR ", " FG_YELLOW "'ir'" NO_COLOR ", " FG_YELLOW "'sync'" NO_COLOR ", " FG_YELLOW "'depth'" << std::endl + << FG_GREEN " board" NO_COLOR ":" << std::endl + << FG_YELLOW " 'circlexx' " NO_COLOR "for symmetric circle grid" << std::endl + << FG_YELLOW " 'acirclexx' " NO_COLOR "for asymmetric circle grid" << std::endl + << FG_YELLOW " 'chessxx' " NO_COLOR "for chessboard pattern" << std::endl + << FG_GREEN " distortion model" NO_COLOR ": " FG_YELLOW "'rational'" NO_COLOR " for using model with 8 instead of 5 coefficients" << std::endl + << FG_GREEN " output path" NO_COLOR ": " FG_YELLOW "'-path '" NO_COLOR << std::endl; +} + +int main(int argc, char **argv) +{ +#if EXTENDED_OUTPUT + ROSCONSOLE_AUTOINIT; + if(!getenv("ROSCONSOLE_FORMAT")) + { + ros::console::g_formatter.tokens_.clear(); + ros::console::g_formatter.init("[${severity}] ${message}"); + } +#endif + + Mode mode = RECORD; + Source source = SYNC; + bool circleBoard = false; + bool symmetric = true; + bool rational = false; + bool calibDepth = false; + cv::Size boardDims = cv::Size(7, 6); + float boardSize = 0.108; + std::string ns = K2_DEFAULT_NS; + std::string path = "./"; + + ros::init(argc, argv, "kinect2_calib", ros::init_options::AnonymousName); + + if(!ros::ok()) + { + return 0; + } + + for(int argI = 1; argI < argc; ++ argI) + { + std::string arg(argv[argI]); + + if(arg == "--help" || arg == "--h" || arg == "-h" || arg == "-?" || arg == "--?") + { + help(argv[0]); + ros::shutdown(); + return 0; + } + else if(arg == "record") + { + mode = RECORD; + } + else if(arg == "calibrate") + { + mode = CALIBRATE; + } + else if(arg == "color") + { + source = COLOR; + } + else if(arg == "ir") + { + source = IR; + } + else if(arg == "sync") + { + source = SYNC; + } + else if(arg == "depth") + { + calibDepth = true; + } + else if(arg == "rational") + { + rational = true; + } + else if(arg.find("circle") == 0 && arg.find('x') != arg.rfind('x') && arg.rfind('x') != std::string::npos) + { + circleBoard = true; + const size_t start = 6; + const size_t leftX = arg.find('x'); + const size_t rightX = arg.rfind('x'); + const size_t end = arg.size(); + + int width = atoi(arg.substr(start, leftX - start).c_str()); + int height = atoi(arg.substr(leftX + 1, rightX - leftX + 1).c_str()); + boardSize = atof(arg.substr(rightX + 1, end - rightX + 1).c_str()); + boardDims = cv::Size(width, height); + } + else if((arg.find("circle") == 0 || arg.find("acircle") == 0) && arg.find('x') != arg.rfind('x') && arg.rfind('x') != std::string::npos) + { + symmetric = arg.find("circle") == 0; + circleBoard = true; + const size_t start = 6 + (symmetric ? 0 : 1); + const size_t leftX = arg.find('x'); + const size_t rightX = arg.rfind('x'); + const size_t end = arg.size(); + + int width = atoi(arg.substr(start, leftX - start).c_str()); + int height = atoi(arg.substr(leftX + 1, rightX - leftX + 1).c_str()); + boardSize = atof(arg.substr(rightX + 1, end - rightX + 1).c_str()); + boardDims = cv::Size(width, height); + } + else if(arg.find("chess") == 0 && arg.find('x') != arg.rfind('x') && arg.rfind('x') != std::string::npos) + { + circleBoard = false; + const size_t start = 5; + const size_t leftX = arg.find('x'); + const size_t rightX = arg.rfind('x'); + const size_t end = arg.size(); + + int width = atoi(arg.substr(start, leftX - start).c_str()); + int height = atoi(arg.substr(leftX + 1, rightX - leftX + 1).c_str()); + boardSize = atof(arg.substr(rightX + 1, end - rightX + 1).c_str()); + boardDims = cv::Size(width, height); + } + else if(arg == "-path" && ++argI < argc) + { + arg = argv[argI]; + struct stat fileStat; + if(stat(arg.c_str(), &fileStat) == 0 && S_ISDIR(fileStat.st_mode)) + { + path = arg; + } + else + { + OUT_ERROR("Unknown path: " << arg); + help(argv[0]); + ros::shutdown(); + return 0; + } + } + else + { + ns = arg; + } + } + + std::string topicColor = "/" + ns + K2_TOPIC_HD + K2_TOPIC_IMAGE_MONO; + std::string topicIr = "/" + ns + K2_TOPIC_SD + K2_TOPIC_IMAGE_IR; + std::string topicDepth = "/" + ns + K2_TOPIC_SD + K2_TOPIC_IMAGE_DEPTH; + OUT_INFO("Start settings:" << std::endl + << " Mode: " FG_CYAN << (mode == RECORD ? "record" : "calibrate") << NO_COLOR << std::endl + << " Source: " FG_CYAN << (calibDepth ? "depth" : (source == COLOR ? "color" : (source == IR ? "ir" : "sync"))) << NO_COLOR << std::endl + << " Board: " FG_CYAN << (circleBoard ? "circles" : "chess") << NO_COLOR << std::endl + << " Dimensions: " FG_CYAN << boardDims.width << " x " << boardDims.height << NO_COLOR << std::endl + << " Field size: " FG_CYAN << boardSize << NO_COLOR << std::endl + << "Dist. model: " FG_CYAN << (rational ? '8' : '5') << " coefficients" << NO_COLOR << std::endl + << "Topic color: " FG_CYAN << topicColor << NO_COLOR << std::endl + << " Topic ir: " FG_CYAN << topicIr << NO_COLOR << std::endl + << "Topic depth: " FG_CYAN << topicDepth << NO_COLOR << std::endl + << " Path: " FG_CYAN << path << NO_COLOR << std::endl); + + if(!ros::master::check()) + { + OUT_ERROR("checking ros master failed."); + return -1; + } + if(mode == RECORD) + { + Recorder recorder(path, topicColor, topicIr, topicDepth, source, circleBoard, symmetric, boardDims, boardSize); + + OUT_INFO("starting recorder..."); + recorder.run(); + + OUT_INFO("stopped recording..."); + } + else if(calibDepth) + { + DepthCalibration calib(path, symmetric, boardDims, boardSize); + + OUT_INFO("restoring files..."); + calib.restore(); + + OUT_INFO("starting calibration..."); + calib.calibrate(); + } + else + { + CameraCalibration calib(path, source, circleBoard, symmetric, boardDims, boardSize, rational); + + OUT_INFO("restoring files..."); + calib.restore(); + + OUT_INFO("starting calibration..."); + calib.calibrate(); + } + + return 0; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/CMakeLists.txt new file mode 100644 index 0000000..da69818 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/CMakeLists.txt @@ -0,0 +1,178 @@ +cmake_minimum_required(VERSION 2.8.3) +project(kinect2_registration CXX) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBT_USE_DOUBLE_PRECISION -Wall") +# Unused warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuninitialized -Winit-self -Wunused-function -Wunused-label -Wunused-variable -Wunused-but-set-variable -Wunused-but-set-parameter") +# Additional warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Warray-bounds -Wtype-limits -Wreturn-type -Wsequence-point -Wparentheses -Wmissing-braces -Wchar-subscripts -Wswitch -Wwrite-strings -Wenum-compare -Wempty-body")# -Wlogical-op") + +# Check for c++11 support +INCLUDE(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +IF(COMPILER_SUPPORTS_CXX11) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +ELSEIF(COMPILER_SUPPORTS_CXX0X) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +ELSE() + MESSAGE(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +ENDIF() + +# additional cmake modules +LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) + +find_package(catkin REQUIRED COMPONENTS roscpp) +find_package(cmake_modules QUIET) + +## System dependencies are found with CMake's conventions +find_package(OpenCV REQUIRED) +find_package(OpenMP) +find_package(Eigen3) +find_package(OpenCL) + +if(OPENMP_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +endif() + +############################################################ +## Check for modules being build based on found libraries ## +############################################################ + +if(EIGEN3_FOUND) + message(STATUS "CPU based depth registration enabled") + include_directories(${EIGEN3_INCLUDE_DIR}) + set(DEPTH_REG_CPU ON) + add_definitions(-DDEPTH_REG_CPU) +else() + message(STATUS "CPU based depth registration disabled") + set(DEPTH_REG_CPU OFF) +endif() + +if(OpenCL_FOUND) + message(STATUS "OpenCL based depth registration enabled") + set(EXPORTED_DEPENDENCIES OpenCL) + + if(UNIX AND NOT APPLE) + include(CheckOpenCLICDLoader) + if(OpenCL_C_WORKS AND NOT OpenCL_CXX_WORKS) + set(KINECT2_OPENCL_ICD_LOADER_IS_OLD 1) + message(WARNING "Your libOpenCL.so is incompatible with CL/cl.h. Install ocl-icd-opencl-dev to update libOpenCL.so?") + endif() + endif() + include_directories(${OpenCL_INCLUDE_DIRS}) + + set(DEPTH_REG_OPENCL ON) + add_definitions(-DDEPTH_REG_OPENCL) +else() + message(STATUS "OpenCL based depth registration disabled") + set(DEPTH_REG_OPENCL OFF) +endif() + +if(NOT DEPTH_REG_CPU AND NOT DEPTH_REG_OPENCL) + message(FATAL_ERROR "No registration method available!") +endif() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( + INCLUDE_DIRS include + LIBRARIES kinect2_registration +# CATKIN_DEPENDS other_catkin_pkg + DEPENDS ${EXPORTED_DEPENDENCIES} + CFG_EXTRAS kinect2_registration.cmake +) + +########### +## Build ## +########### + +# Display additional files in qtcreator +execute_process(COMMAND find ${PROJECT_SOURCE_DIR} -type f OUTPUT_VARIABLE FILES_STRING) +string(REPLACE "\n" ";" FILES_LIST ${FILES_STRING}) +add_custom_target(additional_files_${PROJECT_NAME} + SOURCES + ${FILES_LIST} +) + +include_directories(include + ${catkin_INCLUDE_DIRS} + ${OpenCV_INCLUDE_DIRS} + "${CMAKE_CURRENT_SOURCE_DIR}/include/internal" +) + +if(DEPTH_REG_CPU) + set(MODULES ${MODULES} src/depth_registration_cpu.cpp) +endif() + +if(DEPTH_REG_OPENCL) + add_definitions(-DREG_OPENCL_FILE="${PROJECT_SOURCE_DIR}/src/depth_registration.cl") + set(MODULES ${MODULES} src/depth_registration_opencl.cpp) + set(MODULE_LIBS ${MODULE_LIBS} ${OpenCL_LIBRARIES}) +endif() + +add_library(kinect2_registration SHARED src/kinect2_registration.cpp ${MODULES}) +target_link_libraries(kinect2_registration + ${catkin_LIBRARIES} + ${OpenCV_LIBRARIES} + ${MODULE_LIBS} +) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +install(TARGETS kinect2_registration +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +## Mark cpp header files for installation +install(DIRECTORY include/${PROJECT_NAME}/ + DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} + FILES_MATCHING PATTERN "*.h" + PATTERN ".svn" EXCLUDE +) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_kinect2_bridge.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/README.md b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/README.md new file mode 100644 index 0000000..394f700 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/README.md @@ -0,0 +1,23 @@ +# Kinect2 Registration + +## Maintainer + +- [Thiemo Wiedemeyer](https://ai.uni-bremen.de/team/thiemo_wiedemeyer) <>, [Institute for Artificial Intelligence](http://ai.uni-bremen.de/), University of Bremen + +*Note:* ***Please use the GitHub issues*** *for questions and problems regarding the iai_kinect2 package and its components.* ***Do not write emails.*** + +## Description + +This is a library for projecting the depth image obtained by Kinect like sensors to a color image. It has a OpenCL implementation for registering the depth image, to reduce CPU load. + +## Dependencies + +- ROS Hydro/Indigo +- OpenCV +- Eigen (optional, but recommended) +- OpenCL (optional, but recommended) + +At least one of OpenCL or Eigen has to be installed. If OpenCL is not installed the CPU will be used. For optimal performance OpenCL is recommended. + +*for the ROS packages look at the package.xml* + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/CheckOpenCLICDLoader.cmake b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/CheckOpenCLICDLoader.cmake new file mode 100644 index 0000000..f02b3e6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/CheckOpenCLICDLoader.cmake @@ -0,0 +1,21 @@ +INCLUDE(CheckCXXSourceCompiles) +INCLUDE(CheckCSourceCompiles) + +SET(CMAKE_REQUIRED_INCLUDES "${MY_DIR}/include/internal" ${OpenCL_INCLUDE_DIRS}) +SET(CMAKE_REQUIRED_LIBRARIES ${OpenCL_LIBRARIES}) +CHECK_C_SOURCE_COMPILES(" +#include +int main() { + clGetPlatformIDs(0, 0, 0); + return 0; +}" OpenCL_C_WORKS) +CHECK_CXX_SOURCE_COMPILES(" +#include +int main() { + cl::Context context; + cl::Platform platform; + cl::Device device; + return 0; +}" OpenCL_CXX_WORKS) +SET(CMAKE_REQUIRED_INCLUDES) +SET(CMAKE_REQUIRED_LIBRARIES) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/FindOpenCL.cmake b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/FindOpenCL.cmake new file mode 100644 index 0000000..e0b97f6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/FindOpenCL.cmake @@ -0,0 +1,155 @@ +#.rst: +# FindOpenCL +# ---------- +# +# Try to find OpenCL +# +# Once done this will define:: +# +# OpenCL_FOUND - True if OpenCL was found +# OpenCL_INCLUDE_DIRS - include directories for OpenCL +# OpenCL_LIBRARIES - link against this library to use OpenCL +# OpenCL_VERSION_STRING - Highest supported OpenCL version (eg. 1.2) +# OpenCL_VERSION_MAJOR - The major version of the OpenCL implementation +# OpenCL_VERSION_MINOR - The minor version of the OpenCL implementation +# +# The module will also define two cache variables:: +# +# OpenCL_INCLUDE_DIR - the OpenCL include directory +# OpenCL_LIBRARY - the path to the OpenCL library +# + +#============================================================================= +# Copyright 2014 Matthaeus G. Chajdas +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +function(_FIND_OPENCL_VERSION) + include(CheckSymbolExists) + include(CMakePushCheckState) + set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY}) + + CMAKE_PUSH_CHECK_STATE() + foreach(VERSION "2_0" "1_2" "1_1" "1_0") + set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}") + + if(APPLE) + CHECK_SYMBOL_EXISTS( + CL_VERSION_${VERSION} + "${OpenCL_INCLUDE_DIR}/OpenCL/cl.h" + OPENCL_VERSION_${VERSION}) + else() + CHECK_SYMBOL_EXISTS( + CL_VERSION_${VERSION} + "${OpenCL_INCLUDE_DIR}/CL/cl.h" + OPENCL_VERSION_${VERSION}) + endif() + + if(OPENCL_VERSION_${VERSION}) + string(REPLACE "_" "." VERSION "${VERSION}") + set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE) + string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}") + list(GET version_components 0 major_version) + list(GET version_components 1 minor_version) + set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE) + set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE) + break() + endif() + endforeach() + CMAKE_POP_CHECK_STATE() +endfunction() + +find_path(OpenCL_INCLUDE_DIR + NAMES + CL/cl.h OpenCL/cl.h + PATHS + ENV "PROGRAMFILES(X86)" + ENV AMDAPPSDKROOT + ENV INTELOCLSDKROOT + ENV NVSDKCOMPUTE_ROOT + ENV CUDA_PATH + ENV ATISTREAMSDKROOT + PATH_SUFFIXES + include + OpenCL/common/inc + "AMD APP/include") + +_FIND_OPENCL_VERSION() + +if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + find_library(OpenCL_LIBRARY + NAMES OpenCL + PATHS + ENV "PROGRAMFILES(X86)" + ENV AMDAPPSDKROOT + ENV INTELOCLSDKROOT + ENV CUDA_PATH + ENV NVSDKCOMPUTE_ROOT + ENV ATISTREAMSDKROOT + PATH_SUFFIXES + "AMD APP/lib/x86" + lib/x86 + lib/Win32 + OpenCL/common/lib/Win32) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + find_library(OpenCL_LIBRARY + NAMES OpenCL + PATHS + ENV "PROGRAMFILES(X86)" + ENV AMDAPPSDKROOT + ENV INTELOCLSDKROOT + ENV CUDA_PATH + ENV NVSDKCOMPUTE_ROOT + ENV ATISTREAMSDKROOT + PATH_SUFFIXES + "AMD APP/lib/x86_64" + lib/x86_64 + lib/x64 + OpenCL/common/lib/x64) + endif() +else() + find_library(OpenCL_LIBRARY + NAMES OpenCL) +endif() + +set(OpenCL_LIBRARIES ${OpenCL_LIBRARY}) +set(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + OpenCL + FOUND_VAR OpenCL_FOUND + REQUIRED_VARS OpenCL_LIBRARY OpenCL_INCLUDE_DIR + VERSION_VAR OpenCL_VERSION_STRING) + +mark_as_advanced( + OpenCL_INCLUDE_DIR + OpenCL_LIBRARY) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/kinect2_registration.cmake.in b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/kinect2_registration.cmake.in new file mode 100644 index 0000000..27b92f4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/cmake/kinect2_registration.cmake.in @@ -0,0 +1,2 @@ +set(DEPTH_REG_CPU "@DEPTH_REG_CPU@") +set(DEPTH_REG_OPENCL "@DEPTH_REG_OPENCL@") diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/internal/CL/cl.hpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/internal/CL/cl.hpp new file mode 100644 index 0000000..396b867 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/internal/CL/cl.hpp @@ -0,0 +1,12934 @@ +/******************************************************************************* + * Copyright (c) 2008-2015 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ + +/*! \file + * + * \brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33) and + * OpenCL 1.2 (rev 15) + * \author Benedict R. Gaster, Laurent Morichetti and Lee Howes + * + * Additions and fixes from: + * Brian Cole, March 3rd 2010 and April 2012 + * Matt Gruenke, April 2012. + * Bruce Merry, February 2013. + * Tom Deakin and Simon McIntosh-Smith, July 2013 + * + * \version 1.2.8 + * \date October 2015 + * + * Optional extension support + * + * cl + * cl_ext_device_fission + * #define USE_CL_DEVICE_FISSION + */ + +/*! \mainpage + * \section intro Introduction + * For many large applications C++ is the language of choice and so it seems + * reasonable to define C++ bindings for OpenCL. + * + * + * The interface is contained with a single C++ header file \em cl.hpp and all + * definitions are contained within the namespace \em cl. There is no additional + * requirement to include \em cl.h and to use either the C++ or original C + * bindings it is enough to simply include \em cl.hpp. + * + * The bindings themselves are lightweight and correspond closely to the + * underlying C API. Using the C++ bindings introduces no additional execution + * overhead. + * + * For detail documentation on the bindings see: + * + * The OpenCL C++ Wrapper API 1.2 (revision 09) + * http://www.khronos.org/registry/cl/specs/opencl-cplusplus-1.2.pdf + * + * \section example Example + * + * The following example shows a general use case for the C++ + * bindings, including support for the optional exception feature and + * also the supplied vector and string classes, see following sections for + * decriptions of these features. + * + * \code + * #define __CL_ENABLE_EXCEPTIONS + * + * #if defined(__APPLE__) || defined(__MACOSX) + * #include + * #else + * #include + * #endif + * #include + * #include + * #include + * + * const char * helloStr = "__kernel void " + * "hello(void) " + * "{ " + * " " + * "} "; + * + * int + * main(void) + * { + * cl_int err = CL_SUCCESS; + * try { + * + * std::vector platforms; + * cl::Platform::get(&platforms); + * if (platforms.size() == 0) { + * std::cout << "Platform size 0\n"; + * return -1; + * } + * + * cl_context_properties properties[] = + * { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0}; + * cl::Context context(CL_DEVICE_TYPE_CPU, properties); + * + * std::vector devices = context.getInfo(); + * + * cl::Program::Sources source(1, + * std::make_pair(helloStr,strlen(helloStr))); + * cl::Program program_ = cl::Program(context, source); + * program_.build(devices); + * + * cl::Kernel kernel(program_, "hello", &err); + * + * cl::Event event; + * cl::CommandQueue queue(context, devices[0], 0, &err); + * queue.enqueueNDRangeKernel( + * kernel, + * cl::NullRange, + * cl::NDRange(4,4), + * cl::NullRange, + * NULL, + * &event); + * + * event.wait(); + * } + * catch (cl::Error err) { + * std::cerr + * << "ERROR: " + * << err.what() + * << "(" + * << err.err() + * << ")" + * << std::endl; + * } + * + * return EXIT_SUCCESS; + * } + * + * \endcode + * + */ +#ifndef CL_HPP_ +#define CL_HPP_ + +#ifdef _WIN32 + +#include + +#if defined(USE_DX_INTEROP) +#include +#include +#endif +#endif // _WIN32 + +#if defined(_MSC_VER) +#include +#endif // _MSC_VER + +// +#if defined(USE_CL_DEVICE_FISSION) +#include +#endif + +#if defined(__APPLE__) || defined(__MACOSX) +#include +#else +#include +#endif // !__APPLE__ + +#if (_MSC_VER >= 1700) || (__cplusplus >= 201103L) +#define CL_HPP_RVALUE_REFERENCES_SUPPORTED +#define CL_HPP_CPP11_ATOMICS_SUPPORTED +#include +#endif + +#if (__cplusplus >= 201103L) +#define CL_HPP_NOEXCEPT noexcept +#else +#define CL_HPP_NOEXCEPT +#endif + + +// To avoid accidentally taking ownership of core OpenCL types +// such as cl_kernel constructors are made explicit +// under OpenCL 1.2 +#if defined(CL_VERSION_1_2) && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +#define __CL_EXPLICIT_CONSTRUCTORS explicit +#else // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +#define __CL_EXPLICIT_CONSTRUCTORS +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +// Define deprecated prefixes and suffixes to ensure compilation +// in case they are not pre-defined +#if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) +#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) +#if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED) +#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) + +#if !defined(CL_CALLBACK) +#define CL_CALLBACK +#endif //CL_CALLBACK + +#include +#include +#include + +#if defined(__CL_ENABLE_EXCEPTIONS) +#include +#endif // #if defined(__CL_ENABLE_EXCEPTIONS) + +#if !defined(__NO_STD_VECTOR) +#include +#endif + +#if !defined(__NO_STD_STRING) +#include +#endif + +#if defined(__ANDROID__) || defined(linux) || defined(__APPLE__) || defined(__MACOSX) +#include +#endif // linux + +#include + + +/*! \namespace cl + * + * \brief The OpenCL C++ bindings are defined within this namespace. + * + */ +namespace cl { + +class Memory; + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +#define __INIT_CL_EXT_FCN_PTR(name) \ + if(!pfn_##name) { \ + pfn_##name = (PFN_##name) \ + clGetExtensionFunctionAddress(#name); \ + if(!pfn_##name) { \ + } \ + } +#endif // #if defined(CL_VERSION_1_1) + +#if defined(CL_VERSION_1_2) +#define __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, name) \ + if(!pfn_##name) { \ + pfn_##name = (PFN_##name) \ + clGetExtensionFunctionAddressForPlatform(platform, #name); \ + if(!pfn_##name) { \ + } \ + } +#endif // #if defined(CL_VERSION_1_1) + +class Program; +class Device; +class Context; +class CommandQueue; +class Memory; +class Buffer; + +#if defined(__CL_ENABLE_EXCEPTIONS) +/*! \brief Exception class + * + * This may be thrown by API functions when __CL_ENABLE_EXCEPTIONS is defined. + */ +class Error : public std::exception +{ +private: + cl_int err_; + const char * errStr_; +public: + /*! \brief Create a new CL error exception for a given error code + * and corresponding message. + * + * \param err error code value. + * + * \param errStr a descriptive string that must remain in scope until + * handling of the exception has concluded. If set, it + * will be returned by what(). + */ + Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr) + {} + + ~Error() throw() {} + + /*! \brief Get error string associated with exception + * + * \return A memory pointer to the error message string. + */ + virtual const char * what() const throw () + { + if (errStr_ == NULL) { + return "empty"; + } + else { + return errStr_; + } + } + + /*! \brief Get error code associated with exception + * + * \return The error code. + */ + cl_int err(void) const { return err_; } +}; + +#define __ERR_STR(x) #x +#else +#define __ERR_STR(x) NULL +#endif // __CL_ENABLE_EXCEPTIONS + + +namespace detail +{ +#if defined(__CL_ENABLE_EXCEPTIONS) +static inline cl_int errHandler ( + cl_int err, + const char * errStr = NULL) +{ + if (err != CL_SUCCESS) { + throw Error(err, errStr); + } + return err; +} +#else +static inline cl_int errHandler (cl_int err, const char * errStr = NULL) +{ + (void) errStr; // suppress unused variable warning + return err; +} +#endif // __CL_ENABLE_EXCEPTIONS +} + + + +//! \cond DOXYGEN_DETAIL +#if !defined(__CL_USER_OVERRIDE_ERROR_STRINGS) +#define __GET_DEVICE_INFO_ERR __ERR_STR(clGetDeviceInfo) +#define __GET_PLATFORM_INFO_ERR __ERR_STR(clGetPlatformInfo) +#define __GET_DEVICE_IDS_ERR __ERR_STR(clGetDeviceIDs) +#define __GET_PLATFORM_IDS_ERR __ERR_STR(clGetPlatformIDs) +#define __GET_CONTEXT_INFO_ERR __ERR_STR(clGetContextInfo) +#define __GET_EVENT_INFO_ERR __ERR_STR(clGetEventInfo) +#define __GET_EVENT_PROFILE_INFO_ERR __ERR_STR(clGetEventProfileInfo) +#define __GET_MEM_OBJECT_INFO_ERR __ERR_STR(clGetMemObjectInfo) +#define __GET_IMAGE_INFO_ERR __ERR_STR(clGetImageInfo) +#define __GET_SAMPLER_INFO_ERR __ERR_STR(clGetSamplerInfo) +#define __GET_KERNEL_INFO_ERR __ERR_STR(clGetKernelInfo) +#if defined(CL_VERSION_1_2) +#define __GET_KERNEL_ARG_INFO_ERR __ERR_STR(clGetKernelArgInfo) +#endif // #if defined(CL_VERSION_1_2) +#define __GET_KERNEL_WORK_GROUP_INFO_ERR __ERR_STR(clGetKernelWorkGroupInfo) +#define __GET_PROGRAM_INFO_ERR __ERR_STR(clGetProgramInfo) +#define __GET_PROGRAM_BUILD_INFO_ERR __ERR_STR(clGetProgramBuildInfo) +#define __GET_COMMAND_QUEUE_INFO_ERR __ERR_STR(clGetCommandQueueInfo) + +#define __CREATE_CONTEXT_ERR __ERR_STR(clCreateContext) +#define __CREATE_CONTEXT_FROM_TYPE_ERR __ERR_STR(clCreateContextFromType) +#define __GET_SUPPORTED_IMAGE_FORMATS_ERR __ERR_STR(clGetSupportedImageFormats) + +#define __CREATE_BUFFER_ERR __ERR_STR(clCreateBuffer) +#define __COPY_ERR __ERR_STR(cl::copy) +#define __CREATE_SUBBUFFER_ERR __ERR_STR(clCreateSubBuffer) +#define __CREATE_GL_BUFFER_ERR __ERR_STR(clCreateFromGLBuffer) +#define __CREATE_GL_RENDER_BUFFER_ERR __ERR_STR(clCreateFromGLBuffer) +#define __GET_GL_OBJECT_INFO_ERR __ERR_STR(clGetGLObjectInfo) +#if defined(CL_VERSION_1_2) +#define __CREATE_IMAGE_ERR __ERR_STR(clCreateImage) +#define __CREATE_GL_TEXTURE_ERR __ERR_STR(clCreateFromGLTexture) +#define __IMAGE_DIMENSION_ERR __ERR_STR(Incorrect image dimensions) +#endif // #if defined(CL_VERSION_1_2) +#define __CREATE_SAMPLER_ERR __ERR_STR(clCreateSampler) +#define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR __ERR_STR(clSetMemObjectDestructorCallback) + +#define __CREATE_USER_EVENT_ERR __ERR_STR(clCreateUserEvent) +#define __SET_USER_EVENT_STATUS_ERR __ERR_STR(clSetUserEventStatus) +#define __SET_EVENT_CALLBACK_ERR __ERR_STR(clSetEventCallback) +#define __WAIT_FOR_EVENTS_ERR __ERR_STR(clWaitForEvents) + +#define __CREATE_KERNEL_ERR __ERR_STR(clCreateKernel) +#define __SET_KERNEL_ARGS_ERR __ERR_STR(clSetKernelArg) +#define __CREATE_PROGRAM_WITH_SOURCE_ERR __ERR_STR(clCreateProgramWithSource) +#define __CREATE_PROGRAM_WITH_BINARY_ERR __ERR_STR(clCreateProgramWithBinary) +#if defined(CL_VERSION_1_2) +#define __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR __ERR_STR(clCreateProgramWithBuiltInKernels) +#endif // #if defined(CL_VERSION_1_2) +#define __BUILD_PROGRAM_ERR __ERR_STR(clBuildProgram) +#if defined(CL_VERSION_1_2) +#define __COMPILE_PROGRAM_ERR __ERR_STR(clCompileProgram) +#define __LINK_PROGRAM_ERR __ERR_STR(clLinkProgram) +#endif // #if defined(CL_VERSION_1_2) +#define __CREATE_KERNELS_IN_PROGRAM_ERR __ERR_STR(clCreateKernelsInProgram) + +#define __CREATE_COMMAND_QUEUE_ERR __ERR_STR(clCreateCommandQueue) +#define __SET_COMMAND_QUEUE_PROPERTY_ERR __ERR_STR(clSetCommandQueueProperty) +#define __ENQUEUE_READ_BUFFER_ERR __ERR_STR(clEnqueueReadBuffer) +#define __ENQUEUE_READ_BUFFER_RECT_ERR __ERR_STR(clEnqueueReadBufferRect) +#define __ENQUEUE_WRITE_BUFFER_ERR __ERR_STR(clEnqueueWriteBuffer) +#define __ENQUEUE_WRITE_BUFFER_RECT_ERR __ERR_STR(clEnqueueWriteBufferRect) +#define __ENQEUE_COPY_BUFFER_ERR __ERR_STR(clEnqueueCopyBuffer) +#define __ENQEUE_COPY_BUFFER_RECT_ERR __ERR_STR(clEnqueueCopyBufferRect) +#define __ENQUEUE_FILL_BUFFER_ERR __ERR_STR(clEnqueueFillBuffer) +#define __ENQUEUE_READ_IMAGE_ERR __ERR_STR(clEnqueueReadImage) +#define __ENQUEUE_WRITE_IMAGE_ERR __ERR_STR(clEnqueueWriteImage) +#define __ENQUEUE_COPY_IMAGE_ERR __ERR_STR(clEnqueueCopyImage) +#define __ENQUEUE_FILL_IMAGE_ERR __ERR_STR(clEnqueueFillImage) +#define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR __ERR_STR(clEnqueueCopyImageToBuffer) +#define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR __ERR_STR(clEnqueueCopyBufferToImage) +#define __ENQUEUE_MAP_BUFFER_ERR __ERR_STR(clEnqueueMapBuffer) +#define __ENQUEUE_MAP_IMAGE_ERR __ERR_STR(clEnqueueMapImage) +#define __ENQUEUE_UNMAP_MEM_OBJECT_ERR __ERR_STR(clEnqueueUnMapMemObject) +#define __ENQUEUE_NDRANGE_KERNEL_ERR __ERR_STR(clEnqueueNDRangeKernel) +#define __ENQUEUE_TASK_ERR __ERR_STR(clEnqueueTask) +#define __ENQUEUE_NATIVE_KERNEL __ERR_STR(clEnqueueNativeKernel) +#if defined(CL_VERSION_1_2) +#define __ENQUEUE_MIGRATE_MEM_OBJECTS_ERR __ERR_STR(clEnqueueMigrateMemObjects) +#endif // #if defined(CL_VERSION_1_2) + +#define __ENQUEUE_ACQUIRE_GL_ERR __ERR_STR(clEnqueueAcquireGLObjects) +#define __ENQUEUE_RELEASE_GL_ERR __ERR_STR(clEnqueueReleaseGLObjects) + + +#define __RETAIN_ERR __ERR_STR(Retain Object) +#define __RELEASE_ERR __ERR_STR(Release Object) +#define __FLUSH_ERR __ERR_STR(clFlush) +#define __FINISH_ERR __ERR_STR(clFinish) +#define __VECTOR_CAPACITY_ERR __ERR_STR(Vector capacity error) + +/** + * CL 1.2 version that uses device fission. + */ +#if defined(CL_VERSION_1_2) +#define __CREATE_SUB_DEVICES __ERR_STR(clCreateSubDevices) +#else +#define __CREATE_SUB_DEVICES __ERR_STR(clCreateSubDevicesEXT) +#endif // #if defined(CL_VERSION_1_2) + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +#define __ENQUEUE_MARKER_ERR __ERR_STR(clEnqueueMarker) +#define __ENQUEUE_WAIT_FOR_EVENTS_ERR __ERR_STR(clEnqueueWaitForEvents) +#define __ENQUEUE_BARRIER_ERR __ERR_STR(clEnqueueBarrier) +#define __UNLOAD_COMPILER_ERR __ERR_STR(clUnloadCompiler) +#define __CREATE_GL_TEXTURE_2D_ERR __ERR_STR(clCreateFromGLTexture2D) +#define __CREATE_GL_TEXTURE_3D_ERR __ERR_STR(clCreateFromGLTexture3D) +#define __CREATE_IMAGE2D_ERR __ERR_STR(clCreateImage2D) +#define __CREATE_IMAGE3D_ERR __ERR_STR(clCreateImage3D) +#endif // #if defined(CL_VERSION_1_1) + +#endif // __CL_USER_OVERRIDE_ERROR_STRINGS +//! \endcond + +/** + * CL 1.2 marker and barrier commands + */ +#if defined(CL_VERSION_1_2) +#define __ENQUEUE_MARKER_WAIT_LIST_ERR __ERR_STR(clEnqueueMarkerWithWaitList) +#define __ENQUEUE_BARRIER_WAIT_LIST_ERR __ERR_STR(clEnqueueBarrierWithWaitList) +#endif // #if defined(CL_VERSION_1_2) + +#if !defined(__USE_DEV_STRING) && !defined(__NO_STD_STRING) +typedef std::string STRING_CLASS; +#elif !defined(__USE_DEV_STRING) + +/*! \class string + * \brief Simple string class, that provides a limited subset of std::string + * functionality but avoids many of the issues that come with that class. + + * \note Deprecated. Please use std::string as default or + * re-define the string class to match the std::string + * interface by defining STRING_CLASS + */ +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED string CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED +{ +private: + ::size_t size_; + char * str_; +public: + //! \brief Constructs an empty string, allocating no memory. + string(void) : size_(0), str_(NULL) + { + } + + /*! \brief Constructs a string populated from an arbitrary value of + * specified size. + * + * An extra '\0' is added, in case none was contained in str. + * + * \param str the initial value of the string instance. Note that '\0' + * characters receive no special treatment. If NULL, + * the string is left empty, with a size of 0. + * + * \param size the number of characters to copy from str. + */ + string(const char * str, ::size_t size) : + size_(size), + str_(NULL) + { + if( size > 0 ) { + str_ = new char[size_+1]; + if (str_ != NULL) { + memcpy(str_, str, size_ * sizeof(char)); + str_[size_] = '\0'; + } + else { + size_ = 0; + } + } + } + + /*! \brief Constructs a string populated from a null-terminated value. + * + * \param str the null-terminated initial value of the string instance. + * If NULL, the string is left empty, with a size of 0. + */ + string(const char * str) : + size_(0), + str_(NULL) + { + if( str ) { + size_= ::strlen(str); + } + if( size_ > 0 ) { + str_ = new char[size_ + 1]; + if (str_ != NULL) { + memcpy(str_, str, (size_ + 1) * sizeof(char)); + } + } + } + + void resize( ::size_t n ) + { + if( size_ == n ) { + return; + } + if (n == 0) { + if( str_ ) { + delete [] str_; + } + str_ = NULL; + size_ = 0; + } + else { + char *newString = new char[n + 1]; + ::size_t copySize = n; + if( size_ < n ) { + copySize = size_; + } + size_ = n; + + if(str_) { + memcpy(newString, str_, (copySize + 1) * sizeof(char)); + } + if( copySize < size_ ) { + memset(newString + copySize, 0, size_ - copySize); + } + newString[size_] = '\0'; + + delete [] str_; + str_ = newString; + } + } + + const char& operator[] ( ::size_t pos ) const + { + return str_[pos]; + } + + char& operator[] ( ::size_t pos ) + { + return str_[pos]; + } + + /*! \brief Copies the value of another string to this one. + * + * \param rhs the string to copy. + * + * \returns a reference to the modified instance. + */ + string& operator=(const string& rhs) + { + if (this == &rhs) { + return *this; + } + + if( str_ != NULL ) { + delete [] str_; + str_ = NULL; + size_ = 0; + } + + if (rhs.size_ == 0 || rhs.str_ == NULL) { + str_ = NULL; + size_ = 0; + } + else { + str_ = new char[rhs.size_ + 1]; + size_ = rhs.size_; + + if (str_ != NULL) { + memcpy(str_, rhs.str_, (size_ + 1) * sizeof(char)); + } + else { + size_ = 0; + } + } + + return *this; + } + + /*! \brief Constructs a string by copying the value of another instance. + * + * \param rhs the string to copy. + */ + string(const string& rhs) : + size_(0), + str_(NULL) + { + *this = rhs; + } + + //! \brief Destructor - frees memory used to hold the current value. + ~string() + { + delete[] str_; + str_ = NULL; + } + + //! \brief Queries the length of the string, excluding any added '\0's. + ::size_t size(void) const { return size_; } + + //! \brief Queries the length of the string, excluding any added '\0's. + ::size_t length(void) const { return size(); } + + /*! \brief Returns a pointer to the private copy held by this instance, + * or "" if empty/unset. + */ + const char * c_str(void) const { return (str_) ? str_ : "";} +}; +typedef cl::string STRING_CLASS; +#endif // #elif !defined(__USE_DEV_STRING) + +#if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR) +#define VECTOR_CLASS std::vector +#elif !defined(__USE_DEV_VECTOR) +#define VECTOR_CLASS cl::vector + +#if !defined(__MAX_DEFAULT_VECTOR_SIZE) +#define __MAX_DEFAULT_VECTOR_SIZE 10 +#endif + +/*! \class vector + * \brief Fixed sized vector implementation that mirroring + * + * \note Deprecated. Please use std::vector as default or + * re-define the vector class to match the std::vector + * interface by defining VECTOR_CLASS + + * \note Not recommended for use with custom objects as + * current implementation will construct N elements + * + * std::vector functionality. + * \brief Fixed sized vector compatible with std::vector. + * + * \note + * This differs from std::vector<> not just in memory allocation, + * but also in terms of when members are constructed, destroyed, + * and assigned instead of being copy constructed. + * + * \param T type of element contained in the vector. + * + * \param N maximum size of the vector. + */ +template +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED vector +{ +private: + T data_[N]; + unsigned int size_; + +public: + //! \brief Constructs an empty vector with no memory allocated. + vector() : + size_(static_cast(0)) + {} + + //! \brief Deallocates the vector's memory and destroys all of its elements. + ~vector() + { + clear(); + } + + //! \brief Returns the number of elements currently contained. + unsigned int size(void) const + { + return size_; + } + + /*! \brief Empties the vector of all elements. + * \note + * This does not deallocate memory but will invoke destructors + * on contained elements. + */ + void clear() + { + while(!empty()) { + pop_back(); + } + } + + /*! \brief Appends an element after the last valid element. + * Calling this on a vector that has reached capacity will throw an + * exception if exceptions are enabled. + */ + void push_back (const T& x) + { + if (size() < N) { + new (&data_[size_]) T(x); + size_++; + } else { + detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR); + } + } + + /*! \brief Removes the last valid element from the vector. + * Calling this on an empty vector will throw an exception + * if exceptions are enabled. + */ + void pop_back(void) + { + if (size_ != 0) { + --size_; + data_[size_].~T(); + } else { + detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR); + } + } + + /*! \brief Constructs with a value copied from another. + * + * \param vec the vector to copy. + */ + vector(const vector& vec) : + size_(vec.size_) + { + if (size_ != 0) { + assign(vec.begin(), vec.end()); + } + } + + /*! \brief Constructs with a specified number of initial elements. + * + * \param size number of initial elements. + * + * \param val value of initial elements. + */ + vector(unsigned int size, const T& val = T()) : + size_(0) + { + for (unsigned int i = 0; i < size; i++) { + push_back(val); + } + } + + /*! \brief Overwrites the current content with that copied from another + * instance. + * + * \param rhs vector to copy. + * + * \returns a reference to this. + */ + vector& operator=(const vector& rhs) + { + if (this == &rhs) { + return *this; + } + + if (rhs.size_ != 0) { + assign(rhs.begin(), rhs.end()); + } else { + clear(); + } + + return *this; + } + + /*! \brief Tests equality against another instance. + * + * \param vec the vector against which to compare. + */ + bool operator==(vector &vec) + { + if (size() != vec.size()) { + return false; + } + + for( unsigned int i = 0; i < size(); ++i ) { + if( operator[](i) != vec[i] ) { + return false; + } + } + return true; + } + + //! \brief Conversion operator to T*. + operator T* () { return data_; } + + //! \brief Conversion operator to const T*. + operator const T* () const { return data_; } + + //! \brief Tests whether this instance has any elements. + bool empty (void) const + { + return size_==0; + } + + //! \brief Returns the maximum number of elements this instance can hold. + unsigned int max_size (void) const + { + return N; + } + + //! \brief Returns the maximum number of elements this instance can hold. + unsigned int capacity () const + { + return N; + } + + //! \brief Resizes the vector to the given size + void resize(unsigned int newSize, T fill = T()) + { + if (newSize > N) + { + detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR); + } + else + { + while (size_ < newSize) + { + new (&data_[size_]) T(fill); + size_++; + } + while (size_ > newSize) + { + --size_; + data_[size_].~T(); + } + } + } + + /*! \brief Returns a reference to a given element. + * + * \param index which element to access. * + * \note + * The caller is responsible for ensuring index is >= 0 and < size(). + */ + T& operator[](int index) + { + return data_[index]; + } + + /*! \brief Returns a const reference to a given element. + * + * \param index which element to access. + * + * \note + * The caller is responsible for ensuring index is >= 0 and < size(). + */ + const T& operator[](int index) const + { + return data_[index]; + } + + /*! \brief Assigns elements of the vector based on a source iterator range. + * + * \param start Beginning iterator of source range + * \param end Enditerator of source range + * + * \note + * Will throw an exception if exceptions are enabled and size exceeded. + */ + template + void assign(I start, I end) + { + clear(); + while(start != end) { + push_back(*start); + start++; + } + } + + /*! \class iterator + * \brief Const iterator class for vectors + */ + class iterator + { + private: + const vector *vec_; + int index_; + + /** + * Internal iterator constructor to capture reference + * to the vector it iterates over rather than taking + * the vector by copy. + */ + iterator (const vector &vec, int index) : + vec_(&vec) + { + if( !vec.empty() ) { + index_ = index; + } else { + index_ = -1; + } + } + + public: + iterator(void) : + index_(-1), + vec_(NULL) + { + } + + iterator(const iterator& rhs) : + vec_(rhs.vec_), + index_(rhs.index_) + { + } + + ~iterator(void) {} + + static iterator begin(const cl::vector &vec) + { + iterator i(vec, 0); + + return i; + } + + static iterator end(const cl::vector &vec) + { + iterator i(vec, vec.size()); + + return i; + } + + bool operator==(iterator i) + { + return ((vec_ == i.vec_) && + (index_ == i.index_)); + } + + bool operator!=(iterator i) + { + return (!(*this==i)); + } + + iterator& operator++() + { + ++index_; + return *this; + } + + iterator operator++(int) + { + iterator retVal(*this); + ++index_; + return retVal; + } + + iterator& operator--() + { + --index_; + return *this; + } + + iterator operator--(int) + { + iterator retVal(*this); + --index_; + return retVal; + } + + const T& operator *() const + { + return (*vec_)[index_]; + } + }; + + iterator begin(void) + { + return iterator::begin(*this); + } + + iterator begin(void) const + { + return iterator::begin(*this); + } + + iterator end(void) + { + return iterator::end(*this); + } + + iterator end(void) const + { + return iterator::end(*this); + } + + T& front(void) + { + return data_[0]; + } + + T& back(void) + { + return data_[size_]; + } + + const T& front(void) const + { + return data_[0]; + } + + const T& back(void) const + { + return data_[size_-1]; + } +} CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +#endif // #if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR) + + + + + +namespace detail { +#define __DEFAULT_NOT_INITIALIZED 1 +#define __DEFAULT_BEING_INITIALIZED 2 +#define __DEFAULT_INITIALIZED 4 + + /* + * Compare and exchange primitives are needed for handling of defaults + */ + +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + inline int compare_exchange(std::atomic * dest, int exchange, int comparand) +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED + inline int compare_exchange(volatile int * dest, int exchange, int comparand) +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + { +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + std::atomic_compare_exchange_strong(dest, &comparand, exchange); + return comparand; +#elif _MSC_VER + return (int)(_InterlockedCompareExchange( + (volatile long*)dest, + (long)exchange, + (long)comparand)); +#else // !_MSC_VER && !CL_HPP_CPP11_ATOMICS_SUPPORTED + return (__sync_val_compare_and_swap( + dest, + comparand, + exchange)); +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + } + + inline void fence() { +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + std::atomic_thread_fence(std::memory_order_seq_cst); +#elif _MSC_VER // !CL_HPP_CPP11_ATOMICS_SUPPORTED + _ReadWriteBarrier(); +#else // !_MSC_VER && !CL_HPP_CPP11_ATOMICS_SUPPORTED + __sync_synchronize(); +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + } +} // namespace detail + + +/*! \brief class used to interface between C++ and + * OpenCL C calls that require arrays of size_t values, whose + * size is known statically. + */ +template +class size_t +{ +private: + ::size_t data_[N]; + +public: + //! \brief Initialize size_t to all 0s + size_t() + { + for( int i = 0; i < N; ++i ) { + data_[i] = 0; + } + } + + ::size_t& operator[](int index) + { + return data_[index]; + } + + const ::size_t& operator[](int index) const + { + return data_[index]; + } + + //! \brief Conversion operator to T*. + operator ::size_t* () { return data_; } + + //! \brief Conversion operator to const T*. + operator const ::size_t* () const { return data_; } +}; + +namespace detail { + +// Generic getInfoHelper. The final parameter is used to guide overload +// resolution: the actual parameter passed is an int, which makes this +// a worse conversion sequence than a specialization that declares the +// parameter as an int. +template +inline cl_int getInfoHelper(Functor f, cl_uint name, T* param, long) +{ + return f(name, sizeof(T), param, NULL); +} + +// Specialized getInfoHelper for VECTOR_CLASS params +template +inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS* param, long) +{ + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + T* value = (T*) alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + param->assign(&value[0], &value[required/sizeof(T)]); + return CL_SUCCESS; +} + +/* Specialization for reference-counted types. This depends on the + * existence of Wrapper::cl_type, and none of the other types having the + * cl_type member. Note that simplify specifying the parameter as Wrapper + * does not work, because when using a derived type (e.g. Context) the generic + * template will provide a better match. + */ +template +inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS* param, int, typename T::cl_type = 0) +{ + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + typename T::cl_type * value = (typename T::cl_type *) alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + ::size_t elements = required / sizeof(typename T::cl_type); + param->assign(&value[0], &value[elements]); + for (::size_t i = 0; i < elements; i++) + { + if (value[i] != NULL) + { + err = (*param)[i].retain(); + if (err != CL_SUCCESS) { + return err; + } + } + } + return CL_SUCCESS; +} + +// Specialized for getInfo +template +inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS* param, int) +{ + cl_int err = f(name, param->size() * sizeof(char *), &(*param)[0], NULL); + + if (err != CL_SUCCESS) { + return err; + } + + return CL_SUCCESS; +} + +// Specialized GetInfoHelper for STRING_CLASS params +template +inline cl_int getInfoHelper(Func f, cl_uint name, STRING_CLASS* param, long) +{ +#if defined(__NO_STD_VECTOR) || defined(__NO_STD_STRING) + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + char* value = (char*)alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + *param = value; + return CL_SUCCESS; +#else + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + // std::string has a constant data member + // a char vector does not + VECTOR_CLASS value(required); + err = f(name, required, value.data(), NULL); + if (err != CL_SUCCESS) { + return err; + } + if (param) { + param->assign(value.begin(), value.end()); + } +#endif + return CL_SUCCESS; +} + +// Specialized GetInfoHelper for cl::size_t params +template +inline cl_int getInfoHelper(Func f, cl_uint name, size_t* param, long) +{ + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + ::size_t* value = (::size_t*) alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + for(int i = 0; i < N; ++i) { + (*param)[i] = value[i]; + } + + return CL_SUCCESS; +} + +template struct ReferenceHandler; + +/* Specialization for reference-counted types. This depends on the + * existence of Wrapper::cl_type, and none of the other types having the + * cl_type member. Note that simplify specifying the parameter as Wrapper + * does not work, because when using a derived type (e.g. Context) the generic + * template will provide a better match. + */ +template +inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_type = 0) +{ + typename T::cl_type value; + cl_int err = f(name, sizeof(value), &value, NULL); + if (err != CL_SUCCESS) { + return err; + } + *param = value; + if (value != NULL) + { + err = param->retain(); + if (err != CL_SUCCESS) { + return err; + } + } + return CL_SUCCESS; +} + +#define __PARAM_NAME_INFO_1_0(F) \ + F(cl_platform_info, CL_PLATFORM_PROFILE, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_VERSION, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_NAME, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_VENDOR, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_EXTENSIONS, STRING_CLASS) \ + \ + F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \ + F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, ::size_t) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, VECTOR_CLASS< ::size_t>) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \ + F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_bool) \ + F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, ::size_t) \ + F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \ + F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \ + F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \ + F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \ + F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, ::size_t) \ + F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \ + F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties) \ + F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \ + F(cl_device_info, CL_DEVICE_NAME, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_VENDOR, STRING_CLASS) \ + F(cl_device_info, CL_DRIVER_VERSION, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_PROFILE, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_VERSION, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_EXTENSIONS, STRING_CLASS) \ + \ + F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \ + F(cl_context_info, CL_CONTEXT_DEVICES, VECTOR_CLASS) \ + F(cl_context_info, CL_CONTEXT_PROPERTIES, VECTOR_CLASS) \ + \ + F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \ + F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \ + F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \ + F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int) \ + \ + F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \ + \ + F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \ + F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \ + F(cl_mem_info, CL_MEM_SIZE, ::size_t) \ + F(cl_mem_info, CL_MEM_HOST_PTR, void*) \ + F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \ + F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \ + F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \ + \ + F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \ + F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, ::size_t) \ + F(cl_image_info, CL_IMAGE_ROW_PITCH, ::size_t) \ + F(cl_image_info, CL_IMAGE_SLICE_PITCH, ::size_t) \ + F(cl_image_info, CL_IMAGE_WIDTH, ::size_t) \ + F(cl_image_info, CL_IMAGE_HEIGHT, ::size_t) \ + F(cl_image_info, CL_IMAGE_DEPTH, ::size_t) \ + \ + F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \ + F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \ + F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_bool) \ + F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode) \ + F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_filter_mode) \ + \ + F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \ + F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \ + F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \ + F(cl_program_info, CL_PROGRAM_DEVICES, VECTOR_CLASS) \ + F(cl_program_info, CL_PROGRAM_SOURCE, STRING_CLASS) \ + F(cl_program_info, CL_PROGRAM_BINARY_SIZES, VECTOR_CLASS< ::size_t>) \ + F(cl_program_info, CL_PROGRAM_BINARIES, VECTOR_CLASS) \ + \ + F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, STRING_CLASS) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, STRING_CLASS) \ + \ + F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, STRING_CLASS) \ + F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \ + F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \ + F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \ + F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \ + \ + F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, ::size_t) \ + F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::size_t<3>) \ + F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \ + \ + F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \ + F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \ + F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \ + F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties) + +#if defined(CL_VERSION_1_1) +#define __PARAM_NAME_INFO_1_1(F) \ + F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \ + F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool) \ + F(cl_device_info, CL_DEVICE_OPENCL_C_VERSION, STRING_CLASS) \ + \ + F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \ + F(cl_mem_info, CL_MEM_OFFSET, ::size_t) \ + \ + F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, ::size_t) \ + F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \ + \ + F(cl_event_info, CL_EVENT_CONTEXT, cl::Context) +#endif // CL_VERSION_1_1 + + +#if defined(CL_VERSION_1_2) +#define __PARAM_NAME_INFO_1_2(F) \ + F(cl_image_info, CL_IMAGE_BUFFER, cl::Buffer) \ + \ + F(cl_program_info, CL_PROGRAM_NUM_KERNELS, ::size_t) \ + F(cl_program_info, CL_PROGRAM_KERNEL_NAMES, STRING_CLASS) \ + \ + F(cl_program_build_info, CL_PROGRAM_BINARY_TYPE, cl_program_binary_type) \ + \ + F(cl_kernel_info, CL_KERNEL_ATTRIBUTES, STRING_CLASS) \ + \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_ADDRESS_QUALIFIER, cl_kernel_arg_address_qualifier) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_ACCESS_QUALIFIER, cl_kernel_arg_access_qualifier) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_NAME, STRING_CLASS) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, STRING_CLASS) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \ + \ + F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl_device_id) \ + F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_PARTITION_TYPE, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, ::size_t) \ + F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \ + F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, STRING_CLASS) +#endif // #if defined(CL_VERSION_1_2) + +#if defined(USE_CL_DEVICE_FISSION) +#define __PARAM_NAME_DEVICE_FISSION(F) \ + F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \ + F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \ + F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, VECTOR_CLASS) +#endif // USE_CL_DEVICE_FISSION + +template +struct param_traits {}; + +#define __CL_DECLARE_PARAM_TRAITS(token, param_name, T) \ +struct token; \ +template<> \ +struct param_traits \ +{ \ + enum { value = param_name }; \ + typedef T param_type; \ +}; + +__PARAM_NAME_INFO_1_0(__CL_DECLARE_PARAM_TRAITS) +#if defined(CL_VERSION_1_1) +__PARAM_NAME_INFO_1_1(__CL_DECLARE_PARAM_TRAITS) +#endif // CL_VERSION_1_1 +#if defined(CL_VERSION_1_2) +__PARAM_NAME_INFO_1_2(__CL_DECLARE_PARAM_TRAITS) +#endif // CL_VERSION_1_1 + +#if defined(USE_CL_DEVICE_FISSION) +__PARAM_NAME_DEVICE_FISSION(__CL_DECLARE_PARAM_TRAITS); +#endif // USE_CL_DEVICE_FISSION + +#ifdef CL_PLATFORM_ICD_SUFFIX_KHR +__CL_DECLARE_PARAM_TRAITS(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, STRING_CLASS) +#endif + +#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong) +#endif + +#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, VECTOR_CLASS< ::size_t>) +#endif +#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_SIMD_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_WAVEFRONT_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint) +#endif + +#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint) +#endif +#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, cl_uint) +#endif +#ifdef CL_DEVICE_REGISTERS_PER_BLOCK_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_REGISTERS_PER_BLOCK_NV, cl_uint) +#endif +#ifdef CL_DEVICE_WARP_SIZE_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_WARP_SIZE_NV, cl_uint) +#endif +#ifdef CL_DEVICE_GPU_OVERLAP_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GPU_OVERLAP_NV, cl_bool) +#endif +#ifdef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, cl_bool) +#endif +#ifdef CL_DEVICE_INTEGRATED_MEMORY_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool) +#endif + +// Convenience functions + +template +inline cl_int +getInfo(Func f, cl_uint name, T* param) +{ + return getInfoHelper(f, name, param, 0); +} + +template +struct GetInfoFunctor0 +{ + Func f_; const Arg0& arg0_; + cl_int operator ()( + cl_uint param, ::size_t size, void* value, ::size_t* size_ret) + { return f_(arg0_, param, size, value, size_ret); } +}; + +template +struct GetInfoFunctor1 +{ + Func f_; const Arg0& arg0_; const Arg1& arg1_; + cl_int operator ()( + cl_uint param, ::size_t size, void* value, ::size_t* size_ret) + { return f_(arg0_, arg1_, param, size, value, size_ret); } +}; + +template +inline cl_int +getInfo(Func f, const Arg0& arg0, cl_uint name, T* param) +{ + GetInfoFunctor0 f0 = { f, arg0 }; + return getInfoHelper(f0, name, param, 0); +} + +template +inline cl_int +getInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param) +{ + GetInfoFunctor1 f0 = { f, arg0, arg1 }; + return getInfoHelper(f0, name, param, 0); +} + +template +struct ReferenceHandler +{ }; + +#if defined(CL_VERSION_1_2) +/** + * OpenCL 1.2 devices do have retain/release. + */ +template <> +struct ReferenceHandler +{ + /** + * Retain the device. + * \param device A valid device created using createSubDevices + * \return + * CL_SUCCESS if the function executed successfully. + * CL_INVALID_DEVICE if device was not a valid subdevice + * CL_OUT_OF_RESOURCES + * CL_OUT_OF_HOST_MEMORY + */ + static cl_int retain(cl_device_id device) + { return ::clRetainDevice(device); } + /** + * Retain the device. + * \param device A valid device created using createSubDevices + * \return + * CL_SUCCESS if the function executed successfully. + * CL_INVALID_DEVICE if device was not a valid subdevice + * CL_OUT_OF_RESOURCES + * CL_OUT_OF_HOST_MEMORY + */ + static cl_int release(cl_device_id device) + { return ::clReleaseDevice(device); } +}; +#else // #if defined(CL_VERSION_1_2) +/** + * OpenCL 1.1 devices do not have retain/release. + */ +template <> +struct ReferenceHandler +{ + // cl_device_id does not have retain(). + static cl_int retain(cl_device_id) + { return CL_SUCCESS; } + // cl_device_id does not have release(). + static cl_int release(cl_device_id) + { return CL_SUCCESS; } +}; +#endif // #if defined(CL_VERSION_1_2) + +template <> +struct ReferenceHandler +{ + // cl_platform_id does not have retain(). + static cl_int retain(cl_platform_id) + { return CL_SUCCESS; } + // cl_platform_id does not have release(). + static cl_int release(cl_platform_id) + { return CL_SUCCESS; } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_context context) + { return ::clRetainContext(context); } + static cl_int release(cl_context context) + { return ::clReleaseContext(context); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_command_queue queue) + { return ::clRetainCommandQueue(queue); } + static cl_int release(cl_command_queue queue) + { return ::clReleaseCommandQueue(queue); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_mem memory) + { return ::clRetainMemObject(memory); } + static cl_int release(cl_mem memory) + { return ::clReleaseMemObject(memory); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_sampler sampler) + { return ::clRetainSampler(sampler); } + static cl_int release(cl_sampler sampler) + { return ::clReleaseSampler(sampler); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_program program) + { return ::clRetainProgram(program); } + static cl_int release(cl_program program) + { return ::clReleaseProgram(program); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_kernel kernel) + { return ::clRetainKernel(kernel); } + static cl_int release(cl_kernel kernel) + { return ::clReleaseKernel(kernel); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_event event) + { return ::clRetainEvent(event); } + static cl_int release(cl_event event) + { return ::clReleaseEvent(event); } +}; + + +// Extracts version number with major in the upper 16 bits, minor in the lower 16 +static cl_uint getVersion(const char *versionInfo) +{ + int highVersion = 0; + int lowVersion = 0; + int index = 7; + while(versionInfo[index] != '.' ) { + highVersion *= 10; + highVersion += versionInfo[index]-'0'; + ++index; + } + ++index; + while(versionInfo[index] != ' ' && versionInfo[index] != '\0') { + lowVersion *= 10; + lowVersion += versionInfo[index]-'0'; + ++index; + } + return (highVersion << 16) | lowVersion; +} + +static cl_uint getPlatformVersion(cl_platform_id platform) +{ + ::size_t size = 0; + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &size); + char *versionInfo = (char *) alloca(size); + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, size, &versionInfo[0], &size); + return getVersion(versionInfo); +} + +static cl_uint getDevicePlatformVersion(cl_device_id device) +{ + cl_platform_id platform; + clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + return getPlatformVersion(platform); +} + +#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +static cl_uint getContextPlatformVersion(cl_context context) +{ + // The platform cannot be queried directly, so we first have to grab a + // device and obtain its context + ::size_t size = 0; + clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size); + if (size == 0) + return 0; + cl_device_id *devices = (cl_device_id *) alloca(size); + clGetContextInfo(context, CL_CONTEXT_DEVICES, size, devices, NULL); + return getDevicePlatformVersion(devices[0]); +} +#endif // #if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +template +class Wrapper +{ +public: + typedef T cl_type; + +protected: + cl_type object_; + +public: + Wrapper() : object_(NULL) { } + + Wrapper(const cl_type &obj) : object_(obj) { } + + ~Wrapper() + { + if (object_ != NULL) { release(); } + } + + Wrapper(const Wrapper& rhs) + { + object_ = rhs.object_; + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper(Wrapper&& rhs) CL_HPP_NOEXCEPT + { + object_ = rhs.object_; + rhs.object_ = NULL; + } +#endif + + Wrapper& operator = (const Wrapper& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper& operator = (Wrapper&& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + rhs.object_ = NULL; + } + return *this; + } +#endif + + Wrapper& operator = (const cl_type &rhs) + { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs; + return *this; + } + + cl_type operator ()() const { return object_; } + + cl_type& operator ()() { return object_; } + +protected: + template + friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type); + + cl_int retain() const + { + return ReferenceHandler::retain(object_); + } + + cl_int release() const + { + return ReferenceHandler::release(object_); + } +}; + +template <> +class Wrapper +{ +public: + typedef cl_device_id cl_type; + +protected: + cl_type object_; + bool referenceCountable_; + + static bool isReferenceCountable(cl_device_id device) + { + bool retVal = false; + if (device != NULL) { + int version = getDevicePlatformVersion(device); + if(version > ((1 << 16) + 1)) { + retVal = true; + } + } + return retVal; + } + +public: + Wrapper() : object_(NULL), referenceCountable_(false) + { + } + + Wrapper(const cl_type &obj) : object_(obj), referenceCountable_(false) + { + referenceCountable_ = isReferenceCountable(obj); + } + + ~Wrapper() + { + if (object_ != NULL) { release(); } + } + + Wrapper(const Wrapper& rhs) + { + object_ = rhs.object_; + referenceCountable_ = isReferenceCountable(object_); + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper(Wrapper&& rhs) CL_HPP_NOEXCEPT + { + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + rhs.object_ = NULL; + rhs.referenceCountable_ = false; + } +#endif + + Wrapper& operator = (const Wrapper& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper& operator = (Wrapper&& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + rhs.object_ = NULL; + rhs.referenceCountable_ = false; + } + return *this; + } +#endif + + Wrapper& operator = (const cl_type &rhs) + { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs; + referenceCountable_ = isReferenceCountable(object_); + return *this; + } + + cl_type operator ()() const { return object_; } + + cl_type& operator ()() { return object_; } + +protected: + template + friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type); + + template + friend inline cl_int getInfoHelper(Func, cl_uint, VECTOR_CLASS*, int, typename U::cl_type); + + cl_int retain() const + { + if( referenceCountable_ ) { + return ReferenceHandler::retain(object_); + } + else { + return CL_SUCCESS; + } + } + + cl_int release() const + { + if( referenceCountable_ ) { + return ReferenceHandler::release(object_); + } + else { + return CL_SUCCESS; + } + } +}; + +} // namespace detail +//! \endcond + +/*! \stuct ImageFormat + * \brief Adds constructors and member functions for cl_image_format. + * + * \see cl_image_format + */ +struct ImageFormat : public cl_image_format +{ + //! \brief Default constructor - performs no initialization. + ImageFormat(){} + + //! \brief Initializing constructor. + ImageFormat(cl_channel_order order, cl_channel_type type) + { + image_channel_order = order; + image_channel_data_type = type; + } + + //! \brief Assignment operator. + ImageFormat& operator = (const ImageFormat& rhs) + { + if (this != &rhs) { + this->image_channel_data_type = rhs.image_channel_data_type; + this->image_channel_order = rhs.image_channel_order; + } + return *this; + } +}; + +/*! \brief Class interface for cl_device_id. + * + * \note Copies of these objects are inexpensive, since they don't 'own' + * any underlying resources or data structures. + * + * \see cl_device_id + */ +class Device : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Device() : detail::Wrapper() { } + + /*! \brief Constructor from cl_device_id. + * + * This simply copies the device ID value, which is an inexpensive operation. + */ + __CL_EXPLICIT_CONSTRUCTORS Device(const cl_device_id &device) : detail::Wrapper(device) { } + + /*! \brief Returns the first device on the default context. + * + * \see Context::getDefault() + */ + static Device getDefault(cl_int * err = NULL); + + /*! \brief Assignment operator from cl_device_id. + * + * This simply copies the device ID value, which is an inexpensive operation. + */ + Device& operator = (const cl_device_id& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Device(const Device& dev) : detail::Wrapper(dev) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Device& operator = (const Device &dev) + { + detail::Wrapper::operator=(dev); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Device(Device&& dev) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(dev)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Device& operator = (Device &&dev) + { + detail::Wrapper::operator=(std::move(dev)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetDeviceInfo(). + template + cl_int getInfo(cl_device_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetDeviceInfo, object_, name, param), + __GET_DEVICE_INFO_ERR); + } + + //! \brief Wrapper for clGetDeviceInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_device_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /** + * CL 1.2 version + */ +#if defined(CL_VERSION_1_2) + //! \brief Wrapper for clCreateSubDevicesEXT(). + cl_int createSubDevices( + const cl_device_partition_property * properties, + VECTOR_CLASS* devices) + { + cl_uint n = 0; + cl_int err = clCreateSubDevices(object_, properties, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = clCreateSubDevices(object_, properties, n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } +#endif // #if defined(CL_VERSION_1_2) + +/** + * CL 1.1 version that uses device fission. + */ +#if defined(CL_VERSION_1_1) +#if defined(USE_CL_DEVICE_FISSION) + cl_int createSubDevices( + const cl_device_partition_property_ext * properties, + VECTOR_CLASS* devices) + { + typedef CL_API_ENTRY cl_int + ( CL_API_CALL * PFN_clCreateSubDevicesEXT)( + cl_device_id /*in_device*/, + const cl_device_partition_property_ext * /* properties */, + cl_uint /*num_entries*/, + cl_device_id * /*out_devices*/, + cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL; + __INIT_CL_EXT_FCN_PTR(clCreateSubDevicesEXT); + + cl_uint n = 0; + cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } +#endif // #if defined(USE_CL_DEVICE_FISSION) +#endif // #if defined(CL_VERSION_1_1) +}; + +/*! \brief Class interface for cl_platform_id. + * + * \note Copies of these objects are inexpensive, since they don't 'own' + * any underlying resources or data structures. + * + * \see cl_platform_id + */ +class Platform : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Platform() : detail::Wrapper() { } + + /*! \brief Constructor from cl_platform_id. + * + * This simply copies the platform ID value, which is an inexpensive operation. + */ + __CL_EXPLICIT_CONSTRUCTORS Platform(const cl_platform_id &platform) : detail::Wrapper(platform) { } + + /*! \brief Assignment operator from cl_platform_id. + * + * This simply copies the platform ID value, which is an inexpensive operation. + */ + Platform& operator = (const cl_platform_id& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetPlatformInfo(). + cl_int getInfo(cl_platform_info name, STRING_CLASS* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetPlatformInfo, object_, name, param), + __GET_PLATFORM_INFO_ERR); + } + + //! \brief Wrapper for clGetPlatformInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_platform_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Gets a list of devices for this platform. + * + * Wraps clGetDeviceIDs(). + */ + cl_int getDevices( + cl_device_type type, + VECTOR_CLASS* devices) const + { + cl_uint n = 0; + if( devices == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR); + } + cl_int err = ::clGetDeviceIDs(object_, type, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = ::clGetDeviceIDs(object_, type, n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } + +#if defined(USE_DX_INTEROP) + /*! \brief Get the list of available D3D10 devices. + * + * \param d3d_device_source. + * + * \param d3d_object. + * + * \param d3d_device_set. + * + * \param devices returns a vector of OpenCL D3D10 devices found. The cl::Device + * values returned in devices can be used to identify a specific OpenCL + * device. If \a devices argument is NULL, this argument is ignored. + * + * \return One of the following values: + * - CL_SUCCESS if the function is executed successfully. + * + * The application can query specific capabilities of the OpenCL device(s) + * returned by cl::getDevices. This can be used by the application to + * determine which device(s) to use. + * + * \note In the case that exceptions are enabled and a return value + * other than CL_SUCCESS is generated, then cl::Error exception is + * generated. + */ + cl_int getDevices( + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + VECTOR_CLASS* devices) const + { + typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clGetDeviceIDsFromD3D10KHR)( + cl_platform_id platform, + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + cl_uint num_entries, + cl_device_id * devices, + cl_uint* num_devices); + + if( devices == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR); + } + + static PFN_clGetDeviceIDsFromD3D10KHR pfn_clGetDeviceIDsFromD3D10KHR = NULL; + __INIT_CL_EXT_FCN_PTR_PLATFORM(object_, clGetDeviceIDsFromD3D10KHR); + + cl_uint n = 0; + cl_int err = pfn_clGetDeviceIDsFromD3D10KHR( + object_, + d3d_device_source, + d3d_object, + d3d_device_set, + 0, + NULL, + &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = pfn_clGetDeviceIDsFromD3D10KHR( + object_, + d3d_device_source, + d3d_object, + d3d_device_set, + n, + ids, + NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } +#endif + + /*! \brief Gets a list of available platforms. + * + * Wraps clGetPlatformIDs(). + */ + static cl_int get( + VECTOR_CLASS* platforms) + { + cl_uint n = 0; + + if( platforms == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR); + } + + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + cl_platform_id* ids = (cl_platform_id*) alloca( + n * sizeof(cl_platform_id)); + err = ::clGetPlatformIDs(n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + platforms->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } + + /*! \brief Gets the first available platform. + * + * Wraps clGetPlatformIDs(), returning the first result. + */ + static cl_int get( + Platform * platform) + { + cl_uint n = 0; + + if( platform == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR); + } + + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + cl_platform_id* ids = (cl_platform_id*) alloca( + n * sizeof(cl_platform_id)); + err = ::clGetPlatformIDs(n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + *platform = ids[0]; + return CL_SUCCESS; + } + + /*! \brief Gets the first available platform, returning it by value. + * + * Wraps clGetPlatformIDs(), returning the first result. + */ + static Platform get( + cl_int * errResult = NULL) + { + Platform platform; + cl_uint n = 0; + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + if (errResult != NULL) { + *errResult = err; + } + return Platform(); + } + + cl_platform_id* ids = (cl_platform_id*) alloca( + n * sizeof(cl_platform_id)); + err = ::clGetPlatformIDs(n, ids, NULL); + + if (err != CL_SUCCESS) { + detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + if (errResult != NULL) { + *errResult = err; + } + return Platform(); + } + + + return Platform(ids[0]); + } + + static Platform getDefault( + cl_int *errResult = NULL ) + { + return get(errResult); + } + + +#if defined(CL_VERSION_1_2) + //! \brief Wrapper for clUnloadCompiler(). + cl_int + unloadCompiler() + { + return ::clUnloadPlatformCompiler(object_); + } +#endif // #if defined(CL_VERSION_1_2) +}; // class Platform + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +/** + * Unload the OpenCL compiler. + * \note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead. + */ +inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int +UnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +inline cl_int +UnloadCompiler() +{ + return ::clUnloadCompiler(); +} +#endif // #if defined(CL_VERSION_1_1) + +/*! \brief Class interface for cl_context. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_context as the original. For details, see + * clRetainContext() and clReleaseContext(). + * + * \see cl_context + */ +class Context + : public detail::Wrapper +{ +private: + +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + static std::atomic default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static volatile int default_initialized_; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static Context default_; + static volatile cl_int default_error_; +public: + /*! \brief Constructs a context including a list of specified devices. + * + * Wraps clCreateContext(). + */ + Context( + const VECTOR_CLASS& devices, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + ::size_t, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + + ::size_t numDevices = devices.size(); + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + object_ = ::clCreateContext( + properties, (cl_uint) numDevices, + deviceIDs, + notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + if (err != NULL) { + *err = error; + } + } + + Context( + const Device& device, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + ::size_t, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + + cl_device_id deviceID = device(); + + object_ = ::clCreateContext( + properties, 1, + &deviceID, + notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a context including all or a subset of devices of a specified type. + * + * Wraps clCreateContextFromType(). + */ + Context( + cl_device_type type, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + ::size_t, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + +#if !defined(__APPLE__) && !defined(__MACOS) + cl_context_properties prop[4] = {CL_CONTEXT_PLATFORM, 0, 0, 0 }; + + if (properties == NULL) { + // Get a valid platform ID as we cannot send in a blank one + VECTOR_CLASS platforms; + error = Platform::get(&platforms); + if (error != CL_SUCCESS) { + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + return; + } + + // Check the platforms we found for a device of our specified type + cl_context_properties platform_id = 0; + for (unsigned int i = 0; i < platforms.size(); i++) { + + VECTOR_CLASS devices; + +#if defined(__CL_ENABLE_EXCEPTIONS) + try { +#endif + + error = platforms[i].getDevices(type, &devices); + +#if defined(__CL_ENABLE_EXCEPTIONS) + } catch (Error) {} + // Catch if exceptions are enabled as we don't want to exit if first platform has no devices of type + // We do error checking next anyway, and can throw there if needed +#endif + + // Only squash CL_SUCCESS and CL_DEVICE_NOT_FOUND + if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND) { + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + } + + if (devices.size() > 0) { + platform_id = (cl_context_properties)platforms[i](); + break; + } + } + + if (platform_id == 0) { + detail::errHandler(CL_DEVICE_NOT_FOUND, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = CL_DEVICE_NOT_FOUND; + } + return; + } + + prop[1] = platform_id; + properties = &prop[0]; + } +#endif + object_ = ::clCreateContextFromType( + properties, type, notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Context(const Context& ctx) : detail::Wrapper(ctx) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Context& operator = (const Context &ctx) + { + detail::Wrapper::operator=(ctx); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Context(Context&& ctx) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(ctx)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Context& operator = (Context &&ctx) + { + detail::Wrapper::operator=(std::move(ctx)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + /*! \brief Returns a singleton context including all devices of CL_DEVICE_TYPE_DEFAULT. + * + * \note All calls to this function return the same cl_context as the first. + */ + static Context getDefault(cl_int * err = NULL) + { + int state = detail::compare_exchange( + &default_initialized_, + __DEFAULT_BEING_INITIALIZED, __DEFAULT_NOT_INITIALIZED); + + if (state & __DEFAULT_INITIALIZED) { + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + if (state & __DEFAULT_BEING_INITIALIZED) { + // Assume writes will propagate eventually... + while(default_initialized_ != __DEFAULT_INITIALIZED) { + detail::fence(); + } + + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + cl_int error; + default_ = Context( + CL_DEVICE_TYPE_DEFAULT, + NULL, + NULL, + NULL, + &error); + + detail::fence(); + + default_error_ = error; + // Assume writes will propagate eventually... + default_initialized_ = __DEFAULT_INITIALIZED; + + detail::fence(); + + if (err != NULL) { + *err = default_error_; + } + return default_; + + } + + //! \brief Default constructor - initializes to NULL. + Context() : detail::Wrapper() { } + + /*! \brief Constructor from cl_context - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_context + * into the new Context object. + */ + __CL_EXPLICIT_CONSTRUCTORS Context(const cl_context& context) : detail::Wrapper(context) { } + + /*! \brief Assignment operator from cl_context - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseContext() on the value previously held by this instance. + */ + Context& operator = (const cl_context& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetContextInfo(). + template + cl_int getInfo(cl_context_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetContextInfo, object_, name, param), + __GET_CONTEXT_INFO_ERR); + } + + //! \brief Wrapper for clGetContextInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_context_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Gets a list of supported image formats. + * + * Wraps clGetSupportedImageFormats(). + */ + cl_int getSupportedImageFormats( + cl_mem_flags flags, + cl_mem_object_type type, + VECTOR_CLASS* formats) const + { + cl_uint numEntries; + + if (!formats) { + return CL_SUCCESS; + } + + cl_int err = ::clGetSupportedImageFormats( + object_, + flags, + type, + 0, + NULL, + &numEntries); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR); + } + + if (numEntries > 0) { + ImageFormat* value = (ImageFormat*) + alloca(numEntries * sizeof(ImageFormat)); + err = ::clGetSupportedImageFormats( + object_, + flags, + type, + numEntries, + (cl_image_format*)value, + NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR); + } + + formats->assign(&value[0], &value[numEntries]); + } + else { + formats->clear(); + } + return CL_SUCCESS; + } +}; + +inline Device Device::getDefault(cl_int * err) +{ + cl_int error; + Device device; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + device = context.getInfo()[0]; + if (err != NULL) { + *err = CL_SUCCESS; + } + } + + return device; +} + + +#ifdef _WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) std::atomic Context::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) volatile int Context::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) Context Context::default_; +__declspec(selectany) volatile cl_int Context::default_error_ = CL_SUCCESS; +#else // !_WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) std::atomic Context::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) volatile int Context::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) Context Context::default_; +__attribute__((weak)) volatile cl_int Context::default_error_ = CL_SUCCESS; +#endif // !_WIN32 + +/*! \brief Class interface for cl_event. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_event as the original. For details, see + * clRetainEvent() and clReleaseEvent(). + * + * \see cl_event + */ +class Event : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Event() : detail::Wrapper() { } + + /*! \brief Constructor from cl_event - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_event + * into the new Event object. + */ + __CL_EXPLICIT_CONSTRUCTORS Event(const cl_event& event) : detail::Wrapper(event) { } + + /*! \brief Assignment operator from cl_event - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseEvent() on the value previously held by this instance. + */ + Event& operator = (const cl_event& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetEventInfo(). + template + cl_int getInfo(cl_event_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetEventInfo, object_, name, param), + __GET_EVENT_INFO_ERR); + } + + //! \brief Wrapper for clGetEventInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_event_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + //! \brief Wrapper for clGetEventProfilingInfo(). + template + cl_int getProfilingInfo(cl_profiling_info name, T* param) const + { + return detail::errHandler(detail::getInfo( + &::clGetEventProfilingInfo, object_, name, param), + __GET_EVENT_PROFILE_INFO_ERR); + } + + //! \brief Wrapper for clGetEventProfilingInfo() that returns by value. + template typename + detail::param_traits::param_type + getProfilingInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_profiling_info, name>::param_type param; + cl_int result = getProfilingInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Blocks the calling thread until this event completes. + * + * Wraps clWaitForEvents(). + */ + cl_int wait() const + { + return detail::errHandler( + ::clWaitForEvents(1, &object_), + __WAIT_FOR_EVENTS_ERR); + } + +#if defined(CL_VERSION_1_1) + /*! \brief Registers a user callback function for a specific command execution status. + * + * Wraps clSetEventCallback(). + */ + cl_int setCallback( + cl_int type, + void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *), + void * user_data = NULL) + { + return detail::errHandler( + ::clSetEventCallback( + object_, + type, + pfn_notify, + user_data), + __SET_EVENT_CALLBACK_ERR); + } +#endif + + /*! \brief Blocks the calling thread until every event specified is complete. + * + * Wraps clWaitForEvents(). + */ + static cl_int + waitForEvents(const VECTOR_CLASS& events) + { + return detail::errHandler( + ::clWaitForEvents( + (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL), + __WAIT_FOR_EVENTS_ERR); + } +}; + +#if defined(CL_VERSION_1_1) +/*! \brief Class interface for user events (a subset of cl_event's). + * + * See Event for details about copy semantics, etc. + */ +class UserEvent : public Event +{ +public: + /*! \brief Constructs a user event on a given context. + * + * Wraps clCreateUserEvent(). + */ + UserEvent( + const Context& context, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateUserEvent( + context(), + &error); + + detail::errHandler(error, __CREATE_USER_EVENT_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + UserEvent() : Event() { } + + /*! \brief Sets the execution status of a user event object. + * + * Wraps clSetUserEventStatus(). + */ + cl_int setStatus(cl_int status) + { + return detail::errHandler( + ::clSetUserEventStatus(object_,status), + __SET_USER_EVENT_STATUS_ERR); + } +}; +#endif + +/*! \brief Blocks the calling thread until every event specified is complete. + * + * Wraps clWaitForEvents(). + */ +inline static cl_int +WaitForEvents(const VECTOR_CLASS& events) +{ + return detail::errHandler( + ::clWaitForEvents( + (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL), + __WAIT_FOR_EVENTS_ERR); +} + +/*! \brief Class interface for cl_mem. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_mem as the original. For details, see + * clRetainMemObject() and clReleaseMemObject(). + * + * \see cl_mem + */ +class Memory : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Memory() : detail::Wrapper() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_mem + * into the new Memory object. + */ + __CL_EXPLICIT_CONSTRUCTORS Memory(const cl_mem& memory) : detail::Wrapper(memory) { } + + /*! \brief Assignment operator from cl_mem - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseMemObject() on the value previously held by this instance. + */ + Memory& operator = (const cl_mem& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Memory(const Memory& mem) : detail::Wrapper(mem) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Memory& operator = (const Memory &mem) + { + detail::Wrapper::operator=(mem); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Memory(Memory&& mem) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(mem)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Memory& operator = (Memory &&mem) + { + detail::Wrapper::operator=(std::move(mem)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetMemObjectInfo(). + template + cl_int getInfo(cl_mem_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetMemObjectInfo, object_, name, param), + __GET_MEM_OBJECT_INFO_ERR); + } + + //! \brief Wrapper for clGetMemObjectInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_mem_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if defined(CL_VERSION_1_1) + /*! \brief Registers a callback function to be called when the memory object + * is no longer needed. + * + * Wraps clSetMemObjectDestructorCallback(). + * + * Repeated calls to this function, for a given cl_mem value, will append + * to the list of functions called (in reverse order) when memory object's + * resources are freed and the memory object is deleted. + * + * \note + * The registered callbacks are associated with the underlying cl_mem + * value - not the Memory class instance. + */ + cl_int setDestructorCallback( + void (CL_CALLBACK * pfn_notify)(cl_mem, void *), + void * user_data = NULL) + { + return detail::errHandler( + ::clSetMemObjectDestructorCallback( + object_, + pfn_notify, + user_data), + __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR); + } +#endif + +}; + +// Pre-declare copy functions +class Buffer; +template< typename IteratorType > +cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ); +template< typename IteratorType > +cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ); +template< typename IteratorType > +cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ); +template< typename IteratorType > +cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ); + + +/*! \brief Class interface for Buffer Memory Objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Buffer : public Memory +{ +public: + + /*! \brief Constructs a Buffer in a specified context. + * + * Wraps clCreateBuffer(). + * + * \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was + * specified. Note alignment & exclusivity requirements. + */ + Buffer( + const Context& context, + cl_mem_flags flags, + ::size_t size, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error); + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a Buffer in the default context. + * + * Wraps clCreateBuffer(). + * + * \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was + * specified. Note alignment & exclusivity requirements. + * + * \see Context::getDefault() + */ + Buffer( + cl_mem_flags flags, + ::size_t size, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(err); + + object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error); + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! + * \brief Construct a Buffer from a host container via iterators. + * IteratorType must be random access. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer( + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr = false, + cl_int* err = NULL) + { + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if( readOnly ) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if( useHostPtr ) { + flags |= CL_MEM_USE_HOST_PTR; + } + + ::size_t size = sizeof(DataType)*(endIterator - startIterator); + + Context context = Context::getDefault(err); + + if( useHostPtr ) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if( !useHostPtr ) { + error = cl::copy(startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + } + + /*! + * \brief Construct a Buffer from a host container via iterators using a specified context. + * IteratorType must be random access. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer(const Context &context, IteratorType startIterator, IteratorType endIterator, + bool readOnly, bool useHostPtr = false, cl_int* err = NULL); + + /*! + * \brief Construct a Buffer from a host container via iterators using a specified queue. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer(const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, + bool readOnly, bool useHostPtr = false, cl_int* err = NULL); + + //! \brief Default constructor - initializes to NULL. + Buffer() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Buffer(const cl_mem& buffer) : Memory(buffer) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Buffer& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Buffer(const Buffer& buf) : Memory(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Buffer& operator = (const Buffer &buf) + { + Memory::operator=(buf); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Buffer(Buffer&& buf) CL_HPP_NOEXCEPT : Memory(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Buffer& operator = (Buffer &&buf) + { + Memory::operator=(std::move(buf)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + +#if defined(CL_VERSION_1_1) + /*! \brief Creates a new buffer object from this. + * + * Wraps clCreateSubBuffer(). + */ + Buffer createSubBuffer( + cl_mem_flags flags, + cl_buffer_create_type buffer_create_type, + const void * buffer_create_info, + cl_int * err = NULL) + { + Buffer result; + cl_int error; + result.object_ = ::clCreateSubBuffer( + object_, + flags, + buffer_create_type, + buffer_create_info, + &error); + + detail::errHandler(error, __CREATE_SUBBUFFER_ERR); + if (err != NULL) { + *err = error; + } + + return result; + } +#endif +}; + +#if defined (USE_DX_INTEROP) +/*! \brief Class interface for creating OpenCL buffers from ID3D10Buffer's. + * + * This is provided to facilitate interoperability with Direct3D. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferD3D10 : public Buffer +{ +public: + typedef CL_API_ENTRY cl_mem (CL_API_CALL *PFN_clCreateFromD3D10BufferKHR)( + cl_context context, cl_mem_flags flags, ID3D10Buffer* buffer, + cl_int* errcode_ret); + + /*! \brief Constructs a BufferD3D10, in a specified context, from a + * given ID3D10Buffer. + * + * Wraps clCreateFromD3D10BufferKHR(). + */ + BufferD3D10( + const Context& context, + cl_mem_flags flags, + ID3D10Buffer* bufobj, + cl_int * err = NULL) + { + static PFN_clCreateFromD3D10BufferKHR pfn_clCreateFromD3D10BufferKHR = NULL; + +#if defined(CL_VERSION_1_2) + vector props = context.getInfo(); + cl_platform platform = -1; + for( int i = 0; i < props.size(); ++i ) { + if( props[i] == CL_CONTEXT_PLATFORM ) { + platform = props[i+1]; + } + } + __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clCreateFromD3D10BufferKHR); +#endif +#if defined(CL_VERSION_1_1) + __INIT_CL_EXT_FCN_PTR(clCreateFromD3D10BufferKHR); +#endif + + cl_int error; + object_ = pfn_clCreateFromD3D10BufferKHR( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferD3D10() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS BufferD3D10(const cl_mem& buffer) : Buffer(buffer) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferD3D10& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10(const BufferD3D10& buf) : Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10& operator = (const BufferD3D10 &buf) + { + Buffer::operator=(buf); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10(BufferD3D10&& buf) CL_HPP_NOEXCEPT : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10& operator = (BufferD3D10 &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif + +/*! \brief Class interface for GL Buffer Memory Objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferGL : public Buffer +{ +public: + /*! \brief Constructs a BufferGL in a specified context, from a given + * GL buffer. + * + * Wraps clCreateFromGLBuffer(). + */ + BufferGL( + const Context& context, + cl_mem_flags flags, + cl_GLuint bufobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLBuffer( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferGL() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS BufferGL(const cl_mem& buffer) : Buffer(buffer) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferGL& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferGL(const BufferGL& buf) : Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferGL& operator = (const BufferGL &buf) + { + Buffer::operator=(buf); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferGL(BufferGL&& buf) CL_HPP_NOEXCEPT : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferGL& operator = (BufferGL &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetGLObjectInfo(). + cl_int getObjectInfo( + cl_gl_object_type *type, + cl_GLuint * gl_object_name) + { + return detail::errHandler( + ::clGetGLObjectInfo(object_,type,gl_object_name), + __GET_GL_OBJECT_INFO_ERR); + } +}; + +/*! \brief C++ base class for Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image : public Memory +{ +protected: + //! \brief Default constructor - initializes to NULL. + Image() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image(const cl_mem& image) : Memory(image) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image(const Image& img) : Memory(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image& operator = (const Image &img) + { + Memory::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image(Image&& img) CL_HPP_NOEXCEPT : Memory(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image& operator = (Image &&img) + { + Memory::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + +public: + //! \brief Wrapper for clGetImageInfo(). + template + cl_int getImageInfo(cl_image_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetImageInfo, object_, name, param), + __GET_IMAGE_INFO_ERR); + } + + //! \brief Wrapper for clGetImageInfo() that returns by value. + template typename + detail::param_traits::param_type + getImageInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_image_info, name>::param_type param; + cl_int result = getImageInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; + +#if defined(CL_VERSION_1_2) +/*! \brief Class interface for 1D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image1D : public Image +{ +public: + /*! \brief Constructs a 1D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image1D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D, + width, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Image1D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image1D(const cl_mem& image1D) : Image(image1D) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image1D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1D(const Image1D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1D& operator = (const Image1D &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1D(Image1D&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1D& operator = (Image1D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + +/*! \class Image1DBuffer + * \brief Image interface for 1D buffer images. + */ +class Image1DBuffer : public Image +{ +public: + Image1DBuffer( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + const Buffer &buffer, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D_BUFFER, + width, + 0, 0, 0, 0, 0, 0, 0, + buffer() + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + NULL, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image1DBuffer() { } + + __CL_EXPLICIT_CONSTRUCTORS Image1DBuffer(const cl_mem& image1D) : Image(image1D) { } + + Image1DBuffer& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer(const Image1DBuffer& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer& operator = (const Image1DBuffer &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer(Image1DBuffer&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer& operator = (Image1DBuffer &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + +/*! \class Image1DArray + * \brief Image interface for arrays of 1D images. + */ +class Image1DArray : public Image +{ +public: + Image1DArray( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t arraySize, + ::size_t width, + ::size_t rowPitch, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D_ARRAY, + width, + 0, 0, // height, depth (unused) + arraySize, + rowPitch, + 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image1DArray() { } + + __CL_EXPLICIT_CONSTRUCTORS Image1DArray(const cl_mem& imageArray) : Image(imageArray) { } + + Image1DArray& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DArray(const Image1DArray& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DArray& operator = (const Image1DArray &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DArray(Image1DArray&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DArray& operator = (Image1DArray &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if defined(CL_VERSION_1_2) + + +/*! \brief Class interface for 2D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image2D : public Image +{ +public: + /*! \brief Constructs a 1D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image2D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + ::size_t height, + ::size_t row_pitch = 0, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + bool useCreateImage; + +#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + // Run-time decision based on the actual platform + { + cl_uint version = detail::getContextPlatformVersion(context()); + useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above + } +#elif defined(CL_VERSION_1_2) + useCreateImage = true; +#else + useCreateImage = false; +#endif + +#if defined(CL_VERSION_1_2) + if (useCreateImage) + { + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D, + width, + height, + 0, 0, // depth, array size (unused) + row_pitch, + 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if defined(CL_VERSION_1_2) +#if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + if (!useCreateImage) + { + object_ = ::clCreateImage2D( + context(), flags,&format, width, height, row_pitch, host_ptr, &error); + + detail::errHandler(error, __CREATE_IMAGE2D_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + } + + //! \brief Default constructor - initializes to NULL. + Image2D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image2D(const cl_mem& image2D) : Image(image2D) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image2D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2D(const Image2D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2D& operator = (const Image2D &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2D(Image2D&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2D& operator = (Image2D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + + +#if !defined(CL_VERSION_1_2) +/*! \brief Class interface for GL 2D Image Memory objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + * \note Deprecated for OpenCL 1.2. Please use ImageGL instead. + */ +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED : public Image2D +{ +public: + /*! \brief Constructs an Image2DGL in a specified context, from a given + * GL Texture. + * + * Wraps clCreateFromGLTexture2D(). + */ + Image2DGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture2D( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_2D_ERR); + if (err != NULL) { + *err = error; + } + + } + + //! \brief Default constructor - initializes to NULL. + Image2DGL() : Image2D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image2DGL(const cl_mem& image) : Image2D(image) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image2DGL& operator = (const cl_mem& rhs) + { + Image2D::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DGL(const Image2DGL& img) : Image2D(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DGL& operator = (const Image2DGL &img) + { + Image2D::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DGL(Image2DGL&& img) CL_HPP_NOEXCEPT : Image2D(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DGL& operator = (Image2DGL &&img) + { + Image2D::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if !defined(CL_VERSION_1_2) + +#if defined(CL_VERSION_1_2) +/*! \class Image2DArray + * \brief Image interface for arrays of 2D images. + */ +class Image2DArray : public Image +{ +public: + Image2DArray( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t arraySize, + ::size_t width, + ::size_t height, + ::size_t rowPitch, + ::size_t slicePitch, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D_ARRAY, + width, + height, + 0, // depth (unused) + arraySize, + rowPitch, + slicePitch, + 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image2DArray() { } + + __CL_EXPLICIT_CONSTRUCTORS Image2DArray(const cl_mem& imageArray) : Image(imageArray) { } + + Image2DArray& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DArray(const Image2DArray& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DArray& operator = (const Image2DArray &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DArray(Image2DArray&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DArray& operator = (Image2DArray &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if defined(CL_VERSION_1_2) + +/*! \brief Class interface for 3D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image3D : public Image +{ +public: + /*! \brief Constructs a 3D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image3D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + ::size_t height, + ::size_t depth, + ::size_t row_pitch = 0, + ::size_t slice_pitch = 0, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + bool useCreateImage; + +#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + // Run-time decision based on the actual platform + { + cl_uint version = detail::getContextPlatformVersion(context()); + useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above + } +#elif defined(CL_VERSION_1_2) + useCreateImage = true; +#else + useCreateImage = false; +#endif + +#if defined(CL_VERSION_1_2) + if (useCreateImage) + { + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE3D, + width, + height, + depth, + 0, // array size (unused) + row_pitch, + slice_pitch, + 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if defined(CL_VERSION_1_2) +#if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + if (!useCreateImage) + { + object_ = ::clCreateImage3D( + context(), flags, &format, width, height, depth, row_pitch, + slice_pitch, host_ptr, &error); + + detail::errHandler(error, __CREATE_IMAGE3D_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + } + + //! \brief Default constructor - initializes to NULL. + Image3D() : Image() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image3D(const cl_mem& image3D) : Image(image3D) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image3D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3D(const Image3D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3D& operator = (const Image3D &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3D(Image3D&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3D& operator = (Image3D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + +#if !defined(CL_VERSION_1_2) +/*! \brief Class interface for GL 3D Image Memory objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image3DGL : public Image3D +{ +public: + /*! \brief Constructs an Image3DGL in a specified context, from a given + * GL Texture. + * + * Wraps clCreateFromGLTexture3D(). + */ + Image3DGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture3D( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_3D_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Image3DGL() : Image3D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image3DGL(const cl_mem& image) : Image3D(image) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image3DGL& operator = (const cl_mem& rhs) + { + Image3D::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3DGL(const Image3DGL& img) : Image3D(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3DGL& operator = (const Image3DGL &img) + { + Image3D::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3DGL(Image3DGL&& img) CL_HPP_NOEXCEPT : Image3D(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3DGL& operator = (Image3DGL &&img) + { + Image3D::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if !defined(CL_VERSION_1_2) + +#if defined(CL_VERSION_1_2) +/*! \class ImageGL + * \brief general image interface for GL interop. + * We abstract the 2D and 3D GL images into a single instance here + * that wraps all GL sourced images on the grounds that setup information + * was performed by OpenCL anyway. + */ +class ImageGL : public Image +{ +public: + ImageGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_ERR); + if (err != NULL) { + *err = error; + } + } + + ImageGL() : Image() { } + + __CL_EXPLICIT_CONSTRUCTORS ImageGL(const cl_mem& image) : Image(image) { } + + ImageGL& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + ImageGL(const ImageGL& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + ImageGL& operator = (const ImageGL &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + ImageGL(ImageGL&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + ImageGL& operator = (ImageGL &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if defined(CL_VERSION_1_2) + +/*! \brief Class interface for GL Render Buffer Memory Objects. +* +* This is provided to facilitate interoperability with OpenGL. +* +* See Memory for details about copy semantics, etc. +* +* \see Memory +*/ +class BufferRenderGL : +#if defined(CL_VERSION_1_2) + public ImageGL +#else // #if defined(CL_VERSION_1_2) + public Image2DGL +#endif //#if defined(CL_VERSION_1_2) +{ +public: + /*! \brief Constructs a BufferRenderGL in a specified context, from a given + * GL Renderbuffer. + * + * Wraps clCreateFromGLRenderbuffer(). + */ + BufferRenderGL( + const Context& context, + cl_mem_flags flags, + cl_GLuint bufobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLRenderbuffer( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_RENDER_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. +#if defined(CL_VERSION_1_2) + BufferRenderGL() : ImageGL() {}; +#else // #if defined(CL_VERSION_1_2) + BufferRenderGL() : Image2DGL() {}; +#endif //#if defined(CL_VERSION_1_2) + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ +#if defined(CL_VERSION_1_2) + __CL_EXPLICIT_CONSTRUCTORS BufferRenderGL(const cl_mem& buffer) : ImageGL(buffer) { } +#else // #if defined(CL_VERSION_1_2) + __CL_EXPLICIT_CONSTRUCTORS BufferRenderGL(const cl_mem& buffer) : Image2DGL(buffer) { } +#endif //#if defined(CL_VERSION_1_2) + + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferRenderGL& operator = (const cl_mem& rhs) + { +#if defined(CL_VERSION_1_2) + ImageGL::operator=(rhs); +#else // #if defined(CL_VERSION_1_2) + Image2DGL::operator=(rhs); +#endif //#if defined(CL_VERSION_1_2) + + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ +#if defined(CL_VERSION_1_2) + BufferRenderGL(const BufferRenderGL& buf) : ImageGL(buf) {} +#else // #if defined(CL_VERSION_1_2) + BufferRenderGL(const BufferRenderGL& buf) : Image2DGL(buf) {} +#endif //#if defined(CL_VERSION_1_2) + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL& operator = (const BufferRenderGL &rhs) + { +#if defined(CL_VERSION_1_2) + ImageGL::operator=(rhs); +#else // #if defined(CL_VERSION_1_2) + Image2DGL::operator=(rhs); +#endif //#if defined(CL_VERSION_1_2) + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ +#if defined(CL_VERSION_1_2) + BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT : ImageGL(std::move(buf)) {} +#else // #if defined(CL_VERSION_1_2) + BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT : Image2DGL(std::move(buf)) {} +#endif //#if defined(CL_VERSION_1_2) + + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL& operator = (BufferRenderGL &&buf) + { +#if defined(CL_VERSION_1_2) + ImageGL::operator=(std::move(buf)); +#else // #if defined(CL_VERSION_1_2) + Image2DGL::operator=(std::move(buf)); +#endif //#if defined(CL_VERSION_1_2) + + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetGLObjectInfo(). + cl_int getObjectInfo( + cl_gl_object_type *type, + cl_GLuint * gl_object_name) + { + return detail::errHandler( + ::clGetGLObjectInfo(object_, type, gl_object_name), + __GET_GL_OBJECT_INFO_ERR); + } +}; + +/*! \brief Class interface for cl_sampler. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_sampler as the original. For details, see + * clRetainSampler() and clReleaseSampler(). + * + * \see cl_sampler + */ +class Sampler : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Sampler() { } + + /*! \brief Constructs a Sampler in a specified context. + * + * Wraps clCreateSampler(). + */ + Sampler( + const Context& context, + cl_bool normalized_coords, + cl_addressing_mode addressing_mode, + cl_filter_mode filter_mode, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateSampler( + context(), + normalized_coords, + addressing_mode, + filter_mode, + &error); + + detail::errHandler(error, __CREATE_SAMPLER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructor from cl_sampler - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_sampler + * into the new Sampler object. + */ + __CL_EXPLICIT_CONSTRUCTORS Sampler(const cl_sampler& sampler) : detail::Wrapper(sampler) { } + + /*! \brief Assignment operator from cl_sampler - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseSampler() on the value previously held by this instance. + */ + Sampler& operator = (const cl_sampler& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Sampler(const Sampler& sam) : detail::Wrapper(sam) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Sampler& operator = (const Sampler &sam) + { + detail::Wrapper::operator=(sam); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Sampler(Sampler&& sam) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(sam)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Sampler& operator = (Sampler &&sam) + { + detail::Wrapper::operator=(std::move(sam)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetSamplerInfo(). + template + cl_int getInfo(cl_sampler_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetSamplerInfo, object_, name, param), + __GET_SAMPLER_INFO_ERR); + } + + //! \brief Wrapper for clGetSamplerInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_sampler_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; + +class Program; +class CommandQueue; +class Kernel; + +//! \brief Class interface for specifying NDRange values. +class NDRange +{ +private: + size_t<3> sizes_; + cl_uint dimensions_; + +public: + //! \brief Default constructor - resulting range has zero dimensions. + NDRange() + : dimensions_(0) + { } + + //! \brief Constructs one-dimensional range. + NDRange(::size_t size0) + : dimensions_(1) + { + sizes_[0] = size0; + } + + //! \brief Constructs two-dimensional range. + NDRange(::size_t size0, ::size_t size1) + : dimensions_(2) + { + sizes_[0] = size0; + sizes_[1] = size1; + } + + //! \brief Constructs three-dimensional range. + NDRange(::size_t size0, ::size_t size1, ::size_t size2) + : dimensions_(3) + { + sizes_[0] = size0; + sizes_[1] = size1; + sizes_[2] = size2; + } + + /*! \brief Conversion operator to const ::size_t *. + * + * \returns a pointer to the size of the first dimension. + */ + operator const ::size_t*() const { + return (const ::size_t*) sizes_; + } + + //! \brief Queries the number of dimensions in the range. + ::size_t dimensions() const { return dimensions_; } +}; + +//! \brief A zero-dimensional range. +static const NDRange NullRange; + +//! \brief Local address wrapper for use with Kernel::setArg +struct LocalSpaceArg +{ + ::size_t size_; +}; + +namespace detail { + +template +struct KernelArgumentHandler +{ + static ::size_t size(const T&) { return sizeof(T); } + static const T* ptr(const T& value) { return &value; } +}; + +template <> +struct KernelArgumentHandler +{ + static ::size_t size(const LocalSpaceArg& value) { return value.size_; } + static const void* ptr(const LocalSpaceArg&) { return NULL; } +}; + +} +//! \endcond + +/*! __local + * \brief Helper function for generating LocalSpaceArg objects. + * Deprecated. Replaced with Local. + */ +inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED LocalSpaceArg +__local(::size_t size) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +inline LocalSpaceArg +__local(::size_t size) +{ + LocalSpaceArg ret = { size }; + return ret; +} + +/*! Local + * \brief Helper function for generating LocalSpaceArg objects. + */ +inline LocalSpaceArg +Local(::size_t size) +{ + LocalSpaceArg ret = { size }; + return ret; +} + +//class KernelFunctor; + +/*! \brief Class interface for cl_kernel. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_kernel as the original. For details, see + * clRetainKernel() and clReleaseKernel(). + * + * \see cl_kernel + */ +class Kernel : public detail::Wrapper +{ +public: + inline Kernel(const Program& program, const char* name, cl_int* err = NULL); + + //! \brief Default constructor - initializes to NULL. + Kernel() { } + + /*! \brief Constructor from cl_kernel - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_kernel + * into the new Kernel object. + */ + __CL_EXPLICIT_CONSTRUCTORS Kernel(const cl_kernel& kernel) : detail::Wrapper(kernel) { } + + /*! \brief Assignment operator from cl_kernel - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseKernel() on the value previously held by this instance. + */ + Kernel& operator = (const cl_kernel& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Kernel(const Kernel& kernel) : detail::Wrapper(kernel) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Kernel& operator = (const Kernel &kernel) + { + detail::Wrapper::operator=(kernel); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Kernel(Kernel&& kernel) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(kernel)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Kernel& operator = (Kernel &&kernel) + { + detail::Wrapper::operator=(std::move(kernel)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + template + cl_int getInfo(cl_kernel_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetKernelInfo, object_, name, param), + __GET_KERNEL_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if defined(CL_VERSION_1_2) + template + cl_int getArgInfo(cl_uint argIndex, cl_kernel_arg_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetKernelArgInfo, object_, argIndex, name, param), + __GET_KERNEL_ARG_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getArgInfo(cl_uint argIndex, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_arg_info, name>::param_type param; + cl_int result = getArgInfo(argIndex, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +#endif // #if defined(CL_VERSION_1_2) + + template + cl_int getWorkGroupInfo( + const Device& device, cl_kernel_work_group_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetKernelWorkGroupInfo, object_, device(), name, param), + __GET_KERNEL_WORK_GROUP_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getWorkGroupInfo(const Device& device, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_work_group_info, name>::param_type param; + cl_int result = getWorkGroupInfo(device, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + template + cl_int setArg(cl_uint index, const T &value) + { + return detail::errHandler( + ::clSetKernelArg( + object_, + index, + detail::KernelArgumentHandler::size(value), + detail::KernelArgumentHandler::ptr(value)), + __SET_KERNEL_ARGS_ERR); + } + + cl_int setArg(cl_uint index, ::size_t size, const void* argPtr) + { + return detail::errHandler( + ::clSetKernelArg(object_, index, size, argPtr), + __SET_KERNEL_ARGS_ERR); + } +}; + +/*! \class Program + * \brief Program interface that implements cl_program. + */ +class Program : public detail::Wrapper +{ +public: + typedef VECTOR_CLASS > Binaries; + typedef VECTOR_CLASS > Sources; + + Program( + const STRING_CLASS& source, + bool build = false, + cl_int* err = NULL) + { + cl_int error; + + const char * strings = source.c_str(); + const ::size_t length = source.size(); + + Context context = Context::getDefault(err); + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)1, &strings, &length, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + + if (error == CL_SUCCESS && build) { + + error = ::clBuildProgram( + object_, + 0, + NULL, + "", + NULL, + NULL); + + detail::errHandler(error, __BUILD_PROGRAM_ERR); + } + + if (err != NULL) { + *err = error; + } + } + + Program( + const Context& context, + const STRING_CLASS& source, + bool build = false, + cl_int* err = NULL) + { + cl_int error; + + const char * strings = source.c_str(); + const ::size_t length = source.size(); + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)1, &strings, &length, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + + if (error == CL_SUCCESS && build) { + + error = ::clBuildProgram( + object_, + 0, + NULL, + "", + NULL, + NULL); + + detail::errHandler(error, __BUILD_PROGRAM_ERR); + } + + if (err != NULL) { + *err = error; + } + } + + Program( + const Context& context, + const Sources& sources, + cl_int* err = NULL) + { + cl_int error; + + const ::size_t n = (::size_t)sources.size(); + ::size_t* lengths = (::size_t*) alloca(n * sizeof(::size_t)); + const char** strings = (const char**) alloca(n * sizeof(const char*)); + + for (::size_t i = 0; i < n; ++i) { + strings[i] = sources[(int)i].first; + lengths[i] = sources[(int)i].second; + } + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)n, strings, lengths, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + if (err != NULL) { + *err = error; + } + } + + /** + * Construct a program object from a list of devices and a per-device list of binaries. + * \param context A valid OpenCL context in which to construct the program. + * \param devices A vector of OpenCL device objects for which the program will be created. + * \param binaries A vector of pairs of a pointer to a binary object and its length. + * \param binaryStatus An optional vector that on completion will be resized to + * match the size of binaries and filled with values to specify if each binary + * was successfully loaded. + * Set to CL_SUCCESS if the binary was successfully loaded. + * Set to CL_INVALID_VALUE if the length is 0 or the binary pointer is NULL. + * Set to CL_INVALID_BINARY if the binary provided is not valid for the matching device. + * \param err if non-NULL will be set to CL_SUCCESS on successful operation or one of the following errors: + * CL_INVALID_CONTEXT if context is not a valid context. + * CL_INVALID_VALUE if the length of devices is zero; or if the length of binaries does not match the length of devices; + * or if any entry in binaries is NULL or has length 0. + * CL_INVALID_DEVICE if OpenCL devices listed in devices are not in the list of devices associated with context. + * CL_INVALID_BINARY if an invalid program binary was encountered for any device. binaryStatus will return specific status for each device. + * CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by the OpenCL implementation on the host. + */ + Program( + const Context& context, + const VECTOR_CLASS& devices, + const Binaries& binaries, + VECTOR_CLASS* binaryStatus = NULL, + cl_int* err = NULL) + { + cl_int error; + + const ::size_t numDevices = devices.size(); + + // Catch size mismatch early and return + if(binaries.size() != numDevices) { + error = CL_INVALID_VALUE; + detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR); + if (err != NULL) { + *err = error; + } + return; + } + + ::size_t* lengths = (::size_t*) alloca(numDevices * sizeof(::size_t)); + const unsigned char** images = (const unsigned char**) alloca(numDevices * sizeof(const unsigned char**)); + + for (::size_t i = 0; i < numDevices; ++i) { + images[i] = (const unsigned char*)binaries[i].first; + lengths[i] = binaries[(int)i].second; + } + + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + if(binaryStatus) { + binaryStatus->resize(numDevices); + } + + object_ = ::clCreateProgramWithBinary( + context(), (cl_uint) devices.size(), + deviceIDs, + lengths, images, (binaryStatus != NULL && numDevices > 0) + ? &binaryStatus->front() + : NULL, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR); + if (err != NULL) { + *err = error; + } + } + + +#if defined(CL_VERSION_1_2) + /** + * Create program using builtin kernels. + * \param kernelNames Semi-colon separated list of builtin kernel names + */ + Program( + const Context& context, + const VECTOR_CLASS& devices, + const STRING_CLASS& kernelNames, + cl_int* err = NULL) + { + cl_int error; + + + ::size_t numDevices = devices.size(); + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + object_ = ::clCreateProgramWithBuiltInKernels( + context(), + (cl_uint) devices.size(), + deviceIDs, + kernelNames.c_str(), + &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if defined(CL_VERSION_1_2) + + Program() { } + + __CL_EXPLICIT_CONSTRUCTORS Program(const cl_program& program) : detail::Wrapper(program) { } + + Program& operator = (const cl_program& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Program(const Program& program) : detail::Wrapper(program) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Program& operator = (const Program &program) + { + detail::Wrapper::operator=(program); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Program(Program&& program) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(program)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Program& operator = (Program &&program) + { + detail::Wrapper::operator=(std::move(program)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + cl_int build( + const VECTOR_CLASS& devices, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + ::size_t numDevices = devices.size(); + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + return detail::errHandler( + ::clBuildProgram( + object_, + (cl_uint) + devices.size(), + deviceIDs, + options, + notifyFptr, + data), + __BUILD_PROGRAM_ERR); + } + + cl_int build( + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + return detail::errHandler( + ::clBuildProgram( + object_, + 0, + NULL, + options, + notifyFptr, + data), + __BUILD_PROGRAM_ERR); + } + +#if defined(CL_VERSION_1_2) + cl_int compile( + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + return detail::errHandler( + ::clCompileProgram( + object_, + 0, + NULL, + options, + 0, + NULL, + NULL, + notifyFptr, + data), + __COMPILE_PROGRAM_ERR); + } +#endif + + template + cl_int getInfo(cl_program_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetProgramInfo, object_, name, param), + __GET_PROGRAM_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_program_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + template + cl_int getBuildInfo( + const Device& device, cl_program_build_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetProgramBuildInfo, object_, device(), name, param), + __GET_PROGRAM_BUILD_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getBuildInfo(const Device& device, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_program_build_info, name>::param_type param; + cl_int result = getBuildInfo(device, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + cl_int createKernels(VECTOR_CLASS* kernels) + { + cl_uint numKernels; + cl_int err = ::clCreateKernelsInProgram(object_, 0, NULL, &numKernels); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR); + } + + Kernel* value = (Kernel*) alloca(numKernels * sizeof(Kernel)); + err = ::clCreateKernelsInProgram( + object_, numKernels, (cl_kernel*) value, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR); + } + + kernels->assign(&value[0], &value[numKernels]); + return CL_SUCCESS; + } +}; + +#if defined(CL_VERSION_1_2) +inline Program linkProgram( + Program input1, + Program input2, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL, + cl_int* err = NULL) +{ + cl_int error_local = CL_SUCCESS; + + cl_program programs[2] = { input1(), input2() }; + + Context ctx = input1.getInfo(&error_local); + if(error_local!=CL_SUCCESS) { + detail::errHandler(error_local, __LINK_PROGRAM_ERR); + } + + cl_program prog = ::clLinkProgram( + ctx(), + 0, + NULL, + options, + 2, + programs, + notifyFptr, + data, + &error_local); + + detail::errHandler(error_local,__COMPILE_PROGRAM_ERR); + if (err != NULL) { + *err = error_local; + } + + return Program(prog); +} + +inline Program linkProgram( + VECTOR_CLASS inputPrograms, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL, + cl_int* err = NULL) +{ + cl_int error_local = CL_SUCCESS; + + cl_program * programs = (cl_program*) alloca(inputPrograms.size() * sizeof(cl_program)); + + if (programs != NULL) { + for (unsigned int i = 0; i < inputPrograms.size(); i++) { + programs[i] = inputPrograms[i](); + } + } + + Context ctx; + if(inputPrograms.size() > 0) { + ctx = inputPrograms[0].getInfo(&error_local); + if(error_local!=CL_SUCCESS) { + detail::errHandler(error_local, __LINK_PROGRAM_ERR); + } + } + cl_program prog = ::clLinkProgram( + ctx(), + 0, + NULL, + options, + (cl_uint)inputPrograms.size(), + programs, + notifyFptr, + data, + &error_local); + + detail::errHandler(error_local,__COMPILE_PROGRAM_ERR); + if (err != NULL) { + *err = error_local; + } + + return Program(prog); +} +#endif + +template<> +inline VECTOR_CLASS cl::Program::getInfo(cl_int* err) const +{ + VECTOR_CLASS< ::size_t> sizes = getInfo(); + VECTOR_CLASS binaries; + for (VECTOR_CLASS< ::size_t>::iterator s = sizes.begin(); s != sizes.end(); ++s) + { + char *ptr = NULL; + if (*s != 0) + ptr = new char[*s]; + binaries.push_back(ptr); + } + + cl_int result = getInfo(CL_PROGRAM_BINARIES, &binaries); + if (err != NULL) { + *err = result; + } + return binaries; +} + +inline Kernel::Kernel(const Program& program, const char* name, cl_int* err) +{ + cl_int error; + + object_ = ::clCreateKernel(program(), name, &error); + detail::errHandler(error, __CREATE_KERNEL_ERR); + + if (err != NULL) { + *err = error; + } + +} + +/*! \class CommandQueue + * \brief CommandQueue interface for cl_command_queue. + */ +class CommandQueue : public detail::Wrapper +{ +private: +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + static std::atomic default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static volatile int default_initialized_; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static CommandQueue default_; + static volatile cl_int default_error_; +public: + CommandQueue( + cl_command_queue_properties properties, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + Device device = context.getInfo()[0]; + + object_ = ::clCreateCommandQueue( + context(), device(), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } + } + } + /*! + * \brief Constructs a CommandQueue for an implementation defined device in the given context + */ + explicit CommandQueue( + const Context& context, + cl_command_queue_properties properties = 0, + cl_int* err = NULL) + { + cl_int error; + VECTOR_CLASS devices; + error = context.getInfo(CL_CONTEXT_DEVICES, &devices); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) + { + if (err != NULL) { + *err = error; + } + return; + } + + object_ = ::clCreateCommandQueue(context(), devices[0](), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + + if (err != NULL) { + *err = error; + } + + } + + CommandQueue( + const Context& context, + const Device& device, + cl_command_queue_properties properties = 0, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateCommandQueue( + context(), device(), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + CommandQueue(const CommandQueue& queue) : detail::Wrapper(queue) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + CommandQueue& operator = (const CommandQueue &queue) + { + detail::Wrapper::operator=(queue); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + CommandQueue(CommandQueue&& queue) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(queue)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + CommandQueue& operator = (CommandQueue &&queue) + { + detail::Wrapper::operator=(std::move(queue)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + static CommandQueue getDefault(cl_int * err = NULL) + { + int state = detail::compare_exchange( + &default_initialized_, + __DEFAULT_BEING_INITIALIZED, __DEFAULT_NOT_INITIALIZED); + + if (state & __DEFAULT_INITIALIZED) { + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + if (state & __DEFAULT_BEING_INITIALIZED) { + // Assume writes will propagate eventually... + while(default_initialized_ != __DEFAULT_INITIALIZED) { + detail::fence(); + } + + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + cl_int error; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + Device device = context.getInfo()[0]; + + default_ = CommandQueue(context, device, 0, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } + } + + detail::fence(); + + default_error_ = error; + // Assume writes will propagate eventually... + default_initialized_ = __DEFAULT_INITIALIZED; + + detail::fence(); + + if (err != NULL) { + *err = default_error_; + } + return default_; + + } + + CommandQueue() { } + + __CL_EXPLICIT_CONSTRUCTORS CommandQueue(const cl_command_queue& commandQueue) : detail::Wrapper(commandQueue) { } + + CommandQueue& operator = (const cl_command_queue& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + template + cl_int getInfo(cl_command_queue_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetCommandQueueInfo, object_, name, param), + __GET_COMMAND_QUEUE_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_command_queue_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + cl_int enqueueReadBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadBuffer( + object_, buffer(), blocking, offset, size, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + const void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteBuffer( + object_, buffer(), blocking, offset, size, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBuffer( + const Buffer& src, + const Buffer& dst, + ::size_t src_offset, + ::size_t dst_offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBuffer( + object_, src(), dst(), src_offset, dst_offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQEUE_COPY_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReadBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadBufferRect( + object_, + buffer(), + blocking, + (const ::size_t *)buffer_offset, + (const ::size_t *)host_offset, + (const ::size_t *)region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteBufferRect( + object_, + buffer(), + blocking, + (const ::size_t *)buffer_offset, + (const ::size_t *)host_offset, + (const ::size_t *)region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBufferRect( + const Buffer& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + ::size_t src_row_pitch, + ::size_t src_slice_pitch, + ::size_t dst_row_pitch, + ::size_t dst_slice_pitch, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBufferRect( + object_, + src(), + dst(), + (const ::size_t *)src_origin, + (const ::size_t *)dst_origin, + (const ::size_t *)region, + src_row_pitch, + src_slice_pitch, + dst_row_pitch, + dst_slice_pitch, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQEUE_COPY_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_VERSION_1_2) + /** + * Enqueue a command to fill a buffer object with a pattern + * of a given size. The pattern is specified a as vector. + * \tparam PatternType The datatype of the pattern field. + * The pattern type must be an accepted OpenCL data type. + */ + template + cl_int enqueueFillBuffer( + const Buffer& buffer, + PatternType pattern, + ::size_t offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillBuffer( + object_, + buffer(), + static_cast(&pattern), + sizeof(PatternType), + offset, + size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_VERSION_1_2) + + cl_int enqueueReadImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadImage( + object_, image(), blocking, (const ::size_t *) origin, + (const ::size_t *) region, row_pitch, slice_pitch, ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteImage( + object_, image(), blocking, (const ::size_t *) origin, + (const ::size_t *) region, row_pitch, slice_pitch, ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyImage( + const Image& src, + const Image& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyImage( + object_, src(), dst(), (const ::size_t *) src_origin, + (const ::size_t *)dst_origin, (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_VERSION_1_2) + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA floating-point color value if + * the image channel data type is not an unnormalized signed or + * unsigned data type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_float4 fillColor, + const size_t<3>& origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + (const ::size_t *) origin, + (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA signed integer color value if + * the image channel data type is an unnormalized signed integer + * type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_int4 fillColor, + const size_t<3>& origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + (const ::size_t *) origin, + (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA unsigned integer color value if + * the image channel data type is an unnormalized unsigned integer + * type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_uint4 fillColor, + const size_t<3>& origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + (const ::size_t *) origin, + (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_VERSION_1_2) + + cl_int enqueueCopyImageToBuffer( + const Image& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& region, + ::size_t dst_offset, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyImageToBuffer( + object_, src(), dst(), (const ::size_t *) src_origin, + (const ::size_t *) region, dst_offset, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBufferToImage( + const Buffer& src, + const Image& dst, + ::size_t src_offset, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBufferToImage( + object_, src(), dst(), src_offset, + (const ::size_t *) dst_origin, (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + void* enqueueMapBuffer( + const Buffer& buffer, + cl_bool blocking, + cl_map_flags flags, + ::size_t offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL, + cl_int* err = NULL) const + { + cl_event tmp; + cl_int error; + void * result = ::clEnqueueMapBuffer( + object_, buffer(), blocking, flags, offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + if (event != NULL && error == CL_SUCCESS) + *event = tmp; + + return result; + } + + void* enqueueMapImage( + const Image& buffer, + cl_bool blocking, + cl_map_flags flags, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t * row_pitch, + ::size_t * slice_pitch, + const VECTOR_CLASS* events = NULL, + Event* event = NULL, + cl_int* err = NULL) const + { + cl_event tmp; + cl_int error; + void * result = ::clEnqueueMapImage( + object_, buffer(), blocking, flags, + (const ::size_t *) origin, (const ::size_t *) region, + row_pitch, slice_pitch, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + if (event != NULL && error == CL_SUCCESS) + *event = tmp; + return result; + } + + cl_int enqueueUnmapMemObject( + const Memory& memory, + void* mapped_ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueUnmapMemObject( + object_, memory(), mapped_ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_VERSION_1_2) + /** + * Enqueues a marker command which waits for either a list of events to complete, + * or all previously enqueued commands to complete. + * + * Enqueues a marker command which waits for either a list of events to complete, + * or if the list is empty it waits for all commands previously enqueued in command_queue + * to complete before it completes. This command returns an event which can be waited on, + * i.e. this event can be waited on to insure that all events either in the event_wait_list + * or all previously enqueued commands, queued before this command to command_queue, + * have completed. + */ + cl_int enqueueMarkerWithWaitList( + const VECTOR_CLASS *events = 0, + Event *event = 0) + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueMarkerWithWaitList( + object_, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MARKER_WAIT_LIST_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * A synchronization point that enqueues a barrier operation. + * + * Enqueues a barrier command which waits for either a list of events to complete, + * or if the list is empty it waits for all commands previously enqueued in command_queue + * to complete before it completes. This command blocks command execution, that is, any + * following commands enqueued after it do not execute until it completes. This command + * returns an event which can be waited on, i.e. this event can be waited on to insure that + * all events either in the event_wait_list or all previously enqueued commands, queued + * before this command to command_queue, have completed. + */ + cl_int enqueueBarrierWithWaitList( + const VECTOR_CLASS *events = 0, + Event *event = 0) + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueBarrierWithWaitList( + object_, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_BARRIER_WAIT_LIST_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueues a command to indicate with which device a set of memory objects + * should be associated. + */ + cl_int enqueueMigrateMemObjects( + const VECTOR_CLASS &memObjects, + cl_mem_migration_flags flags, + const VECTOR_CLASS* events = NULL, + Event* event = NULL + ) + { + cl_event tmp; + + cl_mem* localMemObjects = static_cast(alloca(memObjects.size() * sizeof(cl_mem))); + for( int i = 0; i < (int)memObjects.size(); ++i ) { + localMemObjects[i] = memObjects[i](); + } + + + cl_int err = detail::errHandler( + ::clEnqueueMigrateMemObjects( + object_, + (cl_uint)memObjects.size(), + static_cast(localMemObjects), + flags, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_VERSION_1_2) + + cl_int enqueueNDRangeKernel( + const Kernel& kernel, + const NDRange& offset, + const NDRange& global, + const NDRange& local = NullRange, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueNDRangeKernel( + object_, kernel(), (cl_uint) global.dimensions(), + offset.dimensions() != 0 ? (const ::size_t*) offset : NULL, + (const ::size_t*) global, + local.dimensions() != 0 ? (const ::size_t*) local : NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_NDRANGE_KERNEL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueTask( + const Kernel& kernel, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueTask( + object_, kernel(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_TASK_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueNativeKernel( + void (CL_CALLBACK *userFptr)(void *), + std::pair args, + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* mem_locs = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_mem * mems = (mem_objects != NULL && mem_objects->size() > 0) + ? (cl_mem*) alloca(mem_objects->size() * sizeof(cl_mem)) + : NULL; + + if (mems != NULL) { + for (unsigned int i = 0; i < mem_objects->size(); i++) { + mems[i] = ((*mem_objects)[i])(); + } + } + + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueNativeKernel( + object_, userFptr, args.first, args.second, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + mems, + (mem_locs != NULL && mem_locs->size() > 0) ? (const void **) &mem_locs->front() : NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_NATIVE_KERNEL); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueMarker(Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueMarker( + object_, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MARKER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueWaitForEvents(const VECTOR_CLASS& events) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + return detail::errHandler( + ::clEnqueueWaitForEvents( + object_, + (cl_uint) events.size(), + events.size() > 0 ? (const cl_event*) &events.front() : NULL), + __ENQUEUE_WAIT_FOR_EVENTS_ERR); + } +#endif // #if defined(CL_VERSION_1_1) + + cl_int enqueueAcquireGLObjects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueAcquireGLObjects( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_ACQUIRE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReleaseGLObjects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReleaseGLObjects( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_RELEASE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined (USE_DX_INTEROP) +typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueAcquireD3D10ObjectsKHR)( + cl_command_queue command_queue, cl_uint num_objects, + const cl_mem* mem_objects, cl_uint num_events_in_wait_list, + const cl_event* event_wait_list, cl_event* event); +typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueReleaseD3D10ObjectsKHR)( + cl_command_queue command_queue, cl_uint num_objects, + const cl_mem* mem_objects, cl_uint num_events_in_wait_list, + const cl_event* event_wait_list, cl_event* event); + + cl_int enqueueAcquireD3D10Objects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + static PFN_clEnqueueAcquireD3D10ObjectsKHR pfn_clEnqueueAcquireD3D10ObjectsKHR = NULL; +#if defined(CL_VERSION_1_2) + cl_context context = getInfo(); + cl::Device device(getInfo()); + cl_platform_id platform = device.getInfo(); + __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clEnqueueAcquireD3D10ObjectsKHR); +#endif +#if defined(CL_VERSION_1_1) + __INIT_CL_EXT_FCN_PTR(clEnqueueAcquireD3D10ObjectsKHR); +#endif + + cl_event tmp; + cl_int err = detail::errHandler( + pfn_clEnqueueAcquireD3D10ObjectsKHR( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_ACQUIRE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReleaseD3D10Objects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + static PFN_clEnqueueReleaseD3D10ObjectsKHR pfn_clEnqueueReleaseD3D10ObjectsKHR = NULL; +#if defined(CL_VERSION_1_2) + cl_context context = getInfo(); + cl::Device device(getInfo()); + cl_platform_id platform = device.getInfo(); + __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clEnqueueReleaseD3D10ObjectsKHR); +#endif // #if defined(CL_VERSION_1_2) +#if defined(CL_VERSION_1_1) + __INIT_CL_EXT_FCN_PTR(clEnqueueReleaseD3D10ObjectsKHR); +#endif // #if defined(CL_VERSION_1_1) + + cl_event tmp; + cl_int err = detail::errHandler( + pfn_clEnqueueReleaseD3D10ObjectsKHR( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_RELEASE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueBarrier() const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + return detail::errHandler( + ::clEnqueueBarrier(object_), + __ENQUEUE_BARRIER_ERR); + } +#endif // #if defined(CL_VERSION_1_1) + + cl_int flush() const + { + return detail::errHandler(::clFlush(object_), __FLUSH_ERR); + } + + cl_int finish() const + { + return detail::errHandler(::clFinish(object_), __FINISH_ERR); + } +}; + +#ifdef _WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) std::atomic CommandQueue::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) volatile int CommandQueue::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) CommandQueue CommandQueue::default_; +__declspec(selectany) volatile cl_int CommandQueue::default_error_ = CL_SUCCESS; +#else // !_WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) std::atomic CommandQueue::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) volatile int CommandQueue::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) CommandQueue CommandQueue::default_; +__attribute__((weak)) volatile cl_int CommandQueue::default_error_ = CL_SUCCESS; +#endif // !_WIN32 + +template< typename IteratorType > +Buffer::Buffer( + const Context &context, + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr, + cl_int* err) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if( readOnly ) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if( useHostPtr ) { + flags |= CL_MEM_USE_HOST_PTR; + } + + ::size_t size = sizeof(DataType)*(endIterator - startIterator); + + if( useHostPtr ) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if( !useHostPtr ) { + CommandQueue queue(context, 0, &error); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + error = cl::copy(queue, startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } +} + +template< typename IteratorType > +Buffer::Buffer( + const CommandQueue &queue, + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr, + cl_int* err) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if (readOnly) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if (useHostPtr) { + flags |= CL_MEM_USE_HOST_PTR; + } + + ::size_t size = sizeof(DataType)*(endIterator - startIterator); + + Context context = queue.getInfo(); + + if (useHostPtr) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } + else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if (!useHostPtr) { + error = cl::copy(queue, startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } +} + +inline cl_int enqueueReadBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadBuffer(buffer, blocking, offset, size, ptr, events, event); +} + +inline cl_int enqueueWriteBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + const void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteBuffer(buffer, blocking, offset, size, ptr, events, event); +} + +inline void* enqueueMapBuffer( + const Buffer& buffer, + cl_bool blocking, + cl_map_flags flags, + ::size_t offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL, + cl_int* err = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + void * result = ::clEnqueueMapBuffer( + queue(), buffer(), blocking, flags, offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (cl_event*) event, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + return result; +} + +inline cl_int enqueueUnmapMemObject( + const Memory& memory, + void* mapped_ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (error != CL_SUCCESS) { + return error; + } + + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueUnmapMemObject( + queue(), memory(), mapped_ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; +} + +inline cl_int enqueueCopyBuffer( + const Buffer& src, + const Buffer& dst, + ::size_t src_offset, + ::size_t dst_offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBuffer(src, dst, src_offset, dst_offset, size, events, event); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Host to Device. + * Uses default command queue. + */ +template< typename IteratorType > +inline cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) + return error; + + return cl::copy(queue, startIterator, endIterator, buffer); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Device to Host. + * Uses default command queue. + */ +template< typename IteratorType > +inline cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) + return error; + + return cl::copy(queue, buffer, startIterator, endIterator); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Host to Device. + * Uses specified queue. + */ +template< typename IteratorType > +inline cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + ::size_t length = endIterator-startIterator; + ::size_t byteLength = length*sizeof(DataType); + + DataType *pointer = + static_cast(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_WRITE, 0, byteLength, 0, 0, &error)); + // if exceptions enabled, enqueueMapBuffer will throw + if( error != CL_SUCCESS ) { + return error; + } +#if defined(_MSC_VER) + std::copy( + startIterator, + endIterator, + stdext::checked_array_iterator( + pointer, length)); +#else + std::copy(startIterator, endIterator, pointer); +#endif + Event endEvent; + error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent); + // if exceptions enabled, enqueueUnmapMemObject will throw + if( error != CL_SUCCESS ) { + return error; + } + endEvent.wait(); + return CL_SUCCESS; +} + +/** + * Blocking copy operation between iterators and a buffer. + * Device to Host. + * Uses specified queue. + */ +template< typename IteratorType > +inline cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + ::size_t length = endIterator-startIterator; + ::size_t byteLength = length*sizeof(DataType); + + DataType *pointer = + static_cast(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_READ, 0, byteLength, 0, 0, &error)); + // if exceptions enabled, enqueueMapBuffer will throw + if( error != CL_SUCCESS ) { + return error; + } + std::copy(pointer, pointer + length, startIterator); + Event endEvent; + error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent); + // if exceptions enabled, enqueueUnmapMemObject will throw + if( error != CL_SUCCESS ) { + return error; + } + endEvent.wait(); + return CL_SUCCESS; +} + +#if defined(CL_VERSION_1_1) +inline cl_int enqueueReadBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadBufferRect( + buffer, + blocking, + buffer_offset, + host_offset, + region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueWriteBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteBufferRect( + buffer, + blocking, + buffer_offset, + host_offset, + region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueCopyBufferRect( + const Buffer& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + ::size_t src_row_pitch, + ::size_t src_slice_pitch, + ::size_t dst_row_pitch, + ::size_t dst_slice_pitch, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBufferRect( + src, + dst, + src_origin, + dst_origin, + region, + src_row_pitch, + src_slice_pitch, + dst_row_pitch, + dst_slice_pitch, + events, + event); +} +#endif + +inline cl_int enqueueReadImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadImage( + image, + blocking, + origin, + region, + row_pitch, + slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueWriteImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteImage( + image, + blocking, + origin, + region, + row_pitch, + slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueCopyImage( + const Image& src, + const Image& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyImage( + src, + dst, + src_origin, + dst_origin, + region, + events, + event); +} + +inline cl_int enqueueCopyImageToBuffer( + const Image& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& region, + ::size_t dst_offset, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyImageToBuffer( + src, + dst, + src_origin, + region, + dst_offset, + events, + event); +} + +inline cl_int enqueueCopyBufferToImage( + const Buffer& src, + const Image& dst, + ::size_t src_offset, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBufferToImage( + src, + dst, + src_offset, + dst_origin, + region, + events, + event); +} + + +inline cl_int flush(void) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.flush(); +} + +inline cl_int finish(void) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + + return queue.finish(); +} + +// Kernel Functor support +// New interface as of September 2011 +// Requires the C++11 std::tr1::function (note do not support TR1) +// Visual Studio 2010 and GCC 4.2 + +struct EnqueueArgs +{ + CommandQueue queue_; + const NDRange offset_; + const NDRange global_; + const NDRange local_; + VECTOR_CLASS events_; + + EnqueueArgs(NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange) + { + + } + + EnqueueArgs(NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local) + { + + } + + EnqueueArgs(NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local) + { + + } + + EnqueueArgs(Event e, NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange) + { + events_.push_back(e); + } + + EnqueueArgs(Event e, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(Event e, NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(const VECTOR_CLASS &events, NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange), + events_(events) + { + + } + + EnqueueArgs(const VECTOR_CLASS &events, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(const VECTOR_CLASS &events, NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local) + { + + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, const VECTOR_CLASS &events, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, const VECTOR_CLASS &events, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, const VECTOR_CLASS &events, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local), + events_(events) + { + + } +}; + +namespace detail { + +class NullType {}; + +template +struct SetArg +{ + static void set (Kernel kernel, T0 arg) + { + kernel.setArg(index, arg); + } +}; + +template +struct SetArg +{ + static void set (Kernel, NullType) + { + } +}; + +template < + typename T0, typename T1, typename T2, typename T3, + typename T4, typename T5, typename T6, typename T7, + typename T8, typename T9, typename T10, typename T11, + typename T12, typename T13, typename T14, typename T15, + typename T16, typename T17, typename T18, typename T19, + typename T20, typename T21, typename T22, typename T23, + typename T24, typename T25, typename T26, typename T27, + typename T28, typename T29, typename T30, typename T31 +> +class KernelFunctorGlobal +{ +private: + Kernel kernel_; + +public: + KernelFunctorGlobal( + Kernel kernel) : + kernel_(kernel) + {} + + KernelFunctorGlobal( + const Program& program, + const STRING_CLASS name, + cl_int * err = NULL) : + kernel_(program, name.c_str(), err) + {} + + Event operator() ( + const EnqueueArgs& args, + T0 t0, + T1 t1 = NullType(), + T2 t2 = NullType(), + T3 t3 = NullType(), + T4 t4 = NullType(), + T5 t5 = NullType(), + T6 t6 = NullType(), + T7 t7 = NullType(), + T8 t8 = NullType(), + T9 t9 = NullType(), + T10 t10 = NullType(), + T11 t11 = NullType(), + T12 t12 = NullType(), + T13 t13 = NullType(), + T14 t14 = NullType(), + T15 t15 = NullType(), + T16 t16 = NullType(), + T17 t17 = NullType(), + T18 t18 = NullType(), + T19 t19 = NullType(), + T20 t20 = NullType(), + T21 t21 = NullType(), + T22 t22 = NullType(), + T23 t23 = NullType(), + T24 t24 = NullType(), + T25 t25 = NullType(), + T26 t26 = NullType(), + T27 t27 = NullType(), + T28 t28 = NullType(), + T29 t29 = NullType(), + T30 t30 = NullType(), + T31 t31 = NullType() + ) + { + Event event; + SetArg<0, T0>::set(kernel_, t0); + SetArg<1, T1>::set(kernel_, t1); + SetArg<2, T2>::set(kernel_, t2); + SetArg<3, T3>::set(kernel_, t3); + SetArg<4, T4>::set(kernel_, t4); + SetArg<5, T5>::set(kernel_, t5); + SetArg<6, T6>::set(kernel_, t6); + SetArg<7, T7>::set(kernel_, t7); + SetArg<8, T8>::set(kernel_, t8); + SetArg<9, T9>::set(kernel_, t9); + SetArg<10, T10>::set(kernel_, t10); + SetArg<11, T11>::set(kernel_, t11); + SetArg<12, T12>::set(kernel_, t12); + SetArg<13, T13>::set(kernel_, t13); + SetArg<14, T14>::set(kernel_, t14); + SetArg<15, T15>::set(kernel_, t15); + SetArg<16, T16>::set(kernel_, t16); + SetArg<17, T17>::set(kernel_, t17); + SetArg<18, T18>::set(kernel_, t18); + SetArg<19, T19>::set(kernel_, t19); + SetArg<20, T20>::set(kernel_, t20); + SetArg<21, T21>::set(kernel_, t21); + SetArg<22, T22>::set(kernel_, t22); + SetArg<23, T23>::set(kernel_, t23); + SetArg<24, T24>::set(kernel_, t24); + SetArg<25, T25>::set(kernel_, t25); + SetArg<26, T26>::set(kernel_, t26); + SetArg<27, T27>::set(kernel_, t27); + SetArg<28, T28>::set(kernel_, t28); + SetArg<29, T29>::set(kernel_, t29); + SetArg<30, T30>::set(kernel_, t30); + SetArg<31, T31>::set(kernel_, t31); + + args.queue_.enqueueNDRangeKernel( + kernel_, + args.offset_, + args.global_, + args.local_, + &args.events_, + &event); + + return event; + } + +}; + +//------------------------------------------------------------------------------------------------------ + + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28, + typename T29, + typename T30, + typename T31> +struct functionImplementation_ +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + T31> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 32)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + T31); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28, + T29 arg29, + T30 arg30, + T31 arg31) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28, + arg29, + arg30, + arg31); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28, + typename T29, + typename T30> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 31)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28, + T29 arg29, + T30 arg30) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28, + arg29, + arg30); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28, + typename T29> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 30)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28, + T29 arg29) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28, + arg29); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 29)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 28)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 27)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 26)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 25)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 24)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 23)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 22)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 21)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 20)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 19)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 18)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 17)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 16)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 15)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 14)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 13)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 12)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 11)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 10)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 9)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 8)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 7)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 6)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 5)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 4)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3); + } + + +}; + +template< + typename T0, + typename T1, + typename T2> +struct functionImplementation_ +< T0, + T1, + T2, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 3)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2); + } + + +}; + +template< + typename T0, + typename T1> +struct functionImplementation_ +< T0, + T1, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 2)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1) + { + return functor_( + enqueueArgs, + arg0, + arg1); + } + + +}; + +template< + typename T0> +struct functionImplementation_ +< T0, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 1)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0) + { + return functor_( + enqueueArgs, + arg0); + } + + +}; + + + + + +} // namespace detail + +//---------------------------------------------------------------------------------------------- + +template < + typename T0, typename T1 = detail::NullType, typename T2 = detail::NullType, + typename T3 = detail::NullType, typename T4 = detail::NullType, + typename T5 = detail::NullType, typename T6 = detail::NullType, + typename T7 = detail::NullType, typename T8 = detail::NullType, + typename T9 = detail::NullType, typename T10 = detail::NullType, + typename T11 = detail::NullType, typename T12 = detail::NullType, + typename T13 = detail::NullType, typename T14 = detail::NullType, + typename T15 = detail::NullType, typename T16 = detail::NullType, + typename T17 = detail::NullType, typename T18 = detail::NullType, + typename T19 = detail::NullType, typename T20 = detail::NullType, + typename T21 = detail::NullType, typename T22 = detail::NullType, + typename T23 = detail::NullType, typename T24 = detail::NullType, + typename T25 = detail::NullType, typename T26 = detail::NullType, + typename T27 = detail::NullType, typename T28 = detail::NullType, + typename T29 = detail::NullType, typename T30 = detail::NullType, + typename T31 = detail::NullType +> +struct make_kernel : + public detail::functionImplementation_< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + > +{ +public: + typedef detail::KernelFunctorGlobal< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + > FunctorType; + + make_kernel( + const Program& program, + const STRING_CLASS name, + cl_int * err = NULL) : + detail::functionImplementation_< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + >( + FunctorType(program, name, err)) + {} + + make_kernel( + const Kernel kernel) : + detail::functionImplementation_< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + >( + FunctorType(kernel)) + {} +}; + + +//---------------------------------------------------------------------------------------------------------------------- + +#undef __ERR_STR +#if !defined(__CL_USER_OVERRIDE_ERROR_STRINGS) +#undef __GET_DEVICE_INFO_ERR +#undef __GET_PLATFORM_INFO_ERR +#undef __GET_DEVICE_IDS_ERR +#undef __GET_CONTEXT_INFO_ERR +#undef __GET_EVENT_INFO_ERR +#undef __GET_EVENT_PROFILE_INFO_ERR +#undef __GET_MEM_OBJECT_INFO_ERR +#undef __GET_IMAGE_INFO_ERR +#undef __GET_SAMPLER_INFO_ERR +#undef __GET_KERNEL_INFO_ERR +#undef __GET_KERNEL_ARG_INFO_ERR +#undef __GET_KERNEL_WORK_GROUP_INFO_ERR +#undef __GET_PROGRAM_INFO_ERR +#undef __GET_PROGRAM_BUILD_INFO_ERR +#undef __GET_COMMAND_QUEUE_INFO_ERR + +#undef __CREATE_CONTEXT_ERR +#undef __CREATE_CONTEXT_FROM_TYPE_ERR +#undef __GET_SUPPORTED_IMAGE_FORMATS_ERR + +#undef __CREATE_BUFFER_ERR +#undef __CREATE_SUBBUFFER_ERR +#undef __CREATE_IMAGE2D_ERR +#undef __CREATE_IMAGE3D_ERR +#undef __CREATE_SAMPLER_ERR +#undef __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR + +#undef __CREATE_USER_EVENT_ERR +#undef __SET_USER_EVENT_STATUS_ERR +#undef __SET_EVENT_CALLBACK_ERR +#undef __SET_PRINTF_CALLBACK_ERR + +#undef __WAIT_FOR_EVENTS_ERR + +#undef __CREATE_KERNEL_ERR +#undef __SET_KERNEL_ARGS_ERR +#undef __CREATE_PROGRAM_WITH_SOURCE_ERR +#undef __CREATE_PROGRAM_WITH_BINARY_ERR +#undef __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR +#undef __BUILD_PROGRAM_ERR +#undef __CREATE_KERNELS_IN_PROGRAM_ERR + +#undef __CREATE_COMMAND_QUEUE_ERR +#undef __SET_COMMAND_QUEUE_PROPERTY_ERR +#undef __ENQUEUE_READ_BUFFER_ERR +#undef __ENQUEUE_WRITE_BUFFER_ERR +#undef __ENQUEUE_READ_BUFFER_RECT_ERR +#undef __ENQUEUE_WRITE_BUFFER_RECT_ERR +#undef __ENQEUE_COPY_BUFFER_ERR +#undef __ENQEUE_COPY_BUFFER_RECT_ERR +#undef __ENQUEUE_READ_IMAGE_ERR +#undef __ENQUEUE_WRITE_IMAGE_ERR +#undef __ENQUEUE_COPY_IMAGE_ERR +#undef __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR +#undef __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR +#undef __ENQUEUE_MAP_BUFFER_ERR +#undef __ENQUEUE_MAP_IMAGE_ERR +#undef __ENQUEUE_UNMAP_MEM_OBJECT_ERR +#undef __ENQUEUE_NDRANGE_KERNEL_ERR +#undef __ENQUEUE_TASK_ERR +#undef __ENQUEUE_NATIVE_KERNEL + +#undef __CL_EXPLICIT_CONSTRUCTORS + +#undef __UNLOAD_COMPILER_ERR +#endif //__CL_USER_OVERRIDE_ERROR_STRINGS + +#undef __CL_FUNCTION_TYPE + +// Extensions +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_VERSION_1_1) +#undef __INIT_CL_EXT_FCN_PTR +#endif // #if defined(CL_VERSION_1_1) +#undef __CREATE_SUB_DEVICES + +#if defined(USE_CL_DEVICE_FISSION) +#undef __PARAM_NAME_DEVICE_FISSION +#endif // USE_CL_DEVICE_FISSION + +#undef __DEFAULT_NOT_INITIALIZED +#undef __DEFAULT_BEING_INITIALIZED +#undef __DEFAULT_INITIALIZED + +#undef CL_HPP_RVALUE_REFERENCES_SUPPORTED +#undef CL_HPP_NOEXCEPT + +} // namespace cl + +#endif // CL_HPP_ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_console.h b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_console.h new file mode 100644 index 0000000..c6b693f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_console.h @@ -0,0 +1,65 @@ +/** + * Copyright 2015 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#pragma once +#ifndef __KINECT2_CONSOLE_H__ +#define __KINECT2_CONSOLE_H__ + +#include +#include + +// Set this to '0' to disable the extended colored output +#define EXTENDED_OUTPUT 1 + +#if EXTENDED_OUTPUT + +#define NO_COLOR "\033[0m" +#define FG_BLACK "\033[30m" +#define FG_RED "\033[31m" +#define FG_GREEN "\033[32m" +#define FG_YELLOW "\033[33m" +#define FG_BLUE "\033[34m" +#define FG_MAGENTA "\033[35m" +#define FG_CYAN "\033[36m" + +const std::string getFunctionName(const std::string &name); +#define OUT_AUX(FUNC_COLOR, MSG_COLOR, STREAM, MSG) STREAM(FUNC_COLOR "[" << getFunctionName(__PRETTY_FUNCTION__) << "] " MSG_COLOR << MSG << NO_COLOR) + +#define OUT_DEBUG(msg) OUT_AUX(FG_BLUE, NO_COLOR, ROS_DEBUG_STREAM, msg) +#define OUT_INFO(msg) OUT_AUX(FG_GREEN, NO_COLOR, ROS_INFO_STREAM, msg) +#define OUT_WARN(msg) OUT_AUX(FG_YELLOW, FG_YELLOW, ROS_WARN_STREAM, msg) +#define OUT_ERROR(msg) OUT_AUX(FG_RED, FG_RED, ROS_ERROR_STREAM, msg) + +#else + +#define NO_COLOR "" +#define FG_BLACK "" +#define FG_RED "" +#define FG_GREEN "" +#define FG_YELLOW "" +#define FG_BLUE "" +#define FG_MAGENTA "" +#define FG_CYAN "" + +#define OUT_DEBUG(msg) ROS_DEBUG_STREAM(msg) +#define OUT_INFO(msg) ROS_INFO_STREAM(msg) +#define OUT_WARN(msg) ROS_WARN_STREAM(msg) +#define OUT_ERROR(msg) ROS_WARN_STREAM(msg) + +#endif + +#endif //__KINECT2_CONSOLE_H__ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_registration.h b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_registration.h new file mode 100644 index 0000000..db657a3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/include/kinect2_registration/kinect2_registration.h @@ -0,0 +1,57 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#pragma once +#ifndef __KINECT2_REGISTRATION_H__ +#define __KINECT2_REGISTRATION_H__ + +#include + +#include + +class DepthRegistration +{ +public: + enum Method + { + DEFAULT = 0, + CPU, + OPENCL + }; + +protected: + cv::Mat cameraMatrixRegistered, cameraMatrixDepth, rotation, translation, mapX, mapY; + cv::Size sizeRegistered, sizeDepth; + float zNear, zFar; + + DepthRegistration(); + + virtual bool init(const int deviceId) = 0; + +public: + virtual ~DepthRegistration(); + + bool init(const cv::Mat &cameraMatrixRegistered, const cv::Size &sizeRegistered, const cv::Mat &cameraMatrixDepth, const cv::Size &sizeDepth, + const cv::Mat &distortionDepth, const cv::Mat &rotation, const cv::Mat &translation, + const float zNear = 0.5f, const float zFar = 12.0f, const int deviceId = -1); + + virtual bool registerDepth(const cv::Mat &depth, cv::Mat ®istered) = 0; + + static DepthRegistration *New(Method method = DEFAULT); +}; + +#endif //__KINECT2_REGISTRATION_H__ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/package.xml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/package.xml new file mode 100644 index 0000000..ca61c79 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/package.xml @@ -0,0 +1,21 @@ + + + kinect2_registration + 0.0.1 + The kinect2_registration package + + Thiemo Wiedemeyer + + Apache 2.0 + + catkin + + roscpp + cv_bridge + + roscpp + cv_bridge + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration.cl b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration.cl new file mode 100644 index 0000000..4011b9a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration.cl @@ -0,0 +1,196 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +// Set render buffer to zero +void kernel setZero(global ushort* rendered, global float *selDist){ + const uint i = get_global_id(0); + rendered[i] = 0; + selDist[i] = 10; +} + +// Calculate 3d point, project them to color camera coordinate system and create rendered depth image +void kernel project(global const ushort *depth, global int4 *idx, global ushort *zImg, global float4 *dists, global float *selDist, global ushort *rendered){ + const uint i = get_global_id(0); + + const int xR = i % widthR; + const int yR = i / widthR; + + const ushort d = depth[i]; + + // Projection matrix coloumns + const float4 projX = (float4)(r00, r01, r02, tx); + const float4 projY = (float4)(r10, r11, r12, ty); + const float4 projZ = (float4)(r20, r21, r22, tz); + + // Compute 3D point + const float z = d / 1000.0f; + const float4 point = (float4)((xR - cxR) * fxRInv * z, (yR - cyR) * fyRInv * z, z, 1.0f); + + // Rotate and translate + const float3 projected = (float3)(dot(point, projX), dot(point, projY), dot(point, projZ)); + + const float invZ = 1.0f / projected.z; + + // Compute projected image coordinates + const float x = (fxR * projected.x) * invZ + cxR; + const float y = (fyR * projected.y) * invZ + cyR; + const short xL = (short)floor(x); + const short yL = (short)floor(y); + const short xH = xL + 1; + const short yH = yL + 1; + + const float4 distXY = (float4)((x - xL) * (x - xL), (xH - x) * (xH - x), (y - yL) * (y - yL), (yH - y) * (yH - y)); + const float4 dist2 = (float4)(distXY.s0 + distXY.s2, distXY.s1 + distXY.s2, distXY.s0 + distXY.s3, distXY.s1 + distXY.s3); + + const int yLI = yL * widthR; + const int yHI = yH * widthR; + int4 indices = (int4)(yLI + xL, yLI + xH, yHI + xL, yHI + xH); + + const ushort zI = (ushort)(projected.z * 1000.0f); + + // Check if depth is valid and projection is inside the image + if(xL < 0 || xL >= widthR) + { + indices.s0 = indices.s2 = -1; + } + if(yL < 0 || yL >= heightR) + { + indices.s0 = indices.s1 = -1; + } + if(xH < 0 || xH >= widthR) + { + indices.s1 = indices.s3 = -1; + } + if(yH < 0 || yH >= heightR) + { + indices.s2 = indices.s3 = -1; + } + if(indices.s0 >= 0) + { + selDist[indices.s0] = dist2.s0; + rendered[indices.s0] = zI; + } + if(indices.s1 >= 0) + { + selDist[indices.s1] = dist2.s1; + rendered[indices.s1] = zI; + } + if(indices.s2 >= 0) + { + selDist[indices.s2] = dist2.s2; + rendered[indices.s2] = zI; + } + if(indices.s3 >= 0) + { + selDist[indices.s3] = dist2.s3; + rendered[indices.s3] = zI; + } + + idx[i] = indices; + dists[i] = dist2; + zImg[i] = zI; +} + +// checks and updates registered depth image to make sure nearest depth values are used +void kernel checkDepth(global const int4 *idx, global const ushort *zImg, global const float4 *dists, global float *selDist, global ushort *rendered){ + const uint i = get_global_id(0); + + const int4 index = idx[i]; + const ushort zI = zImg[i]; + const ushort thres = 0.01 * zI; + const ushort zIThres = zI + thres; + const float4 dist2 = dists[i]; + + ushort zRen; + zRen = rendered[index.s0]; + if(index.s0 >= 0 && ((abs_diff(zRen, zI) < thres && selDist[index.s0] > dist2.s0) || zRen > zIThres)) + { + selDist[index.s0] = dist2.s0; + rendered[index.s0] = zI; + } + zRen = rendered[index.s1]; + if(index.s1 >= 0 && ((abs_diff(zRen, zI) < thres && selDist[index.s1] > dist2.s1) || zRen > zIThres)) + { + selDist[index.s1] = dist2.s1; + rendered[index.s1] = zI; + } + zRen = rendered[index.s2]; + if(index.s2 >= 0 && ((abs_diff(zRen, zI) < thres && selDist[index.s2] > dist2.s2) || zRen > zIThres)) + { + selDist[index.s2] = dist2.s2; + rendered[index.s2] = zI; + } + zRen = rendered[index.s3]; + if(index.s3 >= 0 && ((abs_diff(zRen, zI) < thres && selDist[index.s3] > dist2.s3) || zRen > zIThres)) + { + selDist[index.s3] = dist2.s3; + rendered[index.s3] = zI; + } +} + +// remap depth image +void kernel remapDepth(global const ushort *in, global ushort *out, global const float *mapX, global const float *mapY) +{ + const uint i = get_global_id(0); + + const float x = mapX[i]; + const float y = mapY[i]; + const int xL = (int)floor(x); + const int xH = xL + 1; + const int yL = (int)floor(y); + const int yH = yL + 1; + + if(xL < 0 || yL < 0 || xH >= widthD || yH >= heightD) + { + out[i] = 0; + return; + } + + const uint iLT = yL * widthD + xL; + const uint iRT = iLT + 1; + const uint iLB = iLT + widthD; + const uint iRB = iLB + 1; + + const float4 p = (float4)(in[iLT], in[iRT], in[iLB], in[iRB]); + int4 valid = isgreaterequal(p, (float4)(1)); + int count = abs(valid.s0 + valid.s1 + valid.s2 + valid.s3); + + if(count < 3) + { + out[i] = 0; + return; + } + + const float avg = (p.s0 + p.s1 + p.s2 + p.s3) / count; + const float thres = 0.01 * avg; + valid = isless(fabs(p - avg), (float4)(thres)); + count = abs(valid.s0 + valid.s1 + valid.s2 + valid.s3); + + if(count < 3) + { + out[i] = 0; + return; + } + + const float4 distXY = (float4)((x - xL) * (x - xL), (xH - x) * (xH - x), (y - yL) * (y - yL), (yH - y) * (yH - y)); + const float4 tmp = (float4)(sqrt(2.0)); + const float4 dist2 = (float4)(distXY.s0 + distXY.s2, distXY.s1 + distXY.s2, distXY.s0 + distXY.s3, distXY.s1 + distXY.s3); + const float4 dist = select((float4)(0), tmp - sqrt(dist2), valid); + const float sum = dist.s0 + dist.s1 + dist.s2 + dist.s3; + + out[i] = (dot(p, dist) / sum) + 0.5; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.cpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.cpp new file mode 100644 index 0000000..a1f71d5 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.cpp @@ -0,0 +1,203 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#include "depth_registration_cpu.h" + +DepthRegistrationCPU::DepthRegistrationCPU() + : DepthRegistration() +{ +} + +DepthRegistrationCPU::~DepthRegistrationCPU() +{ +} + +bool DepthRegistrationCPU::init(const int deviceId) +{ + createLookup(); + + proj(0, 0) = rotation.at(0, 0); + proj(0, 1) = rotation.at(0, 1); + proj(0, 2) = rotation.at(0, 2); + proj(0, 3) = translation.at(0, 0); + proj(1, 0) = rotation.at(1, 0); + proj(1, 1) = rotation.at(1, 1); + proj(1, 2) = rotation.at(1, 2); + proj(1, 3) = translation.at(1, 0); + proj(2, 0) = rotation.at(2, 0); + proj(2, 1) = rotation.at(2, 1); + proj(2, 2) = rotation.at(2, 2); + proj(2, 3) = translation.at(2, 0); + proj(3, 0) = 0; + proj(3, 1) = 0; + proj(3, 2) = 0; + proj(3, 3) = 1; + + fx = cameraMatrixRegistered.at(0, 0); + fy = cameraMatrixRegistered.at(1, 1); + cx = cameraMatrixRegistered.at(0, 2) + 0.5; + cy = cameraMatrixRegistered.at(1, 2) + 0.5; + + return true; +} + +inline uint16_t DepthRegistrationCPU::interpolate(const cv::Mat &in, const float &x, const float &y) const +{ + const int xL = (int)floor(x); + const int xH = (int)ceil(x); + const int yL = (int)floor(y); + const int yH = (int)ceil(y); + + if(xL < 0 || yL < 0 || xH >= in.cols || yH >= in.rows) + { + return 0; + } + + const uint16_t pLT = in.at(yL, xL); + const uint16_t pRT = in.at(yL, xH); + const uint16_t pLB = in.at(yH, xL); + const uint16_t pRB = in.at(yH, xH); + int vLT = pLT > 0; + int vRT = pRT > 0; + int vLB = pLB > 0; + int vRB = pRB > 0; + int count = vLT + vRT + vLB + vRB; + + if(count < 3) + { + return 0; + } + + const uint16_t avg = (pLT + pRT + pLB + pRB) / count; + const uint16_t thres = 0.01 * avg; + vLT = abs(pLT - avg) < thres; + vRT = abs(pRT - avg) < thres; + vLB = abs(pLB - avg) < thres; + vRB = abs(pRB - avg) < thres; + count = vLT + vRT + vLB + vRB; + + if(count < 3) + { + return 0; + } + + double distXL = x - xL; + double distXH = 1.0 - distXL; + double distYL = y - yL; + double distYH = 1.0 - distYL; + distXL *= distXL; + distXH *= distXH; + distYL *= distYL; + distYH *= distYH; + const double tmp = sqrt(2.0); + const double fLT = vLT ? tmp - sqrt(distXL + distYL) : 0; + const double fRT = vRT ? tmp - sqrt(distXH + distYL) : 0; + const double fLB = vLB ? tmp - sqrt(distXL + distYH) : 0; + const double fRB = vRB ? tmp - sqrt(distXH + distYH) : 0; + const double sum = fLT + fRT + fLB + fRB; + + return ((pLT * fLT + pRT * fRT + pLB * fLB + pRB * fRB) / sum) + 0.5; +} + +void DepthRegistrationCPU::remapDepth(const cv::Mat &depth, cv::Mat &scaled) const +{ + scaled.create(sizeRegistered, CV_16U); + #pragma omp parallel for + for(size_t r = 0; r < (size_t)sizeRegistered.height; ++r) + { + uint16_t *itO = scaled.ptr(r); + const float *itX = mapX.ptr(r); + const float *itY = mapY.ptr(r); + for(size_t c = 0; c < (size_t)sizeRegistered.width; ++c, ++itO, ++itX, ++itY) + { + *itO = interpolate(depth, *itX, *itY); + } + } +} + +void DepthRegistrationCPU::projectDepth(const cv::Mat &scaled, cv::Mat ®istered) const +{ + registered = cv::Mat::zeros(sizeRegistered, CV_16U); + + #pragma omp parallel for + for(size_t r = 0; r < (size_t)sizeRegistered.height; ++r) + { + const uint16_t *itD = scaled.ptr(r); + const double y = lookupY.at(0, r); + const double *itX = lookupX.ptr(); + + for(size_t c = 0; c < (size_t)sizeRegistered.width; ++c, ++itD, ++itX) + { + const double depthValue = *itD / 1000.0; + + if(depthValue < zNear || depthValue > zFar) + { + continue; + } + + Eigen::Vector4d pointD(*itX * depthValue, y * depthValue, depthValue, 1); + Eigen::Vector4d pointP = proj * pointD; + + const double z = pointP[2]; + + const double invZ = 1 / z; + const int xP = (fx * pointP[0]) * invZ + cx; + const int yP = (fy * pointP[1]) * invZ + cy; + + if(xP >= 0 && xP < sizeRegistered.width && yP >= 0 && yP < sizeRegistered.height) + { + const uint16_t z16 = z * 1000; + uint16_t &zReg = registered.at(yP, xP); + if(zReg == 0 || z16 < zReg) + { + zReg = z16; + } + } + } + } +} + +bool DepthRegistrationCPU::registerDepth(const cv::Mat &depth, cv::Mat ®istered) +{ + cv::Mat scaled; + remapDepth(depth, scaled); + projectDepth(scaled, registered); + return true; +} + +void DepthRegistrationCPU::createLookup() +{ + const double fx = 1.0 / cameraMatrixRegistered.at(0, 0); + const double fy = 1.0 / cameraMatrixRegistered.at(1, 1); + const double cx = cameraMatrixRegistered.at(0, 2); + const double cy = cameraMatrixRegistered.at(1, 2); + double *it; + + lookupY = cv::Mat(1, sizeRegistered.height, CV_64F); + it = lookupY.ptr(); + for(size_t r = 0; r < (size_t)sizeRegistered.height; ++r, ++it) + { + *it = (r - cy) * fy; + } + + lookupX = cv::Mat(1, sizeRegistered.width, CV_64F); + it = lookupX.ptr(); + for(size_t c = 0; c < (size_t)sizeRegistered.width; ++c, ++it) + { + *it = (c - cx) * fx; + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.h b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.h new file mode 100644 index 0000000..e5f413f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_cpu.h @@ -0,0 +1,51 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#pragma once +#ifndef __DEPTH_REGISTRATION_CPU_H__ +#define __DEPTH_REGISTRATION_CPU_H__ + +#include + +#include + +class DepthRegistrationCPU : public DepthRegistration +{ +private: + cv::Mat lookupX, lookupY; + Eigen::Matrix4d proj; + double fx, fy, cx, cy; + +public: + DepthRegistrationCPU(); + + ~DepthRegistrationCPU(); + + bool init(const int deviceId); + + bool registerDepth(const cv::Mat &depth, cv::Mat ®istered); + +private: + void createLookup(); + + uint16_t interpolate(const cv::Mat &in, const float &x, const float &y) const; + + void remapDepth(const cv::Mat &depth, cv::Mat &scaled) const; + void projectDepth(const cv::Mat &scaled, cv::Mat ®istered) const; +}; + +#endif //__DEPTH_REGISTRATION_CPU_H__ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.cpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.cpp new file mode 100644 index 0000000..bacf247 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.cpp @@ -0,0 +1,389 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#include + +#include + +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#define CL_USE_DEPRECATED_OPENCL_2_0_APIS + +#ifdef KINECT2_OPENCL_ICD_LOADER_IS_OLD +#define CL_USE_DEPRECATED_OPENCL_1_1_APIS +#include +#ifdef CL_VERSION_1_2 +#undef CL_VERSION_1_2 +#endif //CL_VERSION_1_2 +#endif //LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD + +#include + +#ifndef REG_OPENCL_FILE +#define REG_OPENCL_FILE "" +#endif + +#include "depth_registration_opencl.h" + +//#define ENABLE_PROFILING_CL + +#define CL_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#define PRINT_CL_ERROR(expr, err) OUT_ERROR(FG_BLUE "[" << CL_FILENAME << "]" FG_CYAN "(" << __LINE__ << ") " FG_YELLOW << expr << FG_RED " failed: " << err) + +#define CHECK_CL_PARAM(expr) do { cl_int err = CL_SUCCESS; (expr); if (err != CL_SUCCESS) { PRINT_CL_ERROR(#expr, err); return false; } } while(0) +#define CHECK_CL_RETURN(expr) do { cl_int err = (expr); if (err != CL_SUCCESS) { PRINT_CL_ERROR(#expr, err); return false; } } while(0) +#define CHECK_CL_ON_FAIL(expr, on_fail) do { cl_int err = (expr); if (err != CL_SUCCESS) { PRINT_CL_ERROR(#expr, err); on_fail; return false; } } while(0) + +struct DepthRegistrationOpenCL::OCLData +{ + cl::Context context; + cl::Device device; + + cl::Program program; + cl::CommandQueue queue; + + cl::Kernel kernelSetZero; + cl::Kernel kernelProject; + cl::Kernel kernelCheckDepth; + cl::Kernel kernelRemap; + + size_t sizeDepth; + size_t sizeRegistered; + size_t sizeIndex; + size_t sizeImgZ; + size_t sizeDists; + size_t sizeSelDist; + size_t sizeMap; + + cl::Buffer bufferDepth; + cl::Buffer bufferScaled; + cl::Buffer bufferRegistered; + cl::Buffer bufferIndex; + cl::Buffer bufferImgZ; + cl::Buffer bufferDists; + cl::Buffer bufferSelDist; + cl::Buffer bufferMapX; + cl::Buffer bufferMapY; + + cl::Buffer bufferOutput; + unsigned char *dataOutput; + +#ifdef ENABLE_PROFILING_CL + std::vector timings; + int count; +#endif +}; + +DepthRegistrationOpenCL::DepthRegistrationOpenCL() + : DepthRegistration() +{ + data = new OCLData; +} + +DepthRegistrationOpenCL::~DepthRegistrationOpenCL() +{ + delete data; +} + +void getDevices(const std::vector &platforms, std::vector &devices) +{ + devices.clear(); + for(size_t i = 0; i < platforms.size(); ++i) + { + const cl::Platform &platform = platforms[i]; + + std::vector devs; + if(platform.getDevices(CL_DEVICE_TYPE_ALL, &devs) != CL_SUCCESS) + { + continue; + } + + devices.insert(devices.end(), devs.begin(), devs.end()); + } +} + +std::string deviceString(cl::Device &dev) +{ + std::string devName, devVendor, devType; + cl_device_type devTypeID; + dev.getInfo(CL_DEVICE_NAME, &devName); + dev.getInfo(CL_DEVICE_VENDOR, &devVendor); + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + switch(devTypeID) + { + case CL_DEVICE_TYPE_CPU: + devType = "CPU"; + break; + case CL_DEVICE_TYPE_GPU: + devType = "GPU"; + break; + case CL_DEVICE_TYPE_ACCELERATOR: + devType = "ACCELERATOR"; + break; + default: + devType = "CUSTOM/UNKNOWN"; + } + + return devName + " (" + devType + ")[" + devVendor + ']'; +} + +bool selectDevice(std::vector &devices, cl::Device &device, const int deviceId = -1) +{ + if(deviceId != -1 && devices.size() > (size_t)deviceId) + { + device = devices[deviceId]; + return true; + } + + bool selected = false; + cl_device_type selectedType = 0; + + for(size_t i = 0; i < devices.size(); ++i) + { + cl::Device &dev = devices[i]; + cl_device_type devTypeID; + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + if(!selected || (selectedType != CL_DEVICE_TYPE_GPU && devTypeID == CL_DEVICE_TYPE_GPU)) + { + selectedType = devTypeID; + selected = true; + device = dev; + } + } + return selected; +} + +bool DepthRegistrationOpenCL::init(const int deviceId) +{ + std::string sourceCode; + if(!readProgram(sourceCode)) + { + return false; + } + + std::vector platforms; + CHECK_CL_RETURN(cl::Platform::get(&platforms)); + + if(platforms.empty()) + { + OUT_ERROR("no opencl platforms found."); + return false; + } + + std::vector devices; + getDevices(platforms, devices); + + OUT_INFO("devices:"); + for(size_t i = 0; i < devices.size(); ++i) + { + OUT_INFO(" " << i << ": " FG_CYAN << deviceString(devices[i]) << NO_COLOR); + } + + if(!selectDevice(devices, data->device, deviceId)) + { + OUT_ERROR("could not find any suitable device"); + return false; + } + OUT_INFO("selected device: " FG_YELLOW << deviceString(data->device) << NO_COLOR); + + CHECK_CL_PARAM(data->context = cl::Context(data->device, NULL, NULL, NULL, &err)); + + std::string options; + generateOptions(options); + + cl::Program::Sources source(1, std::make_pair(sourceCode.c_str(), sourceCode.length())); + CHECK_CL_PARAM(data->program = cl::Program(data->context, source, &err)); + + CHECK_CL_ON_FAIL(data->program.build(options.c_str()), + OUT_ERROR("failed to build program: " << err); + OUT_ERROR("Build Status: " << data->program.getBuildInfo(data->device)); + OUT_ERROR("Build Options:\t" << data->program.getBuildInfo(data->device)); + OUT_ERROR("Build Log:\t " << data->program.getBuildInfo(data->device))); + +#ifdef ENABLE_PROFILING_CL + data->count = 0; + CHECK_CL_PARAM(data->queue = cl::CommandQueue(data->context, data->device, CL_QUEUE_PROFILING_ENABLE, &err)); +#else + CHECK_CL_PARAM(data->queue = cl::CommandQueue(data->context, data->device, 0, &err)); +#endif + + data->sizeDepth = sizeDepth.height * sizeDepth.width * sizeof(uint16_t); + data->sizeRegistered = sizeRegistered.height * sizeRegistered.width * sizeof(uint16_t); + data->sizeIndex = sizeRegistered.height * sizeRegistered.width * sizeof(cl_int4); + data->sizeImgZ = sizeRegistered.height * sizeRegistered.width * sizeof(uint16_t); + data->sizeDists = sizeRegistered.height * sizeRegistered.width * sizeof(cl_float4); + data->sizeSelDist = sizeRegistered.height * sizeRegistered.width * sizeof(float); + data->sizeMap = sizeRegistered.height * sizeRegistered.width * sizeof(float); + + CHECK_CL_PARAM(data->bufferDepth = cl::Buffer(data->context, CL_MEM_READ_ONLY, data->sizeDepth, NULL, &err)); + CHECK_CL_PARAM(data->bufferScaled = cl::Buffer(data->context, CL_MEM_READ_WRITE, data->sizeRegistered, NULL, &err)); + CHECK_CL_PARAM(data->bufferRegistered = cl::Buffer(data->context, CL_MEM_READ_WRITE, data->sizeRegistered, NULL, &err)); + CHECK_CL_PARAM(data->bufferIndex = cl::Buffer(data->context, CL_MEM_READ_WRITE, data->sizeIndex, NULL, &err)); + CHECK_CL_PARAM(data->bufferImgZ = cl::Buffer(data->context, CL_MEM_READ_WRITE, data->sizeImgZ, NULL, &err)); + CHECK_CL_PARAM(data->bufferDists = cl::Buffer(data->context, CL_MEM_READ_WRITE, data->sizeDists, NULL, &err)); + CHECK_CL_PARAM(data->bufferSelDist = cl::Buffer(data->context, CL_MEM_READ_WRITE, data->sizeSelDist, NULL, &err)); + CHECK_CL_PARAM(data->bufferMapX = cl::Buffer(data->context, CL_MEM_READ_ONLY, data->sizeMap, NULL, &err)); + CHECK_CL_PARAM(data->bufferMapY = cl::Buffer(data->context, CL_MEM_READ_ONLY, data->sizeMap, NULL, &err)); + CHECK_CL_PARAM(data->bufferOutput = cl::Buffer(data->context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, data->sizeRegistered, NULL, &err)); + + CHECK_CL_PARAM(data->kernelSetZero = cl::Kernel(data->program, "setZero", &err)); + CHECK_CL_RETURN(data->kernelSetZero.setArg(0, data->bufferRegistered)); + CHECK_CL_RETURN(data->kernelSetZero.setArg(1, data->bufferSelDist)); + + CHECK_CL_PARAM(data->kernelProject = cl::Kernel(data->program, "project", &err)); + CHECK_CL_RETURN(data->kernelProject.setArg(0, data->bufferScaled)); + CHECK_CL_RETURN(data->kernelProject.setArg(1, data->bufferIndex)); + CHECK_CL_RETURN(data->kernelProject.setArg(2, data->bufferImgZ)); + CHECK_CL_RETURN(data->kernelProject.setArg(3, data->bufferDists)); + CHECK_CL_RETURN(data->kernelProject.setArg(4, data->bufferSelDist)); + CHECK_CL_RETURN(data->kernelProject.setArg(5, data->bufferRegistered)); + + CHECK_CL_PARAM(data->kernelCheckDepth = cl::Kernel(data->program, "checkDepth", &err)); + CHECK_CL_RETURN(data->kernelCheckDepth.setArg(0, data->bufferIndex)); + CHECK_CL_RETURN(data->kernelCheckDepth.setArg(1, data->bufferImgZ)); + CHECK_CL_RETURN(data->kernelCheckDepth.setArg(2, data->bufferDists)); + CHECK_CL_RETURN(data->kernelCheckDepth.setArg(3, data->bufferSelDist)); + CHECK_CL_RETURN(data->kernelCheckDepth.setArg(4, data->bufferRegistered)); + + CHECK_CL_PARAM(data->kernelRemap = cl::Kernel(data->program, "remapDepth", &err)); + CHECK_CL_RETURN(data->kernelRemap.setArg(0, data->bufferDepth)); + CHECK_CL_RETURN(data->kernelRemap.setArg(1, data->bufferScaled)); + CHECK_CL_RETURN(data->kernelRemap.setArg(2, data->bufferMapX)); + CHECK_CL_RETURN(data->kernelRemap.setArg(3, data->bufferMapY)); + + CHECK_CL_RETURN(data->queue.enqueueWriteBuffer(data->bufferMapX, CL_TRUE, 0, data->sizeMap, mapX.data)); + CHECK_CL_RETURN(data->queue.enqueueWriteBuffer(data->bufferMapY, CL_TRUE, 0, data->sizeMap, mapY.data)); + + CHECK_CL_PARAM(data->dataOutput = (unsigned char *)data->queue.enqueueMapBuffer(data->bufferOutput, CL_TRUE, CL_MAP_READ, 0, data->sizeRegistered, NULL, NULL, &err)); + return true; +} + +bool DepthRegistrationOpenCL::registerDepth(const cv::Mat &depth, cv::Mat ®istered) +{ + cl::Event eventRead; + std::vector eventZero(2), eventRemap(1), eventProject(1), eventCheckDepth1(1), eventCheckDepth2(1); + cl::NDRange range(sizeRegistered.height * sizeRegistered.width); + + CHECK_CL_RETURN(data->queue.enqueueWriteBuffer(data->bufferDepth, CL_FALSE, 0, data->sizeDepth, depth.data, NULL, &eventZero[0])); + CHECK_CL_RETURN(data->queue.enqueueNDRangeKernel(data->kernelSetZero, cl::NullRange, range, cl::NullRange, NULL, &eventZero[1])); + + CHECK_CL_RETURN(data->queue.enqueueNDRangeKernel(data->kernelRemap, cl::NullRange, range, cl::NullRange, &eventZero, &eventRemap[0])); + + CHECK_CL_RETURN(data->queue.enqueueNDRangeKernel(data->kernelProject, cl::NullRange, range, cl::NullRange, &eventRemap, &eventProject[0])); + + CHECK_CL_RETURN(data->queue.enqueueNDRangeKernel(data->kernelCheckDepth, cl::NullRange, range, cl::NullRange, &eventProject, &eventCheckDepth1[0])); + + CHECK_CL_RETURN(data->queue.enqueueNDRangeKernel(data->kernelCheckDepth, cl::NullRange, range, cl::NullRange, &eventCheckDepth1, &eventCheckDepth2[0])); + + CHECK_CL_RETURN(data->queue.enqueueReadBuffer(data->bufferRegistered, CL_FALSE, 0, data->sizeRegistered, data->dataOutput, &eventCheckDepth2, &eventRead)); + + CHECK_CL_RETURN(eventRead.wait()); + + registered = cv::Mat(sizeRegistered, CV_16U, data->dataOutput); + +#ifdef ENABLE_PROFILING_CL + if(data->count == 0) + { + data->timings.clear(); + data->timings.resize(7, 0.0); + } + + data->timings[0] += eventZero[0].getProfilingInfo() - eventZero[0].getProfilingInfo(); + data->timings[1] += eventZero[1].getProfilingInfo() - eventZero[1].getProfilingInfo(); + data->timings[2] += eventRemap[0].getProfilingInfo() - eventRemap[0].getProfilingInfo(); + data->timings[3] += eventProject[0].getProfilingInfo() - eventProject[0].getProfilingInfo(); + data->timings[4] += eventCheckDepth1[0].getProfilingInfo() - eventCheckDepth1[0].getProfilingInfo(); + data->timings[5] += eventCheckDepth2[0].getProfilingInfo() - eventCheckDepth2[0].getProfilingInfo(); + data->timings[6] += eventRead.getProfilingInfo() - eventRead.getProfilingInfo(); + + if(++data->count == 100) + { + double sum = data->timings[0] + data->timings[1] + data->timings[2] + data->timings[3] + data->timings[4] + data->timings[5] + data->timings[6]; + OUT_INFO("writing depth: " << data->timings[0] / 100000000.0 << " ms."); + OUT_INFO("setting zero: " << data->timings[1] / 100000000.0 << " ms."); + OUT_INFO("remap: " << data->timings[2] / 100000000.0 << " ms."); + OUT_INFO("project: " << data->timings[3] / 100000000.0 << " ms."); + OUT_INFO("check depth 1: " << data->timings[4] / 100000000.0 << " ms."); + OUT_INFO("check depth 2: " << data->timings[5] / 100000000.0 << " ms."); + OUT_INFO("read registered: " << data->timings[6] / 100000000.0 << " ms."); + OUT_INFO("overall: " << sum / 100000000.0 << " ms."); + data->count = 0; + } +#endif + return true; +} + +void DepthRegistrationOpenCL::generateOptions(std::string &options) const +{ + std::ostringstream oss; + oss.precision(16); + oss << std::scientific; + + // Rotation + oss << " -D r00=" << rotation.at(0, 0) << "f"; + oss << " -D r01=" << rotation.at(0, 1) << "f"; + oss << " -D r02=" << rotation.at(0, 2) << "f"; + oss << " -D r10=" << rotation.at(1, 0) << "f"; + oss << " -D r11=" << rotation.at(1, 1) << "f"; + oss << " -D r12=" << rotation.at(1, 2) << "f"; + oss << " -D r20=" << rotation.at(2, 0) << "f"; + oss << " -D r21=" << rotation.at(2, 1) << "f"; + oss << " -D r22=" << rotation.at(2, 2) << "f"; + + // Translation + oss << " -D tx=" << translation.at(0, 0) << "f"; + oss << " -D ty=" << translation.at(1, 0) << "f"; + oss << " -D tz=" << translation.at(2, 0) << "f"; + + // Camera parameter upscaled depth + oss << " -D fxR=" << cameraMatrixRegistered.at(0, 0) << "f"; + oss << " -D fyR=" << cameraMatrixRegistered.at(1, 1) << "f"; + oss << " -D cxR=" << cameraMatrixRegistered.at(0, 2) << "f"; + oss << " -D cyR=" << cameraMatrixRegistered.at(1, 2) << "f"; + oss << " -D fxRInv=" << (1.0 / cameraMatrixRegistered.at(0, 0)) << "f"; + oss << " -D fyRInv=" << (1.0 / cameraMatrixRegistered.at(1, 1)) << "f"; + + // Clipping distances + oss << " -D zNear=" << (uint16_t)(zNear * 1000); + oss << " -D zFar=" << (uint16_t)(zFar * 1000); + + // Size registered image + oss << " -D heightR=" << sizeRegistered.height; + oss << " -D widthR=" << sizeRegistered.width; + + // Size depth image + oss << " -D heightD=" << sizeDepth.height; + oss << " -D widthD=" << sizeDepth.width; + + options = oss.str(); +} + +bool DepthRegistrationOpenCL::readProgram(std::string &source) const +{ + std::ifstream file(REG_OPENCL_FILE); + + if(!file.is_open()) + { + return false; + } + + source = std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + file.close(); + + return true; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.h b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.h new file mode 100644 index 0000000..0d96345 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/depth_registration_opencl.h @@ -0,0 +1,46 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#pragma once +#ifndef __DEPTH_REGISTRATION_OPENCL_H__ +#define __DEPTH_REGISTRATION_OPENCL_H__ + +#include + +class DepthRegistrationOpenCL : public DepthRegistration +{ +private: + struct OCLData; + + OCLData *data; + +public: + DepthRegistrationOpenCL(); + + ~DepthRegistrationOpenCL(); + + bool init(const int deviceId); + + bool registerDepth(const cv::Mat &depth, cv::Mat ®istered); + +private: + void generateOptions(std::string &options) const; + + bool readProgram(std::string &source) const; +}; + +#endif //__DEPTH_REGISTRATION_OPENCL_H__ diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/kinect2_registration.cpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/kinect2_registration.cpp new file mode 100644 index 0000000..6b7fb00 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_registration/src/kinect2_registration.cpp @@ -0,0 +1,101 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#include +#include + +#ifdef DEPTH_REG_CPU +#include "depth_registration_cpu.h" +#endif + +#ifdef DEPTH_REG_OPENCL +#include "depth_registration_opencl.h" +#endif + +DepthRegistration::DepthRegistration() +{ +} + +DepthRegistration::~DepthRegistration() +{ +} + +bool DepthRegistration::init(const cv::Mat &cameraMatrixRegistered, const cv::Size &sizeRegistered, const cv::Mat &cameraMatrixDepth, const cv::Size &sizeDepth, + const cv::Mat &distortionDepth, const cv::Mat &rotation, const cv::Mat &translation, + const float zNear, const float zFar, const int deviceId) +{ + this->cameraMatrixRegistered = cameraMatrixRegistered; + this->cameraMatrixDepth = cameraMatrixDepth; + this->rotation = rotation; + this->translation = translation; + this->sizeRegistered = sizeRegistered; + this->sizeDepth = sizeDepth; + this->zNear = zNear; + this->zFar = zFar; + + cv::initUndistortRectifyMap(cameraMatrixDepth, distortionDepth, cv::Mat(), cameraMatrixRegistered, sizeRegistered, CV_32FC1, mapX, mapY); + + return init(deviceId); +} + +DepthRegistration *DepthRegistration::New(Method method) +{ + if(method == DEFAULT) + { +#ifdef DEPTH_REG_OPENCL + method = OPENCL; +#elif defined DEPTH_REG_CPU + method = CPU; +#endif + } + + switch(method) + { + case DEFAULT: + OUT_ERROR("No default registration method available!"); + break; + case CPU: +#ifdef DEPTH_REG_CPU + OUT_INFO("Using CPU registration method!"); + return new DepthRegistrationCPU(); +#else + OUT_ERROR("CPU registration method not available!"); + break; +#endif + case OPENCL: +#ifdef DEPTH_REG_OPENCL + OUT_INFO("Using OpenCL registration method!"); + return new DepthRegistrationOpenCL(); +#else + OUT_ERROR("OpenCL registration method not available!"); + break; +#endif + } + return NULL; +} + + +const std::string getFunctionName(const std::string &name) +{ + size_t end = name.rfind('('); + if(end == std::string::npos) + { + end = name.size(); + } + size_t begin = 1 + name.rfind(' ', end); + return name.substr(begin, end - begin); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/CMakeLists.txt new file mode 100644 index 0000000..c68fd59 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/CMakeLists.txt @@ -0,0 +1,126 @@ +cmake_minimum_required(VERSION 2.8.3) +project(kinect2_viewer CXX) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBT_USE_DOUBLE_PRECISION -Wall") +# Unused warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuninitialized -Winit-self -Wunused-function -Wunused-label -Wunused-variable -Wunused-but-set-variable -Wunused-but-set-parameter") +# Additional warnings +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Warray-bounds -Wtype-limits -Wreturn-type -Wsequence-point -Wparentheses -Wmissing-braces -Wchar-subscripts -Wswitch -Wwrite-strings -Wenum-compare -Wempty-body -Wlogical-op") + +# Check for c++11 support +INCLUDE(CheckCXXCompilerFlag) +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) +CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +IF(COMPILER_SUPPORTS_CXX11) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +ELSEIF(COMPILER_SUPPORTS_CXX0X) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +ELSE() + MESSAGE(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +ENDIF() + +find_package(catkin REQUIRED COMPONENTS roscpp rostime std_msgs sensor_msgs message_filters cv_bridge image_transport compressed_image_transport compressed_depth_image_transport kinect2_bridge) + +## System dependencies are found with CMake's conventions +find_package(OpenCV REQUIRED) +find_package(OpenMP) +find_package(PCL REQUIRED) + +if(OPENMP_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +endif() + +################################################ +## Declare ROS messages, services and actions ## +################################################ + +################################### +## catkin specific configuration ## +################################### +## The catkin_package macro generates cmake config files for your package +## Declare things to be passed to dependent projects +## INCLUDE_DIRS: uncomment this if you package contains header files +## LIBRARIES: libraries you create in this project that dependent projects also need +## CATKIN_DEPENDS: catkin_packages dependent projects also need +## DEPENDS: system dependencies of this project that dependent projects also need +catkin_package( +# INCLUDE_DIRS include +# LIBRARIES kinect2_viewer +# CATKIN_DEPENDS other_catkin_pkg +# DEPENDS system_lib +) + +########### +## Build ## +########### + +# Display additional files in qtcreator +execute_process(COMMAND find ${PROJECT_SOURCE_DIR} -type f OUTPUT_VARIABLE FILES_STRING) +string(REPLACE "\n" ";" FILES_LIST ${FILES_STRING}) +add_custom_target(additional_files_${PROJECT_NAME} + SOURCES + ${FILES_LIST} +) + +include_directories(include + ${catkin_INCLUDE_DIRS} + ${OpenCV_INCLUDE_DIRS} + ${PCL_INCLUDE_DIRS} + ${kinect2_bridge_INCLUDE_DIRS} +) + +add_executable(kinect2_viewer src/viewer.cpp) +target_link_libraries(kinect2_viewer + ${catkin_LIBRARIES} + ${OpenCV_LIBRARIES} + ${PCL_LIBRARIES} + ${kinect2_bridge_LIBRARIES} +) + +############# +## Install ## +############# + +# all install targets should use catkin DESTINATION variables +# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +# install(PROGRAMS +# scripts/my_python_script +# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +# ) + +## Mark executables and/or libraries for installation +install(TARGETS kinect2_viewer +# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} +# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + +## Mark cpp header files for installation +# install(DIRECTORY include/${PROJECT_NAME}/ +# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} +# FILES_MATCHING PATTERN "*.h" +# PATTERN ".svn" EXCLUDE +# ) + +## Mark other files for installation (e.g. launch and bag files, etc.) +# install(FILES +# # myfile1 +# # myfile2 +# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} +# ) + +############# +## Testing ## +############# + +## Add gtest based cpp test target and link libraries +# catkin_add_gtest(${PROJECT_NAME}-test test/test_kinect2_bridge.cpp) +# if(TARGET ${PROJECT_NAME}-test) +# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) +# endif() + +## Add folders to be run by python nosetests +# catkin_add_nosetests(test) diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/README.md b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/README.md new file mode 100644 index 0000000..195866e --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/README.md @@ -0,0 +1,44 @@ +# Kinect2 Viewer + +## Maintainer + +- [Thiemo Wiedemeyer](https://ai.uni-bremen.de/team/thiemo_wiedemeyer) <>, [Institute for Artificial Intelligence](http://ai.uni-bremen.de/), University of Bremen + +*Note:* ***Please use the GitHub issues*** *for questions and problems regarding the iai_kinect2 package and its components.* ***Do not write emails.*** + +## Description + +This is a simple viewer for the combined color an depth image provided by Kinect like depth sensors. + +It just listens to two ROS topics and displays a the color with the overlayed colored depth image or a registered point cloud. + +## Dependencies + +- ROS Hydro/Indigo +- OpenCV +- PCL + +*for the ROS packages look at the package.xml* + +## Usage + +``` +kinect2_viewer [options] + name: 'any string' equals to the kinect2_bridge topic base name + mode: 'qhd', 'hd', 'sd' or 'ir' + visualization: 'image', 'cloud' or 'both' + options: + 'compressed' use compressed instead of raw topics + 'approx' use approximate time synchronization +``` + +Example: `rosrun kinect2_viewer kinect2_viewer sd cloud` + +## Key bindings + +Windows: +- `ESC`, `q`: Quit +- `SPACE`, `s`: Save the current image, cloud in the current directory + +Terminal: +- `CRTL`+`c`: Quit diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/package.xml b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/package.xml new file mode 100644 index 0000000..58482ee --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/package.xml @@ -0,0 +1,40 @@ + + + kinect2_viewer + 0.0.1 + The kinect2_viewer package + + Thiemo Wiedemeyer + + Apache 2.0 + + catkin + + roscpp + rostime + std_msgs + sensor_msgs + message_filters + image_transport + compressed_image_transport + compressed_depth_image_transport + kinect2_bridge + libpcl-all-dev + cv_bridge + + message_runtime + roscpp + rostime + std_msgs + sensor_msgs + message_filters + image_transport + compressed_image_transport + compressed_depth_image_transport + libpcl-all-dev + libpcl-all + cv_bridge + + + + diff --git a/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/src/viewer.cpp b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/src/viewer.cpp new file mode 100644 index 0000000..26c170b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/iai_kinect2/kinect2_viewer/src/viewer.cpp @@ -0,0 +1,619 @@ +/** + * Copyright 2014 University of Bremen, Institute for Artificial Intelligence + * Author: Thiemo Wiedemeyer + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +class Receiver +{ +public: + enum Mode + { + IMAGE = 0, + CLOUD, + BOTH + }; + +private: + std::mutex lock; + + const std::string topicColor, topicDepth; + const bool useExact, useCompressed; + + bool updateImage, updateCloud; + bool save; + bool running; + size_t frame; + const size_t queueSize; + + cv::Mat color, depth; + cv::Mat cameraMatrixColor, cameraMatrixDepth; + cv::Mat lookupX, lookupY; + + typedef message_filters::sync_policies::ExactTime ExactSyncPolicy; + typedef message_filters::sync_policies::ApproximateTime ApproximateSyncPolicy; + + ros::NodeHandle nh; + ros::AsyncSpinner spinner; + image_transport::ImageTransport it; + image_transport::SubscriberFilter *subImageColor, *subImageDepth; + message_filters::Subscriber *subCameraInfoColor, *subCameraInfoDepth; + + message_filters::Synchronizer *syncExact; + message_filters::Synchronizer *syncApproximate; + + std::thread imageViewerThread; + Mode mode; + + pcl::PointCloud::Ptr cloud; + pcl::PCDWriter writer; + std::ostringstream oss; + std::vector params; + +public: + Receiver(const std::string &topicColor, const std::string &topicDepth, const bool useExact, const bool useCompressed) + : topicColor(topicColor), topicDepth(topicDepth), useExact(useExact), useCompressed(useCompressed), + updateImage(false), updateCloud(false), save(false), running(false), frame(0), queueSize(5), + nh("~"), spinner(0), it(nh), mode(CLOUD) + { + cameraMatrixColor = cv::Mat::zeros(3, 3, CV_64F); + cameraMatrixDepth = cv::Mat::zeros(3, 3, CV_64F); + params.push_back(cv::IMWRITE_JPEG_QUALITY); + params.push_back(100); + params.push_back(cv::IMWRITE_PNG_COMPRESSION); + params.push_back(1); + params.push_back(cv::IMWRITE_PNG_STRATEGY); + params.push_back(cv::IMWRITE_PNG_STRATEGY_RLE); + params.push_back(0); + } + + ~Receiver() + { + } + + void run(const Mode mode) + { + start(mode); + stop(); + } + +private: + void start(const Mode mode) + { + this->mode = mode; + running = true; + + std::string topicCameraInfoColor = topicColor.substr(0, topicColor.rfind('/')) + "/camera_info"; + std::string topicCameraInfoDepth = topicDepth.substr(0, topicDepth.rfind('/')) + "/camera_info"; + + image_transport::TransportHints hints(useCompressed ? "compressed" : "raw"); + subImageColor = new image_transport::SubscriberFilter(it, topicColor, queueSize, hints); + subImageDepth = new image_transport::SubscriberFilter(it, topicDepth, queueSize, hints); + subCameraInfoColor = new message_filters::Subscriber(nh, topicCameraInfoColor, queueSize); + subCameraInfoDepth = new message_filters::Subscriber(nh, topicCameraInfoDepth, queueSize); + + if(useExact) + { + syncExact = new message_filters::Synchronizer(ExactSyncPolicy(queueSize), *subImageColor, *subImageDepth, *subCameraInfoColor, *subCameraInfoDepth); + syncExact->registerCallback(boost::bind(&Receiver::callback, this, _1, _2, _3, _4)); + } + else + { + syncApproximate = new message_filters::Synchronizer(ApproximateSyncPolicy(queueSize), *subImageColor, *subImageDepth, *subCameraInfoColor, *subCameraInfoDepth); + syncApproximate->registerCallback(boost::bind(&Receiver::callback, this, _1, _2, _3, _4)); + } + + spinner.start(); + + std::chrono::milliseconds duration(1); + while(!updateImage || !updateCloud) + { + if(!ros::ok()) + { + return; + } + std::this_thread::sleep_for(duration); + } + cloud = pcl::PointCloud::Ptr(new pcl::PointCloud()); + cloud->height = color.rows; + cloud->width = color.cols; + cloud->is_dense = false; + cloud->points.resize(cloud->height * cloud->width); + createLookup(this->color.cols, this->color.rows); + + switch(mode) + { + case CLOUD: + cloudViewer(); + break; + case IMAGE: + imageViewer(); + break; + case BOTH: + imageViewerThread = std::thread(&Receiver::imageViewer, this); + cloudViewer(); + break; + } + } + + void stop() + { + spinner.stop(); + + if(useExact) + { + delete syncExact; + } + else + { + delete syncApproximate; + } + + delete subImageColor; + delete subImageDepth; + delete subCameraInfoColor; + delete subCameraInfoDepth; + + running = false; + if(mode == BOTH) + { + imageViewerThread.join(); + } + } + + void callback(const sensor_msgs::Image::ConstPtr imageColor, const sensor_msgs::Image::ConstPtr imageDepth, + const sensor_msgs::CameraInfo::ConstPtr cameraInfoColor, const sensor_msgs::CameraInfo::ConstPtr cameraInfoDepth) + { + cv::Mat color, depth; + + readCameraInfo(cameraInfoColor, cameraMatrixColor); + readCameraInfo(cameraInfoDepth, cameraMatrixDepth); + readImage(imageColor, color); + readImage(imageDepth, depth); + + // IR image input + if(color.type() == CV_16U) + { + cv::Mat tmp; + color.convertTo(tmp, CV_8U, 0.02); + cv::cvtColor(tmp, color, CV_GRAY2BGR); + } + + lock.lock(); + this->color = color; + this->depth = depth; + updateImage = true; + updateCloud = true; + lock.unlock(); + } + + void imageViewer() + { + cv::Mat color, depth, depthDisp, combined; + std::chrono::time_point start, now; + double fps = 0; + size_t frameCount = 0; + std::ostringstream oss; + const cv::Point pos(5, 15); + const cv::Scalar colorText = CV_RGB(255, 255, 255); + const double sizeText = 0.5; + const int lineText = 1; + const int font = cv::FONT_HERSHEY_SIMPLEX; + + cv::namedWindow("Image Viewer"); + oss << "starting..."; + + start = std::chrono::high_resolution_clock::now(); + for(; running && ros::ok();) + { + if(updateImage) + { + lock.lock(); + color = this->color; + depth = this->depth; + updateImage = false; + lock.unlock(); + + ++frameCount; + now = std::chrono::high_resolution_clock::now(); + double elapsed = std::chrono::duration_cast(now - start).count() / 1000.0; + if(elapsed >= 1.0) + { + fps = frameCount / elapsed; + oss.str(""); + oss << "fps: " << fps << " ( " << elapsed / frameCount * 1000.0 << " ms)"; + start = now; + frameCount = 0; + } + + dispDepth(depth, depthDisp, 12000.0f); + combine(color, depthDisp, combined); + //combined = color; + + cv::putText(combined, oss.str(), pos, font, sizeText, colorText, lineText, CV_AA); + cv::imshow("Image Viewer", combined); + } + + int key = cv::waitKey(1); + switch(key & 0xFF) + { + case 27: + case 'q': + running = false; + break; + case ' ': + case 's': + if(mode == IMAGE) + { + createCloud(depth, color, cloud); + saveCloudAndImages(cloud, color, depth, depthDisp); + } + else + { + save = true; + } + break; + } + } + cv::destroyAllWindows(); + cv::waitKey(100); + } + + void cloudViewer() + { + cv::Mat color, depth; + pcl::visualization::PCLVisualizer::Ptr visualizer(new pcl::visualization::PCLVisualizer("Cloud Viewer")); + const std::string cloudName = "rendered"; + + lock.lock(); + color = this->color; + depth = this->depth; + updateCloud = false; + lock.unlock(); + + createCloud(depth, color, cloud); + + visualizer->addPointCloud(cloud, cloudName); + visualizer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, cloudName); + visualizer->initCameraParameters(); + visualizer->setBackgroundColor(0, 0, 0); + visualizer->setPosition(mode == BOTH ? color.cols : 0, 0); + visualizer->setSize(color.cols, color.rows); + visualizer->setShowFPS(true); + visualizer->setCameraPosition(0, 0, 0, 0, -1, 0); + visualizer->registerKeyboardCallback(&Receiver::keyboardEvent, *this); + + for(; running && ros::ok();) + { + if(updateCloud) + { + lock.lock(); + color = this->color; + depth = this->depth; + updateCloud = false; + lock.unlock(); + + createCloud(depth, color, cloud); + + visualizer->updatePointCloud(cloud, cloudName); + } + if(save) + { + save = false; + cv::Mat depthDisp; + dispDepth(depth, depthDisp, 12000.0f); + saveCloudAndImages(cloud, color, depth, depthDisp); + } + visualizer->spinOnce(10); + } + visualizer->close(); + } + + void keyboardEvent(const pcl::visualization::KeyboardEvent &event, void *) + { + if(event.keyUp()) + { + switch(event.getKeyCode()) + { + case 27: + case 'q': + running = false; + break; + case ' ': + case 's': + save = true; + break; + } + } + } + + void readImage(const sensor_msgs::Image::ConstPtr msgImage, cv::Mat &image) const + { + cv_bridge::CvImageConstPtr pCvImage; + pCvImage = cv_bridge::toCvShare(msgImage, msgImage->encoding); + pCvImage->image.copyTo(image); + } + + void readCameraInfo(const sensor_msgs::CameraInfo::ConstPtr cameraInfo, cv::Mat &cameraMatrix) const + { + double *itC = cameraMatrix.ptr(0, 0); + for(size_t i = 0; i < 9; ++i, ++itC) + { + *itC = cameraInfo->K[i]; + } + } + + void dispDepth(const cv::Mat &in, cv::Mat &out, const float maxValue) + { + cv::Mat tmp = cv::Mat(in.rows, in.cols, CV_8U); + const uint32_t maxInt = 255; + + #pragma omp parallel for + for(int r = 0; r < in.rows; ++r) + { + const uint16_t *itI = in.ptr(r); + uint8_t *itO = tmp.ptr(r); + + for(int c = 0; c < in.cols; ++c, ++itI, ++itO) + { + *itO = (uint8_t)std::min((*itI * maxInt / maxValue), 255.0f); + } + } + + cv::applyColorMap(tmp, out, cv::COLORMAP_JET); + } + + void combine(const cv::Mat &inC, const cv::Mat &inD, cv::Mat &out) + { + out = cv::Mat(inC.rows, inC.cols, CV_8UC3); + + #pragma omp parallel for + for(int r = 0; r < inC.rows; ++r) + { + const cv::Vec3b + *itC = inC.ptr(r), + *itD = inD.ptr(r); + cv::Vec3b *itO = out.ptr(r); + + for(int c = 0; c < inC.cols; ++c, ++itC, ++itD, ++itO) + { + itO->val[0] = (itC->val[0] + itD->val[0]) >> 1; + itO->val[1] = (itC->val[1] + itD->val[1]) >> 1; + itO->val[2] = (itC->val[2] + itD->val[2]) >> 1; + } + } + } + + void createCloud(const cv::Mat &depth, const cv::Mat &color, pcl::PointCloud::Ptr &cloud) const + { + const float badPoint = std::numeric_limits::quiet_NaN(); + + #pragma omp parallel for + for(int r = 0; r < depth.rows; ++r) + { + pcl::PointXYZRGBA *itP = &cloud->points[r * depth.cols]; + const uint16_t *itD = depth.ptr(r); + const cv::Vec3b *itC = color.ptr(r); + const float y = lookupY.at(0, r); + const float *itX = lookupX.ptr(); + + for(size_t c = 0; c < (size_t)depth.cols; ++c, ++itP, ++itD, ++itC, ++itX) + { + register const float depthValue = *itD / 1000.0f; + // Check for invalid measurements + if(*itD == 0) + { + // not valid + itP->x = itP->y = itP->z = badPoint; + itP->rgba = 0; + continue; + } + itP->z = depthValue; + itP->x = *itX * depthValue; + itP->y = y * depthValue; + itP->b = itC->val[0]; + itP->g = itC->val[1]; + itP->r = itC->val[2]; + itP->a = 255; + } + } + } + + void saveCloudAndImages(const pcl::PointCloud::ConstPtr cloud, const cv::Mat &color, const cv::Mat &depth, const cv::Mat &depthColored) + { + oss.str(""); + oss << "./" << std::setfill('0') << std::setw(4) << frame; + const std::string baseName = oss.str(); + const std::string cloudName = baseName + "_cloud.pcd"; + const std::string colorName = baseName + "_color.jpg"; + const std::string depthName = baseName + "_depth.png"; + const std::string depthColoredName = baseName + "_depth_colored.png"; + + OUT_INFO("saving cloud: " << cloudName); + writer.writeBinary(cloudName, *cloud); + OUT_INFO("saving color: " << colorName); + cv::imwrite(colorName, color, params); + OUT_INFO("saving depth: " << depthName); + cv::imwrite(depthName, depth, params); + OUT_INFO("saving depth: " << depthColoredName); + cv::imwrite(depthColoredName, depthColored, params); + OUT_INFO("saving complete!"); + ++frame; + } + + void createLookup(size_t width, size_t height) + { + const float fx = 1.0f / cameraMatrixColor.at(0, 0); + const float fy = 1.0f / cameraMatrixColor.at(1, 1); + const float cx = cameraMatrixColor.at(0, 2); + const float cy = cameraMatrixColor.at(1, 2); + float *it; + + lookupY = cv::Mat(1, height, CV_32F); + it = lookupY.ptr(); + for(size_t r = 0; r < height; ++r, ++it) + { + *it = (r - cy) * fy; + } + + lookupX = cv::Mat(1, width, CV_32F); + it = lookupX.ptr(); + for(size_t c = 0; c < width; ++c, ++it) + { + *it = (c - cx) * fx; + } + } +}; + +void help(const std::string &path) +{ + std::cout << path << FG_BLUE " [options]" << std::endl + << FG_GREEN " name" NO_COLOR ": " FG_YELLOW "'any string'" NO_COLOR " equals to the kinect2_bridge topic base name" << std::endl + << FG_GREEN " mode" NO_COLOR ": " FG_YELLOW "'qhd'" NO_COLOR ", " FG_YELLOW "'hd'" NO_COLOR ", " FG_YELLOW "'sd'" NO_COLOR " or " FG_YELLOW "'ir'" << std::endl + << FG_GREEN " visualization" NO_COLOR ": " FG_YELLOW "'image'" NO_COLOR ", " FG_YELLOW "'cloud'" NO_COLOR " or " FG_YELLOW "'both'" << std::endl + << FG_GREEN " options" NO_COLOR ":" << std::endl + << FG_YELLOW " 'compressed'" NO_COLOR " use compressed instead of raw topics" << std::endl + << FG_YELLOW " 'approx'" NO_COLOR " use approximate time synchronization" << std::endl; +} + +int main(int argc, char **argv) +{ +#if EXTENDED_OUTPUT + ROSCONSOLE_AUTOINIT; + if(!getenv("ROSCONSOLE_FORMAT")) + { + ros::console::g_formatter.tokens_.clear(); + ros::console::g_formatter.init("[${severity}] ${message}"); + } +#endif + + ros::init(argc, argv, "kinect2_viewer", ros::init_options::AnonymousName); + + if(!ros::ok()) + { + return 0; + } + + std::string ns = K2_DEFAULT_NS; + std::string topicColor = K2_TOPIC_QHD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + std::string topicDepth = K2_TOPIC_QHD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + bool useExact = true; + bool useCompressed = false; + Receiver::Mode mode = Receiver::CLOUD; + + for(size_t i = 1; i < (size_t)argc; ++i) + { + std::string param(argv[i]); + + if(param == "-h" || param == "--help" || param == "-?" || param == "--?") + { + help(argv[0]); + ros::shutdown(); + return 0; + } + else if(param == "qhd") + { + topicColor = K2_TOPIC_QHD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + topicDepth = K2_TOPIC_QHD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + } + else if(param == "hd") + { + topicColor = K2_TOPIC_HD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + topicDepth = K2_TOPIC_HD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + } + else if(param == "ir") + { + topicColor = K2_TOPIC_SD K2_TOPIC_IMAGE_IR K2_TOPIC_IMAGE_RECT; + topicDepth = K2_TOPIC_SD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + } + else if(param == "sd") + { + topicColor = K2_TOPIC_SD K2_TOPIC_IMAGE_COLOR K2_TOPIC_IMAGE_RECT; + topicDepth = K2_TOPIC_SD K2_TOPIC_IMAGE_DEPTH K2_TOPIC_IMAGE_RECT; + } + else if(param == "approx") + { + useExact = false; + } + + else if(param == "compressed") + { + useCompressed = true; + } + else if(param == "image") + { + mode = Receiver::IMAGE; + } + else if(param == "cloud") + { + mode = Receiver::CLOUD; + } + else if(param == "both") + { + mode = Receiver::BOTH; + } + else + { + ns = param; + } + } + + topicColor = "/" + ns + topicColor; + topicDepth = "/" + ns + topicDepth; + OUT_INFO("topic color: " FG_CYAN << topicColor << NO_COLOR); + OUT_INFO("topic depth: " FG_CYAN << topicDepth << NO_COLOR); + + Receiver receiver(topicColor, topicDepth, useExact, useCompressed); + + OUT_INFO("starting receiver..."); + receiver.run(mode); + + ros::shutdown(); + return 0; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitattributes b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.github/ISSUE_TEMPLATE.md b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..685b0c5 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,24 @@ +Overview Description: + + + +Version, Platform, and Hardware Bug Found: + +1. `git log -1 --oneline` +2. `uname -a` +3. `lsusb -t` +4. `lspci -nn` + +Steps to Reproduce: + +1. +2. +3. + +Actual Results: + +Expected Results: + +Reproducibility: + +Additional Information: diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitignore b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitignore new file mode 100644 index 0000000..6926523 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/.gitignore @@ -0,0 +1,161 @@ +build + +# Dependency folders +depends/*/ +depends/*.deb + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/APACHE20 b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/APACHE20 new file mode 100644 index 0000000..57bc88a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/APACHE20 @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/CMakeLists.txt new file mode 100644 index 0000000..d99c7b4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/CMakeLists.txt @@ -0,0 +1,500 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.1) + +SET(PROJECT_VER_MAJOR 0) +SET(PROJECT_VER_MINOR 2) +SET(PROJECT_VER_PATCH 0) +SET(PROJECT_VER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}.${PROJECT_VER_PATCH}") +SET(PROJECT_APIVER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}") + +SET(CMAKE_CXX_FLAGS "-fPIC") + +if(WIN32 AND NOT MINGW) + if(NOT DEFINED CMAKE_DEBUG_POSTFIX) + set(CMAKE_DEBUG_POSTFIX "d") + endif() +endif() + +IF(WIN32) + # no permission for the default install prefix %ProgramFiles% + SET(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "installation path") +ENDIF() + +IF(NOT DEFINED CMAKE_BUILD_TYPE) + # No effect for multi-configuration generators (e.g. for Visual Studio) + SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose: RelWithDebInfo Release Debug MinSizeRel None") +ENDIF() + +PROJECT(libfreenect2) + +IF(POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) +ENDIF() + +SET(MY_DIR ${libfreenect2_SOURCE_DIR}) +SET(DEPENDS_DIR "${MY_DIR}/depends" CACHE STRING "dependency directory must be set to 'false' if external deps are used") + +OPTION(BUILD_SHARED_LIBS "Build shared (ON) or static (OFF) libraries" ON) +OPTION(BUILD_EXAMPLES "Build examples" ON) +OPTION(BUILD_OPENNI2_DRIVER "Build OpenNI2 driver" ON) +OPTION(ENABLE_CXX11 "Enable C++11 support" OFF) +OPTION(ENABLE_OPENCL "Enable OpenCL support" ON) +OPTION(ENABLE_CUDA "Enable CUDA support" ON) +OPTION(ENABLE_OPENGL "Enable OpenGL support" ON) +OPTION(ENABLE_VAAPI "Enable VA-API support" ON) +OPTION(ENABLE_TEGRAJPEG "Enable Tegra HW JPEG support" ON) +OPTION(ENABLE_PROFILING "Collect profiling stats (memory consuming)" OFF) + +IF(ENABLE_PROFILING) + SET(LIBFREENECT2_WITH_PROFILING 1) +ENDIF() + +IF(MSVC) + # suppress several "possible loss of data" warnings, and + # "zero-length array in struct" from libusb.h + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4244 /wd4200 /wd4305 /wd4146") + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) # no warning for getenv() +ELSE() + # Heed warnings from non-MSVC compilers + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +ENDIF() + +SET(HAVE_CXX11 disabled) +IF(ENABLE_CXX11) + INCLUDE(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) + CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) + IF(COMPILER_SUPPORTS_CXX11) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + SET(LIBFREENECT2_WITH_CXX11_SUPPORT 1) + SET(HAVE_CXX11 yes) + ELSEIF(COMPILER_SUPPORTS_CXX0X) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + SET(HAVE_CXX11 c++0x) + ELSE() + SET(HAVE_CXX11 no) + MESSAGE(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + ENDIF() +ENDIF(ENABLE_CXX11) + +# additional cmake modules +LIST(APPEND CMAKE_MODULE_PATH ${MY_DIR}/cmake_modules) + +# setup threading +INCLUDE(SetupLibfreenect2Threading) + +INCLUDE(GenerateResources) + +#set the default path for built executables to the "bin" directory +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) + +#set the default path for built libraries to the "lib" directory +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) + +# dependencies +FIND_PACKAGE(PkgConfig) # try find PKGConfig as it will be used if found +FIND_PACKAGE(LibUSB REQUIRED) + +# Add includes +INCLUDE_DIRECTORIES( + "${MY_DIR}/include" + "${MY_DIR}/include/internal" + ${PROJECT_BINARY_DIR} # for generated headers + ${LIBFREENECT2_THREADING_INCLUDE_DIR} + ${LibUSB_INCLUDE_DIRS} +) + +SET(RESOURCES_INC_FILE "${PROJECT_BINARY_DIR}/resources.inc.h") + +SET(SOURCES + include/internal/libfreenect2/protocol/command.h + include/internal/libfreenect2/protocol/command_transaction.h + include/internal/libfreenect2/protocol/response.h + include/internal/libfreenect2/protocol/usb_control.h + + include/internal/libfreenect2/usb/event_loop.h + include/internal/libfreenect2/usb/transfer_pool.h + + include/libfreenect2/logger.h + include/internal/libfreenect2/logging.h + + include/internal/libfreenect2/async_packet_processor.h + include/internal/libfreenect2/depth_packet_processor.h + include/internal/libfreenect2/depth_packet_stream_parser.h + include/internal/libfreenect2/allocator.h + include/libfreenect2/frame_listener.hpp + include/libfreenect2/frame_listener_impl.h + include/libfreenect2/libfreenect2.hpp + include/libfreenect2/color_settings.h + include/libfreenect2/led_settings.h + include/libfreenect2/packet_pipeline.h + include/internal/libfreenect2/packet_processor.h + include/libfreenect2/registration.h + include/internal/libfreenect2/resource.h + include/internal/libfreenect2/rgb_packet_processor.h + include/internal/libfreenect2/rgb_packet_stream_parser.h + include/internal/libfreenect2/threading.h + + src/transfer_pool.cpp + src/event_loop.cpp + src/usb_control.cpp + src/allocator.cpp + src/frame_listener_impl.cpp + src/packet_pipeline.cpp + src/rgb_packet_stream_parser.cpp + src/rgb_packet_processor.cpp + src/depth_packet_stream_parser.cpp + src/depth_packet_processor.cpp + src/cpu_depth_packet_processor.cpp + src/resource.cpp + src/command_transaction.cpp + src/registration.cpp + src/logging.cpp + src/libfreenect2.cpp + + ${LIBFREENECT2_THREADING_SOURCE} + ${RESOURCES_INC_FILE} + "${PROJECT_BINARY_DIR}/libfreenect2/config.h" + "${PROJECT_BINARY_DIR}/libfreenect2/export.h" +) + +SET(LIBRARIES + ${LibUSB_LIBRARIES} + ${LIBFREENECT2_THREADING_LIBRARIES} +) + +SET(LIBFREENECT2_DLLS + ${LibUSB_DLL} +) + +SET(HAVE_VideoToolbox "no (Apple only)") +IF(APPLE) + FIND_LIBRARY(VIDEOTOOLBOX_LIBRARY VideoToolbox) + + SET(HAVE_VideoToolbox no) + IF(VIDEOTOOLBOX_LIBRARY) + SET(LIBFREENECT2_WITH_VT_SUPPORT 1) + SET(HAVE_VideoToolbox yes) + + FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) + FIND_LIBRARY(COREMEDIA_LIBRARY CoreMedia REQUIRED) + FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo REQUIRED) + + LIST(APPEND SOURCES + src/vt_rgb_packet_processor.cpp + ) + + LIST(APPEND LIBRARIES + ${VIDEOTOOLBOX_LIBRARY} + ${COREFOUNDATION_LIBRARY} + ${COREMEDIA_LIBRARY} + ${COREVIDEO_LIBRARY} + ) + ENDIF(VIDEOTOOLBOX_LIBRARY) +ENDIF(APPLE) + +SET(HAVE_VAAPI disabled) +IF(ENABLE_VAAPI) + IF(PKG_CONFIG_FOUND) + PKG_CHECK_MODULES(VAAPI libva libva-drm) + ENDIF() + FIND_PACKAGE(JPEG) + + SET(HAVE_VAAPI no) + IF(VAAPI_FOUND AND JPEG_FOUND) + SET(LIBFREENECT2_WITH_VAAPI_SUPPORT 1) + SET(HAVE_VAAPI yes) + + INCLUDE_DIRECTORIES(${VAAPI_INCLUDE_DIRS}) + + LIST(APPEND SOURCES + src/vaapi_rgb_packet_processor.cpp + ) + LIST(APPEND LIBRARIES + ${VAAPI_LIBRARIES} + ${JPEG_LIBRARY} + ) + ENDIF() +ENDIF(ENABLE_VAAPI) + +SET(HAVE_TegraJPEG disabled) +IF(ENABLE_TEGRAJPEG) + FIND_PACKAGE(TegraJPEG) + + SET(HAVE_TegraJPEG no) + IF(TegraJPEG_FOUND) + SET(LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT 1) + SET(HAVE_TegraJPEG yes) + + INCLUDE_DIRECTORIES(${TegraJPEG_INCLUDE_DIRS}) + + LIST(APPEND SOURCES + src/tegra_jpeg_rgb_packet_processor.cpp + ) + + LIST(APPEND LIBRARIES + ${CMAKE_DL_LIBS} + ) + ENDIF() +ENDIF() + +IF(LIBFREENECT2_WITH_VT_SUPPORT) + FIND_PACKAGE(TurboJPEG) +ELSE() + # VAAPI can fail to start at runtime. It must have a fallback. + FIND_PACKAGE(TurboJPEG REQUIRED) +ENDIF() + +SET(HAVE_TurboJPEG no) +IF(TurboJPEG_FOUND) + SET(LIBFREENECT2_WITH_TURBOJPEG_SUPPORT 1) + SET(HAVE_TurboJPEG yes) + + INCLUDE_DIRECTORIES(${TurboJPEG_INCLUDE_DIRS}) + + LIST(APPEND SOURCES + src/turbo_jpeg_rgb_packet_processor.cpp + ) + + LIST(APPEND LIBRARIES + ${TurboJPEG_LIBRARIES} + ) + + LIST(APPEND LIBFREENECT2_DLLS + ${TurboJPEG_DLL} + ) +ENDIF() + +SET(HAVE_OpenGL disabled) +IF(ENABLE_OPENGL) + FIND_PACKAGE(GLFW3) + FIND_PACKAGE(OpenGL) + SET(HAVE_OpenGL no) + IF(GLFW3_FOUND AND OPENGL_FOUND) + SET(LIBFREENECT2_WITH_OPENGL_SUPPORT 1) + SET(HAVE_OpenGL yes) + + INCLUDE_DIRECTORIES(${GLFW3_INCLUDE_DIRS}) + + LIST(APPEND LIBFREENECT2_DLLS ${GLFW3_DLL}) + LIST(APPEND LIBRARIES + ${GLFW3_LIBRARIES} + ${OPENGL_gl_LIBRARY} + ) + LIST(APPEND SOURCES + src/flextGL.cpp + src/opengl_depth_packet_processor.cpp + ) + + LIST(APPEND RESOURCES + src/shader/debug.fs + src/shader/default.vs + src/shader/filter1.fs + src/shader/filter2.fs + src/shader/stage1.fs + src/shader/stage2.fs + ) + ENDIF() +ENDIF(ENABLE_OPENGL) + +SET(HAVE_OpenCL disabled) +IF(ENABLE_OPENCL) + FIND_PACKAGE(OpenCL) + + SET(HAVE_OpenCL no) + IF(OpenCL_FOUND) + SET(LIBFREENECT2_WITH_OPENCL_SUPPORT 1) + SET(HAVE_OpenCL yes) + + IF(UNIX AND NOT APPLE) + INCLUDE(CheckOpenCLICDLoader) + IF(OpenCL_C_WORKS AND NOT OpenCL_CXX_WORKS) + SET(LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD 1) + SET(HAVE_OpenCL "yes but buggy") + MESSAGE(WARNING "Your libOpenCL.so is incompatible with CL/cl.h. Install ocl-icd-opencl-dev to update libOpenCL.so?") + ENDIF() + ENDIF() + INCLUDE_DIRECTORIES(${OpenCL_INCLUDE_DIRS}) + + LIST(APPEND SOURCES + src/opencl_depth_packet_processor.cpp + src/opencl_kde_depth_packet_processor.cpp + ) + + LIST(APPEND LIBRARIES + ${OpenCL_LIBRARIES} + ) + + LIST(APPEND RESOURCES + src/opencl_depth_packet_processor.cl + src/opencl_kde_depth_packet_processor.cl + ) + + # Major Linux distro stable releases have buggy OpenCL ICD loader. + # The workaround of disabling exceptions can only be set up during compile time. + # Diabling it for all should be harmless. The flag is the same for GCC/Clang/ICC. + IF(UNIX AND NOT APPLE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") + ENDIF() + ENDIF(OpenCL_FOUND) +ENDIF(ENABLE_OPENCL) + +SET(HAVE_CUDA disabled) +IF(ENABLE_CUDA) + FIND_PACKAGE(CUDA) + SET(HAVE_CUDA no) + IF(CUDA_FOUND AND MSVC14 AND CUDA_VERSION VERSION_LESS 8.0) + SET(HAVE_CUDA "no (VS2015 not supported)") + ELSEIF(CUDA_FOUND) + SET(LIBFREENECT2_WITH_CUDA_SUPPORT 1) + SET(HAVE_CUDA yes) + + STRING(REPLACE "\\" "/" NVCUDASAMPLES_ROOT "$ENV{NVCUDASAMPLES_ROOT}") + STRING(REPLACE "\\" "/" NVCUDASAMPLES8_0_ROOT "$ENV{NVCUDASAMPLES8_0_ROOT}") + CUDA_INCLUDE_DIRECTORIES( + "${MY_DIR}/include/" + "${CUDA_TOOLKIT_ROOT_DIR}/samples/common/inc" + "${NVCUDASAMPLES_ROOT}/common/inc" + "${NVCUDASAMPLES8_0_ROOT}/common/inc" + ) + SET(CUDA_FLAGS -use_fast_math) + IF(NOT MSVC) + SET(CUDA_FLAGS "${CUDA_FLAGS} -Xcompiler -fPIC") + ENDIF() + IF(HAVE_CXX11 STREQUAL yes AND CUDA_VERSION VERSION_GREATER 7.0) + SET(CUDA_FLAGS "${CUDA_FLAGS} -std=c++11") + ENDIF() + + SET(OLD_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + STRING(REGEX REPLACE "-std=c\\+\\+.." "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + CUDA_COMPILE(CUDA_OBJECTS + src/cuda_depth_packet_processor.cu + src/cuda_kde_depth_packet_processor.cu + OPTIONS ${CUDA_FLAGS} + ) + SET(CMAKE_CXX_FLAGS "${OLD_CMAKE_CXX_FLAGS}") + + INCLUDE_DIRECTORIES(${CUDA_INCLUDE_DIRS}) + + LIST(APPEND SOURCES + ${CUDA_OBJECTS} + ) + + LIST(APPEND LIBRARIES + ${CUDA_LIBRARIES} + ) + ENDIF() +ENDIF(ENABLE_CUDA) + +# RPATH handling for CUDA 8.0 libOpenCL.so conflict. See #804. +IF(HAVE_OpenCL STREQUAL yes AND UNIX AND NOT APPLE) + FILE(GLOB CUDA_ld_so_conf /etc/ld.so.conf.d/cuda*.conf) + IF(CUDA_ld_so_conf) + MESSAGE(WARNING "Your CUDA installation overrides OpenCL system library path.") + GET_FILENAME_COMPONENT(OpenCL_LIB_PATH ${OpenCL_LIBRARY} DIRECTORY) + SET(CMAKE_INSTALL_RPATH ${OpenCL_LIB_PATH} CACHE STRING "Set RPATH for system OpenCL") + ENDIF() +ENDIF() + +# RPATH handling for private libusb copies +# Users have two options: +# 1. Build libusb in depends/ and leave it there: +# Do NOT set CMAKE_INSTALL_RPATH. It works by default. +# 2. Build libusb and install it somewhere: +# Set CMAKE_INSTALL_RPATH to the libusb.so installation directory before compiling. +# Both command line -DCMAKE_INSTALL_RPATH=... and CMake GUI settings are accepted. +# +# Anyway if wrong versions of libusb is used, errors will be reported explicitly. +IF(NOT DEFINED CMAKE_INSTALL_RPATH AND NOT ${LibUSB_LIBDIR} MATCHES "^/usr/lib") + SET(CMAKE_INSTALL_RPATH ${LibUSB_LIBDIR} CACHE STRING "Set RPATH for a private libusb") +ELSEIF(DEFINED CMAKE_INSTALL_RPATH) + SET(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} CACHE STRING "Set RPATH for a private libusb") +ENDIF() +IF(DEFINED CMAKE_INSTALL_RPATH) + MESSAGE(STATUS "RPATH set to ${CMAKE_INSTALL_RPATH}") +ENDIF() + +CONFIGURE_FILE("${MY_DIR}/include/libfreenect2/config.h.in" "${PROJECT_BINARY_DIR}/libfreenect2/config.h" @ONLY) +GENERATE_RESOURCES(${RESOURCES_INC_FILE} ${MY_DIR} ${RESOURCES}) + +ADD_DEFINITIONS(-DRESOURCES_INC) +ADD_LIBRARY(freenect2 ${SOURCES}) +SET_TARGET_PROPERTIES(freenect2 PROPERTIES + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN 1 + VERSION ${PROJECT_VER} + SOVERSION ${PROJECT_APIVER} +) +INCLUDE(GenerateExportHeader) +GENERATE_EXPORT_HEADER(freenect2 + BASE_NAME libfreenect2 + EXPORT_FILE_NAME libfreenect2/export.h +) + +IF(MSVC AND NOT BUILD_SHARED_LIBS) + # MSVC creates freenect2.lib for both dynamic and static by default + set_target_properties(freenect2 PROPERTIES SUFFIX "static.lib") +ENDIF() +STRING(REPLACE ";" "\n " LIBRARIES_STRING "${LIBRARIES}") +MESSAGE(STATUS "Linking with these libraries: \n ${LIBRARIES_STRING}") +TARGET_LINK_LIBRARIES(freenect2 ${LIBRARIES}) + +CONFIGURE_FILE(freenect2.cmake.in "${PROJECT_BINARY_DIR}/freenect2Config.cmake" @ONLY) +CONFIGURE_FILE(freenect2Version.cmake.in "${PROJECT_BINARY_DIR}/freenect2ConfigVersion.cmake" @ONLY) +CONFIGURE_FILE(freenect2.pc.in "${PROJECT_BINARY_DIR}/freenect2.pc" @ONLY) + +INSTALL(TARGETS freenect2 DESTINATION lib RUNTIME DESTINATION bin) +INSTALL(DIRECTORY "${MY_DIR}/include/${PROJECT_NAME}" DESTINATION include PATTERN "*.in" EXCLUDE) +INSTALL(DIRECTORY "${PROJECT_BINARY_DIR}/${PROJECT_NAME}" DESTINATION include) +INSTALL(FILES "${PROJECT_BINARY_DIR}/freenect2Config.cmake" DESTINATION lib/cmake/freenect2/) +INSTALL(FILES "${PROJECT_BINARY_DIR}/freenect2ConfigVersion.cmake" DESTINATION lib/cmake/freenect2/) +INSTALL(FILES "${PROJECT_BINARY_DIR}/freenect2.pc" DESTINATION lib/pkgconfig/) + +ADD_SUBDIRECTORY(${MY_DIR}/doc) + +SET(HAVE_Examples disabled) +IF(BUILD_EXAMPLES) + SET(HAVE_Examples yes) + MESSAGE(STATUS "Configurating examples") + ADD_SUBDIRECTORY(${MY_DIR}/examples) +ENDIF() + +SET(HAVE_OpenNI2 disabled) +IF(BUILD_OPENNI2_DRIVER) + FIND_PACKAGE(OpenNI2) + SET(HAVE_OpenNI2 no) + IF(OpenNI2_FOUND) + SET(HAVE_OpenNI2 yes) + FILE(GLOB OPENNI2_DRIVER_SOURCES src/openni2/*.cpp) + ADD_LIBRARY(freenect2-openni2 ${OPENNI2_DRIVER_SOURCES} ${LIBFREENECT2_THREADING_SOURCE}) + TARGET_INCLUDE_DIRECTORIES(freenect2-openni2 PRIVATE ${OpenNI2_INCLUDE_DIRS}) + TARGET_LINK_LIBRARIES(freenect2-openni2 freenect2 ${LIBFREENECT2_THREADING_LIBRARIES}) + SET_TARGET_PROPERTIES(freenect2-openni2 PROPERTIES SOVERSION 0) + IF(NOT ${CMAKE_INSTALL_PREFIX} MATCHES "^/usr") + SET_TARGET_PROPERTIES(freenect2-openni2 PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + ENDIF() + INSTALL(TARGETS freenect2-openni2 DESTINATION lib/OpenNI2/Drivers RUNTIME DESTINATION bin) + ADD_CUSTOM_TARGET(install-openni2 + DEPENDS freenect2-openni2 + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_INSTALL_PREFIX}/lib/OpenNI2/Drivers/" "${OpenNI2_LIBRARY_DIR}/OpenNI2/Drivers/" + VERBATIM + ) + ENDIF() +ENDIF() + +OPTION(BUILD_STREAMER_RECORDER "Build streamer_recorder" OFF) +SET(HAVE_streamer_recorder disabled) +IF(BUILD_STREAMER_RECORDER) + SET(HAVE_streamer_recorder yes) + MESSAGE(STATUS "Configurating streamer_recorder") + ADD_SUBDIRECTORY(${MY_DIR}/tools/streamer_recorder) +ENDIF() + +GET_CMAKE_PROPERTY(vars VARIABLES) +MESSAGE(STATUS "Feature list:") +FOREACH(var ${vars}) + IF(var MATCHES ^HAVE_) + STRING(REPLACE HAVE_ "" feature ${var}) + MESSAGE(STATUS " ${feature} ${${var}}") + ENDIF() +ENDFOREACH() diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/CONTRIB b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/CONTRIB new file mode 100644 index 0000000..7557c9b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/CONTRIB @@ -0,0 +1,34 @@ +Albert Hofkamp +Alistair +augmenta +Brendan Burns +Christian Kerl +Dave Coleman +Dorian Galvez-Lopez +Federico Spinelli +Florian Echtler +Francisco Facioni +Gabor Papp +Giacomo Dabisias +Henning Jungkurth +James Billingham +Joshua Blake +Lars Glud +Lingzhu Xiang +Ludique +Mario Wündsch +Matthias Goldhoorn +Matthieu FT +MrTatsch +Paul Reynolds +P.E. Viau +rahulraw +Rich Wareham +Ryan Gordon +Sergey Gusarov +Serguei Mokhov +Steffen Fuchs +Thiemo Wiedemeyer +vinouz +yuanmingze <3054502461@sina.com> +Zou Hanya diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/GPL2 b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/GPL2 new file mode 100644 index 0000000..1bb399f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/GPL2 @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/README.md b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/README.md new file mode 100644 index 0000000..6dd34e2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/README.md @@ -0,0 +1,249 @@ +# libfreenect2 + +## Table of Contents + +* [Description](README.md#description) +* [Requirements](README.md#requirements) +* [Troubleshooting](README.md#troubleshooting-and-reporting-bugs) +* [Maintainers](README.md#maintainers) +* [Installation](README.md#installation) + * [Windows / Visual Studio](README.md#windows--visual-studio) + * [MacOS](README.md#macos) + * [Linux](README.md#linux) +* [API Documentation (external)](https://openkinect.github.io/libfreenect2/) + +## Description + +Driver for Kinect for Windows v2 (K4W2) devices (release and developer preview). + +Note: libfreenect2 does not do anything for either Kinect for Windows v1 or Kinect for Xbox 360 sensors. Use libfreenect1 for those sensors. + +If you are using libfreenect2 in an academic context, please cite our work using the following DOI: [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.50641.svg)](https://doi.org/10.5281/zenodo.50641) + + + +If you use the KDE depth unwrapping algorithm implemented in the library, please also cite this ECCV 2016 [paper](http://users.isy.liu.se/cvl/perfo/abstracts/jaremo16.html). + +This driver supports: +* RGB image transfer +* IR and depth image transfer +* registration of RGB and depth images + +Missing features: +* firmware updates (see [issue #460](https://github.com/OpenKinect/libfreenect2/issues/460) for WiP) + +Watch the OpenKinect wiki at www.openkinect.org and the mailing list at https://groups.google.com/forum/#!forum/openkinect for the latest developments and more information about the K4W2 USB protocol. + +The API reference documentation is provided here https://openkinect.github.io/libfreenect2/. + +## Requirements + +### Hardware requirements + +* USB 3.0 controller. USB 2 is not supported. + +Intel and NEC USB 3.0 host controllers are known to work. ASMedia controllers are known to not work. + +Virtual machines likely do not work, because USB 3.0 isochronous transfer is quite delicate. + +##### Requirements for multiple Kinects + +It has been reported to work for up to 5 devices on a high-end PC using multiple separate PCI Express USB3 expansion cards (with NEC controller chip). If you're using Linux, you may have to [increase USBFS memory buffers](https://github.com/OpenKinect/libfreenect2/wiki/Troubleshooting#multiple-kinects-try-increasing-usbfs-buffer-size). Depending on the number of Kinects, you may need to use an even larger buffer size. If you're using an expansion card, make sure it's not plugged into an PCI-E x1 slot. A single lane doesn't have enough bandwidth. x8 or x16 slots usually work. + +### Operating system requirements + +* Windows 7 (buggy), Windows 8, Windows 8.1, and probably Windows 10 +* Debian, Ubuntu 14.04 or newer, probably other Linux distros. Recommend kernel 3.16+ or as new as possible. +* Mac OS X + +### Requirements for optional features + +* OpenGL depth processing: OpenGL 3.1 (Windows, Linux, Mac OS X). OpenGL ES is not supported at the moment. +* OpenCL depth processing: OpenCL 1.1 +* CUDA depth processing: CUDA (6.5 and 7.5 are tested; The minimum version is not clear.) +* VAAPI JPEG decoding: Intel (minimum Ivy Bridge or newer) and Linux only +* VideoToolbox JPEG decoding: Mac OS X only +* OpenNI2 integration: OpenNI2 2.2.0.33 +* Jetson TK1: Linux4Tegra 21.3 or later. Check [Jetson TK1 issues](https://github.com/OpenKinect/libfreenect2/wiki/Troubleshooting#jetson-tk1-issues) before installation. Jetson TX1 is not yet supported as the developers don't have one, but it may be easy to add the support. + +## Troubleshooting and reporting bugs + +First, check https://github.com/OpenKinect/libfreenect2/wiki/Troubleshooting for known issues. + +When you report USB issues, please attach relevant debug log from running the program with environment variable `LIBUSB_DEBUG=3`, and relevant log from `dmesg`. Also include relevant hardware information `lspci` and `lsusb -t`. + +## Maintainers + +* Joshua Blake +* Florian Echtler +* Christian Kerl +* Lingzhu Xiang (development/master branch) + +## Installation + +### Windows / Visual Studio + +* Install UsbDk driver + + 1. (Windows 7) You must first install Microsoft Security Advisory 3033929 otherwise your USB keyboards and mice will stop working! + 2. Download the latest x64 installer from https://github.com/daynix/UsbDk/releases, install it. + 3. If UsbDk somehow does not work, uninstall UsbDk and follow the libusbK instructions. + + This doesn't interfere with the Microsoft SDK. Do not install both UsbDK and libusbK drivers +* (Alternatively) Install libusbK driver + + You don't need the Kinect for Windows v2 SDK to build and install libfreenect2, though it doesn't hurt to have it too. You don't need to uninstall the SDK or the driver before doing this procedure. + + Install the libusbK backend driver for libusb. Please follow the steps exactly: + + 1. Download Zadig from http://zadig.akeo.ie/. + 2. Run Zadig and in options, check "List All Devices" and uncheck "Ignore Hubs or Composite Parents" + 3. Select the "Xbox NUI Sensor (composite parent)" from the drop-down box. (Important: Ignore the "NuiSensor Adaptor" varieties, which are the adapter, NOT the Kinect) The current driver will list usbccgp. USB ID is VID 045E, PID 02C4 or 02D8. + 4. Select libusbK (v3.0.7.0 or newer) from the replacement driver list. + 5. Click the "Replace Driver" button. Click yes on the warning about replacing a system driver. (This is because it is a composite parent.) + + To uninstall the libusbK driver (and get back the official SDK driver, if installed): + + 1. Open "Device Manager" + 2. Under "libusbK USB Devices" tree, right click the "Xbox NUI Sensor (Composite Parent)" device and select uninstall. + 3. Important: Check the "Delete the driver software for this device." checkbox, then click OK. + + If you already had the official SDK driver installed and you want to use it: + + 4. In Device Manager, in the Action menu, click "Scan for hardware changes." + + This will enumerate the Kinect sensor again and it will pick up the K4W2 SDK driver, and you should be ready to run KinectService.exe again immediately. + + You can go back and forth between the SDK driver and the libusbK driver very quickly and easily with these steps. + +* Build libusb + + Open a Git shell (GitHub for Windows), or any shell that has access to git.exe and msbuild.exe + ``` + cd depends/ + .\install_libusb_vs2013.cmd + ``` + Or `install_libusb_vs2015.cmd`. If you see some errors, you can always open the cmd files and follow the git commands, and maybe build `libusb_201x.sln` with Visual Studio by hand. Building with "Win32" is not recommended as it results in lower performance. +* Install TurboJPEG + + Download from http://sourceforge.net/projects/libjpeg-turbo/files, extract it to `c:\libjpeg-turbo64` or `depends/libjpeg-turbo64`, or anywhere as specified by the environment variable `TurboJPEG_ROOT`. +* Install GLFW + + Download from http://www.glfw.org/download.html (64-bit), extract as `depends/glfw` (rename `glfw-3.x.x.bin.WIN64` to `glfw`), or anywhere as specified by the environment variable `GLFW_ROOT`. +* Install OpenCL (optional) + 1. Intel GPU: Download "Intel® SDK for OpenCL™ Applications 2016" from https://software.intel.com/en-us/intel-opencl (requires free registration) and install it. +* Install CUDA (optional, Nvidia only) + 1. Download CUDA Toolkit and install it. You MUST install the samples too. +* Install OpenNI2 (optional) + + Download OpenNI 2.2.0.33 (x64) from http://structure.io/openni, install it to default locations (`C:\Program Files...`). +* Build + + The default installation path is `install`, you may change it by editing `CMAKE_INSTALL_PREFIX`. + ``` + mkdir build && cd build + cmake .. -G "Visual Studio 12 2013 Win64" + cmake --build . --config RelWithDebInfo --target install + ``` + Or `-G "Visual Studio 14 2015 Win64"`. +* Run the test program: `.\install\bin\Protonect.exe`, or start debugging in Visual Studio. +* Test OpenNI2 (optional) + + Copy freenect2-openni2.dll, and other dll files (libusb-1.0.dll, glfw.dll, etc.) in `install\bin` to `C:\Program Files\OpenNI2\Tools\OpenNI2\Drivers`. Then run `C:\Program Files\OpenNI\Tools\NiViewer.exe`. Environment variable `LIBFREENECT2_PIPELINE` can be set to `cl`, `cuda`, etc to specify the pipeline. + +### MacOS + +Use your favorite package managers (brew, ports, etc.) to install most if not all dependencies: + +* Make sure these build tools are available: wget, git, cmake, pkg-config. Xcode may provide some of them. Install the rest via package managers. +* Download libfreenect2 source + ``` + git clone https://github.com/OpenKinect/libfreenect2.git + cd libfreenect2 + ``` +* Install dependencies: libusb, GLFW + ``` + brew update + brew install libusb + brew install glfw3 + ``` +* Install TurboJPEG (optional) + ``` + brew install jpeg-turbo + ``` +* Install CUDA (optional): TODO +* Install OpenNI2 (optional) + ``` + brew tap brewsci/science + brew install openni2 + export OPENNI2_REDIST=/usr/local/lib/ni2 + export OPENNI2_INCLUDE=/usr/local/include/ni2 + ``` +* Build + ``` + mkdir build && cd build + cmake .. + make + make install + ``` +* Run the test program: `./bin/Protonect` +* Test OpenNI2. `make install-openni2` (may need sudo), then run `NiViewer`. Environment variable `LIBFREENECT2_PIPELINE` can be set to `cl`, `cuda`, etc to specify the pipeline. + +### Linux + +Note: Ubuntu 12.04 is too old to support. Debian jessie may also be too old, and Debian stretch is implied in the following. + +* Download libfreenect2 source + ``` + git clone https://github.com/OpenKinect/libfreenect2.git + cd libfreenect2 + ``` +* (Ubuntu 14.04 only) Download upgrade deb files + ``` + cd depends; ./download_debs_trusty.sh + ``` +* Install build tools + ``` + sudo apt-get install build-essential cmake pkg-config + ``` +* Install libusb. The version must be >= 1.0.20. + 1. (Ubuntu 14.04 only) `sudo dpkg -i debs/libusb*deb` + 2. (Other) `sudo apt-get install libusb-1.0-0-dev` +* Install TurboJPEG + 1. (Ubuntu 14.04 to 16.04) `sudo apt-get install libturbojpeg libjpeg-turbo8-dev` + 2. (Debian/Ubuntu 17.10 and newer) `sudo apt-get install libturbojpeg0-dev` +* Install OpenGL + 1. (Ubuntu 14.04 only) `sudo dpkg -i debs/libglfw3*deb; sudo apt-get install -f` + 2. (Odroid XU4) OpenGL 3.1 is not supported on this platform. Use `cmake -DENABLE_OPENGL=OFF` later. + 3. (Other) `sudo apt-get install libglfw3-dev` +* Install OpenCL (optional) + - Intel GPU + 1. (Ubuntu 14.04 only) `sudo apt-add-repository ppa:floe/beignet; sudo apt-get update; sudo apt-get install beignet-dev; sudo dpkg -i debs/ocl-icd*deb` + 2. (Other) `sudo apt-get install beignet-dev` + 3. For older kernels, `# echo 0 >/sys/module/i915/parameters/enable_cmd_parser` is needed. See more known issues at https://www.freedesktop.org/wiki/Software/Beignet/. + - AMD GPU: Install the latest version of the AMD Catalyst drivers from https://support.amd.com and `apt-get install opencl-headers`. + - Mali GPU (e.g. Odroid XU4): (with root) `mkdir -p /etc/OpenCL/vendors; echo /usr/lib/arm-linux-gnueabihf/mali-egl/libmali.so >/etc/OpenCL/vendors/mali.icd; apt-get install opencl-headers`. + - Verify: You can install `clinfo` to verify if you have correctly set up the OpenCL stack. +* Install CUDA (optional, Nvidia only): + - (Ubuntu 14.04 only) Download `cuda-repo-ubuntu1404...*.deb` ("deb (network)") from Nvidia website, follow their installation instructions, including `apt-get install cuda` which installs Nvidia graphics driver. + - (Jetson TK1) It is preloaded. + - (Nvidia/Intel dual GPUs) After `apt-get install cuda`, use `sudo prime-select intel` to use Intel GPU for desktop. + - (Other) Follow Nvidia website's instructions. You must install the samples package. +* Install VAAPI (optional, Intel only) + 1. (Ubuntu 14.04 only) `sudo dpkg -i debs/{libva,i965}*deb; sudo apt-get install -f` + 2. (Other) `sudo apt-get install libva-dev libjpeg-dev` + 3. Linux kernels 4.1 to 4.3 have performance regression. Use 4.0 and earlier or 4.4 and later (Though Ubuntu kernel 4.2.0-28.33~14.04.1 has backported the fix). +* Install OpenNI2 (optional) + 1. (Ubuntu 14.04 only) `sudo apt-add-repository ppa:deb-rob/ros-trusty && sudo apt-get update` (You don't need this if you have ROS repos), then `sudo apt-get install libopenni2-dev` + 2. (Other) `sudo apt-get install libopenni2-dev` +* Build (if you have run `cd depends` previously, `cd ..` back to the libfreenect2 root directory first.) + ``` + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/freenect2 + make + make install + ``` + You need to specify `cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2` for CMake based third-party application to find libfreenect2. +* Set up udev rules for device access: `sudo cp ../platform/linux/udev/90-kinect2.rules /etc/udev/rules.d/`, then replug the Kinect. +* Run the test program: `./bin/Protonect` +* Run OpenNI2 test (optional): `sudo apt-get install openni2-utils && sudo make install-openni2 && NiViewer2`. Environment variable `LIBFREENECT2_PIPELINE` can be set to `cl`, `cuda`, etc to specify the pipeline. diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/CheckOpenCLICDLoader.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/CheckOpenCLICDLoader.cmake new file mode 100644 index 0000000..f02b3e6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/CheckOpenCLICDLoader.cmake @@ -0,0 +1,21 @@ +INCLUDE(CheckCXXSourceCompiles) +INCLUDE(CheckCSourceCompiles) + +SET(CMAKE_REQUIRED_INCLUDES "${MY_DIR}/include/internal" ${OpenCL_INCLUDE_DIRS}) +SET(CMAKE_REQUIRED_LIBRARIES ${OpenCL_LIBRARIES}) +CHECK_C_SOURCE_COMPILES(" +#include +int main() { + clGetPlatformIDs(0, 0, 0); + return 0; +}" OpenCL_C_WORKS) +CHECK_CXX_SOURCE_COMPILES(" +#include +int main() { + cl::Context context; + cl::Platform platform; + cl::Device device; + return 0; +}" OpenCL_CXX_WORKS) +SET(CMAKE_REQUIRED_INCLUDES) +SET(CMAKE_REQUIRED_LIBRARIES) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindGLFW3.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindGLFW3.cmake new file mode 100644 index 0000000..cf1ca41 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindGLFW3.cmake @@ -0,0 +1,75 @@ +# - Try to find GLFW3 +# +# If no pkgconfig, define GLFW_ROOT to installation tree +# Will define the following: +# GLFW3_FOUND +# GLFW3_INCLUDE_DIRS +# GLFW3_LIBRARIES + +IF(PKG_CONFIG_FOUND) + IF(APPLE) + # homebrew or macports pkgconfig locations + SET(ENV{PKG_CONFIG_PATH} "/usr/local/opt/glfw3/lib/pkgconfig:/opt/local/lib/pkgconfig") + ENDIF() + SET(ENV{PKG_CONFIG_PATH} "${DEPENDS_DIR}/glfw/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") + PKG_CHECK_MODULES(GLFW3 glfw3) + + FIND_LIBRARY(GLFW3_LIBRARY + NAMES ${GLFW3_LIBRARIES} + HINTS ${GLFW3_LIBRARY_DIRS} + ) + SET(GLFW3_LIBRARIES ${GLFW3_LIBRARY}) + + RETURN() +ENDIF() + +FIND_PATH(GLFW3_INCLUDE_DIRS + GLFW/glfw3.h + DOC "GLFW include directory " + PATHS + "${DEPENDS_DIR}/glfw" + "$ENV{ProgramW6432}/glfw" + ENV GLFW_ROOT + PATH_SUFFIXES + include +) + +# directories in the official binary package +IF(MINGW) + SET(_SUFFIX lib-mingw) +ELSEIF(MSVC11) + SET(_SUFFIX lib-vc2012) +ELSEIF(MSVC12) + SET(_SUFFIX lib-vc2013) +ELSEIF(MSVC14) + SET(_SUFFIX lib-vc2015) +ELSEIF(MSVC) + SET(_SUFFIX lib-vc2012) +ENDIF() + +FIND_LIBRARY(GLFW3_LIBRARIES + NAMES glfw3dll glfw3 + PATHS + "${DEPENDS_DIR}/glfw" + "$ENV{ProgramW6432}/glfw" + ENV GLFW_ROOT + PATH_SUFFIXES + lib + ${_SUFFIX} +) + +IF(WIN32) +FIND_FILE(GLFW3_DLL + glfw3.dll + PATHS + "${DEPENDS_DIR}/glfw" + "$ENV{ProgramW6432}/glfw" + ENV GLFW_ROOT + PATH_SUFFIXES + ${_SUFFIX} +) +ENDIF() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLFW3 FOUND_VAR GLFW3_FOUND + REQUIRED_VARS GLFW3_LIBRARIES GLFW3_INCLUDE_DIRS) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindLibUSB.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindLibUSB.cmake new file mode 100644 index 0000000..1565c83 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindLibUSB.cmake @@ -0,0 +1,80 @@ +# - Find libusb for portable USB support +# +# If the LibUSB_ROOT environment variable +# is defined, it will be used as base path. +# The following standard variables get defined: +# LibUSB_FOUND: true if LibUSB was found +# LibUSB_INCLUDE_DIR: the directory that contains the include file +# LibUSB_LIBRARIES: the libraries + +IF(PKG_CONFIG_FOUND) + IF(DEPENDS_DIR) #Otherwise use System pkg-config path + SET(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${DEPENDS_DIR}/libusb/lib/pkgconfig") + ENDIF() + SET(MODULE "libusb-1.0") + IF(CMAKE_SYSTEM_NAME MATCHES "Linux") + SET(MODULE "libusb-1.0>=1.0.20") + ENDIF() + IF(LibUSB_FIND_REQUIRED) + SET(LibUSB_REQUIRED "REQUIRED") + ENDIF() + PKG_CHECK_MODULES(LibUSB ${LibUSB_REQUIRED} ${MODULE}) + + FIND_LIBRARY(LibUSB_LIBRARY + NAMES ${LibUSB_LIBRARIES} + HINTS ${LibUSB_LIBRARY_DIRS} + ) + SET(LibUSB_LIBRARIES ${LibUSB_LIBRARY}) + + RETURN() +ENDIF() + +FIND_PATH(LibUSB_INCLUDE_DIRS + NAMES libusb.h + PATHS + "${DEPENDS_DIR}/libusb" + "${DEPENDS_DIR}/libusbx" + ENV LibUSB_ROOT + PATH_SUFFIXES + include + libusb + include/libusb-1.0 +) + +SET(LIBUSB_NAME libusb) + +FIND_LIBRARY(LibUSB_LIBRARIES + NAMES ${LIBUSB_NAME}-1.0 + PATHS + "${DEPENDS_DIR}/libusb" + "${DEPENDS_DIR}/libusbx" + ENV LibUSB_ROOT + PATH_SUFFIXES + x64/Release/dll + x64/Debug/dll + Win32/Release/dll + Win32/Debug/dll + MS64 + MS64/dll +) + +IF(WIN32) +FIND_FILE(LibUSB_DLL + ${LIBUSB_NAME}-1.0.dll + PATHS + "${DEPENDS_DIR}/libusb" + "${DEPENDS_DIR}/libusbx" + ENV LibUSB_ROOT + PATH_SUFFIXES + x64/Release/dll + x64/Debug/dll + Win32/Release/dll + Win32/Debug/dll + MS64 + MS64/dll +) +ENDIF() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUSB FOUND_VAR LibUSB_FOUND + REQUIRED_VARS LibUSB_LIBRARIES LibUSB_INCLUDE_DIRS) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenCL.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenCL.cmake new file mode 100644 index 0000000..e0b97f6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenCL.cmake @@ -0,0 +1,155 @@ +#.rst: +# FindOpenCL +# ---------- +# +# Try to find OpenCL +# +# Once done this will define:: +# +# OpenCL_FOUND - True if OpenCL was found +# OpenCL_INCLUDE_DIRS - include directories for OpenCL +# OpenCL_LIBRARIES - link against this library to use OpenCL +# OpenCL_VERSION_STRING - Highest supported OpenCL version (eg. 1.2) +# OpenCL_VERSION_MAJOR - The major version of the OpenCL implementation +# OpenCL_VERSION_MINOR - The minor version of the OpenCL implementation +# +# The module will also define two cache variables:: +# +# OpenCL_INCLUDE_DIR - the OpenCL include directory +# OpenCL_LIBRARY - the path to the OpenCL library +# + +#============================================================================= +# Copyright 2014 Matthaeus G. Chajdas +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +function(_FIND_OPENCL_VERSION) + include(CheckSymbolExists) + include(CMakePushCheckState) + set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY}) + + CMAKE_PUSH_CHECK_STATE() + foreach(VERSION "2_0" "1_2" "1_1" "1_0") + set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}") + + if(APPLE) + CHECK_SYMBOL_EXISTS( + CL_VERSION_${VERSION} + "${OpenCL_INCLUDE_DIR}/OpenCL/cl.h" + OPENCL_VERSION_${VERSION}) + else() + CHECK_SYMBOL_EXISTS( + CL_VERSION_${VERSION} + "${OpenCL_INCLUDE_DIR}/CL/cl.h" + OPENCL_VERSION_${VERSION}) + endif() + + if(OPENCL_VERSION_${VERSION}) + string(REPLACE "_" "." VERSION "${VERSION}") + set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE) + string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}") + list(GET version_components 0 major_version) + list(GET version_components 1 minor_version) + set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE) + set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE) + break() + endif() + endforeach() + CMAKE_POP_CHECK_STATE() +endfunction() + +find_path(OpenCL_INCLUDE_DIR + NAMES + CL/cl.h OpenCL/cl.h + PATHS + ENV "PROGRAMFILES(X86)" + ENV AMDAPPSDKROOT + ENV INTELOCLSDKROOT + ENV NVSDKCOMPUTE_ROOT + ENV CUDA_PATH + ENV ATISTREAMSDKROOT + PATH_SUFFIXES + include + OpenCL/common/inc + "AMD APP/include") + +_FIND_OPENCL_VERSION() + +if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + find_library(OpenCL_LIBRARY + NAMES OpenCL + PATHS + ENV "PROGRAMFILES(X86)" + ENV AMDAPPSDKROOT + ENV INTELOCLSDKROOT + ENV CUDA_PATH + ENV NVSDKCOMPUTE_ROOT + ENV ATISTREAMSDKROOT + PATH_SUFFIXES + "AMD APP/lib/x86" + lib/x86 + lib/Win32 + OpenCL/common/lib/Win32) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + find_library(OpenCL_LIBRARY + NAMES OpenCL + PATHS + ENV "PROGRAMFILES(X86)" + ENV AMDAPPSDKROOT + ENV INTELOCLSDKROOT + ENV CUDA_PATH + ENV NVSDKCOMPUTE_ROOT + ENV ATISTREAMSDKROOT + PATH_SUFFIXES + "AMD APP/lib/x86_64" + lib/x86_64 + lib/x64 + OpenCL/common/lib/x64) + endif() +else() + find_library(OpenCL_LIBRARY + NAMES OpenCL) +endif() + +set(OpenCL_LIBRARIES ${OpenCL_LIBRARY}) +set(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + OpenCL + FOUND_VAR OpenCL_FOUND + REQUIRED_VARS OpenCL_LIBRARY OpenCL_INCLUDE_DIR + VERSION_VAR OpenCL_VERSION_STRING) + +mark_as_advanced( + OpenCL_INCLUDE_DIR + OpenCL_LIBRARY) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenNI2.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenNI2.cmake new file mode 100644 index 0000000..60569c8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindOpenNI2.cmake @@ -0,0 +1,53 @@ +# - Find OpenNI2 +# +# If the OPENNI2_INCLUDE and OPENNI2_REDIST environment variables +# are defined, they will be used as search path. +# The following standard variables get defined: +# OpenNI2_FOUND: true if found +# OpenNI2_INCLUDE_DIRS: the directory that contains the include file +# OpenNI2_LIBRARY_DIR: the directory that contains the library + +IF(PKG_CONFIG_FOUND) + PKG_CHECK_MODULES(OpenNI2 libopenni2) +ENDIF() + +FIND_PATH(OpenNI2_INCLUDE_DIRS + NAMES Driver/OniDriverAPI.h + PATHS + "/opt/include" + "/opt/local/include" + "/usr/include" + "/usr/local/include" + ENV OPENNI2_INCLUDE + ENV PROGRAMFILES + ENV ProgramW6432 + HINTS ${OpenNI2_INCLUDE_DIRS} + PATH_SUFFIXES + ni2 + openni2 + OpenNI2/Include +) + +FIND_LIBRARY(OpenNI2_LIBRARY + NAMES OpenNI2 ${OpenNI2_LIBRARIES} + PATHS + "/opt/lib" + "/opt/local/lib" + "/usr/lib" + "/usr/local/lib" + "/usr/local/lib/ni2" + ENV OPENNI2_REDIST + ENV PROGRAMFILES + ENV ProgramW6432 + HINTS ${OpenNI2_LIBRARY_DIRS} + PATH_SUFFIXES + ni2/OpenNI2/Drivers + OpenNI2/Drivers/lib + OpenNI2/Lib +) + +GET_FILENAME_COMPONENT(OpenNI2_LIBRARY_DIR ${OpenNI2_LIBRARY} DIRECTORY) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenNI2 FOUND_VAR OpenNI2_FOUND + REQUIRED_VARS OpenNI2_LIBRARY_DIR OpenNI2_INCLUDE_DIRS) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTegraJPEG.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTegraJPEG.cmake new file mode 100644 index 0000000..6246527 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTegraJPEG.cmake @@ -0,0 +1,133 @@ +# FindTegraJPEG.cmake +# - TegraJPEG_FOUND +# - TegraJPEG_INCLUDE_DIRS +# - TegraJPEG_LIBRARIES + +# Detect Linux4Tegra distribution +SET(L4T_RELEASE_FILE /etc/nv_tegra_release) +IF(EXISTS ${L4T_RELEASE_FILE}) + SET(TegraJPEG_IS_L4T TRUE) + EXECUTE_PROCESS( + COMMAND sha1sum --quiet -c /etc/nv_tegra_release + RESULT_VARIABLE TegraJPEG_DRIVER_ERROR + OUTPUT_VARIABLE TegraJPEG_DRIVER_OUTPUT + ERROR_QUIET + ) + IF(TegraJPEG_DRIVER_ERROR) + MESSAGE(WARNING "Tegra drivers have wrong checksum:\n${TegraJPEG_DRIVER_OUTPUT}") + ELSE() + SET(TegraJPEG_DRIVER_OK TRUE) + ENDIF() +ENDIF() + +# Detect L4T version +IF(TegraJPEG_IS_L4T) + FILE(READ ${L4T_RELEASE_FILE} L4T_RELEASE_CONTENT LIMIT 64 OFFSET 2) + STRING(REGEX REPLACE "^R([0-9]*)[^,]*, REVISION: ([0-9.]*).*" "\\1" L4T_VER_MAJOR "${L4T_RELEASE_CONTENT}") + STRING(REGEX REPLACE "^R([0-9]*)[^,]*, REVISION: ([0-9.]*).*" "\\2" L4T_VER_MINOR "${L4T_RELEASE_CONTENT}") + SET(L4T_VER "${L4T_VER_MAJOR}.${L4T_VER_MINOR}") + MESSAGE(STATUS "Found Linux4Tegra ${L4T_VER}") + IF(L4T_VER VERSION_LESS 21.3.0) + MESSAGE(WARNING "Linux4Tegra version (${L4T_VER}) less than minimum requirement (21.3)") + ELSE() + SET(TegraJPEG_L4T_OK TRUE) + ENDIF() + + IF(L4T_VER MATCHES ^21.3) + SET(L4T_SRC_PART r21_Release_v3.0/sources/gstjpeg_src.tbz2) + ELSEIF(L4T_VER MATCHES ^21.4) + SET(L4T_SRC_PART r21_Release_v4.0/source/gstjpeg_src.tbz2) + ELSEIF(L4T_VER MATCHES ^21.5) + SET(L4T_SRC_PART r21_Release_v5.0/source/gstjpeg_src.tbz2) + ELSEIF(L4T_VER MATCHES ^23.1) + SET(L4T_SRC_PART r23_Release_v1.0/source/gstjpeg_src.tbz2) + ELSEIF(L4T_VER MATCHES ^23.2) + SET(L4T_SRC_PART r23_Release_v2.0/source/gstjpeg_src.tbz2) + ELSEIF(L4T_VER MATCHES ^24.1) + SET(L4T_SRC_PART r24_Release_v1.0/24.1_64bit/source/gstjpeg_src.tbz2) + ELSEIF(L4T_VER MATCHES ^24.2) + SET(L4T_SRC_PART r24_Release_v2.0/BSP/sources.tbz2) + ELSEIF(L4T_VER MATCHES ^27.1) + SET(L4T_SRC_PART r27_Release_v1.0/BSP/r27.1.0_sources.tbz2) + ELSEIF(L4T_VER MATCHES ^28.1) + SET(L4T_SRC_PART r28_Release_v1.0/BSP/source_release.tbz2) + ELSEIF(L4T_VER MATCHES ^28.2) + SET(L4T_SRC_PART r28_Release_v2.0/BSP/source_release.tbz2) + ELSE() + MESSAGE(WARNING "Linux4Tegra version (${L4T_VER}) is not recognized. Add the new source URL part to FindTegraJPEG.cmake.") + SET(TegraJPEG_L4T_OK FALSE) + ENDIF() +ENDIF() + +# Download gstjpeg source +IF(TegraJPEG_L4T_OK) + SET(L4T_SRC_PATH ${DEPENDS_DIR}/source/${L4T_SRC_PART}) + GET_FILENAME_COMPONENT(L4T_SRC_DIR ${L4T_SRC_PATH} DIRECTORY) + IF(NOT EXISTS ${L4T_SRC_PATH}) + MESSAGE(STATUS "Downloading ${L4T_SRC_PART}...") + SET(L4T_SRC_URL "http://developer.download.nvidia.com/embedded/L4T/${L4T_SRC_PART}") + # Do we want checksum for the download? + FILE(DOWNLOAD ${L4T_SRC_URL} ${L4T_SRC_PATH} STATUS L4T_SRC_STATUS) + LIST(GET L4T_SRC_STATUS 0 L4T_SRC_ERROR) + LIST(GET L4T_SRC_STATUS 1 L4T_SRC_MSG) + IF(L4T_SRC_ERROR) + MESSAGE(WARNING "Failed to download ${L4T_SRC_PART}: ${L4T_SRC_MSG}") + FILE(REMOVE ${L4T_SRC_PATH}) + ENDIF() + ENDIF() + + FILE(GLOB_RECURSE L4T_GSTJPEG_PATH ${L4T_SRC_DIR}/gstjpeg_src.tbz2) + IF(NOT L4T_GSTJPEG_PATH) + MESSAGE(STATUS "Extracting ${L4T_SRC_PART}...") + EXECUTE_PROCESS( + COMMAND ${CMAKE_COMMAND} -E tar xjf ${L4T_SRC_PATH} + WORKING_DIRECTORY ${L4T_SRC_DIR} + ) + FILE(GLOB_RECURSE L4T_GSTJPEG_PATH ${L4T_SRC_DIR}/gstjpeg_src.tbz2) + ENDIF() + + IF(L4T_GSTJPEG_PATH) + EXECUTE_PROCESS( + COMMAND ${CMAKE_COMMAND} -E tar xjf ${L4T_GSTJPEG_PATH} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE L4T_HEADERS_ERROR + ERROR_VARIABLE L4T_HEADERS_MSG + ) + IF(L4T_HEADERS_ERROR) + MESSAGE(WARNING "Failed to unpack ${L4T_GSTJPEG_PATH}: ${L4T_HEADERS_MSG}") + ENDIF() + ENDIF() +ENDIF() + +FIND_PATH(TegraJPEG_INCLUDE_DIRS + nv_headers/jpeglib.h + DOC "Found TegraJPEG include directory" + PATHS ${CMAKE_BINARY_DIR}/gstjpeg_src + NO_DEFAULT_PATH +) + +FIND_LIBRARY(TegraJPEG_LIBRARIES + NAMES nvjpeg + DOC "Found TegraJPEG library (libnvjpeg.so)" + PATH_SUFFIXES tegra +) + +FIND_LIBRARY(TegraJPEG_LIBRARIES + NAMES jpeg + DOC "Found TegraJPEG library (libjpeg.so)" + PATHS /usr/lib/arm-linux-gnueabihf/tegra + NO_DEFAULT_PATH +) + +IF(TegraJPEG_INCLUDE_DIRS AND TegraJPEG_LIBRARIES) + INCLUDE(CheckCSourceCompiles) + set(CMAKE_REQUIRED_INCLUDES ${TegraJPEG_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LIBRARIES ${TegraJPEG_LIBRARIES}) + check_c_source_compiles("#include \n#include \nint main() { struct jpeg_decompress_struct d; jpeg_create_decompress(&d); d.jpegTegraMgr = 0; d.input_frame_buf = 0; return 0; }" TegraJPEG_WORKS) + set(CMAKE_REQUIRED_INCLUDES) + set(CMAKE_REQUIRED_LIBRARIES) +ENDIF() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TegraJPEG FOUND_VAR TegraJPEG_FOUND + REQUIRED_VARS TegraJPEG_LIBRARIES TegraJPEG_INCLUDE_DIRS TegraJPEG_L4T_OK TegraJPEG_DRIVER_OK TegraJPEG_WORKS) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTurboJPEG.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTurboJPEG.cmake new file mode 100644 index 0000000..55f7307 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/FindTurboJPEG.cmake @@ -0,0 +1,67 @@ +# FindTurboJPEG.cmake +# Uses environment variable TurboJPEG_ROOT as backup +# - TurboJPEG_FOUND +# - TurboJPEG_INCLUDE_DIRS +# - TurboJPEG_LIBRARIES + +FIND_PATH(TurboJPEG_INCLUDE_DIRS + turbojpeg.h + DOC "Found TurboJPEG include directory" + PATHS + "${DEPENDS_DIR}/libjpeg_turbo" + "${DEPENDS_DIR}/libjpeg-turbo64" + "/usr/local/opt/jpeg-turbo" # homebrew + "/opt/local" # macports + "C:/libjpeg-turbo64" + "/opt/libjpeg-turbo" + ENV TurboJPEG_ROOT + PATH_SUFFIXES + include +) + +#Library names: +# debian sid,strech: libturbojpeg0 +# debian/ubuntu else: libturbojpeg1-dev #provided by libjpeg-turbo8-dev (ubuntu) +FIND_LIBRARY(TurboJPEG_LIBRARIES + NAMES libturbojpeg.so.1 libturbojpeg.so.0 turbojpeg + DOC "Found TurboJPEG library path" + PATHS + "${DEPENDS_DIR}/libjpeg_turbo" + "${DEPENDS_DIR}/libjpeg-turbo64" + "/usr/local/opt/jpeg-turbo" # homebrew + "/opt/local" # macports + "C:/libjpeg-turbo64" + "/opt/libjpeg-turbo" + ENV TurboJPEG_ROOT + PATH_SUFFIXES + lib + lib64 +) + +IF(WIN32) +FIND_FILE(TurboJPEG_DLL + turbojpeg.dll + DOC "Found TurboJPEG DLL path" + PATHS + "${DEPENDS_DIR}/libjpeg_turbo" + "${DEPENDS_DIR}/libjpeg-turbo64" + "C:/libjpeg-turbo64" + ENV TurboJPEG_ROOT + PATH_SUFFIXES + bin +) +ENDIF() + +IF(TurboJPEG_INCLUDE_DIRS AND TurboJPEG_LIBRARIES) +INCLUDE(CheckCSourceCompiles) +set(CMAKE_REQUIRED_INCLUDES ${TurboJPEG_INCLUDE_DIRS}) +set(CMAKE_REQUIRED_LIBRARIES ${TurboJPEG_LIBRARIES}) +check_c_source_compiles("#include \nint main(void) { tjhandle h=tjInitCompress(); return 0; }" TURBOJPEG_WORKS) +set(CMAKE_REQUIRED_DEFINITIONS) +set(CMAKE_REQUIRED_INCLUDES) +set(CMAKE_REQUIRED_LIBRARIES) +ENDIF() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TurboJPEG FOUND_VAR TurboJPEG_FOUND + REQUIRED_VARS TurboJPEG_LIBRARIES TurboJPEG_INCLUDE_DIRS TURBOJPEG_WORKS) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/GenerateResources.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/GenerateResources.cmake new file mode 100644 index 0000000..8616e38 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/GenerateResources.cmake @@ -0,0 +1,14 @@ +FUNCTION(GENERATE_RESOURCES OUTPUT BASE_FOLDER) + +ADD_EXECUTABLE(generate_resources_tool + tools/generate_resources.cpp +) + +ADD_CUSTOM_COMMAND( + OUTPUT ${OUTPUT} + COMMAND generate_resources_tool ${BASE_FOLDER} ${ARGN} > ${OUTPUT} + WORKING_DIRECTORY ${BASE_FOLDER} + DEPENDS generate_resources_tool ${ARGN} +) + +ENDFUNCTION(GENERATE_RESOURCES) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/SetupLibfreenect2Threading.cmake b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/SetupLibfreenect2Threading.cmake new file mode 100644 index 0000000..d080579 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/cmake_modules/SetupLibfreenect2Threading.cmake @@ -0,0 +1,44 @@ +INCLUDE(CheckCXXSourceCompiles) + +IF(COMPILER_SUPPORTS_CXX0X OR COMPILER_SUPPORTS_CXX11) +CHECK_CXX_SOURCE_COMPILES(" +#include +#include +#include +#include + +int main(int argc, char** argv) { + std::thread thread; + std::mutex mutex; + std::lock_guard lock_guard(mutex); + std::unique_lock unique_lock(mutex); + std::condition_variable condition_variable; + //thread_local int i; // libfreenect is not using this feature, Mac OSX doesn't support it + + return 0; +} + +" LIBFREENECT2_THREADING_STDLIB) +ENDIF() + +IF(LIBFREENECT2_THREADING_STDLIB) + SET(LIBFREENECT2_THREADING "stdlib") + SET(LIBFREENECT2_THREADING_INCLUDE_DIR "") + SET(LIBFREENECT2_THREADING_SOURCE "") + SET(LIBFREENECT2_THREADING_LIBRARIES "") + SET(LIBFREENECT2_THREADING_STDLIB 1) + SET(HAVE_Threading std::thread) +ELSE(LIBFREENECT2_THREADING_STDLIB) + SET(LIBFREENECT2_THREADING "tinythread") + SET(LIBFREENECT2_THREADING_INCLUDE_DIR "src/tinythread/") + SET(LIBFREENECT2_THREADING_SOURCE "src/tinythread/tinythread.cpp") + IF(NOT WIN32) + SET(LIBFREENECT2_THREADING_LIBRARIES "pthread") + ELSE(NOT WIN32) + SET(LIBFREENECT2_THREADING_LIBRARIES "") + ENDIF(NOT WIN32) + SET(LIBFREENECT2_THREADING_TINYTHREAD 1) + SET(HAVE_Threading tinythread) +ENDIF(LIBFREENECT2_THREADING_STDLIB) + +MESSAGE(STATUS "using ${LIBFREENECT2_THREADING} as threading library") diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/INSTALL-windows.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/INSTALL-windows.txt new file mode 100644 index 0000000..3e42375 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/INSTALL-windows.txt @@ -0,0 +1,49 @@ +Source code: https://github.com/OpenKinect/libfreenect2 +API reference: http://openkinect.github.io/libfreenect2 + +This release is x64 only with basic features enabled. If you want better performance or extra features, you will have to build it from source. + +glfw3.dll, turbojpeg.dll, and libusb-1.0.dll are provided for convenience. You can download and upgrade them yourself. + +"lib" and "include" directories contains libraries and headers. Configure your IDE respectively. + +You must have or install respective version of VC++ runtime, if you are using a -vs201x release variant. + +To try out the OpenNI2 example, copy bin\*.dll to C:\Program Files\OpenNI2\Tools\OpenNI2\Drivers, then run C:\Program Files\OpenNI\Tools\NiViewer.exe. + +You must choose one USB driver backend and follow respective instructions: + +a. UsbDk backend: + +1. (Windows 7) You must first install Microsoft Security Advisory 3033929 otherwise your USB keyboards and mice will stop working! +2. Download the latest x64 installer from https://github.com/daynix/UsbDk/releases, install it. +3. If UsbDk somehow does not work, uninstall UsbDk and follow the libusbK instructions. + +UsbDk overrides libusbK and Microsoft SDK. If you want to use the latter two, just uninstall UsbDk. + +b. libusbK backend: + +You don't need the Kinect for Windows v2 SDK to build and install libfreenect2, though it doesn't hurt to have it too. You don't need to uninstall the SDK or the driver before doing this procedure. + +Install the libusbK backend driver for libusb. Please follow the steps exactly: + +1. Download Zadig from http://zadig.akeo.ie/ +2. Run Zadig and in options, check "List All Devices" and uncheck "Ignore Hubs or Composite Parents" +3. Select the "Xbox NUI Sensor (composite parent)" from the drop-down box. (Important: Ignore the "NuiSensor Adaptor" varieties, which are the adapter, NOT the Kinect) The current driver will list usbccgp. USB ID is VID 045E, PID 02C4 or 02D8. +4. Select libusbK (v3.0.7.0 or newer) from the replacement driver list. +5. Click the "Replace Driver" button. Click yes on the warning about replacing a system driver. (This is because it is a composite parent.) +6. Done. + +To uninstall the libusbK driver (and get back the official SDK driver, if installed): + +1. Open Device Manager +2. Under "libusbK USB Devices" tree, right click the "Xbox NUI Sensor (Composite Parent)" device and select uninstall. +3. Important: Check the "Delete the driver software for this device." checkbox, then click OK. + +If you already had the official SDK driver installed and you want to use it: + +1.In Device Manager, in the Action menu, click "Scan for hardware changes." + +This will enumerate the Kinect sensor again and it will pick up the K4W2 SDK driver, and you should be ready to run KinectService.exe again immediately. + +You can go back and forth between the SDK driver and the libusbK driver very quickly and easily with these steps. \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/LICENSES.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/LICENSES.txt new file mode 100644 index 0000000..714507c --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/LICENSES.txt @@ -0,0 +1,287 @@ +freenect2.dll, Protonect.exe, include/*, lib/* +---------------------------------------------- + +The source code and build system can be found at +https://github.com/OpenKinect/libfreenect2 + +Copyright (c) 2014-2015 individual OpenKinect contributors. + +This code is licensed to you under the terms of the Apache License, version +2.0, or, at your option, the terms of the GNU General Public License, +version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, +or the following URLs: +http://www.apache.org/licenses/LICENSE-2.0 +http://www.gnu.org/licenses/gpl-2.0.txt + +If you redistribute this file in source form, modified or unmodified, you +may: + 1) Leave this header intact and distribute it under the same terms, + accompanying it with the APACHE20 and GPL20 files, or + 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + 3) Delete the GPL v2 clause and accompany it with the APACHE20 file +In all cases you must keep the copyright notice intact and include a copy +of the CONTRIB file. + +Binary distributions must follow the binary distribution requirements of +either License. + +This project incorporates the following code under respective licenses: + +* cl.hpp + +Source: https://www.khronos.org/registry/cl/api/2.1/cl.hpp + +Copyright (c) 2008-2015 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +* tinythread.cpp, tinythread.h + +Copyright (c) 2010-2012 Marcus Geelnard + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +* flextGL.cpp, flextGL.h + +Generated from flextGL https://github.com/ginkgo/flextGL + +Copyright (C) 2011 by Thomas Weber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +* openni2/*, freenect2-openni2.dll + +Modified from: https://github.com/OpenKinect/libfreenect/tree/master/OpenNI2-FreenectDriver + +Original copyright & licenses granted https://github.com/openkinect/libfreenect2/pull/302#issuecomment-118514016 + +Copyright (c) 2014 Benn Snyder + +This code is licensed to you under the terms of the Apache License, version +2.0, or, at your option, the terms of the GNU General Public License, +version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, +or the following URLs: +http://www.apache.org/licenses/LICENSE-2.0 +http://www.gnu.org/licenses/gpl-2.0.txt + +If you redistribute this file in source form, modified or unmodified, you +may: + 1) Leave this header intact and distribute it under the same terms, + accompanying it with the APACHE20 and GPL20 files, or + 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + 3) Delete the GPL v2 clause and accompany it with the APACHE20 file +In all cases you must keep the copyright notice intact and include a copy +of the CONTRIB file. + +Binary distributions must follow the binary distribution requirements of +either License. + +turbojpeg.dll +------------- + +Copyright (C) 1991-2010 Thomas G. Lane +Copyright (C) 1991-2011 Guido Vollbeding +Copyright (C) 1999-2006 MIYASAKA Masaru +Copyright (C) 2009-2011 D. R. Commander +Copyright (C) 2009 Pierre Ossman for Cendio AB +Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies) + +This software is based in part on the work of the Independent JPEG Group. + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltmain.sh). Another support script, install-sh, is copyright by X Consortium +but is also freely distributable. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + +TurboJPEG API library: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +- Neither the name of the libjpeg-turbo Project nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +glfw3.dll +--------- + +Redistributed from http://www.glfw.org/ . + +Copyright (C) 2006-2013 Camilla Berglund +Copyright (C) 2002-2006 Marcus Geelnard + +License: zlib/libpng + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +libusb-1.0.dll +-------------- + +Built from source code obtained https://github.com/libusb/libusb +and patched with the "winiso" branch from +https://github.com/JoshBlake/libusbx.git + +The binary can be rebuilt using install_libusb_vs2015.cmd +from https://github.com/OpenKinect/libfreenect2 + +Copyright (C) 2001-2015 libusb authors + +License: LGPL 2.1 + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301 USA. \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/download_debs_trusty.sh b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/download_debs_trusty.sh new file mode 100644 index 0000000..7041a4d --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/download_debs_trusty.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +set -e + +cd `dirname $0` +ARCH=`/usr/bin/dpkg --print-architecture` + +# download standalone packages for 14.04 LTS +if [ "$ARCH" = amd64 -o "$ARCH" = i386 ]; then + REPO=http://archive.ubuntu.com/ubuntu +else + REPO=http://ports.ubuntu.com/ubuntu-ports +fi + +download() { + path=$1 + ver=$2 + mkdir -p debs + shift 2 + for pkg in "$@"; do + wget -nv -N -P debs -nv $REPO/pool/$path/${pkg}_${ver}_${ARCH}.deb + done +} + +download main/libu/libusb-1.0 1.0.20-1 libusb-1.0-0-dev libusb-1.0-0 +download universe/g/glfw3 3.1.2-3 libglfw3-dev libglfw3 +download main/o/ocl-icd 2.2.8-1 ocl-icd-libopencl1 ocl-icd-opencl-dev +if [ "$ARCH" = amd64 -o "$ARCH" = i386 ]; then + download universe/libv/libva 1.7.0-1 libva-dev libva-drm1 libva-egl1 libva-glx1 libva-tpi1 libva-wayland1 libva-x11-1 libva1 vainfo + download main/i/intel-vaapi-driver 1.7.0-1 i965-va-driver +fi diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_glfw.sh b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_glfw.sh new file mode 100644 index 0000000..73f9f40 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_glfw.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -e + +cd `dirname $0` +DEPENDS_DIR=`pwd` + +# glfw +GLFW_SOURCE_DIR=$DEPENDS_DIR/glfw_src +GLFW_INSTALL_DIR=$DEPENDS_DIR/glfw + +rm -rf $GLFW_SOURCE_DIR $GLFW_INSTALL_DIR + +git clone https://github.com/glfw/glfw.git $GLFW_SOURCE_DIR +cd $GLFW_SOURCE_DIR +git checkout 3.0.4 +mkdir build +cd build +cmake -DCMAKE_INSTALL_PREFIX=$GLFW_INSTALL_DIR -DBUILD_SHARED_LIBS=TRUE .. +make && make install + +cd $DEPENDS_DIR diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb.sh b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb.sh new file mode 100644 index 0000000..4e592af --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb.sh @@ -0,0 +1,22 @@ +#!/bin/sh +set -e + +cd `dirname $0` +DEPENDS_DIR=`pwd` + +# libusbx with superspeed patch +LIBUSB_SOURCE_DIR=$DEPENDS_DIR/libusb_src +LIBUSB_INSTALL_DIR=$DEPENDS_DIR/libusb + +rm -rf $LIBUSB_SOURCE_DIR $LIBUSB_INSTALL_DIR + +git clone https://github.com/libusb/libusb.git $LIBUSB_SOURCE_DIR + +cd $LIBUSB_SOURCE_DIR +git checkout v1.0.20 +./bootstrap.sh +./configure --prefix=$LIBUSB_INSTALL_DIR +make && make install + +cd $DEPENDS_DIR + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2013.cmd b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2013.cmd new file mode 100644 index 0000000..452e295 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2013.cmd @@ -0,0 +1,20 @@ +rem This can only be run in a Git Shell or similar environments +rem with access to git.exe and msbuild.exe. + +rmdir /s /q libusb_src libusb + +git clone https://github.com/libusb/libusb.git libusb_src || exit /b +cd libusb_src + +set CONFIG=Release +set YEAR=2013 +set MSBUILD="C:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" + +%MSBUILD% msvc\libusb_dll_%YEAR%.vcxproj /p:Platform=x64 /p:Configuration=%CONFIG% /target:Rebuild || exit /b + +mkdir ..\libusb\include\libusb-1.0 +copy libusb\libusb.h ..\libusb\include\libusb-1.0 +mkdir ..\libusb\MS64\dll +copy x64\%CONFIG%\dll\*.lib ..\libusb\MS64\dll +copy x64\%CONFIG%\dll\*.dll ..\libusb\MS64\dll +copy x64\%CONFIG%\dll\*.pdb ..\libusb\MS64\dll diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2015.cmd b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2015.cmd new file mode 100644 index 0000000..359a5bb --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_libusb_vs2015.cmd @@ -0,0 +1,20 @@ +rem This can only be run in a Git Shell or similar environments +rem with access to git.exe and msbuild.exe. + +rmdir /s /q libusb_src libusb + +git clone https://github.com/libusb/libusb.git libusb_src || exit /b +cd libusb_src + +set CONFIG=Release +set YEAR=2015 +set MSBUILD="C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe" + +%MSBUILD% msvc\libusb_dll_%YEAR%.vcxproj /p:Platform=x64 /p:Configuration=%CONFIG% /target:Rebuild || exit /b + +mkdir ..\libusb\include\libusb-1.0 +copy libusb\libusb.h ..\libusb\include\libusb-1.0 +mkdir ..\libusb\MS64\dll +copy x64\%CONFIG%\dll\*.lib ..\libusb\MS64\dll +copy x64\%CONFIG%\dll\*.dll ..\libusb\MS64\dll +copy x64\%CONFIG%\dll\*.pdb ..\libusb\MS64\dll diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_ubuntu.sh b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_ubuntu.sh new file mode 100644 index 0000000..917a8e8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/install_ubuntu.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +cd `dirname $0` +ARCH=`/usr/bin/dpkg --print-architecture` + +# download standalone packages for 14.04 LTS +if [ "$ARCH" = amd64 -o "$ARCH" = i386 ]; then + REPO=http://archive.ubuntu.com/ubuntu +else + REPO=http://ports.ubuntu.com/ubuntu-ports +fi +wget -N $REPO/pool/universe/g/glfw3/libglfw3_3.0.4-1_${ARCH}.deb +wget -N $REPO/pool/universe/g/glfw3/libglfw3-dev_3.0.4-1_${ARCH}.deb + +cat <<-EOT + + Execute the following commands to install the remaining dependencies (if you have not already done so): + + sudo dpkg -i libglfw3*_3.0.4-1_*.deb + sudo apt-get install build-essential cmake pkg-config libturbojpeg libjpeg-turbo8-dev mesa-common-dev freeglut3-dev libxrandr-dev libxi-dev + sudo apt-get install libturbojpeg0-dev # (Debian) + +EOT + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/make_release_msvc.cmd b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/make_release_msvc.cmd new file mode 100644 index 0000000..8665a59 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/depends/make_release_msvc.cmd @@ -0,0 +1,34 @@ +@echo off +set ver=%1 +set vs_year=%2 +if "%vs_year%"=="2015" ( + set vs_ver=14 +) else ( + if "%vs_year%"=="2013" ( + set vs_ver=12 + ) else ( + echo Unsupported MSVC version. Usage: %~nx0 version vs_year >&2 + exit /b + ) +) +@echo on + +pushd . +call install_libusb_vs%vs_year%.cmd +popd + +rmdir /s /q build +mkdir build +cd build +cmake ..\.. -G "Visual Studio %vs_ver% %vs_year% Win64" -DENABLE_OPENCL=OFF -DENABLE_CUDA=OFF +cmake --build . --config Release --target install + +rmdir /s /q install\lib\cmake +rmdir /s /q install\lib\pkgconfig +copy ..\LICENSES.txt install +copy ..\INSTALL-windows.txt install +copy ..\..\CONTRIB install +cd .. +rmdir /s /q libfreenect2-%ver%-vs%vs_year%-x64 +move build\install libfreenect2-%ver%-vs%vs_year%-x64 +rmdir /s /q build diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/CMakeLists.txt new file mode 100644 index 0000000..dcc1b17 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/CMakeLists.txt @@ -0,0 +1,8 @@ +find_package(Doxygen) +IF(DOXYGEN_FOUND) + CONFIGURE_FILE(Doxyfile.in "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" @ONLY) + add_custom_target( + doc + COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile + ) +ENDIF() diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyextra.css b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyextra.css new file mode 100644 index 0000000..3562be3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyextra.css @@ -0,0 +1,36 @@ +@import url(https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Mono:400); + +body, table, div, p, dl, table.directory, div.toc li, div.toc h3, div.summary, div.ingroups, .tabsearch, .directory .levels, span.mlabel { + font: 400 18px/24px Lato,sans-serif; +} +.title, .icon, .navpath li.navelem a, #projectname, #projectbrief, #projectnumber, #powerTip div, .tabs, .tabs2, .tabs3 { + font-family: Lato,sans-serif; +} + +#projectname { + font-weight: bold; +} + +.icon { + height: 100%; +} +.title { + font-size: 200%; +} + +code { + font: 400 16px/20px Roboto Mono,monospace; +} +pre.fragment, div.line, .params .paramdir { + font-family: Roboto Mono,monospace; +} + +p, li { + max-width: 50em; +} + +div.contents, #titlearea, div.header, div.navpath ul, .tabs, .tabs2, .tabs3 { + padding-left: 5em; + padding-right: 5em; +} + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyfile.in b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyfile.in new file mode 100644 index 0000000..db4327d --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/Doxyfile.in @@ -0,0 +1,174 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = @PROJECT_NAME@ +PROJECT_NUMBER = @PROJECT_APIVER@ +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English + +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = @CMAKE_SOURCE_DIR@ +STRIP_FROM_INC_PATH = @CMAKE_SOURCE_DIR@/include +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 + +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = YES +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = YES +SORT_GROUP_NAMES = YES +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = NO +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = + +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = + +INPUT = @CMAKE_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/mainpage.dox +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = */include/internal/* +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/examples +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = + +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO + +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/Doxyextra.css +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +GENERATE_HTMLHELP = NO +GENERATE_QHP = NO +GENERATE_ECLIPSEHELP = NO +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +SEARCHENGINE = NO + +GENERATE_LATEX = NO +GENERATE_RTF = NO +GENERATE_MAN = NO +GENERATE_XML = NO +GENERATE_DOCBOOK = NO +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = @PROJECT_BINARY_DIR@ +INCLUDE_FILE_PATTERNS = +PREDEFINED = LIBFREENECT2_API +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES + +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl + +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = NO diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/mainpage.dox b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/mainpage.dox new file mode 100644 index 0000000..608dca7 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/doc/mainpage.dox @@ -0,0 +1,221 @@ +/** @mainpage API Reference + +Older versions: [0.1](0.1). + +Introduction +============ + +%libfreenect2 is an open source cross-platform driver for Kinect for Windows v2 +devices. For information on installation and troubleshooting, see the +[GitHub repository](https://github.com/OpenKinect/libfreenect2). + +This documentation is designed for application developers who want to extract +and use depth and color images from Kinect v2 for further processing. +Additional questions and comments not covered by this documentation can be +posted to [GitHub issues](https://github.com/OpenKinect/libfreenect2/issues). + +This documentation may require some understanding on camera calibration and 3-D +geometry. + +Features +======== + +- Color image processing +- IR and depth image processing +- Registration of color and depth images +- Multiple GPU and hardware acceleration implementations for image processing + +### Issues and Future Work + +- Audio. Raw audio is accessible via Linux USB audio. There is no support for + the calibrated directional audio. +- Unstable USB and crashes. Due to differences in driver support, USB problems + can happen a lot. Error handling in %libfreenect2 is not fully verified for + production use. +- Firmware upload. The protocol has been reverse engineered, but use Windows + for this right now. +- Example of multiple Kinects. +- Example utility of dumping image frames. +- API for on-demand processing. +- Verification of systematic errors through accurate calibration. +- Bindings for C, Python, Java, etc. + +Getting Started +=============== + +To read the API documentation, start with the [Modules](modules.html) page +which nicely organizes classes according to their functionalities. + +Example programs can be found in the source distribution under the `examples` +directory. There also includes an example CMake build system for a standalone +application that uses %libfreenect2 binary installation. + +Many internal details are hidden from this public API. For details on Kinect +v2's USB protocols, depth decoding algorithms, calibration algorithms, and how +to implement performance optimizers, you are encouraged to read the source +code. The source code is the updated and authoritative reference for any +functionalities. + +Environment Variables +===================== + +There are a few environment variables providing controls for both end-users and +programmers: + +* `LIBFREENECT2_LOGGER_LEVEL`: The default logging level if not explicitly set + by the code. +* `LIBFREENECT2_PIPELINE`: The default pipeline if not explicitly set by the + code. +* `LIBFREENECT2_RGB_TRANSFER_SIZE`, `LIBFREENECT2_RGB_TRANSFERS`, + `LIBFREENECT2_IR_PACKETS`, `LIBFREENECT2_IR_TRANSFERS`: Tuning the USB buffer + sizes. Use only if you know what you are doing. + +You can also see the following walkthrough for the most basic usage. + +Walkthrough +=========== + +Here is an example to walk you through the API. See `examples/Protonect.cpp` +for the full source. + +Headers +------- + +First, include necessary headers. `registration.h` and `logger.h` are optional +if you don't use them. + +@snippet Protonect.cpp headers + +Logging +------- + +This shows how to set up the logger and logging level. + +@snippet Protonect.cpp logging + +Though @copydetails libfreenect2::createConsoleLoggerWithDefaultLevel + +You can implement a custom [Logger](@ref libfreenect2::Logger) and redirect +%libfreenect2's log messages to desired places. + +Here is an example to save log messages to a file. + +@snippet Protonect.cpp logger + +And use it + +@snippet Protonect.cpp file logging + +%libfreenect2 uses a single global logger regardless of number of contexts and +devices. You may have to implement thread safety measure in +[log()](@ref libfreenect2::Logger::log), which is called from multiple threads. +Console loggers are thread safe because `std::cout` and `std::cerr` are thread +safe. + +Initialize and Discover Devices +------------------------------- + +You need these structures for all operations. Here it uses only one device. + +@snippet Protonect.cpp context + +You must enumerate all Kinect v2 devices before doing anything else related to +devices. + +@snippet Protonect.cpp discovery + +Also, you can create a specific [PacketPipeline](@ref libfreenect2::PacketPipeline) +instead using the default one for opening the device. Alternatives include +[OpenGLPacketPipeline](@ref libfreenect2::OpenGLPacketPipeline), +[OpenCLPacketPipeline](@ref libfreenect2::OpenCLPacketPipeline), etc. + +@snippet Protonect.cpp pipeline + +Open and Configure the Device +----------------------------- + +Now you can open the device by its serial number, and using the specific +pipeline. + +@snippet Protonect.cpp open + +You can also open the device without providing a pipeline, then a default is +used. There are a few alternative ways to [openDevice()](@ref libfreenect2::Freenect2::openDevice). + +After opening, you need to attach [Framelisteners](@ref libfreenect2::FrameListener) +to the device to receive images frames. + +This [SyncMultiFrameListener](@ref libfreenect2::SyncMultiFrameListener) will +wait until all specified types of frames are received once. Like loggers, you +may also implement your own frame listeners using the same interface. + +@snippet Protonect.cpp listeners + +You cannot configure the device after starting it. + +Start the Device +---------------- + +After finishing configuring the device, you can start the device. You must +start the device before querying any information of the device. + +@snippet Protonect.cpp start + +You can [setIrCameraParams()](@ref libfreenect2::Freenect2Device::setIrCameraParams) +after start if you have your own depth calibration parameters. + +Otherwise you can also use the factory preset parameters for +[Registration](@ref libfreenect2::Registration). You can also provide your own +depth calibration parameterss (though not color camera calibration parameters +right now). Registration is optional. + +@snippet Protonect.cpp registration setup + +At this time, the processing has begun, and the data flows through the pipeline +towards your frame listeners. + +Receive Image Frames +-------------------- + +This example uses a loop to receive image frames. + +@snippet Protonect.cpp loop start + +[waitForNewFrame()](@ref libfreenect2::SyncMultiFrameListener::waitForNewFrame) +here will block until required frames are all received, and then you can +extract `Frame` according to the type. + +See libfreenect2::Frame for details about pixel format, dimensions, and +metadata. + +You can do your own things using the frame data. You can feed it to OpenCV, +PCL, etc. Here, you can perform registration: + +@snippet Protonect.cpp registration + +After you are done with this frame, you must release it. + +@snippet Protonect.cpp loop end + +Stop the Device +--------------- + +If you are finished and no longer need to receive more frames, you can stop +the device and exit. + +@snippet Protonect.cpp stop + +Pause the Device +---------------- + +You can also temporarily pause the device with +[stop()](@ref libfreenect2::Freenect2Device::stop) and +[start()](@ref libfreenect2::Freenect2Device::start). + +@snippet Protonect.cpp pause + +Doing this during `waitForNewFrame()` should be thread safe, and tests also +show well. But a guarantee of thread safety has not been checked yet. + +THE END. +*/ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/CMakeLists.txt new file mode 100644 index 0000000..8741f67 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/CMakeLists.txt @@ -0,0 +1,93 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.1) + +if(WIN32 AND NOT MINGW) + if(NOT DEFINED CMAKE_DEBUG_POSTFIX) + set(CMAKE_DEBUG_POSTFIX "d") + endif() +endif() + +IF(NOT DEFINED CMAKE_BUILD_TYPE) + # No effect for multi-configuration generators (e.g. for Visual Studio) + SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose: RelWithDebInfo Release Debug MinSizeRel None") +ENDIF() + +PROJECT(libfreenect2_examples) + +SET(MY_DIR ${libfreenect2_examples_SOURCE_DIR}) +SET(DEPENDS_DIR "${MY_DIR}/../depends" CACHE STRING "Dependency directory") + +OPTION(ENABLE_OPENGL "Enable OpenGL support" ON) + +# The example build system is standalone and will work out-of-tree with these files copied +SET(freenect2_ROOT_DIR ${MY_DIR}/..) +SET(flextGL_SOURCES ${freenect2_ROOT_DIR}/src/flextGL.cpp) +SET(flextGL_INCLUDE_DIRS ${freenect2_ROOT_DIR}/src) # for flextGL.h + +FIND_PACKAGE(PkgConfig) # try find PKGConfig as it will be used if found +LIST(APPEND CMAKE_MODULE_PATH ${freenect2_ROOT_DIR}/cmake_modules) # FindGLFW3.cmake + +IF(TARGET freenect2) + MESSAGE(STATUS "Using in-tree freenect2 target") + SET(freenect2_LIBRARIES freenect2) + SET(freenect2_DLLS ${LIBFREENECT2_DLLS}) +ELSE() + FIND_PACKAGE(freenect2 REQUIRED) + # Out-of-tree build will have to have DLLs manually copied. +ENDIF() + +INCLUDE_DIRECTORIES( + ${freenect2_INCLUDE_DIR} +) + +SET(Protonect_src + Protonect.cpp +) + +SET(Protonect_LIBRARIES + ${freenect2_LIBRARIES} +) + +SET(Protonect_DLLS + ${freenect2_DLLS} +) + +IF(ENABLE_OPENGL) + FIND_PACKAGE(GLFW3) + FIND_PACKAGE(OpenGL) + IF(GLFW3_FOUND AND OPENGL_FOUND) + INCLUDE_DIRECTORIES( + ${GLFW3_INCLUDE_DIRS} + ${flextGL_INCLUDE_DIRS} + ) + + LIST(APPEND Protonect_DLLS ${GLFW3_DLL}) + LIST(APPEND Protonect_src + viewer.cpp + ${flextGL_SOURCES} + ) + LIST(APPEND Protonect_LIBRARIES + ${GLFW3_LIBRARIES} + ${OPENGL_gl_LIBRARY} + ) + ADD_DEFINITIONS(-DEXAMPLES_WITH_OPENGL_SUPPORT=1) + ENDIF() +ENDIF(ENABLE_OPENGL) + +ADD_EXECUTABLE(Protonect + ${Protonect_src} +) + +TARGET_LINK_LIBRARIES(Protonect + ${Protonect_LIBRARIES} +) + +IF(WIN32) + INSTALL(TARGETS Protonect DESTINATION bin) + LIST(REMOVE_DUPLICATES Protonect_DLLS) + FOREACH(FILEI ${Protonect_DLLS}) + ADD_CUSTOM_COMMAND(TARGET Protonect POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILEI} $ + ) + ENDFOREACH(FILEI) + INSTALL(FILES ${Protonect_DLLS} DESTINATION bin) +ENDIF() diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/Protonect.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/Protonect.cpp new file mode 100644 index 0000000..2fbf4a6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/Protonect.cpp @@ -0,0 +1,411 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file Protonect.cpp Main application file. */ + +#include +#include +#include + +/// [headers] +#include +#include +#include +#include +#include +/// [headers] +#ifdef EXAMPLES_WITH_OPENGL_SUPPORT +#include "viewer.h" +#endif + + +bool protonect_shutdown = false; ///< Whether the running application should shut down. + +void sigint_handler(int s) +{ + protonect_shutdown = true; +} + +bool protonect_paused = false; +libfreenect2::Freenect2Device *devtopause; + +//Doing non-trivial things in signal handler is bad. If you want to pause, +//do it in another thread. +//Though libusb operations are generally thread safe, I cannot guarantee +//everything above is thread safe when calling start()/stop() while +//waitForNewFrame(). +void sigusr1_handler(int s) +{ + if (devtopause == 0) + return; +/// [pause] + if (protonect_paused) + devtopause->start(); + else + devtopause->stop(); + protonect_paused = !protonect_paused; +/// [pause] +} + +//The following demostrates how to create a custom logger +/// [logger] +#include +#include +class MyFileLogger: public libfreenect2::Logger +{ +private: + std::ofstream logfile_; +public: + MyFileLogger(const char *filename) + { + if (filename) + logfile_.open(filename); + level_ = Debug; + } + bool good() + { + return logfile_.is_open() && logfile_.good(); + } + virtual void log(Level level, const std::string &message) + { + logfile_ << "[" << libfreenect2::Logger::level2str(level) << "] " << message << std::endl; + } +}; +/// [logger] + +/// [main] +/** + * Main application entry point. + * + * Accepted argumemnts: + * - cpu Perform depth processing with the CPU. + * - gl Perform depth processing with OpenGL. + * - cl Perform depth processing with OpenCL. + * - Serial number of the device to open. + * - -noviewer Disable viewer window. + */ +int main(int argc, char *argv[]) +/// [main] +{ + std::string program_path(argv[0]); + std::cerr << "Version: " << LIBFREENECT2_VERSION << std::endl; + std::cerr << "Environment variables: LOGFILE=" << std::endl; + std::cerr << "Usage: " << program_path << " [-gpu=] [gl | cl | clkde | cuda | cudakde | cpu] []" << std::endl; + std::cerr << " [-noviewer] [-norgb | -nodepth] [-help] [-version]" << std::endl; + std::cerr << " [-frames ]" << std::endl; + std::cerr << "To pause and unpause: pkill -USR1 Protonect" << std::endl; + size_t executable_name_idx = program_path.rfind("Protonect"); + + std::string binpath = "/"; + + if(executable_name_idx != std::string::npos) + { + binpath = program_path.substr(0, executable_name_idx); + } + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + // avoid flooing the very slow Windows console with debug messages + libfreenect2::setGlobalLogger(libfreenect2::createConsoleLogger(libfreenect2::Logger::Info)); +#else + // create a console logger with debug level (default is console logger with info level) +/// [logging] + libfreenect2::setGlobalLogger(libfreenect2::createConsoleLogger(libfreenect2::Logger::Debug)); +/// [logging] +#endif +/// [file logging] + MyFileLogger *filelogger = new MyFileLogger(getenv("LOGFILE")); + if (filelogger->good()) + libfreenect2::setGlobalLogger(filelogger); + else + delete filelogger; +/// [file logging] + +/// [context] + libfreenect2::Freenect2 freenect2; + libfreenect2::Freenect2Device *dev = 0; + libfreenect2::PacketPipeline *pipeline = 0; +/// [context] + + std::string serial = ""; + + bool viewer_enabled = true; + bool enable_rgb = true; + bool enable_depth = true; + int deviceId = -1; + size_t framemax = -1; + + for(int argI = 1; argI < argc; ++argI) + { + const std::string arg(argv[argI]); + + if(arg == "-help" || arg == "--help" || arg == "-h" || arg == "-v" || arg == "--version" || arg == "-version") + { + // Just let the initial lines display at the beginning of main + return 0; + } + else if(arg.find("-gpu=") == 0) + { + if (pipeline) + { + std::cerr << "-gpu must be specified before pipeline argument" << std::endl; + return -1; + } + deviceId = atoi(argv[argI] + 5); + } + else if(arg == "cpu") + { + if(!pipeline) +/// [pipeline] + pipeline = new libfreenect2::CpuPacketPipeline(); +/// [pipeline] + } + else if(arg == "gl") + { +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::OpenGLPacketPipeline(); +#else + std::cout << "OpenGL pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "cl") + { +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::OpenCLPacketPipeline(deviceId); +#else + std::cout << "OpenCL pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "clkde") + { +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::OpenCLKdePacketPipeline(deviceId); +#else + std::cout << "OpenCL pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "cuda") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::CudaPacketPipeline(deviceId); +#else + std::cout << "CUDA pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "cudakde") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::CudaKdePacketPipeline(deviceId); +#else + std::cout << "CUDA pipeline is not supported!" << std::endl; +#endif + } + else if(arg.find_first_not_of("0123456789") == std::string::npos) //check if parameter could be a serial number + { + serial = arg; + } + else if(arg == "-noviewer" || arg == "--noviewer") + { + viewer_enabled = false; + } + else if(arg == "-norgb" || arg == "--norgb") + { + enable_rgb = false; + } + else if(arg == "-nodepth" || arg == "--nodepth") + { + enable_depth = false; + } + else if(arg == "-frames") + { + ++argI; + framemax = strtol(argv[argI], NULL, 0); + if (framemax == 0) { + std::cerr << "invalid frame count '" << argv[argI] << "'" << std::endl; + return -1; + } + } + else + { + std::cout << "Unknown argument: " << arg << std::endl; + } + } + + if (!enable_rgb && !enable_depth) + { + std::cerr << "Disabling both streams is not allowed!" << std::endl; + return -1; + } + +/// [discovery] + if(freenect2.enumerateDevices() == 0) + { + std::cout << "no device connected!" << std::endl; + return -1; + } + + if (serial == "") + { + serial = freenect2.getDefaultDeviceSerialNumber(); + } +/// [discovery] + + if(pipeline) + { +/// [open] + dev = freenect2.openDevice(serial, pipeline); +/// [open] + } + else + { + dev = freenect2.openDevice(serial); + } + + if(dev == 0) + { + std::cout << "failure opening device!" << std::endl; + return -1; + } + + devtopause = dev; + + signal(SIGINT,sigint_handler); +#ifdef SIGUSR1 + signal(SIGUSR1, sigusr1_handler); +#endif + protonect_shutdown = false; + +/// [listeners] + int types = 0; + if (enable_rgb) + types |= libfreenect2::Frame::Color; + if (enable_depth) + types |= libfreenect2::Frame::Ir | libfreenect2::Frame::Depth; + libfreenect2::SyncMultiFrameListener listener(types); + libfreenect2::FrameMap frames; + + dev->setColorFrameListener(&listener); + dev->setIrAndDepthFrameListener(&listener); +/// [listeners] + +/// [start] + if (enable_rgb && enable_depth) + { + if (!dev->start()) + return -1; + } + else + { + if (!dev->startStreams(enable_rgb, enable_depth)) + return -1; + } + + std::cout << "device serial: " << dev->getSerialNumber() << std::endl; + std::cout << "device firmware: " << dev->getFirmwareVersion() << std::endl; +/// [start] + +/// [registration setup] + libfreenect2::Registration* registration = new libfreenect2::Registration(dev->getIrCameraParams(), dev->getColorCameraParams()); + libfreenect2::Frame undistorted(512, 424, 4), registered(512, 424, 4); +/// [registration setup] + + size_t framecount = 0; +#ifdef EXAMPLES_WITH_OPENGL_SUPPORT + Viewer viewer; + if (viewer_enabled) + viewer.initialize(); +#else + viewer_enabled = false; +#endif + +/// [loop start] + while(!protonect_shutdown && (framemax == (size_t)-1 || framecount < framemax)) + { + if (!listener.waitForNewFrame(frames, 10*1000)) // 10 sconds + { + std::cout << "timeout!" << std::endl; + return -1; + } + libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color]; + libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir]; + libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth]; +/// [loop start] + + if (enable_rgb && enable_depth) + { +/// [registration] + registration->apply(rgb, depth, &undistorted, ®istered); +/// [registration] + } + + framecount++; + if (!viewer_enabled) + { + if (framecount % 100 == 0) + std::cout << "The viewer is turned off. Received " << framecount << " frames. Ctrl-C to stop." << std::endl; + listener.release(frames); + continue; + } + +#ifdef EXAMPLES_WITH_OPENGL_SUPPORT + if (enable_rgb) + { + viewer.addFrame("RGB", rgb); + } + if (enable_depth) + { + viewer.addFrame("ir", ir); + viewer.addFrame("depth", depth); + } + if (enable_rgb && enable_depth) + { + viewer.addFrame("registered", ®istered); + } + + protonect_shutdown = protonect_shutdown || viewer.render(); +#endif + +/// [loop end] + listener.release(frames); + /** libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(100)); */ + } +/// [loop end] + + // TODO: restarting ir stream doesn't work! + // TODO: bad things will happen, if frame listeners are freed before dev->stop() :( +/// [stop] + dev->stop(); + dev->close(); +/// [stop] + + delete registration; + + return 0; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.cpp new file mode 100644 index 0000000..c597256 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.cpp @@ -0,0 +1,244 @@ +#include "viewer.h" +#include + + +Viewer::Viewer() : shader_folder("src/shader/"), + win_width(600), + win_height(400) +{ +} + +static void glfwErrorCallback(int error, const char* description) +{ + std::cerr << "GLFW error " << error << " " << description << std::endl; +} + +void Viewer::initialize() +{ + // init glfw - if already initialized nothing happens + glfwInit(); + + GLFWerrorfun prev_func = glfwSetErrorCallback(glfwErrorCallback); + if (prev_func) + glfwSetErrorCallback(prev_func); + + // setup context + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +#ifdef __APPLE__ + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#else + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); +#endif + //glfwWindowHint(GLFW_VISIBLE, debug ? GL_TRUE : GL_FALSE); + + window = glfwCreateWindow(win_width*2, win_height*2, "Viewer (press ESC to exit)", 0, NULL); + if (window == NULL) + { + std::cerr << "Failed to create opengl window." << std::endl; + exit(-1); + } + + glfwMakeContextCurrent(window); + OpenGLBindings *b = new OpenGLBindings(); + flextInit(b); + gl(b); + + std::string vertexshadersrc = "" + "#version 330\n" + + "in vec2 Position;" + "in vec2 TexCoord;" + + "out VertexData{" + "vec2 TexCoord;" + "} VertexOut;" + + "void main(void)" + "{" + " gl_Position = vec4(Position, 0.0, 1.0);" + " VertexOut.TexCoord = TexCoord;" + "}"; + std::string grayfragmentshader = "" + "#version 330\n" + + "uniform sampler2DRect Data;" + + "vec4 tempColor;" + "in VertexData{" + " vec2 TexCoord;" + "} FragmentIn;" + + "layout(location = 0) out vec4 Color;" + + "void main(void)" + "{" + "ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y);" + "tempColor = texelFetch(Data, uv);" + "Color = vec4(tempColor.x/4500, tempColor.x/4500, tempColor.x/4500, 1);" + "}"; + std::string fragmentshader = "" + "#version 330\n" + + "uniform sampler2DRect Data;" + + "in VertexData{" + " vec2 TexCoord;" + "} FragmentIn;" + + "layout(location = 0) out vec4 Color;" + + "void main(void)" + "{" + " ivec2 uv = ivec2(FragmentIn.TexCoord.x, FragmentIn.TexCoord.y);" + + " Color = texelFetch(Data, uv);" + "}"; + + renderShader.setVertexShader(vertexshadersrc); + renderShader.setFragmentShader(fragmentshader); + renderShader.build(); + + renderGrayShader.setVertexShader(vertexshadersrc); + renderGrayShader.setFragmentShader(grayfragmentshader); + renderGrayShader.build(); + + + glfwSetWindowUserPointer(window, this); + glfwSetKeyCallback(window, Viewer::key_callbackstatic); + glfwSetWindowSizeCallback(window, Viewer::winsize_callbackstatic); + + shouldStop = false; +} + +void Viewer::winsize_callbackstatic(GLFWwindow* window, int w, int h) +{ + Viewer* viewer = reinterpret_cast(glfwGetWindowUserPointer(window)); + viewer->winsize_callback(window, w, h); +} + +void Viewer::winsize_callback(GLFWwindow* window, int w, int h) +{ + win_width = w/2; + win_height = h/2; +} + +void Viewer::key_callbackstatic(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + Viewer* viewer = reinterpret_cast(glfwGetWindowUserPointer(window)); + viewer->key_callback(window, key, scancode, action, mods); +} + +void Viewer::key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + shouldStop = true; +} + +void Viewer::onOpenGLBindingsChanged(OpenGLBindings *b) +{ + renderShader.gl(b); + renderGrayShader.gl(b); + rgb.gl(b); + ir.gl(b); +} + +bool Viewer::render() +{ + // wipe the drawing surface clear + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + GLint x = 0, y = 0; + int fb_width, fb_width_half, fb_height, fb_height_half; + + std::map::iterator iter; + + for (iter = frames.begin(); iter != frames.end(); ++iter) + { + libfreenect2::Frame* frame = iter->second; + + // Using the frame buffer size to account for screens where window.size != framebuffer.size, e.g. retina displays + glfwGetFramebufferSize(window, &fb_width, &fb_height); + fb_width_half = (fb_width + 1) / 2; + fb_height_half = (fb_height + 1) / 2; + + glViewport(x, y, fb_width_half, fb_height_half); + x += fb_width_half; + if (x >= (fb_width - 1)) + { + x = 0; + y += fb_height_half; + } + + float w = static_cast(frame->width); + float h = static_cast(frame->height); + + Vertex bl = { -1.0f, -1.0f, 0.0f, 0.0f }; + Vertex br = { 1.0f, -1.0f, w, 0.0f }; + Vertex tl = { -1.0f, 1.0f, 0.0f, h }; + Vertex tr = { 1.0f, 1.0f, w, h }; + Vertex vertices[] = { + bl, tl, tr, + tr, br, bl + }; + + gl()->glGenBuffers(1, &triangle_vbo); + gl()->glGenVertexArrays(1, &triangle_vao); + + gl()->glBindVertexArray(triangle_vao); + gl()->glBindBuffer(GL_ARRAY_BUFFER, triangle_vbo); + gl()->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + GLint position_attr = renderShader.getAttributeLocation("Position"); + gl()->glVertexAttribPointer(position_attr, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); + gl()->glEnableVertexAttribArray(position_attr); + + GLint texcoord_attr = renderShader.getAttributeLocation("TexCoord"); + gl()->glVertexAttribPointer(texcoord_attr, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(2 * sizeof(float))); + gl()->glEnableVertexAttribArray(texcoord_attr); + + + if (iter->first == "RGB" || iter->first == "registered") + { + renderShader.use(); + + rgb.allocate(frame->width, frame->height); + std::copy(frame->data, frame->data + frame->width * frame->height * frame->bytes_per_pixel, rgb.data); + rgb.flipY(); + rgb.upload(); + glDrawArrays(GL_TRIANGLES, 0, 6); + + rgb.deallocate(); + + } + else + { + renderGrayShader.use(); + + ir.allocate(frame->width, frame->height); + std::copy(frame->data, frame->data + frame->width * frame->height * frame->bytes_per_pixel, ir.data); + ir.flipY(); + ir.upload(); + glDrawArrays(GL_TRIANGLES, 0, 6); + ir.deallocate(); + } + + gl()->glDeleteBuffers(1, &triangle_vbo); + gl()->glDeleteVertexArrays(1, &triangle_vao); + } + + // put the stuff we've been drawing onto the display + glfwSwapBuffers(window); + // update other events like input handling + glfwPollEvents(); + + return shouldStop || glfwWindowShouldClose(window); +} + +void Viewer::addFrame(std::string id, libfreenect2::Frame* frame) +{ + frames[id] = frame; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.h new file mode 100644 index 0000000..970352a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/examples/viewer.h @@ -0,0 +1,288 @@ +#ifndef VIEWER_H +#define VIEWER_H + +#include +#include +#include +#include +#include + +#include "flextGL.h" +#include + +struct Vertex +{ + float x, y; + float u, v; +}; + +class WithOpenGLBindings +{ +private: + OpenGLBindings *bindings; +protected: + WithOpenGLBindings() : bindings(0) {} + virtual ~WithOpenGLBindings() {} + + virtual void onOpenGLBindingsChanged(OpenGLBindings *b) { } +public: + void gl(OpenGLBindings *bindings) + { + this->bindings = bindings; + onOpenGLBindingsChanged(this->bindings); + } + + OpenGLBindings *gl() + { + return bindings; + } +}; + +template +struct ImageFormat +{ + static const size_t BytesPerPixel = TBytesPerPixel; + static const GLenum InternalFormat = TInternalFormat; + static const GLenum Format = TFormat; + static const GLenum Type = TType; +}; + +typedef ImageFormat<1, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE> U8C1; +typedef ImageFormat<2, GL_R16I, GL_RED_INTEGER, GL_SHORT> S16C1; +typedef ImageFormat<2, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT> U16C1; +typedef ImageFormat<4, GL_R32F, GL_RED, GL_FLOAT> F32C1; +typedef ImageFormat<8, GL_RG32F, GL_RG, GL_FLOAT> F32C2; +typedef ImageFormat<12, GL_RGB32F, GL_RGB, GL_FLOAT> F32C3; +typedef ImageFormat<4, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE> F8C4; +typedef ImageFormat<16, GL_RGBA32F, GL_RGBA, GL_FLOAT> F32C4; + +template +struct Texture : public WithOpenGLBindings +{ +protected: + size_t bytes_per_pixel, height, width; + +public: + GLuint texture; + unsigned char *data; + size_t size; + + Texture() : bytes_per_pixel(FormatT::BytesPerPixel), height(0), width(0), texture(0), data(0), size(0) + { + } + + void bindToUnit(GLenum unit) + { + gl()->glActiveTexture(unit); + glBindTexture(GL_TEXTURE_RECTANGLE, texture); + } + + void allocate(size_t new_width, size_t new_height) + { + width = new_width; + height = new_height; + size = height * width * bytes_per_pixel; + data = new unsigned char[size]; + + glGenTextures(1, &texture); + bindToUnit(GL_TEXTURE0); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, FormatT::InternalFormat, width, height, 0, FormatT::Format, FormatT::Type, 0); + } + + void deallocate() + { + glDeleteTextures(1, &texture); + delete[] data; + } + + void upload() + { + bindToUnit(GL_TEXTURE0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_RECTANGLE, /*level*/0, /*xoffset*/0, /*yoffset*/0, width, height, FormatT::Format, FormatT::Type, data); + } + + void download() + { + downloadToBuffer(data); + } + + void downloadToBuffer(unsigned char *data) + { + glReadPixels(0, 0, width, height, FormatT::Format, FormatT::Type, data); + } + + void flipY() + { + flipYBuffer(data); + } + + void flipYBuffer(unsigned char *data) + { + typedef unsigned char type; + + size_t linestep = width * bytes_per_pixel / sizeof(type); + + type *first_line = reinterpret_cast(data), *last_line = reinterpret_cast(data) + (height - 1) * linestep; + + for (size_t y = 0; y < height / 2; ++y) + { + for (size_t x = 0; x < linestep; ++x, ++first_line, ++last_line) + { + std::swap(*first_line, *last_line); + } + last_line -= 2 * linestep; + } + } + + libfreenect2::Frame *downloadToNewFrame() + { + libfreenect2::Frame *f = new libfreenect2::Frame(width, height, bytes_per_pixel); + downloadToBuffer(f->data); + flipYBuffer(f->data); + + return f; + } +}; + +struct ShaderProgram : public WithOpenGLBindings +{ + GLuint program, vertex_shader, fragment_shader; + + char error_buffer[2048]; + + ShaderProgram() : + program(0), + vertex_shader(0), + fragment_shader(0) + { + } + + void setVertexShader(const std::string& src) + { + const char* src_ = src.c_str(); + int length_ = src.length(); + vertex_shader = gl()->glCreateShader(GL_VERTEX_SHADER); + gl()->glShaderSource(vertex_shader, 1, &src_, &length_); + } + + void setFragmentShader(const std::string& src) + { + const char* src_ = src.c_str(); + int length_ = src.length(); + fragment_shader = gl()->glCreateShader(GL_FRAGMENT_SHADER); + gl()->glShaderSource(fragment_shader, 1, &src_, &length_); + } + + void build() + { + GLint status; + + gl()->glCompileShader(vertex_shader); + gl()->glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status); + + if (status != GL_TRUE) + { + gl()->glGetShaderInfoLog(vertex_shader, sizeof(error_buffer), NULL, error_buffer); + + std::cerr << "failed to compile vertex shader!" << std::endl << error_buffer << std::endl; + } + + gl()->glCompileShader(fragment_shader); + + gl()->glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) + { + gl()->glGetShaderInfoLog(fragment_shader, sizeof(error_buffer), NULL, error_buffer); + + std::cerr << "failed to compile fragment shader!" << std::endl << error_buffer << std::endl; + } + + program = gl()->glCreateProgram(); + gl()->glAttachShader(program, vertex_shader); + gl()->glAttachShader(program, fragment_shader); + + gl()->glLinkProgram(program); + + gl()->glGetProgramiv(program, GL_LINK_STATUS, &status); + + if (status != GL_TRUE) + { + gl()->glGetProgramInfoLog(program, sizeof(error_buffer), NULL, error_buffer); + std::cerr << "failed to link shader program!" << std::endl << error_buffer << std::endl; + } + } + + GLint getAttributeLocation(const std::string& name) + { + return gl()->glGetAttribLocation(program, name.c_str()); + } + + void setUniform(const std::string& name, GLint value) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if (idx == -1) return; + + gl()->glUniform1i(idx, value); + } + + void setUniform(const std::string& name, GLfloat value) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if (idx == -1) return; + + gl()->glUniform1f(idx, value); + } + + void setUniformVector3(const std::string& name, GLfloat value[3]) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if (idx == -1) return; + + gl()->glUniform3fv(idx, 1, value); + } + + void setUniformMatrix3(const std::string& name, GLfloat value[9]) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if (idx == -1) return; + + gl()->glUniformMatrix3fv(idx, 1, false, value); + } + + void use() + { + gl()->glUseProgram(program); + } +}; + +class Viewer : WithOpenGLBindings { +private: + bool shouldStop; + GLFWwindow* window; + GLuint triangle_vbo, triangle_vao; + ShaderProgram renderShader; + ShaderProgram renderGrayShader; + std::string shader_folder; + std::map frames; + Texture rgb; + Texture ir; + int win_width; + int win_height; +public: + Viewer(); + void initialize(); + virtual void onOpenGLBindingsChanged(OpenGLBindings *b); + bool render(); + void addFrame(std::string id,libfreenect2::Frame* frame); + void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); + void winsize_callback(GLFWwindow* window, int w, int h); + static void key_callbackstatic(GLFWwindow* window, int key, int scancode, int action, int mods); + static void winsize_callbackstatic(GLFWwindow* window, int w, int h); +}; + +#endif diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.cmake.in b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.cmake.in new file mode 100644 index 0000000..05df1af --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.cmake.in @@ -0,0 +1,10 @@ +FIND_LIBRARY(freenect2_LIBRARY freenect2 + PATHS @CMAKE_INSTALL_PREFIX@/lib + NO_DEFAULT_PATH +) +SET(freenect2_LIBRARIES ${freenect2_LIBRARY} @LIBFREENECT2_THREADING_LIBRARIES@) +FIND_PATH(freenect2_INCLUDE_DIR @PROJECT_NAME@/libfreenect2.hpp + PATHS @CMAKE_INSTALL_PREFIX@/include + NO_DEFAULT_PATH +) +SET(freenect2_INCLUDE_DIRS ${freenect2_INCLUDE_DIR}) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.pc.in b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.pc.in new file mode 100644 index 0000000..0e72ecd --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: freenect2 +Description: Driver for the Kinect v2 (aka K4W) +Version: @PROJECT_VER@ +Libs: -L${libdir} -lfreenect2 +Cflags: -I${includedir} + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2Version.cmake.in b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2Version.cmake.in new file mode 100644 index 0000000..bbc7114 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/freenect2Version.cmake.in @@ -0,0 +1,11 @@ +set(PACKAGE_VERSION "@PROJECT_VER@") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/CL/cl.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/CL/cl.hpp new file mode 100644 index 0000000..f4b28ca --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/CL/cl.hpp @@ -0,0 +1,12939 @@ +/******************************************************************************* + * Copyright (c) 2008-2015 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + ******************************************************************************/ + +/*! \file + * + * \brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33) and + * OpenCL 1.2 (rev 15) + * \author Benedict R. Gaster, Laurent Morichetti and Lee Howes + * + * Additions and fixes from: + * Brian Cole, March 3rd 2010 and April 2012 + * Matt Gruenke, April 2012. + * Bruce Merry, February 2013. + * Tom Deakin and Simon McIntosh-Smith, July 2013 + * + * \version 1.2.8 + * \date October 2015 + * + * Optional extension support + * + * cl + * cl_ext_device_fission + * #define USE_CL_DEVICE_FISSION + */ + +/*! \mainpage + * \section intro Introduction + * For many large applications C++ is the language of choice and so it seems + * reasonable to define C++ bindings for OpenCL. + * + * + * The interface is contained with a single C++ header file \em cl.hpp and all + * definitions are contained within the namespace \em cl. There is no additional + * requirement to include \em cl.h and to use either the C++ or original C + * bindings it is enough to simply include \em cl.hpp. + * + * The bindings themselves are lightweight and correspond closely to the + * underlying C API. Using the C++ bindings introduces no additional execution + * overhead. + * + * For detail documentation on the bindings see: + * + * The OpenCL C++ Wrapper API 1.2 (revision 09) + * http://www.khronos.org/registry/cl/specs/opencl-cplusplus-1.2.pdf + * + * \section example Example + * + * The following example shows a general use case for the C++ + * bindings, including support for the optional exception feature and + * also the supplied vector and string classes, see following sections for + * decriptions of these features. + * + * \code + * #define __CL_ENABLE_EXCEPTIONS + * + * #if defined(__APPLE__) || defined(__MACOSX) + * #include + * #else + * #include + * #endif + * #include + * #include + * #include + * + * const char * helloStr = "__kernel void " + * "hello(void) " + * "{ " + * " " + * "} "; + * + * int + * main(void) + * { + * cl_int err = CL_SUCCESS; + * try { + * + * std::vector platforms; + * cl::Platform::get(&platforms); + * if (platforms.size() == 0) { + * std::cout << "Platform size 0\n"; + * return -1; + * } + * + * cl_context_properties properties[] = + * { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0}; + * cl::Context context(CL_DEVICE_TYPE_CPU, properties); + * + * std::vector devices = context.getInfo(); + * + * cl::Program::Sources source(1, + * std::make_pair(helloStr,strlen(helloStr))); + * cl::Program program_ = cl::Program(context, source); + * program_.build(devices); + * + * cl::Kernel kernel(program_, "hello", &err); + * + * cl::Event event; + * cl::CommandQueue queue(context, devices[0], 0, &err); + * queue.enqueueNDRangeKernel( + * kernel, + * cl::NullRange, + * cl::NDRange(4,4), + * cl::NullRange, + * NULL, + * &event); + * + * event.wait(); + * } + * catch (cl::Error err) { + * std::cerr + * << "ERROR: " + * << err.what() + * << "(" + * << err.err() + * << ")" + * << std::endl; + * } + * + * return EXIT_SUCCESS; + * } + * + * \endcode + * + */ +#ifndef CL_HPP_ +#define CL_HPP_ + +#ifdef _WIN32 + +#include + +#if defined(USE_DX_INTEROP) +#include +#include +#endif +#endif // _WIN32 + +#if defined(_MSC_VER) +#include +#endif // _MSC_VER + +// +#if defined(USE_CL_DEVICE_FISSION) +#include +#endif + +// Disable warnings about "ignoring attributes on template argument" +#if defined(__GNUC__) && __GNUC__ >= 6 +#pragma GCC diagnostic ignored "-Wignored-attributes" +#endif + +#if defined(__APPLE__) || defined(__MACOSX) +#include +#else +#include +#endif // !__APPLE__ + +#if (_MSC_VER >= 1700) || (__cplusplus >= 201103L) +#define CL_HPP_RVALUE_REFERENCES_SUPPORTED +#define CL_HPP_CPP11_ATOMICS_SUPPORTED +#include +#endif + +#if (__cplusplus >= 201103L) +#define CL_HPP_NOEXCEPT noexcept +#else +#define CL_HPP_NOEXCEPT +#endif + + +// To avoid accidentally taking ownership of core OpenCL types +// such as cl_kernel constructors are made explicit +// under OpenCL 1.2 +#if defined(CL_VERSION_1_2) && !defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +#define __CL_EXPLICIT_CONSTRUCTORS explicit +#else // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +#define __CL_EXPLICIT_CONSTRUCTORS +#endif // #if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +// Define deprecated prefixes and suffixes to ensure compilation +// in case they are not pre-defined +#if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) +#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) +#if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED) +#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED +#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED) + +#if !defined(CL_CALLBACK) +#define CL_CALLBACK +#endif //CL_CALLBACK + +#include +#include +#include + +#if defined(__CL_ENABLE_EXCEPTIONS) +#include +#endif // #if defined(__CL_ENABLE_EXCEPTIONS) + +#if !defined(__NO_STD_VECTOR) +#include +#endif + +#if !defined(__NO_STD_STRING) +#include +#endif + +#if defined(__ANDROID__) || defined(linux) || defined(__APPLE__) || defined(__MACOSX) +#include +#endif // linux + +#include + + +/*! \namespace cl + * + * \brief The OpenCL C++ bindings are defined within this namespace. + * + */ +namespace cl { + +class Memory; + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +#define __INIT_CL_EXT_FCN_PTR(name) \ + if(!pfn_##name) { \ + pfn_##name = (PFN_##name) \ + clGetExtensionFunctionAddress(#name); \ + if(!pfn_##name) { \ + } \ + } +#endif // #if defined(CL_VERSION_1_1) + +#if defined(CL_VERSION_1_2) +#define __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, name) \ + if(!pfn_##name) { \ + pfn_##name = (PFN_##name) \ + clGetExtensionFunctionAddressForPlatform(platform, #name); \ + if(!pfn_##name) { \ + } \ + } +#endif // #if defined(CL_VERSION_1_1) + +class Program; +class Device; +class Context; +class CommandQueue; +class Memory; +class Buffer; + +#if defined(__CL_ENABLE_EXCEPTIONS) +/*! \brief Exception class + * + * This may be thrown by API functions when __CL_ENABLE_EXCEPTIONS is defined. + */ +class Error : public std::exception +{ +private: + cl_int err_; + const char * errStr_; +public: + /*! \brief Create a new CL error exception for a given error code + * and corresponding message. + * + * \param err error code value. + * + * \param errStr a descriptive string that must remain in scope until + * handling of the exception has concluded. If set, it + * will be returned by what(). + */ + Error(cl_int err, const char * errStr = NULL) : err_(err), errStr_(errStr) + {} + + ~Error() throw() {} + + /*! \brief Get error string associated with exception + * + * \return A memory pointer to the error message string. + */ + virtual const char * what() const throw () + { + if (errStr_ == NULL) { + return "empty"; + } + else { + return errStr_; + } + } + + /*! \brief Get error code associated with exception + * + * \return The error code. + */ + cl_int err(void) const { return err_; } +}; + +#define __ERR_STR(x) #x +#else +#define __ERR_STR(x) NULL +#endif // __CL_ENABLE_EXCEPTIONS + + +namespace detail +{ +#if defined(__CL_ENABLE_EXCEPTIONS) +static inline cl_int errHandler ( + cl_int err, + const char * errStr = NULL) +{ + if (err != CL_SUCCESS) { + throw Error(err, errStr); + } + return err; +} +#else +static inline cl_int errHandler (cl_int err, const char * errStr = NULL) +{ + (void) errStr; // suppress unused variable warning + return err; +} +#endif // __CL_ENABLE_EXCEPTIONS +} + + + +//! \cond DOXYGEN_DETAIL +#if !defined(__CL_USER_OVERRIDE_ERROR_STRINGS) +#define __GET_DEVICE_INFO_ERR __ERR_STR(clGetDeviceInfo) +#define __GET_PLATFORM_INFO_ERR __ERR_STR(clGetPlatformInfo) +#define __GET_DEVICE_IDS_ERR __ERR_STR(clGetDeviceIDs) +#define __GET_PLATFORM_IDS_ERR __ERR_STR(clGetPlatformIDs) +#define __GET_CONTEXT_INFO_ERR __ERR_STR(clGetContextInfo) +#define __GET_EVENT_INFO_ERR __ERR_STR(clGetEventInfo) +#define __GET_EVENT_PROFILE_INFO_ERR __ERR_STR(clGetEventProfileInfo) +#define __GET_MEM_OBJECT_INFO_ERR __ERR_STR(clGetMemObjectInfo) +#define __GET_IMAGE_INFO_ERR __ERR_STR(clGetImageInfo) +#define __GET_SAMPLER_INFO_ERR __ERR_STR(clGetSamplerInfo) +#define __GET_KERNEL_INFO_ERR __ERR_STR(clGetKernelInfo) +#if defined(CL_VERSION_1_2) +#define __GET_KERNEL_ARG_INFO_ERR __ERR_STR(clGetKernelArgInfo) +#endif // #if defined(CL_VERSION_1_2) +#define __GET_KERNEL_WORK_GROUP_INFO_ERR __ERR_STR(clGetKernelWorkGroupInfo) +#define __GET_PROGRAM_INFO_ERR __ERR_STR(clGetProgramInfo) +#define __GET_PROGRAM_BUILD_INFO_ERR __ERR_STR(clGetProgramBuildInfo) +#define __GET_COMMAND_QUEUE_INFO_ERR __ERR_STR(clGetCommandQueueInfo) + +#define __CREATE_CONTEXT_ERR __ERR_STR(clCreateContext) +#define __CREATE_CONTEXT_FROM_TYPE_ERR __ERR_STR(clCreateContextFromType) +#define __GET_SUPPORTED_IMAGE_FORMATS_ERR __ERR_STR(clGetSupportedImageFormats) + +#define __CREATE_BUFFER_ERR __ERR_STR(clCreateBuffer) +#define __COPY_ERR __ERR_STR(cl::copy) +#define __CREATE_SUBBUFFER_ERR __ERR_STR(clCreateSubBuffer) +#define __CREATE_GL_BUFFER_ERR __ERR_STR(clCreateFromGLBuffer) +#define __CREATE_GL_RENDER_BUFFER_ERR __ERR_STR(clCreateFromGLBuffer) +#define __GET_GL_OBJECT_INFO_ERR __ERR_STR(clGetGLObjectInfo) +#if defined(CL_VERSION_1_2) +#define __CREATE_IMAGE_ERR __ERR_STR(clCreateImage) +#define __CREATE_GL_TEXTURE_ERR __ERR_STR(clCreateFromGLTexture) +#define __IMAGE_DIMENSION_ERR __ERR_STR(Incorrect image dimensions) +#endif // #if defined(CL_VERSION_1_2) +#define __CREATE_SAMPLER_ERR __ERR_STR(clCreateSampler) +#define __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR __ERR_STR(clSetMemObjectDestructorCallback) + +#define __CREATE_USER_EVENT_ERR __ERR_STR(clCreateUserEvent) +#define __SET_USER_EVENT_STATUS_ERR __ERR_STR(clSetUserEventStatus) +#define __SET_EVENT_CALLBACK_ERR __ERR_STR(clSetEventCallback) +#define __WAIT_FOR_EVENTS_ERR __ERR_STR(clWaitForEvents) + +#define __CREATE_KERNEL_ERR __ERR_STR(clCreateKernel) +#define __SET_KERNEL_ARGS_ERR __ERR_STR(clSetKernelArg) +#define __CREATE_PROGRAM_WITH_SOURCE_ERR __ERR_STR(clCreateProgramWithSource) +#define __CREATE_PROGRAM_WITH_BINARY_ERR __ERR_STR(clCreateProgramWithBinary) +#if defined(CL_VERSION_1_2) +#define __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR __ERR_STR(clCreateProgramWithBuiltInKernels) +#endif // #if defined(CL_VERSION_1_2) +#define __BUILD_PROGRAM_ERR __ERR_STR(clBuildProgram) +#if defined(CL_VERSION_1_2) +#define __COMPILE_PROGRAM_ERR __ERR_STR(clCompileProgram) +#define __LINK_PROGRAM_ERR __ERR_STR(clLinkProgram) +#endif // #if defined(CL_VERSION_1_2) +#define __CREATE_KERNELS_IN_PROGRAM_ERR __ERR_STR(clCreateKernelsInProgram) + +#define __CREATE_COMMAND_QUEUE_ERR __ERR_STR(clCreateCommandQueue) +#define __SET_COMMAND_QUEUE_PROPERTY_ERR __ERR_STR(clSetCommandQueueProperty) +#define __ENQUEUE_READ_BUFFER_ERR __ERR_STR(clEnqueueReadBuffer) +#define __ENQUEUE_READ_BUFFER_RECT_ERR __ERR_STR(clEnqueueReadBufferRect) +#define __ENQUEUE_WRITE_BUFFER_ERR __ERR_STR(clEnqueueWriteBuffer) +#define __ENQUEUE_WRITE_BUFFER_RECT_ERR __ERR_STR(clEnqueueWriteBufferRect) +#define __ENQEUE_COPY_BUFFER_ERR __ERR_STR(clEnqueueCopyBuffer) +#define __ENQEUE_COPY_BUFFER_RECT_ERR __ERR_STR(clEnqueueCopyBufferRect) +#define __ENQUEUE_FILL_BUFFER_ERR __ERR_STR(clEnqueueFillBuffer) +#define __ENQUEUE_READ_IMAGE_ERR __ERR_STR(clEnqueueReadImage) +#define __ENQUEUE_WRITE_IMAGE_ERR __ERR_STR(clEnqueueWriteImage) +#define __ENQUEUE_COPY_IMAGE_ERR __ERR_STR(clEnqueueCopyImage) +#define __ENQUEUE_FILL_IMAGE_ERR __ERR_STR(clEnqueueFillImage) +#define __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR __ERR_STR(clEnqueueCopyImageToBuffer) +#define __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR __ERR_STR(clEnqueueCopyBufferToImage) +#define __ENQUEUE_MAP_BUFFER_ERR __ERR_STR(clEnqueueMapBuffer) +#define __ENQUEUE_MAP_IMAGE_ERR __ERR_STR(clEnqueueMapImage) +#define __ENQUEUE_UNMAP_MEM_OBJECT_ERR __ERR_STR(clEnqueueUnMapMemObject) +#define __ENQUEUE_NDRANGE_KERNEL_ERR __ERR_STR(clEnqueueNDRangeKernel) +#define __ENQUEUE_TASK_ERR __ERR_STR(clEnqueueTask) +#define __ENQUEUE_NATIVE_KERNEL __ERR_STR(clEnqueueNativeKernel) +#if defined(CL_VERSION_1_2) +#define __ENQUEUE_MIGRATE_MEM_OBJECTS_ERR __ERR_STR(clEnqueueMigrateMemObjects) +#endif // #if defined(CL_VERSION_1_2) + +#define __ENQUEUE_ACQUIRE_GL_ERR __ERR_STR(clEnqueueAcquireGLObjects) +#define __ENQUEUE_RELEASE_GL_ERR __ERR_STR(clEnqueueReleaseGLObjects) + + +#define __RETAIN_ERR __ERR_STR(Retain Object) +#define __RELEASE_ERR __ERR_STR(Release Object) +#define __FLUSH_ERR __ERR_STR(clFlush) +#define __FINISH_ERR __ERR_STR(clFinish) +#define __VECTOR_CAPACITY_ERR __ERR_STR(Vector capacity error) + +/** + * CL 1.2 version that uses device fission. + */ +#if defined(CL_VERSION_1_2) +#define __CREATE_SUB_DEVICES __ERR_STR(clCreateSubDevices) +#else +#define __CREATE_SUB_DEVICES __ERR_STR(clCreateSubDevicesEXT) +#endif // #if defined(CL_VERSION_1_2) + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +#define __ENQUEUE_MARKER_ERR __ERR_STR(clEnqueueMarker) +#define __ENQUEUE_WAIT_FOR_EVENTS_ERR __ERR_STR(clEnqueueWaitForEvents) +#define __ENQUEUE_BARRIER_ERR __ERR_STR(clEnqueueBarrier) +#define __UNLOAD_COMPILER_ERR __ERR_STR(clUnloadCompiler) +#define __CREATE_GL_TEXTURE_2D_ERR __ERR_STR(clCreateFromGLTexture2D) +#define __CREATE_GL_TEXTURE_3D_ERR __ERR_STR(clCreateFromGLTexture3D) +#define __CREATE_IMAGE2D_ERR __ERR_STR(clCreateImage2D) +#define __CREATE_IMAGE3D_ERR __ERR_STR(clCreateImage3D) +#endif // #if defined(CL_VERSION_1_1) + +#endif // __CL_USER_OVERRIDE_ERROR_STRINGS +//! \endcond + +/** + * CL 1.2 marker and barrier commands + */ +#if defined(CL_VERSION_1_2) +#define __ENQUEUE_MARKER_WAIT_LIST_ERR __ERR_STR(clEnqueueMarkerWithWaitList) +#define __ENQUEUE_BARRIER_WAIT_LIST_ERR __ERR_STR(clEnqueueBarrierWithWaitList) +#endif // #if defined(CL_VERSION_1_2) + +#if !defined(__USE_DEV_STRING) && !defined(__NO_STD_STRING) +typedef std::string STRING_CLASS; +#elif !defined(__USE_DEV_STRING) + +/*! \class string + * \brief Simple string class, that provides a limited subset of std::string + * functionality but avoids many of the issues that come with that class. + + * \note Deprecated. Please use std::string as default or + * re-define the string class to match the std::string + * interface by defining STRING_CLASS + */ +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED string CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED +{ +private: + ::size_t size_; + char * str_; +public: + //! \brief Constructs an empty string, allocating no memory. + string(void) : size_(0), str_(NULL) + { + } + + /*! \brief Constructs a string populated from an arbitrary value of + * specified size. + * + * An extra '\0' is added, in case none was contained in str. + * + * \param str the initial value of the string instance. Note that '\0' + * characters receive no special treatment. If NULL, + * the string is left empty, with a size of 0. + * + * \param size the number of characters to copy from str. + */ + string(const char * str, ::size_t size) : + size_(size), + str_(NULL) + { + if( size > 0 ) { + str_ = new char[size_+1]; + if (str_ != NULL) { + memcpy(str_, str, size_ * sizeof(char)); + str_[size_] = '\0'; + } + else { + size_ = 0; + } + } + } + + /*! \brief Constructs a string populated from a null-terminated value. + * + * \param str the null-terminated initial value of the string instance. + * If NULL, the string is left empty, with a size of 0. + */ + string(const char * str) : + size_(0), + str_(NULL) + { + if( str ) { + size_= ::strlen(str); + } + if( size_ > 0 ) { + str_ = new char[size_ + 1]; + if (str_ != NULL) { + memcpy(str_, str, (size_ + 1) * sizeof(char)); + } + } + } + + void resize( ::size_t n ) + { + if( size_ == n ) { + return; + } + if (n == 0) { + if( str_ ) { + delete [] str_; + } + str_ = NULL; + size_ = 0; + } + else { + char *newString = new char[n + 1]; + ::size_t copySize = n; + if( size_ < n ) { + copySize = size_; + } + size_ = n; + + if(str_) { + memcpy(newString, str_, (copySize + 1) * sizeof(char)); + } + if( copySize < size_ ) { + memset(newString + copySize, 0, size_ - copySize); + } + newString[size_] = '\0'; + + delete [] str_; + str_ = newString; + } + } + + const char& operator[] ( ::size_t pos ) const + { + return str_[pos]; + } + + char& operator[] ( ::size_t pos ) + { + return str_[pos]; + } + + /*! \brief Copies the value of another string to this one. + * + * \param rhs the string to copy. + * + * \returns a reference to the modified instance. + */ + string& operator=(const string& rhs) + { + if (this == &rhs) { + return *this; + } + + if( str_ != NULL ) { + delete [] str_; + str_ = NULL; + size_ = 0; + } + + if (rhs.size_ == 0 || rhs.str_ == NULL) { + str_ = NULL; + size_ = 0; + } + else { + str_ = new char[rhs.size_ + 1]; + size_ = rhs.size_; + + if (str_ != NULL) { + memcpy(str_, rhs.str_, (size_ + 1) * sizeof(char)); + } + else { + size_ = 0; + } + } + + return *this; + } + + /*! \brief Constructs a string by copying the value of another instance. + * + * \param rhs the string to copy. + */ + string(const string& rhs) : + size_(0), + str_(NULL) + { + *this = rhs; + } + + //! \brief Destructor - frees memory used to hold the current value. + ~string() + { + delete[] str_; + str_ = NULL; + } + + //! \brief Queries the length of the string, excluding any added '\0's. + ::size_t size(void) const { return size_; } + + //! \brief Queries the length of the string, excluding any added '\0's. + ::size_t length(void) const { return size(); } + + /*! \brief Returns a pointer to the private copy held by this instance, + * or "" if empty/unset. + */ + const char * c_str(void) const { return (str_) ? str_ : "";} +}; +typedef cl::string STRING_CLASS; +#endif // #elif !defined(__USE_DEV_STRING) + +#if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR) +#define VECTOR_CLASS std::vector +#elif !defined(__USE_DEV_VECTOR) +#define VECTOR_CLASS cl::vector + +#if !defined(__MAX_DEFAULT_VECTOR_SIZE) +#define __MAX_DEFAULT_VECTOR_SIZE 10 +#endif + +/*! \class vector + * \brief Fixed sized vector implementation that mirroring + * + * \note Deprecated. Please use std::vector as default or + * re-define the vector class to match the std::vector + * interface by defining VECTOR_CLASS + + * \note Not recommended for use with custom objects as + * current implementation will construct N elements + * + * std::vector functionality. + * \brief Fixed sized vector compatible with std::vector. + * + * \note + * This differs from std::vector<> not just in memory allocation, + * but also in terms of when members are constructed, destroyed, + * and assigned instead of being copy constructed. + * + * \param T type of element contained in the vector. + * + * \param N maximum size of the vector. + */ +template +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED vector +{ +private: + T data_[N]; + unsigned int size_; + +public: + //! \brief Constructs an empty vector with no memory allocated. + vector() : + size_(static_cast(0)) + {} + + //! \brief Deallocates the vector's memory and destroys all of its elements. + ~vector() + { + clear(); + } + + //! \brief Returns the number of elements currently contained. + unsigned int size(void) const + { + return size_; + } + + /*! \brief Empties the vector of all elements. + * \note + * This does not deallocate memory but will invoke destructors + * on contained elements. + */ + void clear() + { + while(!empty()) { + pop_back(); + } + } + + /*! \brief Appends an element after the last valid element. + * Calling this on a vector that has reached capacity will throw an + * exception if exceptions are enabled. + */ + void push_back (const T& x) + { + if (size() < N) { + new (&data_[size_]) T(x); + size_++; + } else { + detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR); + } + } + + /*! \brief Removes the last valid element from the vector. + * Calling this on an empty vector will throw an exception + * if exceptions are enabled. + */ + void pop_back(void) + { + if (size_ != 0) { + --size_; + data_[size_].~T(); + } else { + detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR); + } + } + + /*! \brief Constructs with a value copied from another. + * + * \param vec the vector to copy. + */ + vector(const vector& vec) : + size_(vec.size_) + { + if (size_ != 0) { + assign(vec.begin(), vec.end()); + } + } + + /*! \brief Constructs with a specified number of initial elements. + * + * \param size number of initial elements. + * + * \param val value of initial elements. + */ + vector(unsigned int size, const T& val = T()) : + size_(0) + { + for (unsigned int i = 0; i < size; i++) { + push_back(val); + } + } + + /*! \brief Overwrites the current content with that copied from another + * instance. + * + * \param rhs vector to copy. + * + * \returns a reference to this. + */ + vector& operator=(const vector& rhs) + { + if (this == &rhs) { + return *this; + } + + if (rhs.size_ != 0) { + assign(rhs.begin(), rhs.end()); + } else { + clear(); + } + + return *this; + } + + /*! \brief Tests equality against another instance. + * + * \param vec the vector against which to compare. + */ + bool operator==(vector &vec) + { + if (size() != vec.size()) { + return false; + } + + for( unsigned int i = 0; i < size(); ++i ) { + if( operator[](i) != vec[i] ) { + return false; + } + } + return true; + } + + //! \brief Conversion operator to T*. + operator T* () { return data_; } + + //! \brief Conversion operator to const T*. + operator const T* () const { return data_; } + + //! \brief Tests whether this instance has any elements. + bool empty (void) const + { + return size_==0; + } + + //! \brief Returns the maximum number of elements this instance can hold. + unsigned int max_size (void) const + { + return N; + } + + //! \brief Returns the maximum number of elements this instance can hold. + unsigned int capacity () const + { + return N; + } + + //! \brief Resizes the vector to the given size + void resize(unsigned int newSize, T fill = T()) + { + if (newSize > N) + { + detail::errHandler(CL_MEM_OBJECT_ALLOCATION_FAILURE, __VECTOR_CAPACITY_ERR); + } + else + { + while (size_ < newSize) + { + new (&data_[size_]) T(fill); + size_++; + } + while (size_ > newSize) + { + --size_; + data_[size_].~T(); + } + } + } + + /*! \brief Returns a reference to a given element. + * + * \param index which element to access. * + * \note + * The caller is responsible for ensuring index is >= 0 and < size(). + */ + T& operator[](int index) + { + return data_[index]; + } + + /*! \brief Returns a const reference to a given element. + * + * \param index which element to access. + * + * \note + * The caller is responsible for ensuring index is >= 0 and < size(). + */ + const T& operator[](int index) const + { + return data_[index]; + } + + /*! \brief Assigns elements of the vector based on a source iterator range. + * + * \param start Beginning iterator of source range + * \param end Enditerator of source range + * + * \note + * Will throw an exception if exceptions are enabled and size exceeded. + */ + template + void assign(I start, I end) + { + clear(); + while(start != end) { + push_back(*start); + start++; + } + } + + /*! \class iterator + * \brief Const iterator class for vectors + */ + class iterator + { + private: + const vector *vec_; + int index_; + + /** + * Internal iterator constructor to capture reference + * to the vector it iterates over rather than taking + * the vector by copy. + */ + iterator (const vector &vec, int index) : + vec_(&vec) + { + if( !vec.empty() ) { + index_ = index; + } else { + index_ = -1; + } + } + + public: + iterator(void) : + index_(-1), + vec_(NULL) + { + } + + iterator(const iterator& rhs) : + vec_(rhs.vec_), + index_(rhs.index_) + { + } + + ~iterator(void) {} + + static iterator begin(const cl::vector &vec) + { + iterator i(vec, 0); + + return i; + } + + static iterator end(const cl::vector &vec) + { + iterator i(vec, vec.size()); + + return i; + } + + bool operator==(iterator i) + { + return ((vec_ == i.vec_) && + (index_ == i.index_)); + } + + bool operator!=(iterator i) + { + return (!(*this==i)); + } + + iterator& operator++() + { + ++index_; + return *this; + } + + iterator operator++(int) + { + iterator retVal(*this); + ++index_; + return retVal; + } + + iterator& operator--() + { + --index_; + return *this; + } + + iterator operator--(int) + { + iterator retVal(*this); + --index_; + return retVal; + } + + const T& operator *() const + { + return (*vec_)[index_]; + } + }; + + iterator begin(void) + { + return iterator::begin(*this); + } + + iterator begin(void) const + { + return iterator::begin(*this); + } + + iterator end(void) + { + return iterator::end(*this); + } + + iterator end(void) const + { + return iterator::end(*this); + } + + T& front(void) + { + return data_[0]; + } + + T& back(void) + { + return data_[size_]; + } + + const T& front(void) const + { + return data_[0]; + } + + const T& back(void) const + { + return data_[size_-1]; + } +} CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +#endif // #if !defined(__USE_DEV_VECTOR) && !defined(__NO_STD_VECTOR) + + + + + +namespace detail { +#define __DEFAULT_NOT_INITIALIZED 1 +#define __DEFAULT_BEING_INITIALIZED 2 +#define __DEFAULT_INITIALIZED 4 + + /* + * Compare and exchange primitives are needed for handling of defaults + */ + +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + inline int compare_exchange(std::atomic * dest, int exchange, int comparand) +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED + inline int compare_exchange(volatile int * dest, int exchange, int comparand) +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + { +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + std::atomic_compare_exchange_strong(dest, &comparand, exchange); + return comparand; +#elif _MSC_VER + return (int)(_InterlockedCompareExchange( + (volatile long*)dest, + (long)exchange, + (long)comparand)); +#else // !_MSC_VER && !CL_HPP_CPP11_ATOMICS_SUPPORTED + return (__sync_val_compare_and_swap( + dest, + comparand, + exchange)); +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + } + + inline void fence() { +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + std::atomic_thread_fence(std::memory_order_seq_cst); +#elif _MSC_VER // !CL_HPP_CPP11_ATOMICS_SUPPORTED + _ReadWriteBarrier(); +#else // !_MSC_VER && !CL_HPP_CPP11_ATOMICS_SUPPORTED + __sync_synchronize(); +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + } +} // namespace detail + + +/*! \brief class used to interface between C++ and + * OpenCL C calls that require arrays of size_t values, whose + * size is known statically. + */ +template +class size_t +{ +private: + ::size_t data_[N]; + +public: + //! \brief Initialize size_t to all 0s + size_t() + { + for( int i = 0; i < N; ++i ) { + data_[i] = 0; + } + } + + ::size_t& operator[](int index) + { + return data_[index]; + } + + const ::size_t& operator[](int index) const + { + return data_[index]; + } + + //! \brief Conversion operator to T*. + operator ::size_t* () { return data_; } + + //! \brief Conversion operator to const T*. + operator const ::size_t* () const { return data_; } +}; + +namespace detail { + +// Generic getInfoHelper. The final parameter is used to guide overload +// resolution: the actual parameter passed is an int, which makes this +// a worse conversion sequence than a specialization that declares the +// parameter as an int. +template +inline cl_int getInfoHelper(Functor f, cl_uint name, T* param, long) +{ + return f(name, sizeof(T), param, NULL); +} + +// Specialized getInfoHelper for VECTOR_CLASS params +template +inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS* param, long) +{ + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + T* value = (T*) alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + param->assign(&value[0], &value[required/sizeof(T)]); + return CL_SUCCESS; +} + +/* Specialization for reference-counted types. This depends on the + * existence of Wrapper::cl_type, and none of the other types having the + * cl_type member. Note that simplify specifying the parameter as Wrapper + * does not work, because when using a derived type (e.g. Context) the generic + * template will provide a better match. + */ +template +inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS* param, int, typename T::cl_type = 0) +{ + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + typename T::cl_type * value = (typename T::cl_type *) alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + ::size_t elements = required / sizeof(typename T::cl_type); + param->assign(&value[0], &value[elements]); + for (::size_t i = 0; i < elements; i++) + { + if (value[i] != NULL) + { + err = (*param)[i].retain(); + if (err != CL_SUCCESS) { + return err; + } + } + } + return CL_SUCCESS; +} + +// Specialized for getInfo +template +inline cl_int getInfoHelper(Func f, cl_uint name, VECTOR_CLASS* param, int) +{ + cl_int err = f(name, param->size() * sizeof(char *), &(*param)[0], NULL); + + if (err != CL_SUCCESS) { + return err; + } + + return CL_SUCCESS; +} + +// Specialized GetInfoHelper for STRING_CLASS params +template +inline cl_int getInfoHelper(Func f, cl_uint name, STRING_CLASS* param, long) +{ +#if defined(__NO_STD_VECTOR) || defined(__NO_STD_STRING) + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + char* value = (char*)alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + *param = value; + return CL_SUCCESS; +#else + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + // std::string has a constant data member + // a char vector does not + VECTOR_CLASS value(required); + err = f(name, required, value.data(), NULL); + if (err != CL_SUCCESS) { + return err; + } + if (param) { + param->assign(value.begin(), value.end()); + } +#endif + return CL_SUCCESS; +} + +// Specialized GetInfoHelper for cl::size_t params +template +inline cl_int getInfoHelper(Func f, cl_uint name, size_t* param, long) +{ + ::size_t required; + cl_int err = f(name, 0, NULL, &required); + if (err != CL_SUCCESS) { + return err; + } + + ::size_t* value = (::size_t*) alloca(required); + err = f(name, required, value, NULL); + if (err != CL_SUCCESS) { + return err; + } + + for(int i = 0; i < N; ++i) { + (*param)[i] = value[i]; + } + + return CL_SUCCESS; +} + +template struct ReferenceHandler; + +/* Specialization for reference-counted types. This depends on the + * existence of Wrapper::cl_type, and none of the other types having the + * cl_type member. Note that simplify specifying the parameter as Wrapper + * does not work, because when using a derived type (e.g. Context) the generic + * template will provide a better match. + */ +template +inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_type = 0) +{ + typename T::cl_type value; + cl_int err = f(name, sizeof(value), &value, NULL); + if (err != CL_SUCCESS) { + return err; + } + *param = value; + if (value != NULL) + { + err = param->retain(); + if (err != CL_SUCCESS) { + return err; + } + } + return CL_SUCCESS; +} + +#define __PARAM_NAME_INFO_1_0(F) \ + F(cl_platform_info, CL_PLATFORM_PROFILE, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_VERSION, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_NAME, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_VENDOR, STRING_CLASS) \ + F(cl_platform_info, CL_PLATFORM_EXTENSIONS, STRING_CLASS) \ + \ + F(cl_device_info, CL_DEVICE_TYPE, cl_device_type) \ + F(cl_device_info, CL_DEVICE_VENDOR_ID, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_GROUP_SIZE, ::size_t) \ + F(cl_device_info, CL_DEVICE_MAX_WORK_ITEM_SIZES, VECTOR_CLASS< ::size_t>) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint) \ + F(cl_device_info, CL_DEVICE_ADDRESS_BITS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_READ_IMAGE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MAX_MEM_ALLOC_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_WIDTH, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE2D_MAX_HEIGHT, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_WIDTH, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_HEIGHT, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE3D_MAX_DEPTH, ::size_t) \ + F(cl_device_info, CL_DEVICE_IMAGE_SUPPORT, cl_bool) \ + F(cl_device_info, CL_DEVICE_MAX_PARAMETER_SIZE, ::size_t) \ + F(cl_device_info, CL_DEVICE_MAX_SAMPLERS, cl_uint) \ + F(cl_device_info, CL_DEVICE_MEM_BASE_ADDR_ALIGN, cl_uint) \ + F(cl_device_info, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, cl_uint) \ + F(cl_device_info, CL_DEVICE_SINGLE_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE, cl_device_mem_cache_type) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, cl_uint)\ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_GLOBAL_MEM_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_MAX_CONSTANT_ARGS, cl_uint) \ + F(cl_device_info, CL_DEVICE_LOCAL_MEM_TYPE, cl_device_local_mem_type) \ + F(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE, cl_ulong) \ + F(cl_device_info, CL_DEVICE_ERROR_CORRECTION_SUPPORT, cl_bool) \ + F(cl_device_info, CL_DEVICE_PROFILING_TIMER_RESOLUTION, ::size_t) \ + F(cl_device_info, CL_DEVICE_ENDIAN_LITTLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_AVAILABLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_COMPILER_AVAILABLE, cl_bool) \ + F(cl_device_info, CL_DEVICE_EXECUTION_CAPABILITIES, cl_device_exec_capabilities) \ + F(cl_device_info, CL_DEVICE_QUEUE_PROPERTIES, cl_command_queue_properties) \ + F(cl_device_info, CL_DEVICE_PLATFORM, cl_platform_id) \ + F(cl_device_info, CL_DEVICE_NAME, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_VENDOR, STRING_CLASS) \ + F(cl_device_info, CL_DRIVER_VERSION, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_PROFILE, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_VERSION, STRING_CLASS) \ + F(cl_device_info, CL_DEVICE_EXTENSIONS, STRING_CLASS) \ + \ + F(cl_context_info, CL_CONTEXT_REFERENCE_COUNT, cl_uint) \ + F(cl_context_info, CL_CONTEXT_DEVICES, VECTOR_CLASS) \ + F(cl_context_info, CL_CONTEXT_PROPERTIES, VECTOR_CLASS) \ + \ + F(cl_event_info, CL_EVENT_COMMAND_QUEUE, cl::CommandQueue) \ + F(cl_event_info, CL_EVENT_COMMAND_TYPE, cl_command_type) \ + F(cl_event_info, CL_EVENT_REFERENCE_COUNT, cl_uint) \ + F(cl_event_info, CL_EVENT_COMMAND_EXECUTION_STATUS, cl_int) \ + \ + F(cl_profiling_info, CL_PROFILING_COMMAND_QUEUED, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_SUBMIT, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_START, cl_ulong) \ + F(cl_profiling_info, CL_PROFILING_COMMAND_END, cl_ulong) \ + \ + F(cl_mem_info, CL_MEM_TYPE, cl_mem_object_type) \ + F(cl_mem_info, CL_MEM_FLAGS, cl_mem_flags) \ + F(cl_mem_info, CL_MEM_SIZE, ::size_t) \ + F(cl_mem_info, CL_MEM_HOST_PTR, void*) \ + F(cl_mem_info, CL_MEM_MAP_COUNT, cl_uint) \ + F(cl_mem_info, CL_MEM_REFERENCE_COUNT, cl_uint) \ + F(cl_mem_info, CL_MEM_CONTEXT, cl::Context) \ + \ + F(cl_image_info, CL_IMAGE_FORMAT, cl_image_format) \ + F(cl_image_info, CL_IMAGE_ELEMENT_SIZE, ::size_t) \ + F(cl_image_info, CL_IMAGE_ROW_PITCH, ::size_t) \ + F(cl_image_info, CL_IMAGE_SLICE_PITCH, ::size_t) \ + F(cl_image_info, CL_IMAGE_WIDTH, ::size_t) \ + F(cl_image_info, CL_IMAGE_HEIGHT, ::size_t) \ + F(cl_image_info, CL_IMAGE_DEPTH, ::size_t) \ + \ + F(cl_sampler_info, CL_SAMPLER_REFERENCE_COUNT, cl_uint) \ + F(cl_sampler_info, CL_SAMPLER_CONTEXT, cl::Context) \ + F(cl_sampler_info, CL_SAMPLER_NORMALIZED_COORDS, cl_bool) \ + F(cl_sampler_info, CL_SAMPLER_ADDRESSING_MODE, cl_addressing_mode) \ + F(cl_sampler_info, CL_SAMPLER_FILTER_MODE, cl_filter_mode) \ + \ + F(cl_program_info, CL_PROGRAM_REFERENCE_COUNT, cl_uint) \ + F(cl_program_info, CL_PROGRAM_CONTEXT, cl::Context) \ + F(cl_program_info, CL_PROGRAM_NUM_DEVICES, cl_uint) \ + F(cl_program_info, CL_PROGRAM_DEVICES, VECTOR_CLASS) \ + F(cl_program_info, CL_PROGRAM_SOURCE, STRING_CLASS) \ + F(cl_program_info, CL_PROGRAM_BINARY_SIZES, VECTOR_CLASS< ::size_t>) \ + F(cl_program_info, CL_PROGRAM_BINARIES, VECTOR_CLASS) \ + \ + F(cl_program_build_info, CL_PROGRAM_BUILD_STATUS, cl_build_status) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_OPTIONS, STRING_CLASS) \ + F(cl_program_build_info, CL_PROGRAM_BUILD_LOG, STRING_CLASS) \ + \ + F(cl_kernel_info, CL_KERNEL_FUNCTION_NAME, STRING_CLASS) \ + F(cl_kernel_info, CL_KERNEL_NUM_ARGS, cl_uint) \ + F(cl_kernel_info, CL_KERNEL_REFERENCE_COUNT, cl_uint) \ + F(cl_kernel_info, CL_KERNEL_CONTEXT, cl::Context) \ + F(cl_kernel_info, CL_KERNEL_PROGRAM, cl::Program) \ + \ + F(cl_kernel_work_group_info, CL_KERNEL_WORK_GROUP_SIZE, ::size_t) \ + F(cl_kernel_work_group_info, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, cl::size_t<3>) \ + F(cl_kernel_work_group_info, CL_KERNEL_LOCAL_MEM_SIZE, cl_ulong) \ + \ + F(cl_command_queue_info, CL_QUEUE_CONTEXT, cl::Context) \ + F(cl_command_queue_info, CL_QUEUE_DEVICE, cl::Device) \ + F(cl_command_queue_info, CL_QUEUE_REFERENCE_COUNT, cl_uint) \ + F(cl_command_queue_info, CL_QUEUE_PROPERTIES, cl_command_queue_properties) + +#if defined(CL_VERSION_1_1) +#define __PARAM_NAME_INFO_1_1(F) \ + F(cl_context_info, CL_CONTEXT_NUM_DEVICES, cl_uint)\ + F(cl_device_info, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE, cl_uint) \ + F(cl_device_info, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF, cl_uint) \ + F(cl_device_info, CL_DEVICE_DOUBLE_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_HALF_FP_CONFIG, cl_device_fp_config) \ + F(cl_device_info, CL_DEVICE_HOST_UNIFIED_MEMORY, cl_bool) \ + F(cl_device_info, CL_DEVICE_OPENCL_C_VERSION, STRING_CLASS) \ + \ + F(cl_mem_info, CL_MEM_ASSOCIATED_MEMOBJECT, cl::Memory) \ + F(cl_mem_info, CL_MEM_OFFSET, ::size_t) \ + \ + F(cl_kernel_work_group_info, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, ::size_t) \ + F(cl_kernel_work_group_info, CL_KERNEL_PRIVATE_MEM_SIZE, cl_ulong) \ + \ + F(cl_event_info, CL_EVENT_CONTEXT, cl::Context) +#endif // CL_VERSION_1_1 + + +#if defined(CL_VERSION_1_2) +#define __PARAM_NAME_INFO_1_2(F) \ + F(cl_image_info, CL_IMAGE_BUFFER, cl::Buffer) \ + \ + F(cl_program_info, CL_PROGRAM_NUM_KERNELS, ::size_t) \ + F(cl_program_info, CL_PROGRAM_KERNEL_NAMES, STRING_CLASS) \ + \ + F(cl_program_build_info, CL_PROGRAM_BINARY_TYPE, cl_program_binary_type) \ + \ + F(cl_kernel_info, CL_KERNEL_ATTRIBUTES, STRING_CLASS) \ + \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_ADDRESS_QUALIFIER, cl_kernel_arg_address_qualifier) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_ACCESS_QUALIFIER, cl_kernel_arg_access_qualifier) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_NAME, STRING_CLASS) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, STRING_CLASS) \ + F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \ + \ + F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl_device_id) \ + F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_PARTITION_TYPE, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \ + F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, ::size_t) \ + F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \ + F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, STRING_CLASS) +#endif // #if defined(CL_VERSION_1_2) + +#if defined(USE_CL_DEVICE_FISSION) +#define __PARAM_NAME_DEVICE_FISSION(F) \ + F(cl_device_info, CL_DEVICE_PARENT_DEVICE_EXT, cl_device_id) \ + F(cl_device_info, CL_DEVICE_PARTITION_TYPES_EXT, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_AFFINITY_DOMAINS_EXT, VECTOR_CLASS) \ + F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \ + F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, VECTOR_CLASS) +#endif // USE_CL_DEVICE_FISSION + +template +struct param_traits {}; + +#define __CL_DECLARE_PARAM_TRAITS(token, param_name, T) \ +struct token; \ +template<> \ +struct param_traits \ +{ \ + enum { value = param_name }; \ + typedef T param_type; \ +}; + +__PARAM_NAME_INFO_1_0(__CL_DECLARE_PARAM_TRAITS) +#if defined(CL_VERSION_1_1) +__PARAM_NAME_INFO_1_1(__CL_DECLARE_PARAM_TRAITS) +#endif // CL_VERSION_1_1 +#if defined(CL_VERSION_1_2) +__PARAM_NAME_INFO_1_2(__CL_DECLARE_PARAM_TRAITS) +#endif // CL_VERSION_1_1 + +#if defined(USE_CL_DEVICE_FISSION) +__PARAM_NAME_DEVICE_FISSION(__CL_DECLARE_PARAM_TRAITS); +#endif // USE_CL_DEVICE_FISSION + +#ifdef CL_PLATFORM_ICD_SUFFIX_KHR +__CL_DECLARE_PARAM_TRAITS(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, STRING_CLASS) +#endif + +#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong) +#endif + +#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, VECTOR_CLASS< ::size_t>) +#endif +#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_SIMD_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_WAVEFRONT_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, cl_uint) +#endif +#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint) +#endif + +#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint) +#endif +#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV, cl_uint) +#endif +#ifdef CL_DEVICE_REGISTERS_PER_BLOCK_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_REGISTERS_PER_BLOCK_NV, cl_uint) +#endif +#ifdef CL_DEVICE_WARP_SIZE_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_WARP_SIZE_NV, cl_uint) +#endif +#ifdef CL_DEVICE_GPU_OVERLAP_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_GPU_OVERLAP_NV, cl_bool) +#endif +#ifdef CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, cl_bool) +#endif +#ifdef CL_DEVICE_INTEGRATED_MEMORY_NV +__CL_DECLARE_PARAM_TRAITS(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool) +#endif + +// Convenience functions + +template +inline cl_int +getInfo(Func f, cl_uint name, T* param) +{ + return getInfoHelper(f, name, param, 0); +} + +template +struct GetInfoFunctor0 +{ + Func f_; const Arg0& arg0_; + cl_int operator ()( + cl_uint param, ::size_t size, void* value, ::size_t* size_ret) + { return f_(arg0_, param, size, value, size_ret); } +}; + +template +struct GetInfoFunctor1 +{ + Func f_; const Arg0& arg0_; const Arg1& arg1_; + cl_int operator ()( + cl_uint param, ::size_t size, void* value, ::size_t* size_ret) + { return f_(arg0_, arg1_, param, size, value, size_ret); } +}; + +template +inline cl_int +getInfo(Func f, const Arg0& arg0, cl_uint name, T* param) +{ + GetInfoFunctor0 f0 = { f, arg0 }; + return getInfoHelper(f0, name, param, 0); +} + +template +inline cl_int +getInfo(Func f, const Arg0& arg0, const Arg1& arg1, cl_uint name, T* param) +{ + GetInfoFunctor1 f0 = { f, arg0, arg1 }; + return getInfoHelper(f0, name, param, 0); +} + +template +struct ReferenceHandler +{ }; + +#if defined(CL_VERSION_1_2) +/** + * OpenCL 1.2 devices do have retain/release. + */ +template <> +struct ReferenceHandler +{ + /** + * Retain the device. + * \param device A valid device created using createSubDevices + * \return + * CL_SUCCESS if the function executed successfully. + * CL_INVALID_DEVICE if device was not a valid subdevice + * CL_OUT_OF_RESOURCES + * CL_OUT_OF_HOST_MEMORY + */ + static cl_int retain(cl_device_id device) + { return ::clRetainDevice(device); } + /** + * Retain the device. + * \param device A valid device created using createSubDevices + * \return + * CL_SUCCESS if the function executed successfully. + * CL_INVALID_DEVICE if device was not a valid subdevice + * CL_OUT_OF_RESOURCES + * CL_OUT_OF_HOST_MEMORY + */ + static cl_int release(cl_device_id device) + { return ::clReleaseDevice(device); } +}; +#else // #if defined(CL_VERSION_1_2) +/** + * OpenCL 1.1 devices do not have retain/release. + */ +template <> +struct ReferenceHandler +{ + // cl_device_id does not have retain(). + static cl_int retain(cl_device_id) + { return CL_SUCCESS; } + // cl_device_id does not have release(). + static cl_int release(cl_device_id) + { return CL_SUCCESS; } +}; +#endif // #if defined(CL_VERSION_1_2) + +template <> +struct ReferenceHandler +{ + // cl_platform_id does not have retain(). + static cl_int retain(cl_platform_id) + { return CL_SUCCESS; } + // cl_platform_id does not have release(). + static cl_int release(cl_platform_id) + { return CL_SUCCESS; } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_context context) + { return ::clRetainContext(context); } + static cl_int release(cl_context context) + { return ::clReleaseContext(context); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_command_queue queue) + { return ::clRetainCommandQueue(queue); } + static cl_int release(cl_command_queue queue) + { return ::clReleaseCommandQueue(queue); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_mem memory) + { return ::clRetainMemObject(memory); } + static cl_int release(cl_mem memory) + { return ::clReleaseMemObject(memory); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_sampler sampler) + { return ::clRetainSampler(sampler); } + static cl_int release(cl_sampler sampler) + { return ::clReleaseSampler(sampler); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_program program) + { return ::clRetainProgram(program); } + static cl_int release(cl_program program) + { return ::clReleaseProgram(program); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_kernel kernel) + { return ::clRetainKernel(kernel); } + static cl_int release(cl_kernel kernel) + { return ::clReleaseKernel(kernel); } +}; + +template <> +struct ReferenceHandler +{ + static cl_int retain(cl_event event) + { return ::clRetainEvent(event); } + static cl_int release(cl_event event) + { return ::clReleaseEvent(event); } +}; + + +// Extracts version number with major in the upper 16 bits, minor in the lower 16 +static cl_uint getVersion(const char *versionInfo) +{ + int highVersion = 0; + int lowVersion = 0; + int index = 7; + while(versionInfo[index] != '.' ) { + highVersion *= 10; + highVersion += versionInfo[index]-'0'; + ++index; + } + ++index; + while(versionInfo[index] != ' ' && versionInfo[index] != '\0') { + lowVersion *= 10; + lowVersion += versionInfo[index]-'0'; + ++index; + } + return (highVersion << 16) | lowVersion; +} + +static cl_uint getPlatformVersion(cl_platform_id platform) +{ + ::size_t size = 0; + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 0, NULL, &size); + char *versionInfo = (char *) alloca(size); + clGetPlatformInfo(platform, CL_PLATFORM_VERSION, size, &versionInfo[0], &size); + return getVersion(versionInfo); +} + +static cl_uint getDevicePlatformVersion(cl_device_id device) +{ + cl_platform_id platform; + clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(platform), &platform, NULL); + return getPlatformVersion(platform); +} + +#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) +static cl_uint getContextPlatformVersion(cl_context context) +{ + // The platform cannot be queried directly, so we first have to grab a + // device and obtain its context + ::size_t size = 0; + clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &size); + if (size == 0) + return 0; + cl_device_id *devices = (cl_device_id *) alloca(size); + clGetContextInfo(context, CL_CONTEXT_DEVICES, size, devices, NULL); + return getDevicePlatformVersion(devices[0]); +} +#endif // #if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + +template +class Wrapper +{ +public: + typedef T cl_type; + +protected: + cl_type object_; + +public: + Wrapper() : object_(NULL) { } + + Wrapper(const cl_type &obj) : object_(obj) { } + + ~Wrapper() + { + if (object_ != NULL) { release(); } + } + + Wrapper(const Wrapper& rhs) + { + object_ = rhs.object_; + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper(Wrapper&& rhs) CL_HPP_NOEXCEPT + { + object_ = rhs.object_; + rhs.object_ = NULL; + } +#endif + + Wrapper& operator = (const Wrapper& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper& operator = (Wrapper&& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + rhs.object_ = NULL; + } + return *this; + } +#endif + + Wrapper& operator = (const cl_type &rhs) + { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs; + return *this; + } + + cl_type operator ()() const { return object_; } + + cl_type& operator ()() { return object_; } + +protected: + template + friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type); + + cl_int retain() const + { + return ReferenceHandler::retain(object_); + } + + cl_int release() const + { + return ReferenceHandler::release(object_); + } +}; + +template <> +class Wrapper +{ +public: + typedef cl_device_id cl_type; + +protected: + cl_type object_; + bool referenceCountable_; + + static bool isReferenceCountable(cl_device_id device) + { + bool retVal = false; + if (device != NULL) { + int version = getDevicePlatformVersion(device); + if(version > ((1 << 16) + 1)) { + retVal = true; + } + } + return retVal; + } + +public: + Wrapper() : object_(NULL), referenceCountable_(false) + { + } + + Wrapper(const cl_type &obj) : object_(obj), referenceCountable_(false) + { + referenceCountable_ = isReferenceCountable(obj); + } + + ~Wrapper() + { + if (object_ != NULL) { release(); } + } + + Wrapper(const Wrapper& rhs) + { + object_ = rhs.object_; + referenceCountable_ = isReferenceCountable(object_); + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper(Wrapper&& rhs) CL_HPP_NOEXCEPT + { + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + rhs.object_ = NULL; + rhs.referenceCountable_ = false; + } +#endif + + Wrapper& operator = (const Wrapper& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + if (object_ != NULL) { detail::errHandler(retain(), __RETAIN_ERR); } + } + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + Wrapper& operator = (Wrapper&& rhs) + { + if (this != &rhs) { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs.object_; + referenceCountable_ = rhs.referenceCountable_; + rhs.object_ = NULL; + rhs.referenceCountable_ = false; + } + return *this; + } +#endif + + Wrapper& operator = (const cl_type &rhs) + { + if (object_ != NULL) { detail::errHandler(release(), __RELEASE_ERR); } + object_ = rhs; + referenceCountable_ = isReferenceCountable(object_); + return *this; + } + + cl_type operator ()() const { return object_; } + + cl_type& operator ()() { return object_; } + +protected: + template + friend inline cl_int getInfoHelper(Func, cl_uint, U*, int, typename U::cl_type); + + template + friend inline cl_int getInfoHelper(Func, cl_uint, VECTOR_CLASS*, int, typename U::cl_type); + + cl_int retain() const + { + if( referenceCountable_ ) { + return ReferenceHandler::retain(object_); + } + else { + return CL_SUCCESS; + } + } + + cl_int release() const + { + if( referenceCountable_ ) { + return ReferenceHandler::release(object_); + } + else { + return CL_SUCCESS; + } + } +}; + +} // namespace detail +//! \endcond + +/*! \stuct ImageFormat + * \brief Adds constructors and member functions for cl_image_format. + * + * \see cl_image_format + */ +struct ImageFormat : public cl_image_format +{ + //! \brief Default constructor - performs no initialization. + ImageFormat(){} + + //! \brief Initializing constructor. + ImageFormat(cl_channel_order order, cl_channel_type type) + { + image_channel_order = order; + image_channel_data_type = type; + } + + //! \brief Assignment operator. + ImageFormat& operator = (const ImageFormat& rhs) + { + if (this != &rhs) { + this->image_channel_data_type = rhs.image_channel_data_type; + this->image_channel_order = rhs.image_channel_order; + } + return *this; + } +}; + +/*! \brief Class interface for cl_device_id. + * + * \note Copies of these objects are inexpensive, since they don't 'own' + * any underlying resources or data structures. + * + * \see cl_device_id + */ +class Device : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Device() : detail::Wrapper() { } + + /*! \brief Constructor from cl_device_id. + * + * This simply copies the device ID value, which is an inexpensive operation. + */ + __CL_EXPLICIT_CONSTRUCTORS Device(const cl_device_id &device) : detail::Wrapper(device) { } + + /*! \brief Returns the first device on the default context. + * + * \see Context::getDefault() + */ + static Device getDefault(cl_int * err = NULL); + + /*! \brief Assignment operator from cl_device_id. + * + * This simply copies the device ID value, which is an inexpensive operation. + */ + Device& operator = (const cl_device_id& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Device(const Device& dev) : detail::Wrapper(dev) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Device& operator = (const Device &dev) + { + detail::Wrapper::operator=(dev); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Device(Device&& dev) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(dev)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Device& operator = (Device &&dev) + { + detail::Wrapper::operator=(std::move(dev)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetDeviceInfo(). + template + cl_int getInfo(cl_device_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetDeviceInfo, object_, name, param), + __GET_DEVICE_INFO_ERR); + } + + //! \brief Wrapper for clGetDeviceInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_device_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /** + * CL 1.2 version + */ +#if defined(CL_VERSION_1_2) + //! \brief Wrapper for clCreateSubDevicesEXT(). + cl_int createSubDevices( + const cl_device_partition_property * properties, + VECTOR_CLASS* devices) + { + cl_uint n = 0; + cl_int err = clCreateSubDevices(object_, properties, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = clCreateSubDevices(object_, properties, n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } +#endif // #if defined(CL_VERSION_1_2) + +/** + * CL 1.1 version that uses device fission. + */ +#if defined(CL_VERSION_1_1) +#if defined(USE_CL_DEVICE_FISSION) + cl_int createSubDevices( + const cl_device_partition_property_ext * properties, + VECTOR_CLASS* devices) + { + typedef CL_API_ENTRY cl_int + ( CL_API_CALL * PFN_clCreateSubDevicesEXT)( + cl_device_id /*in_device*/, + const cl_device_partition_property_ext * /* properties */, + cl_uint /*num_entries*/, + cl_device_id * /*out_devices*/, + cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1; + + static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL; + __INIT_CL_EXT_FCN_PTR(clCreateSubDevicesEXT); + + cl_uint n = 0; + cl_int err = pfn_clCreateSubDevicesEXT(object_, properties, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = pfn_clCreateSubDevicesEXT(object_, properties, n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_SUB_DEVICES); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } +#endif // #if defined(USE_CL_DEVICE_FISSION) +#endif // #if defined(CL_VERSION_1_1) +}; + +/*! \brief Class interface for cl_platform_id. + * + * \note Copies of these objects are inexpensive, since they don't 'own' + * any underlying resources or data structures. + * + * \see cl_platform_id + */ +class Platform : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Platform() : detail::Wrapper() { } + + /*! \brief Constructor from cl_platform_id. + * + * This simply copies the platform ID value, which is an inexpensive operation. + */ + __CL_EXPLICIT_CONSTRUCTORS Platform(const cl_platform_id &platform) : detail::Wrapper(platform) { } + + /*! \brief Assignment operator from cl_platform_id. + * + * This simply copies the platform ID value, which is an inexpensive operation. + */ + Platform& operator = (const cl_platform_id& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetPlatformInfo(). + cl_int getInfo(cl_platform_info name, STRING_CLASS* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetPlatformInfo, object_, name, param), + __GET_PLATFORM_INFO_ERR); + } + + //! \brief Wrapper for clGetPlatformInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_platform_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Gets a list of devices for this platform. + * + * Wraps clGetDeviceIDs(). + */ + cl_int getDevices( + cl_device_type type, + VECTOR_CLASS* devices) const + { + cl_uint n = 0; + if( devices == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR); + } + cl_int err = ::clGetDeviceIDs(object_, type, 0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = ::clGetDeviceIDs(object_, type, n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } + +#if defined(USE_DX_INTEROP) + /*! \brief Get the list of available D3D10 devices. + * + * \param d3d_device_source. + * + * \param d3d_object. + * + * \param d3d_device_set. + * + * \param devices returns a vector of OpenCL D3D10 devices found. The cl::Device + * values returned in devices can be used to identify a specific OpenCL + * device. If \a devices argument is NULL, this argument is ignored. + * + * \return One of the following values: + * - CL_SUCCESS if the function is executed successfully. + * + * The application can query specific capabilities of the OpenCL device(s) + * returned by cl::getDevices. This can be used by the application to + * determine which device(s) to use. + * + * \note In the case that exceptions are enabled and a return value + * other than CL_SUCCESS is generated, then cl::Error exception is + * generated. + */ + cl_int getDevices( + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + VECTOR_CLASS* devices) const + { + typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clGetDeviceIDsFromD3D10KHR)( + cl_platform_id platform, + cl_d3d10_device_source_khr d3d_device_source, + void * d3d_object, + cl_d3d10_device_set_khr d3d_device_set, + cl_uint num_entries, + cl_device_id * devices, + cl_uint* num_devices); + + if( devices == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_DEVICE_IDS_ERR); + } + + static PFN_clGetDeviceIDsFromD3D10KHR pfn_clGetDeviceIDsFromD3D10KHR = NULL; + __INIT_CL_EXT_FCN_PTR_PLATFORM(object_, clGetDeviceIDsFromD3D10KHR); + + cl_uint n = 0; + cl_int err = pfn_clGetDeviceIDsFromD3D10KHR( + object_, + d3d_device_source, + d3d_object, + d3d_device_set, + 0, + NULL, + &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + cl_device_id* ids = (cl_device_id*) alloca(n * sizeof(cl_device_id)); + err = pfn_clGetDeviceIDsFromD3D10KHR( + object_, + d3d_device_source, + d3d_object, + d3d_device_set, + n, + ids, + NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_DEVICE_IDS_ERR); + } + + devices->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } +#endif + + /*! \brief Gets a list of available platforms. + * + * Wraps clGetPlatformIDs(). + */ + static cl_int get( + VECTOR_CLASS* platforms) + { + cl_uint n = 0; + + if( platforms == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR); + } + + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + cl_platform_id* ids = (cl_platform_id*) alloca( + n * sizeof(cl_platform_id)); + err = ::clGetPlatformIDs(n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + platforms->assign(&ids[0], &ids[n]); + return CL_SUCCESS; + } + + /*! \brief Gets the first available platform. + * + * Wraps clGetPlatformIDs(), returning the first result. + */ + static cl_int get( + Platform * platform) + { + cl_uint n = 0; + + if( platform == NULL ) { + return detail::errHandler(CL_INVALID_ARG_VALUE, __GET_PLATFORM_IDS_ERR); + } + + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + cl_platform_id* ids = (cl_platform_id*) alloca( + n * sizeof(cl_platform_id)); + err = ::clGetPlatformIDs(n, ids, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + } + + *platform = ids[0]; + return CL_SUCCESS; + } + + /*! \brief Gets the first available platform, returning it by value. + * + * Wraps clGetPlatformIDs(), returning the first result. + */ + static Platform get( + cl_int * errResult = NULL) + { + Platform platform; + cl_uint n = 0; + cl_int err = ::clGetPlatformIDs(0, NULL, &n); + if (err != CL_SUCCESS) { + detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + if (errResult != NULL) { + *errResult = err; + } + return Platform(); + } + + cl_platform_id* ids = (cl_platform_id*) alloca( + n * sizeof(cl_platform_id)); + err = ::clGetPlatformIDs(n, ids, NULL); + + if (err != CL_SUCCESS) { + detail::errHandler(err, __GET_PLATFORM_IDS_ERR); + if (errResult != NULL) { + *errResult = err; + } + return Platform(); + } + + + return Platform(ids[0]); + } + + static Platform getDefault( + cl_int *errResult = NULL ) + { + return get(errResult); + } + + +#if defined(CL_VERSION_1_2) + //! \brief Wrapper for clUnloadCompiler(). + cl_int + unloadCompiler() + { + return ::clUnloadPlatformCompiler(object_); + } +#endif // #if defined(CL_VERSION_1_2) +}; // class Platform + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) +/** + * Unload the OpenCL compiler. + * \note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead. + */ +inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int +UnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +inline cl_int +UnloadCompiler() +{ + return ::clUnloadCompiler(); +} +#endif // #if defined(CL_VERSION_1_1) + +/*! \brief Class interface for cl_context. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_context as the original. For details, see + * clRetainContext() and clReleaseContext(). + * + * \see cl_context + */ +class Context + : public detail::Wrapper +{ +private: + +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + static std::atomic default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static volatile int default_initialized_; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static Context default_; + static volatile cl_int default_error_; +public: + /*! \brief Constructs a context including a list of specified devices. + * + * Wraps clCreateContext(). + */ + Context( + const VECTOR_CLASS& devices, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + ::size_t, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + + ::size_t numDevices = devices.size(); + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + object_ = ::clCreateContext( + properties, (cl_uint) numDevices, + deviceIDs, + notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + if (err != NULL) { + *err = error; + } + } + + Context( + const Device& device, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + ::size_t, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + + cl_device_id deviceID = device(); + + object_ = ::clCreateContext( + properties, 1, + &deviceID, + notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a context including all or a subset of devices of a specified type. + * + * Wraps clCreateContextFromType(). + */ + Context( + cl_device_type type, + cl_context_properties* properties = NULL, + void (CL_CALLBACK * notifyFptr)( + const char *, + const void *, + ::size_t, + void *) = NULL, + void* data = NULL, + cl_int* err = NULL) + { + cl_int error; + +#if !defined(__APPLE__) && !defined(__MACOS) + cl_context_properties prop[4] = {CL_CONTEXT_PLATFORM, 0, 0, 0 }; + + if (properties == NULL) { + // Get a valid platform ID as we cannot send in a blank one + VECTOR_CLASS platforms; + error = Platform::get(&platforms); + if (error != CL_SUCCESS) { + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + return; + } + + // Check the platforms we found for a device of our specified type + cl_context_properties platform_id = 0; + for (unsigned int i = 0; i < platforms.size(); i++) { + + VECTOR_CLASS devices; + +#if defined(__CL_ENABLE_EXCEPTIONS) + try { +#endif + + error = platforms[i].getDevices(type, &devices); + +#if defined(__CL_ENABLE_EXCEPTIONS) + } catch (Error) {} + // Catch if exceptions are enabled as we don't want to exit if first platform has no devices of type + // We do error checking next anyway, and can throw there if needed +#endif + + // Only squash CL_SUCCESS and CL_DEVICE_NOT_FOUND + if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND) { + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + } + + if (devices.size() > 0) { + platform_id = (cl_context_properties)platforms[i](); + break; + } + } + + if (platform_id == 0) { + detail::errHandler(CL_DEVICE_NOT_FOUND, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = CL_DEVICE_NOT_FOUND; + } + return; + } + + prop[1] = platform_id; + properties = &prop[0]; + } +#endif + object_ = ::clCreateContextFromType( + properties, type, notifyFptr, data, &error); + + detail::errHandler(error, __CREATE_CONTEXT_FROM_TYPE_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Context(const Context& ctx) : detail::Wrapper(ctx) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Context& operator = (const Context &ctx) + { + detail::Wrapper::operator=(ctx); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Context(Context&& ctx) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(ctx)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Context& operator = (Context &&ctx) + { + detail::Wrapper::operator=(std::move(ctx)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + /*! \brief Returns a singleton context including all devices of CL_DEVICE_TYPE_DEFAULT. + * + * \note All calls to this function return the same cl_context as the first. + */ + static Context getDefault(cl_int * err = NULL) + { + int state = detail::compare_exchange( + &default_initialized_, + __DEFAULT_BEING_INITIALIZED, __DEFAULT_NOT_INITIALIZED); + + if (state & __DEFAULT_INITIALIZED) { + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + if (state & __DEFAULT_BEING_INITIALIZED) { + // Assume writes will propagate eventually... + while(default_initialized_ != __DEFAULT_INITIALIZED) { + detail::fence(); + } + + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + cl_int error; + default_ = Context( + CL_DEVICE_TYPE_DEFAULT, + NULL, + NULL, + NULL, + &error); + + detail::fence(); + + default_error_ = error; + // Assume writes will propagate eventually... + default_initialized_ = __DEFAULT_INITIALIZED; + + detail::fence(); + + if (err != NULL) { + *err = default_error_; + } + return default_; + + } + + //! \brief Default constructor - initializes to NULL. + Context() : detail::Wrapper() { } + + /*! \brief Constructor from cl_context - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_context + * into the new Context object. + */ + __CL_EXPLICIT_CONSTRUCTORS Context(const cl_context& context) : detail::Wrapper(context) { } + + /*! \brief Assignment operator from cl_context - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseContext() on the value previously held by this instance. + */ + Context& operator = (const cl_context& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetContextInfo(). + template + cl_int getInfo(cl_context_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetContextInfo, object_, name, param), + __GET_CONTEXT_INFO_ERR); + } + + //! \brief Wrapper for clGetContextInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_context_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Gets a list of supported image formats. + * + * Wraps clGetSupportedImageFormats(). + */ + cl_int getSupportedImageFormats( + cl_mem_flags flags, + cl_mem_object_type type, + VECTOR_CLASS* formats) const + { + cl_uint numEntries; + + if (!formats) { + return CL_SUCCESS; + } + + cl_int err = ::clGetSupportedImageFormats( + object_, + flags, + type, + 0, + NULL, + &numEntries); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR); + } + + if (numEntries > 0) { + ImageFormat* value = (ImageFormat*) + alloca(numEntries * sizeof(ImageFormat)); + err = ::clGetSupportedImageFormats( + object_, + flags, + type, + numEntries, + (cl_image_format*)value, + NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __GET_SUPPORTED_IMAGE_FORMATS_ERR); + } + + formats->assign(&value[0], &value[numEntries]); + } + else { + formats->clear(); + } + return CL_SUCCESS; + } +}; + +inline Device Device::getDefault(cl_int * err) +{ + cl_int error; + Device device; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + device = context.getInfo()[0]; + if (err != NULL) { + *err = CL_SUCCESS; + } + } + + return device; +} + + +#ifdef _WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) std::atomic Context::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) volatile int Context::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) Context Context::default_; +__declspec(selectany) volatile cl_int Context::default_error_ = CL_SUCCESS; +#else // !_WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) std::atomic Context::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) volatile int Context::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) Context Context::default_; +__attribute__((weak)) volatile cl_int Context::default_error_ = CL_SUCCESS; +#endif // !_WIN32 + +/*! \brief Class interface for cl_event. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_event as the original. For details, see + * clRetainEvent() and clReleaseEvent(). + * + * \see cl_event + */ +class Event : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Event() : detail::Wrapper() { } + + /*! \brief Constructor from cl_event - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_event + * into the new Event object. + */ + __CL_EXPLICIT_CONSTRUCTORS Event(const cl_event& event) : detail::Wrapper(event) { } + + /*! \brief Assignment operator from cl_event - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseEvent() on the value previously held by this instance. + */ + Event& operator = (const cl_event& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + //! \brief Wrapper for clGetEventInfo(). + template + cl_int getInfo(cl_event_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetEventInfo, object_, name, param), + __GET_EVENT_INFO_ERR); + } + + //! \brief Wrapper for clGetEventInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_event_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + //! \brief Wrapper for clGetEventProfilingInfo(). + template + cl_int getProfilingInfo(cl_profiling_info name, T* param) const + { + return detail::errHandler(detail::getInfo( + &::clGetEventProfilingInfo, object_, name, param), + __GET_EVENT_PROFILE_INFO_ERR); + } + + //! \brief Wrapper for clGetEventProfilingInfo() that returns by value. + template typename + detail::param_traits::param_type + getProfilingInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_profiling_info, name>::param_type param; + cl_int result = getProfilingInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + /*! \brief Blocks the calling thread until this event completes. + * + * Wraps clWaitForEvents(). + */ + cl_int wait() const + { + return detail::errHandler( + ::clWaitForEvents(1, &object_), + __WAIT_FOR_EVENTS_ERR); + } + +#if defined(CL_VERSION_1_1) + /*! \brief Registers a user callback function for a specific command execution status. + * + * Wraps clSetEventCallback(). + */ + cl_int setCallback( + cl_int type, + void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *), + void * user_data = NULL) + { + return detail::errHandler( + ::clSetEventCallback( + object_, + type, + pfn_notify, + user_data), + __SET_EVENT_CALLBACK_ERR); + } +#endif + + /*! \brief Blocks the calling thread until every event specified is complete. + * + * Wraps clWaitForEvents(). + */ + static cl_int + waitForEvents(const VECTOR_CLASS& events) + { + return detail::errHandler( + ::clWaitForEvents( + (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL), + __WAIT_FOR_EVENTS_ERR); + } +}; + +#if defined(CL_VERSION_1_1) +/*! \brief Class interface for user events (a subset of cl_event's). + * + * See Event for details about copy semantics, etc. + */ +class UserEvent : public Event +{ +public: + /*! \brief Constructs a user event on a given context. + * + * Wraps clCreateUserEvent(). + */ + UserEvent( + const Context& context, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateUserEvent( + context(), + &error); + + detail::errHandler(error, __CREATE_USER_EVENT_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + UserEvent() : Event() { } + + /*! \brief Sets the execution status of a user event object. + * + * Wraps clSetUserEventStatus(). + */ + cl_int setStatus(cl_int status) + { + return detail::errHandler( + ::clSetUserEventStatus(object_,status), + __SET_USER_EVENT_STATUS_ERR); + } +}; +#endif + +/*! \brief Blocks the calling thread until every event specified is complete. + * + * Wraps clWaitForEvents(). + */ +inline static cl_int +WaitForEvents(const VECTOR_CLASS& events) +{ + return detail::errHandler( + ::clWaitForEvents( + (cl_uint) events.size(), (events.size() > 0) ? (cl_event*)&events.front() : NULL), + __WAIT_FOR_EVENTS_ERR); +} + +/*! \brief Class interface for cl_mem. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_mem as the original. For details, see + * clRetainMemObject() and clReleaseMemObject(). + * + * \see cl_mem + */ +class Memory : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Memory() : detail::Wrapper() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_mem + * into the new Memory object. + */ + __CL_EXPLICIT_CONSTRUCTORS Memory(const cl_mem& memory) : detail::Wrapper(memory) { } + + /*! \brief Assignment operator from cl_mem - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseMemObject() on the value previously held by this instance. + */ + Memory& operator = (const cl_mem& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Memory(const Memory& mem) : detail::Wrapper(mem) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Memory& operator = (const Memory &mem) + { + detail::Wrapper::operator=(mem); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Memory(Memory&& mem) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(mem)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Memory& operator = (Memory &&mem) + { + detail::Wrapper::operator=(std::move(mem)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetMemObjectInfo(). + template + cl_int getInfo(cl_mem_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetMemObjectInfo, object_, name, param), + __GET_MEM_OBJECT_INFO_ERR); + } + + //! \brief Wrapper for clGetMemObjectInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_mem_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if defined(CL_VERSION_1_1) + /*! \brief Registers a callback function to be called when the memory object + * is no longer needed. + * + * Wraps clSetMemObjectDestructorCallback(). + * + * Repeated calls to this function, for a given cl_mem value, will append + * to the list of functions called (in reverse order) when memory object's + * resources are freed and the memory object is deleted. + * + * \note + * The registered callbacks are associated with the underlying cl_mem + * value - not the Memory class instance. + */ + cl_int setDestructorCallback( + void (CL_CALLBACK * pfn_notify)(cl_mem, void *), + void * user_data = NULL) + { + return detail::errHandler( + ::clSetMemObjectDestructorCallback( + object_, + pfn_notify, + user_data), + __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR); + } +#endif + +}; + +// Pre-declare copy functions +class Buffer; +template< typename IteratorType > +cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ); +template< typename IteratorType > +cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ); +template< typename IteratorType > +cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ); +template< typename IteratorType > +cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ); + + +/*! \brief Class interface for Buffer Memory Objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Buffer : public Memory +{ +public: + + /*! \brief Constructs a Buffer in a specified context. + * + * Wraps clCreateBuffer(). + * + * \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was + * specified. Note alignment & exclusivity requirements. + */ + Buffer( + const Context& context, + cl_mem_flags flags, + ::size_t size, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error); + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructs a Buffer in the default context. + * + * Wraps clCreateBuffer(). + * + * \param host_ptr Storage to be used if the CL_MEM_USE_HOST_PTR flag was + * specified. Note alignment & exclusivity requirements. + * + * \see Context::getDefault() + */ + Buffer( + cl_mem_flags flags, + ::size_t size, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(err); + + object_ = ::clCreateBuffer(context(), flags, size, host_ptr, &error); + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! + * \brief Construct a Buffer from a host container via iterators. + * IteratorType must be random access. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer( + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr = false, + cl_int* err = NULL) + { + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if( readOnly ) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if( useHostPtr ) { + flags |= CL_MEM_USE_HOST_PTR; + } + + ::size_t size = sizeof(DataType)*(endIterator - startIterator); + + Context context = Context::getDefault(err); + + if( useHostPtr ) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if( !useHostPtr ) { + error = cl::copy(startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + } + + /*! + * \brief Construct a Buffer from a host container via iterators using a specified context. + * IteratorType must be random access. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer(const Context &context, IteratorType startIterator, IteratorType endIterator, + bool readOnly, bool useHostPtr = false, cl_int* err = NULL); + + /*! + * \brief Construct a Buffer from a host container via iterators using a specified queue. + * If useHostPtr is specified iterators must represent contiguous data. + */ + template< typename IteratorType > + Buffer(const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, + bool readOnly, bool useHostPtr = false, cl_int* err = NULL); + + //! \brief Default constructor - initializes to NULL. + Buffer() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Buffer(const cl_mem& buffer) : Memory(buffer) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Buffer& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Buffer(const Buffer& buf) : Memory(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Buffer& operator = (const Buffer &buf) + { + Memory::operator=(buf); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Buffer(Buffer&& buf) CL_HPP_NOEXCEPT : Memory(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Buffer& operator = (Buffer &&buf) + { + Memory::operator=(std::move(buf)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + +#if defined(CL_VERSION_1_1) + /*! \brief Creates a new buffer object from this. + * + * Wraps clCreateSubBuffer(). + */ + Buffer createSubBuffer( + cl_mem_flags flags, + cl_buffer_create_type buffer_create_type, + const void * buffer_create_info, + cl_int * err = NULL) + { + Buffer result; + cl_int error; + result.object_ = ::clCreateSubBuffer( + object_, + flags, + buffer_create_type, + buffer_create_info, + &error); + + detail::errHandler(error, __CREATE_SUBBUFFER_ERR); + if (err != NULL) { + *err = error; + } + + return result; + } +#endif +}; + +#if defined (USE_DX_INTEROP) +/*! \brief Class interface for creating OpenCL buffers from ID3D10Buffer's. + * + * This is provided to facilitate interoperability with Direct3D. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferD3D10 : public Buffer +{ +public: + typedef CL_API_ENTRY cl_mem (CL_API_CALL *PFN_clCreateFromD3D10BufferKHR)( + cl_context context, cl_mem_flags flags, ID3D10Buffer* buffer, + cl_int* errcode_ret); + + /*! \brief Constructs a BufferD3D10, in a specified context, from a + * given ID3D10Buffer. + * + * Wraps clCreateFromD3D10BufferKHR(). + */ + BufferD3D10( + const Context& context, + cl_mem_flags flags, + ID3D10Buffer* bufobj, + cl_int * err = NULL) + { + static PFN_clCreateFromD3D10BufferKHR pfn_clCreateFromD3D10BufferKHR = NULL; + +#if defined(CL_VERSION_1_2) + vector props = context.getInfo(); + cl_platform platform = -1; + for( int i = 0; i < props.size(); ++i ) { + if( props[i] == CL_CONTEXT_PLATFORM ) { + platform = props[i+1]; + } + } + __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clCreateFromD3D10BufferKHR); +#endif +#if defined(CL_VERSION_1_1) + __INIT_CL_EXT_FCN_PTR(clCreateFromD3D10BufferKHR); +#endif + + cl_int error; + object_ = pfn_clCreateFromD3D10BufferKHR( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferD3D10() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS BufferD3D10(const cl_mem& buffer) : Buffer(buffer) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferD3D10& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10(const BufferD3D10& buf) : Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10& operator = (const BufferD3D10 &buf) + { + Buffer::operator=(buf); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10(BufferD3D10&& buf) CL_HPP_NOEXCEPT : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferD3D10& operator = (BufferD3D10 &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif + +/*! \brief Class interface for GL Buffer Memory Objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class BufferGL : public Buffer +{ +public: + /*! \brief Constructs a BufferGL in a specified context, from a given + * GL buffer. + * + * Wraps clCreateFromGLBuffer(). + */ + BufferGL( + const Context& context, + cl_mem_flags flags, + cl_GLuint bufobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLBuffer( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + BufferGL() : Buffer() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS BufferGL(const cl_mem& buffer) : Buffer(buffer) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferGL& operator = (const cl_mem& rhs) + { + Buffer::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferGL(const BufferGL& buf) : Buffer(buf) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferGL& operator = (const BufferGL &buf) + { + Buffer::operator=(buf); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferGL(BufferGL&& buf) CL_HPP_NOEXCEPT : Buffer(std::move(buf)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferGL& operator = (BufferGL &&buf) + { + Buffer::operator=(std::move(buf)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetGLObjectInfo(). + cl_int getObjectInfo( + cl_gl_object_type *type, + cl_GLuint * gl_object_name) + { + return detail::errHandler( + ::clGetGLObjectInfo(object_,type,gl_object_name), + __GET_GL_OBJECT_INFO_ERR); + } +}; + +/*! \brief C++ base class for Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image : public Memory +{ +protected: + //! \brief Default constructor - initializes to NULL. + Image() : Memory() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image(const cl_mem& image) : Memory(image) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image& operator = (const cl_mem& rhs) + { + Memory::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image(const Image& img) : Memory(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image& operator = (const Image &img) + { + Memory::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image(Image&& img) CL_HPP_NOEXCEPT : Memory(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image& operator = (Image &&img) + { + Memory::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + +public: + //! \brief Wrapper for clGetImageInfo(). + template + cl_int getImageInfo(cl_image_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetImageInfo, object_, name, param), + __GET_IMAGE_INFO_ERR); + } + + //! \brief Wrapper for clGetImageInfo() that returns by value. + template typename + detail::param_traits::param_type + getImageInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_image_info, name>::param_type param; + cl_int result = getImageInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; + +#if defined(CL_VERSION_1_2) +/*! \brief Class interface for 1D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image1D : public Image +{ +public: + /*! \brief Constructs a 1D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image1D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D, + width, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Image1D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image1D(const cl_mem& image1D) : Image(image1D) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image1D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1D(const Image1D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1D& operator = (const Image1D &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1D(Image1D&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1D& operator = (Image1D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + +/*! \class Image1DBuffer + * \brief Image interface for 1D buffer images. + */ +class Image1DBuffer : public Image +{ +public: + Image1DBuffer( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + const Buffer &buffer, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D_BUFFER, + width, + 0, 0, 0, 0, 0, 0, 0, + buffer() + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + NULL, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image1DBuffer() { } + + __CL_EXPLICIT_CONSTRUCTORS Image1DBuffer(const cl_mem& image1D) : Image(image1D) { } + + Image1DBuffer& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer(const Image1DBuffer& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer& operator = (const Image1DBuffer &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer(Image1DBuffer&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DBuffer& operator = (Image1DBuffer &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + +/*! \class Image1DArray + * \brief Image interface for arrays of 1D images. + */ +class Image1DArray : public Image +{ +public: + Image1DArray( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t arraySize, + ::size_t width, + ::size_t rowPitch, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE1D_ARRAY, + width, + 0, 0, // height, depth (unused) + arraySize, + rowPitch, + 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image1DArray() { } + + __CL_EXPLICIT_CONSTRUCTORS Image1DArray(const cl_mem& imageArray) : Image(imageArray) { } + + Image1DArray& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DArray(const Image1DArray& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image1DArray& operator = (const Image1DArray &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DArray(Image1DArray&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image1DArray& operator = (Image1DArray &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if defined(CL_VERSION_1_2) + + +/*! \brief Class interface for 2D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image2D : public Image +{ +public: + /*! \brief Constructs a 1D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image2D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + ::size_t height, + ::size_t row_pitch = 0, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + bool useCreateImage; + +#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + // Run-time decision based on the actual platform + { + cl_uint version = detail::getContextPlatformVersion(context()); + useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above + } +#elif defined(CL_VERSION_1_2) + useCreateImage = true; +#else + useCreateImage = false; +#endif + +#if defined(CL_VERSION_1_2) + if (useCreateImage) + { + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D, + width, + height, + 0, 0, // depth, array size (unused) + row_pitch, + 0, 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if defined(CL_VERSION_1_2) +#if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + if (!useCreateImage) + { + object_ = ::clCreateImage2D( + context(), flags,&format, width, height, row_pitch, host_ptr, &error); + + detail::errHandler(error, __CREATE_IMAGE2D_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + } + + //! \brief Default constructor - initializes to NULL. + Image2D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image2D(const cl_mem& image2D) : Image(image2D) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image2D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2D(const Image2D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2D& operator = (const Image2D &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2D(Image2D&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2D& operator = (Image2D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + + +#if !defined(CL_VERSION_1_2) +/*! \brief Class interface for GL 2D Image Memory objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + * \note Deprecated for OpenCL 1.2. Please use ImageGL instead. + */ +class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED : public Image2D +{ +public: + /*! \brief Constructs an Image2DGL in a specified context, from a given + * GL Texture. + * + * Wraps clCreateFromGLTexture2D(). + */ + Image2DGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture2D( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_2D_ERR); + if (err != NULL) { + *err = error; + } + + } + + //! \brief Default constructor - initializes to NULL. + Image2DGL() : Image2D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image2DGL(const cl_mem& image) : Image2D(image) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image2DGL& operator = (const cl_mem& rhs) + { + Image2D::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DGL(const Image2DGL& img) : Image2D(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DGL& operator = (const Image2DGL &img) + { + Image2D::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DGL(Image2DGL&& img) CL_HPP_NOEXCEPT : Image2D(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DGL& operator = (Image2DGL &&img) + { + Image2D::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if !defined(CL_VERSION_1_2) + +#if defined(CL_VERSION_1_2) +/*! \class Image2DArray + * \brief Image interface for arrays of 2D images. + */ +class Image2DArray : public Image +{ +public: + Image2DArray( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t arraySize, + ::size_t width, + ::size_t height, + ::size_t rowPitch, + ::size_t slicePitch, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE2D_ARRAY, + width, + height, + 0, // depth (unused) + arraySize, + rowPitch, + slicePitch, + 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } + + Image2DArray() { } + + __CL_EXPLICIT_CONSTRUCTORS Image2DArray(const cl_mem& imageArray) : Image(imageArray) { } + + Image2DArray& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DArray(const Image2DArray& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image2DArray& operator = (const Image2DArray &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DArray(Image2DArray&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image2DArray& operator = (Image2DArray &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if defined(CL_VERSION_1_2) + +/*! \brief Class interface for 3D Image Memory objects. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image3D : public Image +{ +public: + /*! \brief Constructs a 3D Image in a specified context. + * + * Wraps clCreateImage(). + */ + Image3D( + const Context& context, + cl_mem_flags flags, + ImageFormat format, + ::size_t width, + ::size_t height, + ::size_t depth, + ::size_t row_pitch = 0, + ::size_t slice_pitch = 0, + void* host_ptr = NULL, + cl_int* err = NULL) + { + cl_int error; + bool useCreateImage; + +#if defined(CL_VERSION_1_2) && defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + // Run-time decision based on the actual platform + { + cl_uint version = detail::getContextPlatformVersion(context()); + useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above + } +#elif defined(CL_VERSION_1_2) + useCreateImage = true; +#else + useCreateImage = false; +#endif + +#if defined(CL_VERSION_1_2) + if (useCreateImage) + { + cl_image_desc desc = + { + CL_MEM_OBJECT_IMAGE3D, + width, + height, + depth, + 0, // array size (unused) + row_pitch, + slice_pitch, + 0, 0, 0 + }; + object_ = ::clCreateImage( + context(), + flags, + &format, + &desc, + host_ptr, + &error); + + detail::errHandler(error, __CREATE_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if defined(CL_VERSION_1_2) +#if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + if (!useCreateImage) + { + object_ = ::clCreateImage3D( + context(), flags, &format, width, height, depth, row_pitch, + slice_pitch, host_ptr, &error); + + detail::errHandler(error, __CREATE_IMAGE3D_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if !defined(CL_VERSION_1_2) || defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) + } + + //! \brief Default constructor - initializes to NULL. + Image3D() : Image() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image3D(const cl_mem& image3D) : Image(image3D) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image3D& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3D(const Image3D& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3D& operator = (const Image3D &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3D(Image3D&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3D& operator = (Image3D &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; + +#if !defined(CL_VERSION_1_2) +/*! \brief Class interface for GL 3D Image Memory objects. + * + * This is provided to facilitate interoperability with OpenGL. + * + * See Memory for details about copy semantics, etc. + * + * \see Memory + */ +class Image3DGL : public Image3D +{ +public: + /*! \brief Constructs an Image3DGL in a specified context, from a given + * GL Texture. + * + * Wraps clCreateFromGLTexture3D(). + */ + Image3DGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture3D( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_3D_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. + Image3DGL() : Image3D() { } + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ + __CL_EXPLICIT_CONSTRUCTORS Image3DGL(const cl_mem& image) : Image3D(image) { } + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + Image3DGL& operator = (const cl_mem& rhs) + { + Image3D::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3DGL(const Image3DGL& img) : Image3D(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Image3DGL& operator = (const Image3DGL &img) + { + Image3D::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3DGL(Image3DGL&& img) CL_HPP_NOEXCEPT : Image3D(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Image3DGL& operator = (Image3DGL &&img) + { + Image3D::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if !defined(CL_VERSION_1_2) + +#if defined(CL_VERSION_1_2) +/*! \class ImageGL + * \brief general image interface for GL interop. + * We abstract the 2D and 3D GL images into a single instance here + * that wraps all GL sourced images on the grounds that setup information + * was performed by OpenCL anyway. + */ +class ImageGL : public Image +{ +public: + ImageGL( + const Context& context, + cl_mem_flags flags, + cl_GLenum target, + cl_GLint miplevel, + cl_GLuint texobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLTexture( + context(), + flags, + target, + miplevel, + texobj, + &error); + + detail::errHandler(error, __CREATE_GL_TEXTURE_ERR); + if (err != NULL) { + *err = error; + } + } + + ImageGL() : Image() { } + + __CL_EXPLICIT_CONSTRUCTORS ImageGL(const cl_mem& image) : Image(image) { } + + ImageGL& operator = (const cl_mem& rhs) + { + Image::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + ImageGL(const ImageGL& img) : Image(img) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + ImageGL& operator = (const ImageGL &img) + { + Image::operator=(img); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + ImageGL(ImageGL&& img) CL_HPP_NOEXCEPT : Image(std::move(img)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + ImageGL& operator = (ImageGL &&img) + { + Image::operator=(std::move(img)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) +}; +#endif // #if defined(CL_VERSION_1_2) + +/*! \brief Class interface for GL Render Buffer Memory Objects. +* +* This is provided to facilitate interoperability with OpenGL. +* +* See Memory for details about copy semantics, etc. +* +* \see Memory +*/ +class BufferRenderGL : +#if defined(CL_VERSION_1_2) + public ImageGL +#else // #if defined(CL_VERSION_1_2) + public Image2DGL +#endif //#if defined(CL_VERSION_1_2) +{ +public: + /*! \brief Constructs a BufferRenderGL in a specified context, from a given + * GL Renderbuffer. + * + * Wraps clCreateFromGLRenderbuffer(). + */ + BufferRenderGL( + const Context& context, + cl_mem_flags flags, + cl_GLuint bufobj, + cl_int * err = NULL) + { + cl_int error; + object_ = ::clCreateFromGLRenderbuffer( + context(), + flags, + bufobj, + &error); + + detail::errHandler(error, __CREATE_GL_RENDER_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } + + //! \brief Default constructor - initializes to NULL. +#if defined(CL_VERSION_1_2) + BufferRenderGL() : ImageGL() {}; +#else // #if defined(CL_VERSION_1_2) + BufferRenderGL() : Image2DGL() {}; +#endif //#if defined(CL_VERSION_1_2) + + /*! \brief Constructor from cl_mem - takes ownership. + * + * See Memory for further details. + */ +#if defined(CL_VERSION_1_2) + __CL_EXPLICIT_CONSTRUCTORS BufferRenderGL(const cl_mem& buffer) : ImageGL(buffer) { } +#else // #if defined(CL_VERSION_1_2) + __CL_EXPLICIT_CONSTRUCTORS BufferRenderGL(const cl_mem& buffer) : Image2DGL(buffer) { } +#endif //#if defined(CL_VERSION_1_2) + + + /*! \brief Assignment from cl_mem - performs shallow copy. + * + * See Memory for further details. + */ + BufferRenderGL& operator = (const cl_mem& rhs) + { +#if defined(CL_VERSION_1_2) + ImageGL::operator=(rhs); +#else // #if defined(CL_VERSION_1_2) + Image2DGL::operator=(rhs); +#endif //#if defined(CL_VERSION_1_2) + + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ +#if defined(CL_VERSION_1_2) + BufferRenderGL(const BufferRenderGL& buf) : ImageGL(buf) {} +#else // #if defined(CL_VERSION_1_2) + BufferRenderGL(const BufferRenderGL& buf) : Image2DGL(buf) {} +#endif //#if defined(CL_VERSION_1_2) + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL& operator = (const BufferRenderGL &rhs) + { +#if defined(CL_VERSION_1_2) + ImageGL::operator=(rhs); +#else // #if defined(CL_VERSION_1_2) + Image2DGL::operator=(rhs); +#endif //#if defined(CL_VERSION_1_2) + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ +#if defined(CL_VERSION_1_2) + BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT : ImageGL(std::move(buf)) {} +#else // #if defined(CL_VERSION_1_2) + BufferRenderGL(BufferRenderGL&& buf) CL_HPP_NOEXCEPT : Image2DGL(std::move(buf)) {} +#endif //#if defined(CL_VERSION_1_2) + + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + BufferRenderGL& operator = (BufferRenderGL &&buf) + { +#if defined(CL_VERSION_1_2) + ImageGL::operator=(std::move(buf)); +#else // #if defined(CL_VERSION_1_2) + Image2DGL::operator=(std::move(buf)); +#endif //#if defined(CL_VERSION_1_2) + + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetGLObjectInfo(). + cl_int getObjectInfo( + cl_gl_object_type *type, + cl_GLuint * gl_object_name) + { + return detail::errHandler( + ::clGetGLObjectInfo(object_, type, gl_object_name), + __GET_GL_OBJECT_INFO_ERR); + } +}; + +/*! \brief Class interface for cl_sampler. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_sampler as the original. For details, see + * clRetainSampler() and clReleaseSampler(). + * + * \see cl_sampler + */ +class Sampler : public detail::Wrapper +{ +public: + //! \brief Default constructor - initializes to NULL. + Sampler() { } + + /*! \brief Constructs a Sampler in a specified context. + * + * Wraps clCreateSampler(). + */ + Sampler( + const Context& context, + cl_bool normalized_coords, + cl_addressing_mode addressing_mode, + cl_filter_mode filter_mode, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateSampler( + context(), + normalized_coords, + addressing_mode, + filter_mode, + &error); + + detail::errHandler(error, __CREATE_SAMPLER_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Constructor from cl_sampler - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_sampler + * into the new Sampler object. + */ + __CL_EXPLICIT_CONSTRUCTORS Sampler(const cl_sampler& sampler) : detail::Wrapper(sampler) { } + + /*! \brief Assignment operator from cl_sampler - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseSampler() on the value previously held by this instance. + */ + Sampler& operator = (const cl_sampler& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Sampler(const Sampler& sam) : detail::Wrapper(sam) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Sampler& operator = (const Sampler &sam) + { + detail::Wrapper::operator=(sam); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Sampler(Sampler&& sam) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(sam)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Sampler& operator = (Sampler &&sam) + { + detail::Wrapper::operator=(std::move(sam)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + //! \brief Wrapper for clGetSamplerInfo(). + template + cl_int getInfo(cl_sampler_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetSamplerInfo, object_, name, param), + __GET_SAMPLER_INFO_ERR); + } + + //! \brief Wrapper for clGetSamplerInfo() that returns by value. + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_sampler_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +}; + +class Program; +class CommandQueue; +class Kernel; + +//! \brief Class interface for specifying NDRange values. +class NDRange +{ +private: + size_t<3> sizes_; + cl_uint dimensions_; + +public: + //! \brief Default constructor - resulting range has zero dimensions. + NDRange() + : dimensions_(0) + { } + + //! \brief Constructs one-dimensional range. + NDRange(::size_t size0) + : dimensions_(1) + { + sizes_[0] = size0; + } + + //! \brief Constructs two-dimensional range. + NDRange(::size_t size0, ::size_t size1) + : dimensions_(2) + { + sizes_[0] = size0; + sizes_[1] = size1; + } + + //! \brief Constructs three-dimensional range. + NDRange(::size_t size0, ::size_t size1, ::size_t size2) + : dimensions_(3) + { + sizes_[0] = size0; + sizes_[1] = size1; + sizes_[2] = size2; + } + + /*! \brief Conversion operator to const ::size_t *. + * + * \returns a pointer to the size of the first dimension. + */ + operator const ::size_t*() const { + return (const ::size_t*) sizes_; + } + + //! \brief Queries the number of dimensions in the range. + ::size_t dimensions() const { return dimensions_; } +}; + +//! \brief A zero-dimensional range. +static const NDRange NullRange; + +//! \brief Local address wrapper for use with Kernel::setArg +struct LocalSpaceArg +{ + ::size_t size_; +}; + +namespace detail { + +template +struct KernelArgumentHandler +{ + static ::size_t size(const T&) { return sizeof(T); } + static const T* ptr(const T& value) { return &value; } +}; + +template <> +struct KernelArgumentHandler +{ + static ::size_t size(const LocalSpaceArg& value) { return value.size_; } + static const void* ptr(const LocalSpaceArg&) { return NULL; } +}; + +} +//! \endcond + +/*! __local + * \brief Helper function for generating LocalSpaceArg objects. + * Deprecated. Replaced with Local. + */ +inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED LocalSpaceArg +__local(::size_t size) CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED; +inline LocalSpaceArg +__local(::size_t size) +{ + LocalSpaceArg ret = { size }; + return ret; +} + +/*! Local + * \brief Helper function for generating LocalSpaceArg objects. + */ +inline LocalSpaceArg +Local(::size_t size) +{ + LocalSpaceArg ret = { size }; + return ret; +} + +//class KernelFunctor; + +/*! \brief Class interface for cl_kernel. + * + * \note Copies of these objects are shallow, meaning that the copy will refer + * to the same underlying cl_kernel as the original. For details, see + * clRetainKernel() and clReleaseKernel(). + * + * \see cl_kernel + */ +class Kernel : public detail::Wrapper +{ +public: + inline Kernel(const Program& program, const char* name, cl_int* err = NULL); + + //! \brief Default constructor - initializes to NULL. + Kernel() { } + + /*! \brief Constructor from cl_kernel - takes ownership. + * + * This effectively transfers ownership of a refcount on the cl_kernel + * into the new Kernel object. + */ + __CL_EXPLICIT_CONSTRUCTORS Kernel(const cl_kernel& kernel) : detail::Wrapper(kernel) { } + + /*! \brief Assignment operator from cl_kernel - takes ownership. + * + * This effectively transfers ownership of a refcount on the rhs and calls + * clReleaseKernel() on the value previously held by this instance. + */ + Kernel& operator = (const cl_kernel& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Kernel(const Kernel& kernel) : detail::Wrapper(kernel) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Kernel& operator = (const Kernel &kernel) + { + detail::Wrapper::operator=(kernel); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Kernel(Kernel&& kernel) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(kernel)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Kernel& operator = (Kernel &&kernel) + { + detail::Wrapper::operator=(std::move(kernel)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + template + cl_int getInfo(cl_kernel_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetKernelInfo, object_, name, param), + __GET_KERNEL_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + +#if defined(CL_VERSION_1_2) + template + cl_int getArgInfo(cl_uint argIndex, cl_kernel_arg_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetKernelArgInfo, object_, argIndex, name, param), + __GET_KERNEL_ARG_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getArgInfo(cl_uint argIndex, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_arg_info, name>::param_type param; + cl_int result = getArgInfo(argIndex, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } +#endif // #if defined(CL_VERSION_1_2) + + template + cl_int getWorkGroupInfo( + const Device& device, cl_kernel_work_group_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetKernelWorkGroupInfo, object_, device(), name, param), + __GET_KERNEL_WORK_GROUP_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getWorkGroupInfo(const Device& device, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_kernel_work_group_info, name>::param_type param; + cl_int result = getWorkGroupInfo(device, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + template + cl_int setArg(cl_uint index, const T &value) + { + return detail::errHandler( + ::clSetKernelArg( + object_, + index, + detail::KernelArgumentHandler::size(value), + detail::KernelArgumentHandler::ptr(value)), + __SET_KERNEL_ARGS_ERR); + } + + cl_int setArg(cl_uint index, ::size_t size, const void* argPtr) + { + return detail::errHandler( + ::clSetKernelArg(object_, index, size, argPtr), + __SET_KERNEL_ARGS_ERR); + } +}; + +/*! \class Program + * \brief Program interface that implements cl_program. + */ +class Program : public detail::Wrapper +{ +public: + typedef VECTOR_CLASS > Binaries; + typedef VECTOR_CLASS > Sources; + + Program( + const STRING_CLASS& source, + bool build = false, + cl_int* err = NULL) + { + cl_int error; + + const char * strings = source.c_str(); + const ::size_t length = source.size(); + + Context context = Context::getDefault(err); + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)1, &strings, &length, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + + if (error == CL_SUCCESS && build) { + + error = ::clBuildProgram( + object_, + 0, + NULL, + "", + NULL, + NULL); + + detail::errHandler(error, __BUILD_PROGRAM_ERR); + } + + if (err != NULL) { + *err = error; + } + } + + Program( + const Context& context, + const STRING_CLASS& source, + bool build = false, + cl_int* err = NULL) + { + cl_int error; + + const char * strings = source.c_str(); + const ::size_t length = source.size(); + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)1, &strings, &length, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + + if (error == CL_SUCCESS && build) { + + error = ::clBuildProgram( + object_, + 0, + NULL, + "", + NULL, + NULL); + + detail::errHandler(error, __BUILD_PROGRAM_ERR); + } + + if (err != NULL) { + *err = error; + } + } + + Program( + const Context& context, + const Sources& sources, + cl_int* err = NULL) + { + cl_int error; + + const ::size_t n = (::size_t)sources.size(); + ::size_t* lengths = (::size_t*) alloca(n * sizeof(::size_t)); + const char** strings = (const char**) alloca(n * sizeof(const char*)); + + for (::size_t i = 0; i < n; ++i) { + strings[i] = sources[(int)i].first; + lengths[i] = sources[(int)i].second; + } + + object_ = ::clCreateProgramWithSource( + context(), (cl_uint)n, strings, lengths, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_SOURCE_ERR); + if (err != NULL) { + *err = error; + } + } + + /** + * Construct a program object from a list of devices and a per-device list of binaries. + * \param context A valid OpenCL context in which to construct the program. + * \param devices A vector of OpenCL device objects for which the program will be created. + * \param binaries A vector of pairs of a pointer to a binary object and its length. + * \param binaryStatus An optional vector that on completion will be resized to + * match the size of binaries and filled with values to specify if each binary + * was successfully loaded. + * Set to CL_SUCCESS if the binary was successfully loaded. + * Set to CL_INVALID_VALUE if the length is 0 or the binary pointer is NULL. + * Set to CL_INVALID_BINARY if the binary provided is not valid for the matching device. + * \param err if non-NULL will be set to CL_SUCCESS on successful operation or one of the following errors: + * CL_INVALID_CONTEXT if context is not a valid context. + * CL_INVALID_VALUE if the length of devices is zero; or if the length of binaries does not match the length of devices; + * or if any entry in binaries is NULL or has length 0. + * CL_INVALID_DEVICE if OpenCL devices listed in devices are not in the list of devices associated with context. + * CL_INVALID_BINARY if an invalid program binary was encountered for any device. binaryStatus will return specific status for each device. + * CL_OUT_OF_HOST_MEMORY if there is a failure to allocate resources required by the OpenCL implementation on the host. + */ + Program( + const Context& context, + const VECTOR_CLASS& devices, + const Binaries& binaries, + VECTOR_CLASS* binaryStatus = NULL, + cl_int* err = NULL) + { + cl_int error; + + const ::size_t numDevices = devices.size(); + + // Catch size mismatch early and return + if(binaries.size() != numDevices) { + error = CL_INVALID_VALUE; + detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR); + if (err != NULL) { + *err = error; + } + return; + } + + ::size_t* lengths = (::size_t*) alloca(numDevices * sizeof(::size_t)); + const unsigned char** images = (const unsigned char**) alloca(numDevices * sizeof(const unsigned char**)); + + for (::size_t i = 0; i < numDevices; ++i) { + images[i] = (const unsigned char*)binaries[i].first; + lengths[i] = binaries[(int)i].second; + } + + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + if(binaryStatus) { + binaryStatus->resize(numDevices); + } + + object_ = ::clCreateProgramWithBinary( + context(), (cl_uint) devices.size(), + deviceIDs, + lengths, images, (binaryStatus != NULL && numDevices > 0) + ? &binaryStatus->front() + : NULL, &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_BINARY_ERR); + if (err != NULL) { + *err = error; + } + } + + +#if defined(CL_VERSION_1_2) + /** + * Create program using builtin kernels. + * \param kernelNames Semi-colon separated list of builtin kernel names + */ + Program( + const Context& context, + const VECTOR_CLASS& devices, + const STRING_CLASS& kernelNames, + cl_int* err = NULL) + { + cl_int error; + + + ::size_t numDevices = devices.size(); + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + object_ = ::clCreateProgramWithBuiltInKernels( + context(), + (cl_uint) devices.size(), + deviceIDs, + kernelNames.c_str(), + &error); + + detail::errHandler(error, __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR); + if (err != NULL) { + *err = error; + } + } +#endif // #if defined(CL_VERSION_1_2) + + Program() { } + + __CL_EXPLICIT_CONSTRUCTORS Program(const cl_program& program) : detail::Wrapper(program) { } + + Program& operator = (const cl_program& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + Program(const Program& program) : detail::Wrapper(program) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + Program& operator = (const Program &program) + { + detail::Wrapper::operator=(program); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + Program(Program&& program) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(program)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + Program& operator = (Program &&program) + { + detail::Wrapper::operator=(std::move(program)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + cl_int build( + const VECTOR_CLASS& devices, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + ::size_t numDevices = devices.size(); + cl_device_id* deviceIDs = (cl_device_id*) alloca(numDevices * sizeof(cl_device_id)); + for( ::size_t deviceIndex = 0; deviceIndex < numDevices; ++deviceIndex ) { + deviceIDs[deviceIndex] = (devices[deviceIndex])(); + } + + return detail::errHandler( + ::clBuildProgram( + object_, + (cl_uint) + devices.size(), + deviceIDs, + options, + notifyFptr, + data), + __BUILD_PROGRAM_ERR); + } + + cl_int build( + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + return detail::errHandler( + ::clBuildProgram( + object_, + 0, + NULL, + options, + notifyFptr, + data), + __BUILD_PROGRAM_ERR); + } + +#if defined(CL_VERSION_1_2) + cl_int compile( + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL) const + { + return detail::errHandler( + ::clCompileProgram( + object_, + 0, + NULL, + options, + 0, + NULL, + NULL, + notifyFptr, + data), + __COMPILE_PROGRAM_ERR); + } +#endif + + template + cl_int getInfo(cl_program_info name, T* param) const + { + return detail::errHandler( + detail::getInfo(&::clGetProgramInfo, object_, name, param), + __GET_PROGRAM_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_program_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + template + cl_int getBuildInfo( + const Device& device, cl_program_build_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetProgramBuildInfo, object_, device(), name, param), + __GET_PROGRAM_BUILD_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getBuildInfo(const Device& device, cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_program_build_info, name>::param_type param; + cl_int result = getBuildInfo(device, name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + cl_int createKernels(VECTOR_CLASS* kernels) + { + cl_uint numKernels; + cl_int err = ::clCreateKernelsInProgram(object_, 0, NULL, &numKernels); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR); + } + + Kernel* value = (Kernel*) alloca(numKernels * sizeof(Kernel)); + err = ::clCreateKernelsInProgram( + object_, numKernels, (cl_kernel*) value, NULL); + if (err != CL_SUCCESS) { + return detail::errHandler(err, __CREATE_KERNELS_IN_PROGRAM_ERR); + } + + kernels->assign(&value[0], &value[numKernels]); + return CL_SUCCESS; + } +}; + +#if defined(CL_VERSION_1_2) +inline Program linkProgram( + Program input1, + Program input2, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL, + cl_int* err = NULL) +{ + cl_int error_local = CL_SUCCESS; + + cl_program programs[2] = { input1(), input2() }; + + Context ctx = input1.getInfo(&error_local); + if(error_local!=CL_SUCCESS) { + detail::errHandler(error_local, __LINK_PROGRAM_ERR); + } + + cl_program prog = ::clLinkProgram( + ctx(), + 0, + NULL, + options, + 2, + programs, + notifyFptr, + data, + &error_local); + + detail::errHandler(error_local,__COMPILE_PROGRAM_ERR); + if (err != NULL) { + *err = error_local; + } + + return Program(prog); +} + +inline Program linkProgram( + VECTOR_CLASS inputPrograms, + const char* options = NULL, + void (CL_CALLBACK * notifyFptr)(cl_program, void *) = NULL, + void* data = NULL, + cl_int* err = NULL) +{ + cl_int error_local = CL_SUCCESS; + + cl_program * programs = (cl_program*) alloca(inputPrograms.size() * sizeof(cl_program)); + + if (programs != NULL) { + for (unsigned int i = 0; i < inputPrograms.size(); i++) { + programs[i] = inputPrograms[i](); + } + } + + Context ctx; + if(inputPrograms.size() > 0) { + ctx = inputPrograms[0].getInfo(&error_local); + if(error_local!=CL_SUCCESS) { + detail::errHandler(error_local, __LINK_PROGRAM_ERR); + } + } + cl_program prog = ::clLinkProgram( + ctx(), + 0, + NULL, + options, + (cl_uint)inputPrograms.size(), + programs, + notifyFptr, + data, + &error_local); + + detail::errHandler(error_local,__COMPILE_PROGRAM_ERR); + if (err != NULL) { + *err = error_local; + } + + return Program(prog); +} +#endif + +template<> +inline VECTOR_CLASS cl::Program::getInfo(cl_int* err) const +{ + VECTOR_CLASS< ::size_t> sizes = getInfo(); + VECTOR_CLASS binaries; + for (VECTOR_CLASS< ::size_t>::iterator s = sizes.begin(); s != sizes.end(); ++s) + { + char *ptr = NULL; + if (*s != 0) + ptr = new char[*s]; + binaries.push_back(ptr); + } + + cl_int result = getInfo(CL_PROGRAM_BINARIES, &binaries); + if (err != NULL) { + *err = result; + } + return binaries; +} + +inline Kernel::Kernel(const Program& program, const char* name, cl_int* err) +{ + cl_int error; + + object_ = ::clCreateKernel(program(), name, &error); + detail::errHandler(error, __CREATE_KERNEL_ERR); + + if (err != NULL) { + *err = error; + } + +} + +/*! \class CommandQueue + * \brief CommandQueue interface for cl_command_queue. + */ +class CommandQueue : public detail::Wrapper +{ +private: +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED + static std::atomic default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static volatile int default_initialized_; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED + static CommandQueue default_; + static volatile cl_int default_error_; +public: + CommandQueue( + cl_command_queue_properties properties, + cl_int* err = NULL) + { + cl_int error; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + Device device = context.getInfo()[0]; + + object_ = ::clCreateCommandQueue( + context(), device(), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } + } + } + /*! + * \brief Constructs a CommandQueue for an implementation defined device in the given context + */ + explicit CommandQueue( + const Context& context, + cl_command_queue_properties properties = 0, + cl_int* err = NULL) + { + cl_int error; + VECTOR_CLASS devices; + error = context.getInfo(CL_CONTEXT_DEVICES, &devices); + + detail::errHandler(error, __CREATE_CONTEXT_ERR); + + if (error != CL_SUCCESS) + { + if (err != NULL) { + *err = error; + } + return; + } + + object_ = ::clCreateCommandQueue(context(), devices[0](), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + + if (err != NULL) { + *err = error; + } + + } + + CommandQueue( + const Context& context, + const Device& device, + cl_command_queue_properties properties = 0, + cl_int* err = NULL) + { + cl_int error; + object_ = ::clCreateCommandQueue( + context(), device(), properties, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } + } + + /*! \brief Copy constructor to forward copy to the superclass correctly. + * Required for MSVC. + */ + CommandQueue(const CommandQueue& queue) : detail::Wrapper(queue) {} + + /*! \brief Copy assignment to forward copy to the superclass correctly. + * Required for MSVC. + */ + CommandQueue& operator = (const CommandQueue &queue) + { + detail::Wrapper::operator=(queue); + return *this; + } + +#if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + /*! \brief Move constructor to forward move to the superclass correctly. + * Required for MSVC. + */ + CommandQueue(CommandQueue&& queue) CL_HPP_NOEXCEPT : detail::Wrapper(std::move(queue)) {} + + /*! \brief Move assignment to forward move to the superclass correctly. + * Required for MSVC. + */ + CommandQueue& operator = (CommandQueue &&queue) + { + detail::Wrapper::operator=(std::move(queue)); + return *this; + } +#endif // #if defined(CL_HPP_RVALUE_REFERENCES_SUPPORTED) + + static CommandQueue getDefault(cl_int * err = NULL) + { + int state = detail::compare_exchange( + &default_initialized_, + __DEFAULT_BEING_INITIALIZED, __DEFAULT_NOT_INITIALIZED); + + if (state & __DEFAULT_INITIALIZED) { + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + if (state & __DEFAULT_BEING_INITIALIZED) { + // Assume writes will propagate eventually... + while(default_initialized_ != __DEFAULT_INITIALIZED) { + detail::fence(); + } + + if (err != NULL) { + *err = default_error_; + } + return default_; + } + + cl_int error; + + Context context = Context::getDefault(&error); + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + + if (error != CL_SUCCESS) { + if (err != NULL) { + *err = error; + } + } + else { + Device device = context.getInfo()[0]; + + default_ = CommandQueue(context, device, 0, &error); + + detail::errHandler(error, __CREATE_COMMAND_QUEUE_ERR); + if (err != NULL) { + *err = error; + } + } + + detail::fence(); + + default_error_ = error; + // Assume writes will propagate eventually... + default_initialized_ = __DEFAULT_INITIALIZED; + + detail::fence(); + + if (err != NULL) { + *err = default_error_; + } + return default_; + + } + + CommandQueue() { } + + __CL_EXPLICIT_CONSTRUCTORS CommandQueue(const cl_command_queue& commandQueue) : detail::Wrapper(commandQueue) { } + + CommandQueue& operator = (const cl_command_queue& rhs) + { + detail::Wrapper::operator=(rhs); + return *this; + } + + template + cl_int getInfo(cl_command_queue_info name, T* param) const + { + return detail::errHandler( + detail::getInfo( + &::clGetCommandQueueInfo, object_, name, param), + __GET_COMMAND_QUEUE_INFO_ERR); + } + + template typename + detail::param_traits::param_type + getInfo(cl_int* err = NULL) const + { + typename detail::param_traits< + detail::cl_command_queue_info, name>::param_type param; + cl_int result = getInfo(name, ¶m); + if (err != NULL) { + *err = result; + } + return param; + } + + cl_int enqueueReadBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadBuffer( + object_, buffer(), blocking, offset, size, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + const void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteBuffer( + object_, buffer(), blocking, offset, size, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBuffer( + const Buffer& src, + const Buffer& dst, + ::size_t src_offset, + ::size_t dst_offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBuffer( + object_, src(), dst(), src_offset, dst_offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQEUE_COPY_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReadBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadBufferRect( + object_, + buffer(), + blocking, + (const ::size_t *)buffer_offset, + (const ::size_t *)host_offset, + (const ::size_t *)region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteBufferRect( + object_, + buffer(), + blocking, + (const ::size_t *)buffer_offset, + (const ::size_t *)host_offset, + (const ::size_t *)region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBufferRect( + const Buffer& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + ::size_t src_row_pitch, + ::size_t src_slice_pitch, + ::size_t dst_row_pitch, + ::size_t dst_slice_pitch, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBufferRect( + object_, + src(), + dst(), + (const ::size_t *)src_origin, + (const ::size_t *)dst_origin, + (const ::size_t *)region, + src_row_pitch, + src_slice_pitch, + dst_row_pitch, + dst_slice_pitch, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQEUE_COPY_BUFFER_RECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_VERSION_1_2) + /** + * Enqueue a command to fill a buffer object with a pattern + * of a given size. The pattern is specified a as vector. + * \tparam PatternType The datatype of the pattern field. + * The pattern type must be an accepted OpenCL data type. + */ + template + cl_int enqueueFillBuffer( + const Buffer& buffer, + PatternType pattern, + ::size_t offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillBuffer( + object_, + buffer(), + static_cast(&pattern), + sizeof(PatternType), + offset, + size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_VERSION_1_2) + + cl_int enqueueReadImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReadImage( + object_, image(), blocking, (const ::size_t *) origin, + (const ::size_t *) region, row_pitch, slice_pitch, ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_READ_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueWriteImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueWriteImage( + object_, image(), blocking, (const ::size_t *) origin, + (const ::size_t *) region, row_pitch, slice_pitch, ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_WRITE_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyImage( + const Image& src, + const Image& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyImage( + object_, src(), dst(), (const ::size_t *) src_origin, + (const ::size_t *)dst_origin, (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_VERSION_1_2) + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA floating-point color value if + * the image channel data type is not an unnormalized signed or + * unsigned data type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_float4 fillColor, + const size_t<3>& origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + (const ::size_t *) origin, + (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA signed integer color value if + * the image channel data type is an unnormalized signed integer + * type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_int4 fillColor, + const size_t<3>& origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + (const ::size_t *) origin, + (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueue a command to fill an image object with a specified color. + * \param fillColor is the color to use to fill the image. + * This is a four component RGBA unsigned integer color value if + * the image channel data type is an unnormalized unsigned integer + * type. + */ + cl_int enqueueFillImage( + const Image& image, + cl_uint4 fillColor, + const size_t<3>& origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueFillImage( + object_, + image(), + static_cast(&fillColor), + (const ::size_t *) origin, + (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_FILL_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_VERSION_1_2) + + cl_int enqueueCopyImageToBuffer( + const Image& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& region, + ::size_t dst_offset, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyImageToBuffer( + object_, src(), dst(), (const ::size_t *) src_origin, + (const ::size_t *) region, dst_offset, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueCopyBufferToImage( + const Buffer& src, + const Image& dst, + ::size_t src_offset, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueCopyBufferToImage( + object_, src(), dst(), src_offset, + (const ::size_t *) dst_origin, (const ::size_t *) region, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + void* enqueueMapBuffer( + const Buffer& buffer, + cl_bool blocking, + cl_map_flags flags, + ::size_t offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL, + cl_int* err = NULL) const + { + cl_event tmp; + cl_int error; + void * result = ::clEnqueueMapBuffer( + object_, buffer(), blocking, flags, offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + if (event != NULL && error == CL_SUCCESS) + *event = tmp; + + return result; + } + + void* enqueueMapImage( + const Image& buffer, + cl_bool blocking, + cl_map_flags flags, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t * row_pitch, + ::size_t * slice_pitch, + const VECTOR_CLASS* events = NULL, + Event* event = NULL, + cl_int* err = NULL) const + { + cl_event tmp; + cl_int error; + void * result = ::clEnqueueMapImage( + object_, buffer(), blocking, flags, + (const ::size_t *) origin, (const ::size_t *) region, + row_pitch, slice_pitch, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_IMAGE_ERR); + if (err != NULL) { + *err = error; + } + if (event != NULL && error == CL_SUCCESS) + *event = tmp; + return result; + } + + cl_int enqueueUnmapMemObject( + const Memory& memory, + void* mapped_ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueUnmapMemObject( + object_, memory(), mapped_ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined(CL_VERSION_1_2) + /** + * Enqueues a marker command which waits for either a list of events to complete, + * or all previously enqueued commands to complete. + * + * Enqueues a marker command which waits for either a list of events to complete, + * or if the list is empty it waits for all commands previously enqueued in command_queue + * to complete before it completes. This command returns an event which can be waited on, + * i.e. this event can be waited on to insure that all events either in the event_wait_list + * or all previously enqueued commands, queued before this command to command_queue, + * have completed. + */ + cl_int enqueueMarkerWithWaitList( + const VECTOR_CLASS *events = 0, + Event *event = 0) + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueMarkerWithWaitList( + object_, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MARKER_WAIT_LIST_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * A synchronization point that enqueues a barrier operation. + * + * Enqueues a barrier command which waits for either a list of events to complete, + * or if the list is empty it waits for all commands previously enqueued in command_queue + * to complete before it completes. This command blocks command execution, that is, any + * following commands enqueued after it do not execute until it completes. This command + * returns an event which can be waited on, i.e. this event can be waited on to insure that + * all events either in the event_wait_list or all previously enqueued commands, queued + * before this command to command_queue, have completed. + */ + cl_int enqueueBarrierWithWaitList( + const VECTOR_CLASS *events = 0, + Event *event = 0) + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueBarrierWithWaitList( + object_, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_BARRIER_WAIT_LIST_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + /** + * Enqueues a command to indicate with which device a set of memory objects + * should be associated. + */ + cl_int enqueueMigrateMemObjects( + const VECTOR_CLASS &memObjects, + cl_mem_migration_flags flags, + const VECTOR_CLASS* events = NULL, + Event* event = NULL + ) + { + cl_event tmp; + + cl_mem* localMemObjects = static_cast(alloca(memObjects.size() * sizeof(cl_mem))); + for( int i = 0; i < (int)memObjects.size(); ++i ) { + localMemObjects[i] = memObjects[i](); + } + + + cl_int err = detail::errHandler( + ::clEnqueueMigrateMemObjects( + object_, + (cl_uint)memObjects.size(), + static_cast(localMemObjects), + flags, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif // #if defined(CL_VERSION_1_2) + + cl_int enqueueNDRangeKernel( + const Kernel& kernel, + const NDRange& offset, + const NDRange& global, + const NDRange& local = NullRange, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueNDRangeKernel( + object_, kernel(), (cl_uint) global.dimensions(), + offset.dimensions() != 0 ? (const ::size_t*) offset : NULL, + (const ::size_t*) global, + local.dimensions() != 0 ? (const ::size_t*) local : NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_NDRANGE_KERNEL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueTask( + const Kernel& kernel, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueTask( + object_, kernel(), + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_TASK_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueNativeKernel( + void (CL_CALLBACK *userFptr)(void *), + std::pair args, + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* mem_locs = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_mem * mems = (mem_objects != NULL && mem_objects->size() > 0) + ? (cl_mem*) alloca(mem_objects->size() * sizeof(cl_mem)) + : NULL; + + if (mems != NULL) { + for (unsigned int i = 0; i < mem_objects->size(); i++) { + mems[i] = ((*mem_objects)[i])(); + } + } + + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueNativeKernel( + object_, userFptr, args.first, args.second, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + mems, + (mem_locs != NULL && mem_locs->size() > 0) ? (const void **) &mem_locs->front() : NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_NATIVE_KERNEL); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueMarker(Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueMarker( + object_, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_MARKER_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueWaitForEvents(const VECTOR_CLASS& events) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + return detail::errHandler( + ::clEnqueueWaitForEvents( + object_, + (cl_uint) events.size(), + events.size() > 0 ? (const cl_event*) &events.front() : NULL), + __ENQUEUE_WAIT_FOR_EVENTS_ERR); + } +#endif // #if defined(CL_VERSION_1_1) + + cl_int enqueueAcquireGLObjects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueAcquireGLObjects( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_ACQUIRE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReleaseGLObjects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueReleaseGLObjects( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_RELEASE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + +#if defined (USE_DX_INTEROP) +typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueAcquireD3D10ObjectsKHR)( + cl_command_queue command_queue, cl_uint num_objects, + const cl_mem* mem_objects, cl_uint num_events_in_wait_list, + const cl_event* event_wait_list, cl_event* event); +typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueReleaseD3D10ObjectsKHR)( + cl_command_queue command_queue, cl_uint num_objects, + const cl_mem* mem_objects, cl_uint num_events_in_wait_list, + const cl_event* event_wait_list, cl_event* event); + + cl_int enqueueAcquireD3D10Objects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + static PFN_clEnqueueAcquireD3D10ObjectsKHR pfn_clEnqueueAcquireD3D10ObjectsKHR = NULL; +#if defined(CL_VERSION_1_2) + cl_context context = getInfo(); + cl::Device device(getInfo()); + cl_platform_id platform = device.getInfo(); + __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clEnqueueAcquireD3D10ObjectsKHR); +#endif +#if defined(CL_VERSION_1_1) + __INIT_CL_EXT_FCN_PTR(clEnqueueAcquireD3D10ObjectsKHR); +#endif + + cl_event tmp; + cl_int err = detail::errHandler( + pfn_clEnqueueAcquireD3D10ObjectsKHR( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_ACQUIRE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } + + cl_int enqueueReleaseD3D10Objects( + const VECTOR_CLASS* mem_objects = NULL, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) const + { + static PFN_clEnqueueReleaseD3D10ObjectsKHR pfn_clEnqueueReleaseD3D10ObjectsKHR = NULL; +#if defined(CL_VERSION_1_2) + cl_context context = getInfo(); + cl::Device device(getInfo()); + cl_platform_id platform = device.getInfo(); + __INIT_CL_EXT_FCN_PTR_PLATFORM(platform, clEnqueueReleaseD3D10ObjectsKHR); +#endif // #if defined(CL_VERSION_1_2) +#if defined(CL_VERSION_1_1) + __INIT_CL_EXT_FCN_PTR(clEnqueueReleaseD3D10ObjectsKHR); +#endif // #if defined(CL_VERSION_1_1) + + cl_event tmp; + cl_int err = detail::errHandler( + pfn_clEnqueueReleaseD3D10ObjectsKHR( + object_, + (mem_objects != NULL) ? (cl_uint) mem_objects->size() : 0, + (mem_objects != NULL && mem_objects->size() > 0) ? (const cl_mem *) &mem_objects->front(): NULL, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_RELEASE_GL_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; + } +#endif + +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS) || (defined(CL_VERSION_1_1) && !defined(CL_VERSION_1_2)) + CL_EXT_PREFIX__VERSION_1_1_DEPRECATED + cl_int enqueueBarrier() const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED + { + return detail::errHandler( + ::clEnqueueBarrier(object_), + __ENQUEUE_BARRIER_ERR); + } +#endif // #if defined(CL_VERSION_1_1) + + cl_int flush() const + { + return detail::errHandler(::clFlush(object_), __FLUSH_ERR); + } + + cl_int finish() const + { + return detail::errHandler(::clFinish(object_), __FINISH_ERR); + } +}; + +#ifdef _WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) std::atomic CommandQueue::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) volatile int CommandQueue::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__declspec(selectany) CommandQueue CommandQueue::default_; +__declspec(selectany) volatile cl_int CommandQueue::default_error_ = CL_SUCCESS; +#else // !_WIN32 +#ifdef CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) std::atomic CommandQueue::default_initialized_; +#else // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) volatile int CommandQueue::default_initialized_ = __DEFAULT_NOT_INITIALIZED; +#endif // !CL_HPP_CPP11_ATOMICS_SUPPORTED +__attribute__((weak)) CommandQueue CommandQueue::default_; +__attribute__((weak)) volatile cl_int CommandQueue::default_error_ = CL_SUCCESS; +#endif // !_WIN32 + +template< typename IteratorType > +Buffer::Buffer( + const Context &context, + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr, + cl_int* err) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if( readOnly ) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if( useHostPtr ) { + flags |= CL_MEM_USE_HOST_PTR; + } + + ::size_t size = sizeof(DataType)*(endIterator - startIterator); + + if( useHostPtr ) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if( !useHostPtr ) { + CommandQueue queue(context, 0, &error); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + error = cl::copy(queue, startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } +} + +template< typename IteratorType > +Buffer::Buffer( + const CommandQueue &queue, + IteratorType startIterator, + IteratorType endIterator, + bool readOnly, + bool useHostPtr, + cl_int* err) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + cl_mem_flags flags = 0; + if (readOnly) { + flags |= CL_MEM_READ_ONLY; + } + else { + flags |= CL_MEM_READ_WRITE; + } + if (useHostPtr) { + flags |= CL_MEM_USE_HOST_PTR; + } + + ::size_t size = sizeof(DataType)*(endIterator - startIterator); + + Context context = queue.getInfo(); + + if (useHostPtr) { + object_ = ::clCreateBuffer(context(), flags, size, static_cast(&*startIterator), &error); + } + else { + object_ = ::clCreateBuffer(context(), flags, size, 0, &error); + } + + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + if (!useHostPtr) { + error = cl::copy(queue, startIterator, endIterator, *this); + detail::errHandler(error, __CREATE_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + } +} + +inline cl_int enqueueReadBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadBuffer(buffer, blocking, offset, size, ptr, events, event); +} + +inline cl_int enqueueWriteBuffer( + const Buffer& buffer, + cl_bool blocking, + ::size_t offset, + ::size_t size, + const void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteBuffer(buffer, blocking, offset, size, ptr, events, event); +} + +inline void* enqueueMapBuffer( + const Buffer& buffer, + cl_bool blocking, + cl_map_flags flags, + ::size_t offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL, + cl_int* err = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + + void * result = ::clEnqueueMapBuffer( + queue(), buffer(), blocking, flags, offset, size, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (cl_event*) event, + &error); + + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (err != NULL) { + *err = error; + } + return result; +} + +inline cl_int enqueueUnmapMemObject( + const Memory& memory, + void* mapped_ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + detail::errHandler(error, __ENQUEUE_MAP_BUFFER_ERR); + if (error != CL_SUCCESS) { + return error; + } + + cl_event tmp; + cl_int err = detail::errHandler( + ::clEnqueueUnmapMemObject( + queue(), memory(), mapped_ptr, + (events != NULL) ? (cl_uint) events->size() : 0, + (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL, + (event != NULL) ? &tmp : NULL), + __ENQUEUE_UNMAP_MEM_OBJECT_ERR); + + if (event != NULL && err == CL_SUCCESS) + *event = tmp; + + return err; +} + +inline cl_int enqueueCopyBuffer( + const Buffer& src, + const Buffer& dst, + ::size_t src_offset, + ::size_t dst_offset, + ::size_t size, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBuffer(src, dst, src_offset, dst_offset, size, events, event); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Host to Device. + * Uses default command queue. + */ +template< typename IteratorType > +inline cl_int copy( IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) + return error; + + return cl::copy(queue, startIterator, endIterator, buffer); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Device to Host. + * Uses default command queue. + */ +template< typename IteratorType > +inline cl_int copy( const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + if (error != CL_SUCCESS) + return error; + + return cl::copy(queue, buffer, startIterator, endIterator); +} + +/** + * Blocking copy operation between iterators and a buffer. + * Host to Device. + * Uses specified queue. + */ +template< typename IteratorType > +inline cl_int copy( const CommandQueue &queue, IteratorType startIterator, IteratorType endIterator, cl::Buffer &buffer ) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + ::size_t length = endIterator-startIterator; + ::size_t byteLength = length*sizeof(DataType); + + DataType *pointer = + static_cast(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_WRITE, 0, byteLength, 0, 0, &error)); + // if exceptions enabled, enqueueMapBuffer will throw + if( error != CL_SUCCESS ) { + return error; + } +#if defined(_MSC_VER) + std::copy( + startIterator, + endIterator, + stdext::checked_array_iterator( + pointer, length)); +#else + std::copy(startIterator, endIterator, pointer); +#endif + Event endEvent; + error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent); + // if exceptions enabled, enqueueUnmapMemObject will throw + if( error != CL_SUCCESS ) { + return error; + } + endEvent.wait(); + return CL_SUCCESS; +} + +/** + * Blocking copy operation between iterators and a buffer. + * Device to Host. + * Uses specified queue. + */ +template< typename IteratorType > +inline cl_int copy( const CommandQueue &queue, const cl::Buffer &buffer, IteratorType startIterator, IteratorType endIterator ) +{ + typedef typename std::iterator_traits::value_type DataType; + cl_int error; + + ::size_t length = endIterator-startIterator; + ::size_t byteLength = length*sizeof(DataType); + + DataType *pointer = + static_cast(queue.enqueueMapBuffer(buffer, CL_TRUE, CL_MAP_READ, 0, byteLength, 0, 0, &error)); + // if exceptions enabled, enqueueMapBuffer will throw + if( error != CL_SUCCESS ) { + return error; + } + std::copy(pointer, pointer + length, startIterator); + Event endEvent; + error = queue.enqueueUnmapMemObject(buffer, pointer, 0, &endEvent); + // if exceptions enabled, enqueueUnmapMemObject will throw + if( error != CL_SUCCESS ) { + return error; + } + endEvent.wait(); + return CL_SUCCESS; +} + +#if defined(CL_VERSION_1_1) +inline cl_int enqueueReadBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadBufferRect( + buffer, + blocking, + buffer_offset, + host_offset, + region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueWriteBufferRect( + const Buffer& buffer, + cl_bool blocking, + const size_t<3>& buffer_offset, + const size_t<3>& host_offset, + const size_t<3>& region, + ::size_t buffer_row_pitch, + ::size_t buffer_slice_pitch, + ::size_t host_row_pitch, + ::size_t host_slice_pitch, + void *ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteBufferRect( + buffer, + blocking, + buffer_offset, + host_offset, + region, + buffer_row_pitch, + buffer_slice_pitch, + host_row_pitch, + host_slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueCopyBufferRect( + const Buffer& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + ::size_t src_row_pitch, + ::size_t src_slice_pitch, + ::size_t dst_row_pitch, + ::size_t dst_slice_pitch, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBufferRect( + src, + dst, + src_origin, + dst_origin, + region, + src_row_pitch, + src_slice_pitch, + dst_row_pitch, + dst_slice_pitch, + events, + event); +} +#endif + +inline cl_int enqueueReadImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueReadImage( + image, + blocking, + origin, + region, + row_pitch, + slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueWriteImage( + const Image& image, + cl_bool blocking, + const size_t<3>& origin, + const size_t<3>& region, + ::size_t row_pitch, + ::size_t slice_pitch, + void* ptr, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueWriteImage( + image, + blocking, + origin, + region, + row_pitch, + slice_pitch, + ptr, + events, + event); +} + +inline cl_int enqueueCopyImage( + const Image& src, + const Image& dst, + const size_t<3>& src_origin, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyImage( + src, + dst, + src_origin, + dst_origin, + region, + events, + event); +} + +inline cl_int enqueueCopyImageToBuffer( + const Image& src, + const Buffer& dst, + const size_t<3>& src_origin, + const size_t<3>& region, + ::size_t dst_offset, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyImageToBuffer( + src, + dst, + src_origin, + region, + dst_offset, + events, + event); +} + +inline cl_int enqueueCopyBufferToImage( + const Buffer& src, + const Image& dst, + ::size_t src_offset, + const size_t<3>& dst_origin, + const size_t<3>& region, + const VECTOR_CLASS* events = NULL, + Event* event = NULL) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.enqueueCopyBufferToImage( + src, + dst, + src_offset, + dst_origin, + region, + events, + event); +} + + +inline cl_int flush(void) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + return queue.flush(); +} + +inline cl_int finish(void) +{ + cl_int error; + CommandQueue queue = CommandQueue::getDefault(&error); + + if (error != CL_SUCCESS) { + return error; + } + + + return queue.finish(); +} + +// Kernel Functor support +// New interface as of September 2011 +// Requires the C++11 std::tr1::function (note do not support TR1) +// Visual Studio 2010 and GCC 4.2 + +struct EnqueueArgs +{ + CommandQueue queue_; + const NDRange offset_; + const NDRange global_; + const NDRange local_; + VECTOR_CLASS events_; + + EnqueueArgs(NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange) + { + + } + + EnqueueArgs(NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local) + { + + } + + EnqueueArgs(NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local) + { + + } + + EnqueueArgs(Event e, NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange) + { + events_.push_back(e); + } + + EnqueueArgs(Event e, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(Event e, NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(const VECTOR_CLASS &events, NDRange global) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(NullRange), + events_(events) + { + + } + + EnqueueArgs(const VECTOR_CLASS &events, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(NullRange), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(const VECTOR_CLASS &events, NDRange offset, NDRange global, NDRange local) : + queue_(CommandQueue::getDefault()), + offset_(offset), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local) + { + + } + + EnqueueArgs(CommandQueue &queue, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local) + { + + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, Event e, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local) + { + events_.push_back(e); + } + + EnqueueArgs(CommandQueue &queue, const VECTOR_CLASS &events, NDRange global) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(NullRange), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, const VECTOR_CLASS &events, NDRange global, NDRange local) : + queue_(queue), + offset_(NullRange), + global_(global), + local_(local), + events_(events) + { + + } + + EnqueueArgs(CommandQueue &queue, const VECTOR_CLASS &events, NDRange offset, NDRange global, NDRange local) : + queue_(queue), + offset_(offset), + global_(global), + local_(local), + events_(events) + { + + } +}; + +namespace detail { + +class NullType {}; + +template +struct SetArg +{ + static void set (Kernel kernel, T0 arg) + { + kernel.setArg(index, arg); + } +}; + +template +struct SetArg +{ + static void set (Kernel, NullType) + { + } +}; + +template < + typename T0, typename T1, typename T2, typename T3, + typename T4, typename T5, typename T6, typename T7, + typename T8, typename T9, typename T10, typename T11, + typename T12, typename T13, typename T14, typename T15, + typename T16, typename T17, typename T18, typename T19, + typename T20, typename T21, typename T22, typename T23, + typename T24, typename T25, typename T26, typename T27, + typename T28, typename T29, typename T30, typename T31 +> +class KernelFunctorGlobal +{ +private: + Kernel kernel_; + +public: + KernelFunctorGlobal( + Kernel kernel) : + kernel_(kernel) + {} + + KernelFunctorGlobal( + const Program& program, + const STRING_CLASS name, + cl_int * err = NULL) : + kernel_(program, name.c_str(), err) + {} + + Event operator() ( + const EnqueueArgs& args, + T0 t0, + T1 t1 = NullType(), + T2 t2 = NullType(), + T3 t3 = NullType(), + T4 t4 = NullType(), + T5 t5 = NullType(), + T6 t6 = NullType(), + T7 t7 = NullType(), + T8 t8 = NullType(), + T9 t9 = NullType(), + T10 t10 = NullType(), + T11 t11 = NullType(), + T12 t12 = NullType(), + T13 t13 = NullType(), + T14 t14 = NullType(), + T15 t15 = NullType(), + T16 t16 = NullType(), + T17 t17 = NullType(), + T18 t18 = NullType(), + T19 t19 = NullType(), + T20 t20 = NullType(), + T21 t21 = NullType(), + T22 t22 = NullType(), + T23 t23 = NullType(), + T24 t24 = NullType(), + T25 t25 = NullType(), + T26 t26 = NullType(), + T27 t27 = NullType(), + T28 t28 = NullType(), + T29 t29 = NullType(), + T30 t30 = NullType(), + T31 t31 = NullType() + ) + { + Event event; + SetArg<0, T0>::set(kernel_, t0); + SetArg<1, T1>::set(kernel_, t1); + SetArg<2, T2>::set(kernel_, t2); + SetArg<3, T3>::set(kernel_, t3); + SetArg<4, T4>::set(kernel_, t4); + SetArg<5, T5>::set(kernel_, t5); + SetArg<6, T6>::set(kernel_, t6); + SetArg<7, T7>::set(kernel_, t7); + SetArg<8, T8>::set(kernel_, t8); + SetArg<9, T9>::set(kernel_, t9); + SetArg<10, T10>::set(kernel_, t10); + SetArg<11, T11>::set(kernel_, t11); + SetArg<12, T12>::set(kernel_, t12); + SetArg<13, T13>::set(kernel_, t13); + SetArg<14, T14>::set(kernel_, t14); + SetArg<15, T15>::set(kernel_, t15); + SetArg<16, T16>::set(kernel_, t16); + SetArg<17, T17>::set(kernel_, t17); + SetArg<18, T18>::set(kernel_, t18); + SetArg<19, T19>::set(kernel_, t19); + SetArg<20, T20>::set(kernel_, t20); + SetArg<21, T21>::set(kernel_, t21); + SetArg<22, T22>::set(kernel_, t22); + SetArg<23, T23>::set(kernel_, t23); + SetArg<24, T24>::set(kernel_, t24); + SetArg<25, T25>::set(kernel_, t25); + SetArg<26, T26>::set(kernel_, t26); + SetArg<27, T27>::set(kernel_, t27); + SetArg<28, T28>::set(kernel_, t28); + SetArg<29, T29>::set(kernel_, t29); + SetArg<30, T30>::set(kernel_, t30); + SetArg<31, T31>::set(kernel_, t31); + + args.queue_.enqueueNDRangeKernel( + kernel_, + args.offset_, + args.global_, + args.local_, + &args.events_, + &event); + + return event; + } + +}; + +//------------------------------------------------------------------------------------------------------ + + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28, + typename T29, + typename T30, + typename T31> +struct functionImplementation_ +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + T31> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 32)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + T31); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28, + T29 arg29, + T30 arg30, + T31 arg31) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28, + arg29, + arg30, + arg31); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28, + typename T29, + typename T30> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 31)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + T30); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28, + T29 arg29, + T30 arg30) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28, + arg29, + arg30); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28, + typename T29> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 30)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + T29); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28, + T29 arg29) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28, + arg29); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27, + typename T28> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 29)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + T28); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27, + T28 arg28) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27, + arg28); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26, + typename T27> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 28)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + T27); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26, + T27 arg27) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26, + arg27); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25, + typename T26> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 27)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + T26); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25, + T26 arg26) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25, + arg26); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24, + typename T25> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 26)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + T25); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24, + T25 arg25) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24, + arg25); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23, + typename T24> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 25)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + T24); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23, + T24 arg24) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23, + arg24); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22, + typename T23> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 24)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + T23); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22, + T23 arg23) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22, + arg23); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21, + typename T22> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 23)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + T22); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21, + T22 arg22) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21, + arg22); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20, + typename T21> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 22)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + T21); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20, + T21 arg21) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20, + arg21); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19, + typename T20> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 21)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + T20); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19, + T20 arg20) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19, + arg20); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18, + typename T19> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 20)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + T19); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18, + T19 arg19) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18, + arg19); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17, + typename T18> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 19)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + T18); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17, + T18 arg18) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17, + arg18); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16, + typename T17> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 18)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + T17); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16, + T17 arg17) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16, + arg17); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15, + typename T16> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 17)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + T16); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15, + T16 arg16) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15, + arg16); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14, + typename T15> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 16)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + T15); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14, + T15 arg15) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14, + arg15); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13, + typename T14> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 15)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + T14); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13, + T14 arg14) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13, + arg14); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12, + typename T13> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 14)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + T13); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12, + T13 arg13) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12, + arg13); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11, + typename T12> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 13)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + T12); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11, + T12 arg12) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11, + arg12); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10, + typename T11> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 12)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + T11); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10, + T11 arg11) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10, + arg11); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9, + typename T10> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 11)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + T10); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9, + T10 arg10) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9, + arg10); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8, + typename T9> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 10)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + T9); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8, + T9 arg9) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8, + arg9); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7, + typename T8> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 9)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + T8); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7, + T8 arg8) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7, + arg8); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6, + typename T7> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 8)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6, + T7); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6, + T7 arg7) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6, + arg7); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5, + typename T6> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + T6, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + T6, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 7)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5, + T6); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5, + T6 arg6) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5, + arg6); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4, + typename T5> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + T5, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + T5, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 6)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4, + T5); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4, + T5 arg5) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4, + arg5); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3, + typename T4> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + T4, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + T4, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 5)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3, + T4); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3, + arg4); + } + + +}; + +template< + typename T0, + typename T1, + typename T2, + typename T3> +struct functionImplementation_ +< T0, + T1, + T2, + T3, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + T3, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 4)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2, + T3); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2, + T3 arg3) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2, + arg3); + } + + +}; + +template< + typename T0, + typename T1, + typename T2> +struct functionImplementation_ +< T0, + T1, + T2, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + T2, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 3)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1, + T2); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1, + T2 arg2) + { + return functor_( + enqueueArgs, + arg0, + arg1, + arg2); + } + + +}; + +template< + typename T0, + typename T1> +struct functionImplementation_ +< T0, + T1, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + T1, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 2)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0, + T1); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0, + T1 arg1) + { + return functor_( + enqueueArgs, + arg0, + arg1); + } + + +}; + +template< + typename T0> +struct functionImplementation_ +< T0, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> +{ + typedef detail::KernelFunctorGlobal< + T0, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType, + NullType> FunctorType; + + FunctorType functor_; + + functionImplementation_(const FunctorType &functor) : + functor_(functor) + { + + #if (defined(_WIN32) && defined(_VARIADIC_MAX) && (_VARIADIC_MAX < 1)) + // Fail variadic expansion for dev11 + static_assert(0, "Visual Studio has a hard limit of argument count for a std::function expansion. Please define _VARIADIC_MAX to be 10. If you need more arguments than that VC12 and below cannot support it."); + #endif + + } + + //! \brief Return type of the functor + typedef Event result_type; + + //! \brief Function signature of kernel functor with no event dependency. + typedef Event type_( + const EnqueueArgs&, + T0); + + Event operator()( + const EnqueueArgs& enqueueArgs, + T0 arg0) + { + return functor_( + enqueueArgs, + arg0); + } + + +}; + + + + + +} // namespace detail + +//---------------------------------------------------------------------------------------------- + +template < + typename T0, typename T1 = detail::NullType, typename T2 = detail::NullType, + typename T3 = detail::NullType, typename T4 = detail::NullType, + typename T5 = detail::NullType, typename T6 = detail::NullType, + typename T7 = detail::NullType, typename T8 = detail::NullType, + typename T9 = detail::NullType, typename T10 = detail::NullType, + typename T11 = detail::NullType, typename T12 = detail::NullType, + typename T13 = detail::NullType, typename T14 = detail::NullType, + typename T15 = detail::NullType, typename T16 = detail::NullType, + typename T17 = detail::NullType, typename T18 = detail::NullType, + typename T19 = detail::NullType, typename T20 = detail::NullType, + typename T21 = detail::NullType, typename T22 = detail::NullType, + typename T23 = detail::NullType, typename T24 = detail::NullType, + typename T25 = detail::NullType, typename T26 = detail::NullType, + typename T27 = detail::NullType, typename T28 = detail::NullType, + typename T29 = detail::NullType, typename T30 = detail::NullType, + typename T31 = detail::NullType +> +struct make_kernel : + public detail::functionImplementation_< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + > +{ +public: + typedef detail::KernelFunctorGlobal< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + > FunctorType; + + make_kernel( + const Program& program, + const STRING_CLASS name, + cl_int * err = NULL) : + detail::functionImplementation_< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + >( + FunctorType(program, name, err)) + {} + + make_kernel( + const Kernel kernel) : + detail::functionImplementation_< + T0, T1, T2, T3, + T4, T5, T6, T7, + T8, T9, T10, T11, + T12, T13, T14, T15, + T16, T17, T18, T19, + T20, T21, T22, T23, + T24, T25, T26, T27, + T28, T29, T30, T31 + >( + FunctorType(kernel)) + {} +}; + + +//---------------------------------------------------------------------------------------------------------------------- + +#undef __ERR_STR +#if !defined(__CL_USER_OVERRIDE_ERROR_STRINGS) +#undef __GET_DEVICE_INFO_ERR +#undef __GET_PLATFORM_INFO_ERR +#undef __GET_DEVICE_IDS_ERR +#undef __GET_CONTEXT_INFO_ERR +#undef __GET_EVENT_INFO_ERR +#undef __GET_EVENT_PROFILE_INFO_ERR +#undef __GET_MEM_OBJECT_INFO_ERR +#undef __GET_IMAGE_INFO_ERR +#undef __GET_SAMPLER_INFO_ERR +#undef __GET_KERNEL_INFO_ERR +#undef __GET_KERNEL_ARG_INFO_ERR +#undef __GET_KERNEL_WORK_GROUP_INFO_ERR +#undef __GET_PROGRAM_INFO_ERR +#undef __GET_PROGRAM_BUILD_INFO_ERR +#undef __GET_COMMAND_QUEUE_INFO_ERR + +#undef __CREATE_CONTEXT_ERR +#undef __CREATE_CONTEXT_FROM_TYPE_ERR +#undef __GET_SUPPORTED_IMAGE_FORMATS_ERR + +#undef __CREATE_BUFFER_ERR +#undef __CREATE_SUBBUFFER_ERR +#undef __CREATE_IMAGE2D_ERR +#undef __CREATE_IMAGE3D_ERR +#undef __CREATE_SAMPLER_ERR +#undef __SET_MEM_OBJECT_DESTRUCTOR_CALLBACK_ERR + +#undef __CREATE_USER_EVENT_ERR +#undef __SET_USER_EVENT_STATUS_ERR +#undef __SET_EVENT_CALLBACK_ERR +#undef __SET_PRINTF_CALLBACK_ERR + +#undef __WAIT_FOR_EVENTS_ERR + +#undef __CREATE_KERNEL_ERR +#undef __SET_KERNEL_ARGS_ERR +#undef __CREATE_PROGRAM_WITH_SOURCE_ERR +#undef __CREATE_PROGRAM_WITH_BINARY_ERR +#undef __CREATE_PROGRAM_WITH_BUILT_IN_KERNELS_ERR +#undef __BUILD_PROGRAM_ERR +#undef __CREATE_KERNELS_IN_PROGRAM_ERR + +#undef __CREATE_COMMAND_QUEUE_ERR +#undef __SET_COMMAND_QUEUE_PROPERTY_ERR +#undef __ENQUEUE_READ_BUFFER_ERR +#undef __ENQUEUE_WRITE_BUFFER_ERR +#undef __ENQUEUE_READ_BUFFER_RECT_ERR +#undef __ENQUEUE_WRITE_BUFFER_RECT_ERR +#undef __ENQEUE_COPY_BUFFER_ERR +#undef __ENQEUE_COPY_BUFFER_RECT_ERR +#undef __ENQUEUE_READ_IMAGE_ERR +#undef __ENQUEUE_WRITE_IMAGE_ERR +#undef __ENQUEUE_COPY_IMAGE_ERR +#undef __ENQUEUE_COPY_IMAGE_TO_BUFFER_ERR +#undef __ENQUEUE_COPY_BUFFER_TO_IMAGE_ERR +#undef __ENQUEUE_MAP_BUFFER_ERR +#undef __ENQUEUE_MAP_IMAGE_ERR +#undef __ENQUEUE_UNMAP_MEM_OBJECT_ERR +#undef __ENQUEUE_NDRANGE_KERNEL_ERR +#undef __ENQUEUE_TASK_ERR +#undef __ENQUEUE_NATIVE_KERNEL + +#undef __CL_EXPLICIT_CONSTRUCTORS + +#undef __UNLOAD_COMPILER_ERR +#endif //__CL_USER_OVERRIDE_ERROR_STRINGS + +#undef __CL_FUNCTION_TYPE + +// Extensions +/** + * Deprecated APIs for 1.2 + */ +#if defined(CL_VERSION_1_1) +#undef __INIT_CL_EXT_FCN_PTR +#endif // #if defined(CL_VERSION_1_1) +#undef __CREATE_SUB_DEVICES + +#if defined(USE_CL_DEVICE_FISSION) +#undef __PARAM_NAME_DEVICE_FISSION +#endif // USE_CL_DEVICE_FISSION + +#undef __DEFAULT_NOT_INITIALIZED +#undef __DEFAULT_BEING_INITIALIZED +#undef __DEFAULT_INITIALIZED + +#undef CL_HPP_RVALUE_REFERENCES_SUPPORTED +#undef CL_HPP_NOEXCEPT + +} // namespace cl + +#endif // CL_HPP_ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/allocator.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/allocator.h new file mode 100644 index 0000000..4fb529f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/allocator.h @@ -0,0 +1,99 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file allocator.h Allocator definitions. */ + +#ifndef ALLOCATOR_H_ +#define ALLOCATOR_H_ + +#include + +namespace libfreenect2 +{ + +class Allocator; + +class Buffer +{ +public: + size_t capacity; ///< Capacity of the buffer. + size_t length; ///< Used length of the buffer. + unsigned char* data; ///< Start address of the buffer. + Allocator *allocator; +}; + +class Allocator +{ +public: + /* If the inner allocator fails to allocate, it MUST not return NULL. + * Instead it MUST return a Buffer with data being NULL. + * The stdlib will throw std::bad_alloc if new Buffer fails. + */ + virtual Buffer *allocate(size_t size) = 0; + virtual void free(Buffer *b) = 0; + virtual ~Allocator() {} +}; + +class PoolAllocatorImpl; + +class PoolAllocator: public Allocator +{ +public: + /* Use new as the inner allocator. */ + PoolAllocator(); + + /* This inner allocator will be freed by PoolAllocator. */ + PoolAllocator(Allocator *inner); + + virtual ~PoolAllocator(); + + /* allocate() will block until an allocation is possible. + * It should be called as late as possible before the memory is required + * for write access. + * + * This allocate() never returns NULL as required by Allocator. + * + * All calls to allocate() MUST have the same size. + * + * allocate() MUST be called from the same thread. + */ + virtual Buffer *allocate(size_t size); + + /* free() will unblock pending allocation. + * It should be called as early as possible after the memory is no longer + * required for read access. + * + * The inner free() can be called with NULL. + * + * free() can be called from different threads than allocate(). + */ + virtual void free(Buffer *b); +private: + PoolAllocatorImpl *impl_; +}; + +} /* namespace libfreenect2 */ +#endif /* ALLOCATOR_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/async_packet_processor.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/async_packet_processor.h new file mode 100644 index 0000000..54f911f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/async_packet_processor.h @@ -0,0 +1,157 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file async_packet_processor.h Asynchronous processing of packets. */ + +#ifndef ASYNC_PACKET_PROCESSOR_H_ +#define ASYNC_PACKET_PROCESSOR_H_ + +#include +#include + +namespace libfreenect2 +{ + +/** + * Packet processor that runs asynchronously. + * @tparam PacketT Type of the packet being processed. + */ +template +class AsyncPacketProcessor : public PacketProcessor +{ +public: + typedef PacketProcessor* PacketProcessorPtr; + + /** + * Constructor. + * @param processor Object performing the processing. + */ + AsyncPacketProcessor(PacketProcessorPtr processor) : + processor_(processor), + current_packet_available_(false), + shutdown_(false), + thread_(&AsyncPacketProcessor::static_execute, this) + { + } + + virtual ~AsyncPacketProcessor() + { + shutdown_ = true; + packet_condition_.notify_one(); + + thread_.join(); + } + + virtual bool ready() + { + // try to aquire lock, if we succeed the background thread is waiting on packet_condition_ + bool locked = packet_mutex_.try_lock(); + + if(locked) + { + packet_mutex_.unlock(); + } + + return locked; + } + + virtual bool good() + { + return processor_->good(); + } + + virtual void process(const PacketT &packet) + { + { + libfreenect2::lock_guard l(packet_mutex_); + current_packet_ = packet; + current_packet_available_ = true; + } + packet_condition_.notify_one(); + } + + virtual void allocateBuffer(PacketT &p, size_t size) + { + processor_->allocateBuffer(p, size); + } + + virtual void releaseBuffer(PacketT &p) + { + processor_->releaseBuffer(p); + } + +private: + PacketProcessorPtr processor_; ///< The processing routine, executed in the asynchronous thread. + bool current_packet_available_; ///< Whether #current_packet_ still needs processing. + PacketT current_packet_; ///< Packet being processed. + + bool shutdown_; + libfreenect2::mutex packet_mutex_; ///< Mutex indicating a new packet can be stored in #current_packet_. + libfreenect2::condition_variable packet_condition_; ///< Mutex indicating processing is blocked on lack of packets. + libfreenect2::thread thread_; ///< Asynchronous thread. + + /** + * Wrapper function to start the thread. + * @param data The #AsyncPacketProcessor object to use. + */ + static void static_execute(void *data) + { + static_cast *>(data)->execute(); + } + + /** Asynchronously process a provided packet. */ + void execute() + { + this_thread::set_name(processor_->name()); + libfreenect2::unique_lock l(packet_mutex_); + + while(!shutdown_) + { + WAIT_CONDITION(packet_condition_, packet_mutex_, l); + + if(current_packet_available_) + { + // invoke process impl + if (processor_->good()) + processor_->process(current_packet_); + /* + * The stream parser passes the buffer asynchronously to processors so + * it can not wait after process() finishes and free the buffer. In + * theory releaseBuffer() should be called as soon as the access to it + * is finished, but right now no new allocateBuffer() will be called + * before ready() becomes true, so releaseBuffer() in the main loop of + * the async processor is OK. + */ + releaseBuffer(current_packet_); + + current_packet_available_ = false; + } + } + } +}; + +} /* namespace libfreenect2 */ +#endif /* ASYNC_PACKET_PROCESSOR_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/data_callback.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/data_callback.h new file mode 100644 index 0000000..9fb2800 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/data_callback.h @@ -0,0 +1,51 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file data_callback.h Callback interface on arrival of new data. */ + +#ifndef DATA_CALLBACK_H_ +#define DATA_CALLBACK_H_ + +#include +#include + +namespace libfreenect2 +{ + +class DataCallback +{ +public: + /** + * Callback that new data has arrived. + * @param buffer Buffer with new data. + * @param n Size of the new data. + */ + virtual void onDataReceived(unsigned char *buffer, size_t n) = 0; +}; + +} // namespace libfreenect2 + +#endif // DATA_CALLBACK_H_ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_processor.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_processor.h new file mode 100644 index 0000000..ad74ed1 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_processor.h @@ -0,0 +1,312 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file depth_packet_processor.h Depth processor definitions. */ + +#ifndef DEPTH_PACKET_PROCESSOR_H_ +#define DEPTH_PACKET_PROCESSOR_H_ + +#include +#include + +#include +#include +#include +#include + +namespace libfreenect2 +{ + +/** Data packet with depth information. */ +struct DepthPacket +{ + uint32_t sequence; + uint32_t timestamp; + unsigned char *buffer; ///< Depth data. + size_t buffer_length; ///< Size of depth data. + + Buffer *memory; +}; + +/** Class for processing depth information. */ +typedef PacketProcessor BaseDepthPacketProcessor; + +class DepthPacketProcessor : public BaseDepthPacketProcessor +{ +public: + typedef Freenect2Device::Config Config; + + /** Parameters of depth processing. */ + struct Parameters + { + float ab_multiplier; + float ab_multiplier_per_frq[3]; + float ab_output_multiplier; + + float phase_in_rad[3]; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + float gaussian_kernel[9]; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float kde_sigma_sqr; + float unwrapping_likelihood_scale; + float phase_confidence_scale; + float kde_threshold; + size_t kde_neigborhood_size; + size_t num_hyps; + + float min_depth; + float max_depth; + + Parameters(); + }; + + DepthPacketProcessor(); + virtual ~DepthPacketProcessor(); + + virtual void setFrameListener(libfreenect2::FrameListener *listener); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) = 0; + + static const size_t TABLE_SIZE = 512*424; + static const size_t LUT_SIZE = 2048; + virtual void loadXZTables(const float *xtable, const float *ztable) = 0; + virtual void loadLookupTable(const short *lut) = 0; + +protected: + libfreenect2::DepthPacketProcessor::Config config_; + libfreenect2::FrameListener *listener_; +}; + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +class OpenGLDepthPacketProcessorImpl; + +/** Depth packet processor using OpenGL. */ +class OpenGLDepthPacketProcessor : public DepthPacketProcessor +{ +public: + OpenGLDepthPacketProcessor(void *parent_opengl_context_ptr, bool debug); + virtual ~OpenGLDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + virtual const char *name() { return "OpenGL"; } + virtual void process(const DepthPacket &packet); +private: + OpenGLDepthPacketProcessorImpl *impl_; +}; +#endif // LIBFREENECT2_WITH_OPENGL_SUPPORT + +// TODO: push this to some internal namespace +class CpuDepthPacketProcessorImpl; + +/** Depth packet processor using the CPU. */ +class CpuDepthPacketProcessor : public DepthPacketProcessor +{ +public: + CpuDepthPacketProcessor(); + virtual ~CpuDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + virtual const char *name() { return "CPU"; } + virtual void process(const DepthPacket &packet); +private: + CpuDepthPacketProcessorImpl *impl_; +}; + +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT +class OpenCLDepthPacketProcessorImpl; + +/** Depth packet processor using OpenCL. */ +class OpenCLDepthPacketProcessor : public DepthPacketProcessor +{ +public: + OpenCLDepthPacketProcessor(const int deviceId = -1); + virtual ~OpenCLDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + virtual bool good(); + virtual const char *name() { return "OpenCL"; } + + virtual void process(const DepthPacket &packet); +protected: + virtual Allocator *getAllocator(); +private: + OpenCLDepthPacketProcessorImpl *impl_; +}; + +/* + * The class below implement a depth packet processor using the phase unwrapping + * algorithm described in the paper "Efficient Phase Unwrapping using Kernel + * Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ +class OpenCLKdeDepthPacketProcessorImpl; + +/** Depth packet processor using OpenCL. */ +class OpenCLKdeDepthPacketProcessor : public DepthPacketProcessor +{ +public: + OpenCLKdeDepthPacketProcessor(const int deviceId = -1); + virtual ~OpenCLKdeDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + virtual bool good(); + virtual const char *name() { return "OpenCLKde"; } + + virtual void process(const DepthPacket &packet); +protected: + virtual Allocator *getAllocator(); +private: + OpenCLKdeDepthPacketProcessorImpl *impl_; +}; +#endif // LIBFREENECT2_WITH_OPENCL_SUPPORT + +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT +class CudaDepthPacketProcessorImpl; + +class CudaDepthPacketProcessor : public DepthPacketProcessor +{ +public: + CudaDepthPacketProcessor(const int deviceId = -1); + virtual ~CudaDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + virtual bool good(); + virtual const char *name() { return "CUDA"; } + + virtual void process(const DepthPacket &packet); +protected: + virtual Allocator *getAllocator(); +private: + CudaDepthPacketProcessorImpl *impl_; +}; + +/* + * The class below implement a depth packet processor using the phase unwrapping + * algorithm described in the paper "Efficient Phase Unwrapping using Kernel + * Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ +class CudaKdeDepthPacketProcessorImpl; + +class CudaKdeDepthPacketProcessor : public DepthPacketProcessor +{ +public: + CudaKdeDepthPacketProcessor(const int deviceId = -1); + virtual ~CudaKdeDepthPacketProcessor(); + virtual void setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + virtual bool good(); + virtual const char *name() { return "CUDAKde"; } + + virtual void process(const DepthPacket &packet); +protected: + virtual Allocator *getAllocator(); +private: + CudaKdeDepthPacketProcessorImpl *impl_; +}; +#endif // LIBFREENECT2_WITH_CUDA_SUPPORT + +class DumpDepthPacketProcessor : public DepthPacketProcessor +{ + public: + DumpDepthPacketProcessor(); + virtual ~DumpDepthPacketProcessor(); + + virtual void process(const DepthPacket &packet); + + virtual void loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length); + virtual void loadXZTables(const float *xtable, const float *ztable); + virtual void loadLookupTable(const short *lut); + + const unsigned char* getP0Tables(); + + const float* getXTable(); + const float* getZTable(); + + const short* getLookupTable(); + + protected: + unsigned char* p0table_; + + float* xtable_; + float* ztable_; + + short* lut_; +}; + +} /* namespace libfreenect2 */ +#endif /* DEPTH_PACKET_PROCESSOR_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_stream_parser.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_stream_parser.h new file mode 100644 index 0000000..2db3c4f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/depth_packet_stream_parser.h @@ -0,0 +1,82 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file depth_packet_stream_parser.h Parser processor definitions of depth packets. */ + +#ifndef DEPTH_PACKET_STREAM_PARSER_H_ +#define DEPTH_PACKET_STREAM_PARSER_H_ + +#include +#include + +#include + +#include + +#include + +namespace libfreenect2 +{ + +/** Footer of a depth packet. */ +LIBFREENECT2_PACK(struct DepthSubPacketFooter +{ + uint32_t magic0; + uint32_t magic1; + uint32_t timestamp; + uint32_t sequence; + uint32_t subsequence; + uint32_t length; + uint32_t fields[32]; +}); + +/** + * Parser of th depth stream, recognizes valid depth packets in the stream, and + * passes them on for further processing. + */ +class DepthPacketStreamParser : public DataCallback +{ +public: + DepthPacketStreamParser(); + virtual ~DepthPacketStreamParser(); + + void setPacketProcessor(libfreenect2::BaseDepthPacketProcessor *processor); + + virtual void onDataReceived(unsigned char* buffer, size_t length); +private: + libfreenect2::BaseDepthPacketProcessor *processor_; + + size_t buffer_size_; + DepthPacket packet_; + libfreenect2::Buffer work_buffer_; + + uint32_t processed_packets_; + uint32_t current_sequence_; + uint32_t current_subsequence_; +}; + +} /* namespace libfreenect2 */ +#endif /* DEPTH_PACKET_STREAM_PARSER_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/logging.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/logging.h new file mode 100644 index 0000000..d38fbfd --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/logging.h @@ -0,0 +1,82 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef LOGGING_H_ +#define LOGGING_H_ + +#include +#include + +#include +#include + +namespace libfreenect2 +{ + +class WithPerfLoggingImpl; + +class WithPerfLogging +{ +public: + WithPerfLogging(); + virtual ~WithPerfLogging(); + void startTiming(); + std::ostream &stopTiming(std::ostream &stream); +private: + WithPerfLoggingImpl *impl_; +}; + +class LogMessage +{ +private: + Logger *logger_; + Logger::Level level_; + std::ostringstream stream_; +public: + LogMessage(Logger *logger, Logger::Level level); + LogMessage(Logger *logger, Logger::Level level, const char *source); + ~LogMessage(); + + std::ostream &stream(); +}; + +} /* namespace libfreenect2 */ + +#if defined(__GNUC__) || defined(__clang__) +#define LOG_SOURCE __PRETTY_FUNCTION__ +#elif defined(_MSC_VER) +#define LOG_SOURCE __FUNCSIG__ +#else +#define LOG_SOURCE "" +#endif + +#define LOG(LEVEL) (::libfreenect2::LogMessage(::libfreenect2::getGlobalLogger(), ::libfreenect2::Logger::LEVEL, LOG_SOURCE).stream()) +#define LOG_DEBUG LOG(Debug) +#define LOG_INFO LOG(Info) +#define LOG_WARNING LOG(Warning) +#define LOG_ERROR LOG(Error) + +#endif /* LOGGING_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/packet_processor.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/packet_processor.h new file mode 100644 index 0000000..a6b0a52 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/packet_processor.h @@ -0,0 +1,112 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file packet_processor.h Packet processor definitions. */ + +#ifndef PACKET_PROCESSOR_H_ +#define PACKET_PROCESSOR_H_ + +#include "libfreenect2/allocator.h" + +namespace libfreenect2 +{ + +/** + * Processor node in the pipeline. + * @tparam PacketT Type of the packet being processed. + */ +template +class PacketProcessor +{ +public: + virtual ~PacketProcessor() {} + + /** + * Test whether the processor is idle. + * @return True if the processor is idle, else false. + */ + virtual bool ready() { return true; } + + virtual bool good() { return true; } + + virtual const char *name() { return "a packet processor"; } + + /** + * A new packet has arrived, process it. + * @param packet Packet to process. + */ + virtual void process(const PacketT &packet) = 0; + + virtual void allocateBuffer(PacketT &p, size_t size) + { + Allocator *a = getAllocator(); + if (a) + p.memory = a->allocate(size); + } + + virtual void releaseBuffer(PacketT &p) + { + Allocator *a = getAllocator(); + if (a) + a->free(p.memory); + p.memory = NULL; + } + +protected: + virtual Allocator *getAllocator() { return &default_allocator_; } + +private: + PoolAllocator default_allocator_; +}; + +/** + * Dummy processor class. + * @tparam PacketT Type of the packet being processed. + */ +template +class NoopPacketProcessor : public PacketProcessor +{ +public: + NoopPacketProcessor() {} + virtual ~NoopPacketProcessor() {} + + virtual void process(const PacketT &packet) {} +}; + +/** + * Factory function for creating a dummy packet processor. + * @tparam PacketT Type of the packet being processed. + * @return The dummy (noop) processor. + */ +template +PacketProcessor *noopProcessor() +{ + static NoopPacketProcessor noop_processor_; + return &noop_processor_; +} + +} /* namespace libfreenect2 */ +#endif /* PACKET_PROCESSOR_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command.h new file mode 100644 index 0000000..3d37d18 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command.h @@ -0,0 +1,272 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef COMMAND_H_ +#define COMMAND_H_ + +#include +#include +#include "libfreenect2/protocol/response.h" +#include "libfreenect2/led_settings.h" + +#define KCMD_READ_FIRMWARE_VERSIONS 0x02 +#define KCMD_INIT_STREAMS 0x09 +#define KCMD_READ_HARDWARE_INFO 0x14 +#define KCMD_READ_STATUS 0x16 +#define KCMD_READ_DATA_PAGE 0x22 +#define KCMD_READ_DATA_0x26 0x26 + +#define KCMD_SET_STREAMING 0x2B +#define KCMD_SET_MODE 0x4B + +#define KCMD_RGB_SETTING 0x3E // Command value for color camera settings +#define KCMD_LED_SETTING 0x4B + +#define KCMD_0x46 0x46 +#define KCMD_0x47 0x47 + +// observed in sensor stop/shutdown sequence +#define KCMD_STOP 0x0A +#define KCMD_SHUTDOWN 0x00 + +namespace libfreenect2 +{ + +namespace protocol +{ + +template +struct CommandData +{ + uint32_t magic; + uint32_t sequence; + uint32_t max_response_length; + uint32_t command; + uint32_t reserved0; + uint32_t parameters[NParam]; + + CommandData() + { + for(int i = 0; i < NParam; ++i) + parameters[i] = 0; + } +}; + +template<> +struct CommandData<0> +{ + uint32_t magic; + uint32_t sequence; + uint32_t max_response_length; + uint32_t command; + uint32_t reserved0; +}; + +struct CommandBase +{ + virtual ~CommandBase() {} + + virtual uint32_t sequence() const = 0; + virtual uint32_t maxResponseLength() const = 0; + virtual uint32_t minResponseLength() const = 0; + + virtual const uint8_t *data() const = 0; + virtual uint32_t size() const = 0; +}; + +template +class Command : public CommandBase +{ +public: + typedef CommandData Data; + + static const uint32_t MagicNumber = 0x06022009; + static const uint32_t Size = sizeof(Data); + + uint32_t min_response_length; + + Command(uint32_t seq) + { + data_.magic = MagicNumber; + data_.sequence = seq; + data_.max_response_length = MaxResponseLength; + data_.command = CommandId; + data_.reserved0 = 0; + min_response_length = MinResponseLength; + } + + virtual ~Command() + { + } + + virtual uint32_t sequence() const + { + return data_.sequence; + } + + virtual uint32_t maxResponseLength() const + { + return data_.max_response_length; + } + + virtual uint32_t minResponseLength() const + { + return min_response_length; + } + + virtual const uint8_t *data() const + { + return reinterpret_cast(&data_); + } + + virtual uint32_t size() const + { + return Size; + } + +protected: + Data data_; +}; + +template +struct CommandWith0Params : public Command +{ + CommandWith0Params(uint32_t seq) : Command(seq) + { + } +}; + +template +struct CommandWith1Param : public Command +{ + CommandWith1Param(uint32_t seq) : Command(seq) + { + this->data_.parameters[0] = Param1; + } +}; + +template +struct CommandWith1ParamLarge : public Command +{ + CommandWith1ParamLarge(uint32_t seq) : Command(seq) + { + this->data_.parameters[0] = Param1; + } +}; + +template +struct CommandWith4Params : public Command +{ + CommandWith4Params(uint32_t seq) : Command(seq) + { + this->data_.parameters[0] = Param1; + this->data_.parameters[1] = Param2; + this->data_.parameters[2] = Param3; + this->data_.parameters[3] = Param4; + } +}; + +typedef CommandWith0Params<0x02, 0x200> ReadFirmwareVersionsCommand; + +typedef CommandWith0Params ReadHardwareInfoCommand; + +typedef CommandWith0Params InitStreamsCommand; + +typedef CommandWith1Param ReadSerialNumberCommand; +typedef CommandWith1ParamLarge ReadP0TablesCommand; +typedef CommandWith1ParamLarge ReadDepthCameraParametersCommand; +typedef CommandWith1ParamLarge ReadRgbCameraParametersCommand; + +typedef CommandWith1Param ReadStatus0x090000Command; +typedef CommandWith1Param ReadStatus0x100007Command; +// TODO: are they ever used?! +typedef CommandWith1Param ReadStatus0x02006FCommand; +typedef CommandWith1Param ReadStatus0x020070Command; + +// TODO: is the following actually correct? +typedef CommandWith0Params ReadData0x26Command; +//typedef CommandWith1Param ReadData0x26_0x00Command; + +typedef CommandWith1Param SetStreamDisabledCommand; +typedef CommandWith1Param SetStreamEnabledCommand; + +// TODO: are they ever used?! +typedef CommandWith4Params Unknown0x46Command; +typedef CommandWith0Params Unknown0x47Command; + +typedef CommandWith0Params StopCommand; +typedef CommandWith0Params ShutdownCommand; + +typedef CommandWith4Params SetModeDisabledCommand; +typedef CommandWith4Params SetModeEnabledCommand; +typedef CommandWith4Params SetModeEnabledWith0x00640064Command; +typedef CommandWith4Params SetModeEnabledWith0x00500050Command; + +// The following information was found by using the library released by Microsoft under MIT license, +// https://github.com/Microsoft/MixedRealityCompanionKit/tree/master/KinectIPD/NuiSensor +// Command values come from headers, packet CommandId from stepping through assembly in NuiSensorLib.lib +#define ColorSettingResponseSize sizeof(ColorSettingResponse) +struct ColorSettingCommand : public Command +{ + ColorSettingCommand(ColorSettingCommandType cmd, uint32_t value = 0) + : Command(0) // seq always zero + { + // Data parameters are elements of struct NUISENSOR_RGB_CHANGE_STREAM_SETTING + // which supports multiple settings for a single call. + this->data_.parameters[0] = 1; // NumCommands = 1 for single command + this->data_.parameters[1] = 0; // SequenceId = 0 for RGB commands + this->data_.parameters[2] = (uint32_t)cmd; // Cmd with a value from NUISENSOR_RGB_COMMAND_* + this->data_.parameters[3] = value; // Arg is int or float depending on Cmd, zero for GET_* + } + + // Could overload ctor to ease usage for float-valued settings. + ColorSettingCommand(ColorSettingCommandType cmd, float value) + : Command(0) + { + this->data_.parameters[0] = 1; + this->data_.parameters[1] = 0; + this->data_.parameters[2] = (uint32_t)cmd; + uint32_t value2; + memcpy(&value2, &value, sizeof(value2)); + this->data_.parameters[3] = value2; + } +}; + + +#define LedSettingResponseSize 0 +struct LedSettingCommand : public libfreenect2::protocol::Command +{ + LedSettingCommand(LedSettings led) + : Command(0) // seq always zero + { + memcpy(this->data_.parameters, &led, sizeof(led)); + } +}; + + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* COMMAND_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command_transaction.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command_transaction.h new file mode 100644 index 0000000..9865442 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/command_transaction.h @@ -0,0 +1,65 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef COMMAND_TRANSACTION_H_ +#define COMMAND_TRANSACTION_H_ + +#include +#include +#include + +namespace libfreenect2 +{ +namespace protocol +{ + +class CommandTransaction +{ +public: + static const int ResponseCompleteLength = 16; + static const uint32_t ResponseCompleteMagic = 0x0A6FE000; + + typedef std::vector Result; + + CommandTransaction(libusb_device_handle *handle, int inbound_endpoint, int outbound_endpoint); + ~CommandTransaction(); + + bool execute(const CommandBase& command, Result& result); +private: + libusb_device_handle *handle_; + int inbound_endpoint_, outbound_endpoint_, timeout_; + Result response_complete_result_; + + bool send(const CommandBase& command); + + bool receive(Result& result, uint32_t min_length); + + bool isResponseCompleteResult(Result& result, uint32_t sequence); +}; + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* COMMAND_TRANSACTION_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/response.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/response.h new file mode 100644 index 0000000..b83c8e2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/response.h @@ -0,0 +1,340 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef RESPONSE_H_ +#define RESPONSE_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ +namespace protocol +{ + +class SerialNumberResponse +{ +private: + std::string serial_; +public: + SerialNumberResponse(const std::vector &data) + { + int length = data.size(); + char *c = new char[length / 2 + 1](); + + for(int i = 0, j = 0; i < length; i += 2, ++j) + { + c[j] = (char)data[i]; + if(c[j] == 0) break; + } + + serial_.assign(c); + + delete[] c; + } + + std::string toString() + { + return serial_; + } +}; + +class FirmwareVersionResponse +{ +private: + struct FWSubsystemVersion + { + uint32_t maj_min; + uint32_t revision; + uint32_t build; + uint32_t reserved0; + + FWSubsystemVersion() + { + maj_min = 0; + revision = 0; + build = 0; + } + }; + + std::vector versions_; +public: + FirmwareVersionResponse(const std::vector &data) + { + int length = data.size(); + int n = length / sizeof(FWSubsystemVersion); + const FWSubsystemVersion *sv = reinterpret_cast(&data[0]); + + for(int i = 0; i < 7 && i < n; ++i) + { + versions_.push_back(sv[i]); + } + } + + std::string toString() + { + FWSubsystemVersion max; + std::stringstream version_string; + // the main blob's index + size_t i = 3; + if (i < versions_.size()) + { + const FWSubsystemVersion &ver = versions_[i]; + version_string << (ver.maj_min >> 16) << "." << (ver.maj_min & 0xffff) << "." << ver.revision << "." << ver.build; + } + + return version_string.str(); + } +}; + +class Status0x090000Response +{ +private: + uint32_t status_; +public: + Status0x090000Response(const std::vector &data) + { + status_ = *reinterpret_cast(&data[0]); + } + + uint32_t toNumber() + { + return status_; + } +}; + +class GenericResponse +{ +private: + std::string dump_; +public: + GenericResponse(const std::vector &data) + { + int length = data.size(); + std::stringstream dump; + dump << length << " bytes of raw data" << std::endl; + + int lines = length >> 4; + if (length % 16 != 0) lines += 1; + + for (int i = 0; i < lines; i++) + { + dump << "0x" << std::hex << std::setfill('0') << std::setw(4) << (i*16) << ": "; + for (int j = 0; j < 16; j++) + { + if (j < length) dump << std::hex << std::setfill('0') << std::setw(2) << int(data[i*16+j]) << " "; + else dump << " "; + } + dump << " "; + for (int j = 0; (j < 16) && (j < length); j++) + { + unsigned char c = data[i*16+j]; + dump << (((c<32)||(c>128))?'.':c); + } + dump << std::endl; + length -= 16; + } + + dump_ = dump.str(); + } + + std::string toString() + { + return dump_; + } +}; + +// probably some combination of color camera intrinsics + depth coefficient tables +LIBFREENECT2_PACK(struct RgbCameraParamsResponse +{ + // unknown, always seen as 1 so far + uint8_t table_id; + + // color -> depth mapping parameters + float color_f; + float color_cx; + float color_cy; + + float shift_d; + float shift_m; + + float mx_x3y0; // xxx + float mx_x0y3; // yyy + float mx_x2y1; // xxy + float mx_x1y2; // yyx + float mx_x2y0; // xx + float mx_x0y2; // yy + float mx_x1y1; // xy + float mx_x1y0; // x + float mx_x0y1; // y + float mx_x0y0; // 1 + + float my_x3y0; // xxx + float my_x0y3; // yyy + float my_x2y1; // xxy + float my_x1y2; // yyx + float my_x2y0; // xx + float my_x0y2; // yy + float my_x1y1; // xy + float my_x1y0; // x + float my_x0y1; // y + float my_x0y0; // 1 + + // perhaps related to xtable/ztable in the deconvolution code. + // data seems to be arranged into two tables of 28*23, which + // matches the depth image aspect ratio of 512*424 very closely + float table1[28 * 23 * 4]; + float table2[28 * 23]; + + RgbCameraParamsResponse(const std::vector &data) + { + *this = *reinterpret_cast(&data[0]); + } + + Freenect2Device::ColorCameraParams toColorCameraParams() + { + Freenect2Device::ColorCameraParams params; + params.fx = color_f; + params.fy = color_f; + params.cx = color_cx; + params.cy = color_cy; + + params.shift_d = shift_d; + params.shift_m = shift_m; + + params.mx_x3y0 = mx_x3y0; // xxx + params.mx_x0y3 = mx_x0y3; // yyy + params.mx_x2y1 = mx_x2y1; // xxy + params.mx_x1y2 = mx_x1y2; // yyx + params.mx_x2y0 = mx_x2y0; // xx + params.mx_x0y2 = mx_x0y2; // yy + params.mx_x1y1 = mx_x1y1; // xy + params.mx_x1y0 = mx_x1y0; // x + params.mx_x0y1 = mx_x0y1; // y + params.mx_x0y0 = mx_x0y0; // 1 + + params.my_x3y0 = my_x3y0; // xxx + params.my_x0y3 = my_x0y3; // yyy + params.my_x2y1 = my_x2y1; // xxy + params.my_x1y2 = my_x1y2; // yyx + params.my_x2y0 = my_x2y0; // xx + params.my_x0y2 = my_x0y2; // yy + params.my_x1y1 = my_x1y1; // xy + params.my_x1y0 = my_x1y0; // x + params.my_x0y1 = my_x0y1; // y + params.my_x0y0 = my_x0y0; // 1 + return params; + } +}); + + +// depth camera intrinsic & distortion parameters +LIBFREENECT2_PACK(struct DepthCameraParamsResponse +{ + // intrinsics (this is pretty certain) + float fx; + float fy; + float unknown0; // assumed to be always zero + float cx; + float cy; + + // radial distortion (educated guess based on calibration data from Kinect SDK) + float k1; + float k2; + float p1; // always seen as zero so far, so purely a guess + float p2; // always seen as zero so far, so purely a guess + float k3; + + float unknown1[13]; // assumed to be always zero + + DepthCameraParamsResponse(const std::vector &data) + { + *this = *reinterpret_cast(&data[0]); + } + + Freenect2Device::IrCameraParams toIrCameraParams() + { + Freenect2Device::IrCameraParams params; + params.fx = fx; + params.fy = fy; + params.cx = cx; + params.cy = cy; + params.k1 = k1; + params.k2 = k2; + params.k3 = k3; + params.p1 = p1; + params.p2 = p2; + return params; + } +}); + +// "P0" coefficient tables, input to the deconvolution code +LIBFREENECT2_PACK(struct P0TablesResponse +{ + uint32_t headersize; + uint32_t unknown1; + uint32_t unknown2; + uint32_t tablesize; + uint32_t unknown3; + uint32_t unknown4; + uint32_t unknown5; + uint32_t unknown6; + + uint16_t unknown7; + uint16_t p0table0[512*424]; // row[0] == row[511] == 0x2c9a + uint16_t unknown8; + + uint16_t unknown9; + uint16_t p0table1[512*424]; // row[0] == row[511] == 0x08ec + uint16_t unknownA; + + uint16_t unknownB; + uint16_t p0table2[512*424]; // row[0] == row[511] == 0x42e8 + uint16_t unknownC; + + uint8_t unknownD[]; +}); + +// RGB camera settings reply for a single setting change. +// Equivalent of NUISENSOR_RGB_CHANGE_STREAM_SETTING_REPLY in NuiSensorLib.h +LIBFREENECT2_PACK(struct ColorSettingResponse +{ + uint32_t NumStatus; + uint32_t CommandListStatus; + // Result of the first command -- we only send one at a time for now. + // Equivalent of a fixed-length array of NUISENSOR_RGB_CHANGE_STREAM_SETTING_REPLY_STATUS in NuiSensorLib.h + uint32_t Status; + uint32_t Data; +}); + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* RESPONSE_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/usb_control.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/usb_control.h new file mode 100644 index 0000000..f42cafe --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/protocol/usb_control.h @@ -0,0 +1,108 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef USB_CONTROL_H_ +#define USB_CONTROL_H_ + +#include + +namespace libfreenect2 +{ +namespace protocol +{ +/** + * The Kinect2 device defines 2 USB interface associations (=device functions) + * + * 1. Interface Association: video transfer + * 2. Interface Association: audio transfer + * + * The first interface association is enabled/disabled by setting the feature FUNCTION_SUSPEND. + * + * The following describes the interfaces in the video transfer interface association. + * + * It contains 2 USB interfaces + * + * 1. Interface: control communication, RGB transfer + * 2. Interface: IR transfer + * + * Each interface has different endpoints + * + * 1. Interface + * - 0x81 (bulk) control communication IN + * - 0x02 (bulk) control communication OUT + * - 0x83 (bulk) RGB transfer IN + * - 0x82 (interrupt) unknown IN + * + * 2. Interface + * - 0x84 (isochronous) IR transfer IN + * + * The 2. interface can be enabled/disabled by changing its alternate setting to 1/0 + */ +class UsbControl +{ +public: + UsbControl(libusb_device_handle *handle); + virtual ~UsbControl(); + + enum State + { + Enabled, + Disabled + }; + + enum ResultCode + { + Success, + Error + }; + + ResultCode getIrMaxIsoPacketSize(int &size); + + ResultCode setConfiguration(); + ResultCode claimInterfaces(); + ResultCode releaseInterfaces(); + + ResultCode setIsochronousDelay(); + ResultCode setPowerStateLatencies(); + ResultCode enablePowerStates(); + + // enable/suspend 1. Interface Association + ResultCode setVideoTransferFunctionState(State state); + + // enable/disable 2. Interface using alternate setting + ResultCode setIrInterfaceState(State state); + +private: + static const int ControlAndRgbInterfaceId = 0; + static const int IrInterfaceId = 1; + + libusb_device_handle* handle_; + int timeout_; +}; + +} /* namespace protocol */ +} /* namespace libfreenect2 */ +#endif /* USB_CONTROL_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/resource.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/resource.h new file mode 100644 index 0000000..3b4f8d8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/resource.h @@ -0,0 +1,41 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file resource.h Resource file loading functions. */ + +#ifndef RESOURCE_H_ +#define RESOURCE_H_ + +#include + +namespace libfreenect2 +{ + +bool loadResource(const std::string &name, unsigned char const**data, size_t *length); +bool loadBufferFromResources(const std::string &filename, unsigned char *buffer, const size_t n); + +} /* namespace libfreenect2 */ +#endif /* RESOURCE_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_processor.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_processor.h new file mode 100644 index 0000000..5974a61 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_processor.h @@ -0,0 +1,146 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file rgb_packet_processor.h JPEG decoder processors. */ + +#ifndef RGB_PACKET_PROCESSOR_H_ +#define RGB_PACKET_PROCESSOR_H_ + +#include +#include + +#include +#include +#include + +namespace libfreenect2 +{ + +/** Packet with JPEG data. */ +struct RgbPacket +{ + uint32_t sequence; + + uint32_t timestamp; + unsigned char *jpeg_buffer; ///< JPEG data. + size_t jpeg_buffer_length; ///< Length of the JPEG data. + float exposure; + float gain; + float gamma; + + Buffer *memory; +}; + +typedef PacketProcessor BaseRgbPacketProcessor; + +/** JPEG processor. */ +class RgbPacketProcessor : public BaseRgbPacketProcessor +{ +public: + RgbPacketProcessor(); + virtual ~RgbPacketProcessor(); + + virtual void setFrameListener(libfreenect2::FrameListener *listener); +protected: + libfreenect2::FrameListener *listener_; +}; + +/** Class for dumping the JPEG information, eg to file. */ +class DumpRgbPacketProcessor : public RgbPacketProcessor +{ +public: + DumpRgbPacketProcessor(); + virtual ~DumpRgbPacketProcessor(); + virtual void process(const libfreenect2::RgbPacket &packet); +}; + +#ifdef LIBFREENECT2_WITH_TURBOJPEG_SUPPORT +class TurboJpegRgbPacketProcessorImpl; + +/** Processor to decode JPEG to image, using TurboJpeg. */ +class TurboJpegRgbPacketProcessor : public RgbPacketProcessor +{ +public: + TurboJpegRgbPacketProcessor(); + virtual ~TurboJpegRgbPacketProcessor(); + virtual void process(const libfreenect2::RgbPacket &packet); + virtual const char *name() { return "TurboJPEG"; } +private: + TurboJpegRgbPacketProcessorImpl *impl_; ///< Decoder implementation. +}; +#endif + +#ifdef LIBFREENECT2_WITH_VT_SUPPORT +class VTRgbPacketProcessorImpl; + +class VTRgbPacketProcessor : public RgbPacketProcessor +{ +public: + VTRgbPacketProcessor(); + virtual ~VTRgbPacketProcessor(); + virtual void process(const libfreenect2::RgbPacket &packet); + virtual const char *name() { return "VideoToolbox"; } +private: + VTRgbPacketProcessorImpl *impl_; +}; +#endif + +#ifdef LIBFREENECT2_WITH_VAAPI_SUPPORT +class VaapiRgbPacketProcessorImpl; + +class VaapiRgbPacketProcessor : public RgbPacketProcessor +{ +public: + VaapiRgbPacketProcessor(); + virtual ~VaapiRgbPacketProcessor(); + virtual bool good(); + virtual const char *name() { return "VAAPI"; } + virtual void process(const libfreenect2::RgbPacket &packet); +protected: + virtual Allocator *getAllocator(); +private: + VaapiRgbPacketProcessorImpl *impl_; +}; +#endif //LIBFREENECT2_WITH_VAAPI_SUPPORT + +#ifdef LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT +class TegraJpegRgbPacketProcessorImpl; + +class TegraJpegRgbPacketProcessor : public RgbPacketProcessor +{ +public: + TegraJpegRgbPacketProcessor(); + virtual ~TegraJpegRgbPacketProcessor(); + virtual bool good(); + virtual const char *name() { return "TegraJPEG"; } + virtual void process(const libfreenect2::RgbPacket &packet); +private: + TegraJpegRgbPacketProcessorImpl *impl_; +}; +#endif //LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT + +} /* namespace libfreenect2 */ +#endif /* RGB_PACKET_PROCESSOR_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_stream_parser.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_stream_parser.h new file mode 100644 index 0000000..2cc7558 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/rgb_packet_stream_parser.h @@ -0,0 +1,59 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file rgb_packet_stream_parser.h Parser classes for getting RGB packets from the stream. */ + +#ifndef RGB_PACKET_STREAM_PARSER_H_ +#define RGB_PACKET_STREAM_PARSER_H_ + +#include + +#include +#include + +#include + +namespace libfreenect2 +{ + +/** Parser for getting an RGB packet from the stream. */ +class RgbPacketStreamParser : public DataCallback +{ +public: + RgbPacketStreamParser(); + virtual ~RgbPacketStreamParser(); + + void setPacketProcessor(BaseRgbPacketProcessor *processor); + + virtual void onDataReceived(unsigned char* buffer, size_t length); +private: + size_t buffer_size_; + RgbPacket packet_; + BaseRgbPacketProcessor *processor_; ///< Parser implementation. +}; + +} /* namespace libfreenect2 */ +#endif /* RGB_PACKET_STREAM_PARSER_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/threading.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/threading.h new file mode 100644 index 0000000..8527cc1 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/threading.h @@ -0,0 +1,118 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file threading.h Threading abstraction definitions. */ + +#ifndef THREADING_H_ +#define THREADING_H_ + +#include + +#ifdef LIBFREENECT2_THREADING_STDLIB + +#include +#include +#include +#include + +#define WAIT_CONDITION(var, mutex, lock) var.wait(lock); + +namespace libfreenect2 +{ + +typedef std::thread thread; +typedef std::mutex mutex; +typedef std::lock_guard lock_guard; +typedef std::unique_lock unique_lock; +typedef std::condition_variable condition_variable; + +namespace chrono +{ +using namespace std::chrono; +} + +namespace this_thread +{ +using namespace std::this_thread; +} + +} /* libfreenect2 */ + +#endif + +#ifdef LIBFREENECT2_THREADING_TINYTHREAD + +#include + +// TODO: work around for tinythread incompatibility +#define WAIT_CONDITION(var, mutex, lock) var.wait(mutex); + +namespace libfreenect2 +{ + +typedef tthread::thread thread; +typedef tthread::mutex mutex; +typedef tthread::lock_guard lock_guard; +// TODO: this is not optimal +typedef tthread::lock_guard unique_lock; +typedef tthread::condition_variable condition_variable; + +namespace chrono +{ +using namespace tthread::chrono; +} + +namespace this_thread +{ +using namespace tthread::this_thread; +} + +} /* libfreenect2 */ + +#endif + +#if defined(__linux__) +#include +#elif defined(__APPLE__) +#include +#endif + +namespace libfreenect2 +{ +namespace this_thread +{ + static inline void set_name(const char *name) + { +#if defined(__linux__) + prctl(PR_SET_NAME, name); +#elif defined(__APPLE__) + pthread_setname_np(name); +#endif + } +} +} + +#endif /* THREADING_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/event_loop.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/event_loop.h new file mode 100644 index 0000000..61c298b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/event_loop.h @@ -0,0 +1,57 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef EVENT_LOOP_H_ +#define EVENT_LOOP_H_ + +#include + +namespace libfreenect2 +{ +namespace usb +{ + +class EventLoop +{ +public: + EventLoop(); + virtual ~EventLoop(); + + void start(void *usb_context); + + void stop(); +private: + bool shutdown_; + libfreenect2::thread *thread_; + void *usb_context_; + + static void static_execute(void *cookie); + void execute(); +}; + +} /* namespace usb */ +} /* namespace libfreenect2 */ +#endif /* EVENT_LOOP_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/transfer_pool.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/transfer_pool.h new file mode 100644 index 0000000..4f386ce --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/internal/libfreenect2/usb/transfer_pool.h @@ -0,0 +1,141 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef TRANSFER_POOL_H_ +#define TRANSFER_POOL_H_ + +#include +#include + +#include +#include + +namespace libfreenect2 +{ + +namespace usb +{ + +class TransferPool +{ +public: + TransferPool(libusb_device_handle *device_handle, unsigned char device_endpoint); + virtual ~TransferPool(); + + void deallocate(); + + void enableSubmission(); + + void disableSubmission(); + + bool enabled(); + + bool submit(); + + void cancel(); + + void setCallback(DataCallback *callback); +protected: + libfreenect2::mutex stopped_mutex; + struct Transfer + { + libusb_transfer *transfer; + TransferPool *pool; + bool stopped; + Transfer(libusb_transfer *transfer, TransferPool *pool): + transfer(transfer), pool(pool), stopped(true) {} + void setStopped(bool value) + { + libfreenect2::lock_guard guard(pool->stopped_mutex); + stopped = value; + } + bool getStopped() + { + libfreenect2::lock_guard guard(pool->stopped_mutex); + return stopped; + } + }; + + void allocateTransfers(size_t num_transfers, size_t transfer_size); + + virtual libusb_transfer *allocateTransfer() = 0; + virtual void fillTransfer(libusb_transfer *transfer) = 0; + + virtual void processTransfer(libusb_transfer *transfer) = 0; + + DataCallback *callback_; +private: + typedef std::vector TransferQueue; + + libusb_device_handle *device_handle_; + unsigned char device_endpoint_; + + TransferQueue transfers_; + unsigned char *buffer_; + size_t buffer_size_; + + bool enable_submit_; + + static void onTransferCompleteStatic(libusb_transfer *transfer); + + void onTransferComplete(Transfer *transfer); +}; + +class BulkTransferPool : public TransferPool +{ +public: + BulkTransferPool(libusb_device_handle *device_handle, unsigned char device_endpoint); + virtual ~BulkTransferPool(); + + void allocate(size_t num_transfers, size_t transfer_size); + +protected: + virtual libusb_transfer *allocateTransfer(); + virtual void fillTransfer(libusb_transfer *transfer); + virtual void processTransfer(libusb_transfer *transfer); +}; + +class IsoTransferPool : public TransferPool +{ +public: + IsoTransferPool(libusb_device_handle *device_handle, unsigned char device_endpoint); + virtual ~IsoTransferPool(); + + void allocate(size_t num_transfers, size_t num_packets, size_t packet_size); + +protected: + virtual libusb_transfer *allocateTransfer(); + virtual void fillTransfer(libusb_transfer *transfer); + virtual void processTransfer(libusb_transfer *transfer); + +private: + size_t num_packets_; + size_t packet_size_; +}; + +} /* namespace usb */ +} /* namespace libfreenect2 */ +#endif /* TRANSFER_POOL_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/color_settings.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/color_settings.h new file mode 100644 index 0000000..1d50ff2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/color_settings.h @@ -0,0 +1,118 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef COLOR_SETTINGS_H_ +#define COLOR_SETTINGS_H_ + +namespace libfreenect2 +{ + +// The following information was found by using the library released by Microsoft under MIT license, +// https://github.com/Microsoft/MixedRealityCompanionKit/tree/master/KinectIPD/NuiSensor +enum ColorSettingCommandType +{ + COLOR_SETTING_SET_EXPOSURE_MODE = 0, + COLOR_SETTING_SET_INTEGRATION_TIME = 1, + COLOR_SETTING_GET_INTEGRATION_TIME = 2, + COLOR_SETTING_SET_WHITE_BALANCE_MODE = 10, + COLOR_SETTING_SET_RED_CHANNEL_GAIN = 11, + COLOR_SETTING_SET_GREEN_CHANNEL_GAIN = 12, + COLOR_SETTING_SET_BLUE_CHANNEL_GAIN = 13, + COLOR_SETTING_GET_RED_CHANNEL_GAIN = 14, + COLOR_SETTING_GET_GREEN_CHANNEL_GAIN = 15, + COLOR_SETTING_GET_BLUE_CHANNEL_GAIN = 16, + COLOR_SETTING_SET_EXPOSURE_TIME_MS = 17, + COLOR_SETTING_GET_EXPOSURE_TIME_MS = 18, + COLOR_SETTING_SET_DIGITAL_GAIN = 19, + COLOR_SETTING_GET_DIGITAL_GAIN = 20, + COLOR_SETTING_SET_ANALOG_GAIN = 21, + COLOR_SETTING_GET_ANALOG_GAIN = 22, + COLOR_SETTING_SET_EXPOSURE_COMPENSATION = 23, + COLOR_SETTING_GET_EXPOSURE_COMPENSATION = 24, + COLOR_SETTING_SET_ACS = 25, + COLOR_SETTING_GET_ACS = 26, + COLOR_SETTING_SET_EXPOSURE_METERING_MODE = 27, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONES = 28, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_0_WEIGHT = 29, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_1_WEIGHT = 30, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_2_WEIGHT = 31, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_3_WEIGHT = 32, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_4_WEIGHT = 33, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_5_WEIGHT = 34, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_6_WEIGHT = 35, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_7_WEIGHT = 36, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_8_WEIGHT = 37, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_9_WEIGHT = 38, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_10_WEIGHT = 39, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_11_WEIGHT = 40, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_12_WEIGHT = 41, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_13_WEIGHT = 42, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_14_WEIGHT = 43, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_15_WEIGHT = 44, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_16_WEIGHT = 45, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_17_WEIGHT = 46, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_18_WEIGHT = 47, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_19_WEIGHT = 48, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_20_WEIGHT = 49, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_21_WEIGHT = 50, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_22_WEIGHT = 51, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_23_WEIGHT = 52, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_24_WEIGHT = 53, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_25_WEIGHT = 54, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_26_WEIGHT = 55, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_27_WEIGHT = 56, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_28_WEIGHT = 57, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_29_WEIGHT = 58, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_30_WEIGHT = 59, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_31_WEIGHT = 60, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_32_WEIGHT = 61, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_33_WEIGHT = 62, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_34_WEIGHT = 63, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_35_WEIGHT = 64, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_36_WEIGHT = 65, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_37_WEIGHT = 66, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_38_WEIGHT = 67, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_39_WEIGHT = 68, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_40_WEIGHT = 69, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_41_WEIGHT = 70, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_42_WEIGHT = 71, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_43_WEIGHT = 72, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_44_WEIGHT = 73, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_45_WEIGHT = 74, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_46_WEIGHT = 75, + COLOR_SETTING_SET_EXPOSURE_METERING_ZONE_47_WEIGHT = 76, + COLOR_SETTING_SET_MAX_ANALOG_GAIN_CAP = 77, + COLOR_SETTING_SET_MAX_DIGITAL_GAIN_CAP = 78, + COLOR_SETTING_SET_FLICKER_FREE_FREQUENCY = 79, + COLOR_SETTING_GET_EXPOSURE_MODE = 80, + COLOR_SETTING_GET_WHITE_BALANCE_MODE = 81, + COLOR_SETTING_SET_FRAME_RATE = 82, + COLOR_SETTING_GET_FRAME_RATE = 83, +}; + +} /* namespace libfreenect2 */ + +#endif /* COLOR_SETTINGS_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/config.h.in b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/config.h.in new file mode 100644 index 0000000..35a0f63 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/config.h.in @@ -0,0 +1,66 @@ +/* +* This file is part of the OpenKinect Project. http://www.openkinect.org +* +* Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file +* for details. +* +* This code is licensed to you under the terms of the Apache License, version +* 2.0, or, at your option, the terms of the GNU General Public License, +* version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, +* or the following URLs: +* http://www.apache.org/licenses/LICENSE-2.0 +* http://www.gnu.org/licenses/gpl-2.0.txt +* +* If you redistribute this file in source form, modified or unmodified, you +* may: +* 1) Leave this header intact and distribute it under the same terms, +* accompanying it with the APACHE20 and GPL20 files, or +* 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or +* 3) Delete the GPL v2 clause and accompany it with the APACHE20 file +* In all cases you must keep the copyright notice intact and include a copy +* of the CONTRIB file. +* +* Binary distributions must follow the binary distribution requirements of +* either License. +*/ + +#ifndef LIBFREENECT2_CONFIG_H +#define LIBFREENECT2_CONFIG_H + +#define LIBFREENECT2_VERSION "@PROJECT_VER@" +#define LIBFREENECT2_API_VERSION ((@PROJECT_VER_MAJOR@ << 16) | @PROJECT_VER_MINOR@) + +#ifdef _MSC_VER +#define LIBFREENECT2_PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) +#else +#define LIBFREENECT2_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#endif + +#include +#define LIBFREENECT2_API LIBFREENECT2_EXPORT + +#cmakedefine LIBFREENECT2_WITH_OPENGL_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_OPENCL_SUPPORT +#cmakedefine LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD + +#cmakedefine LIBFREENECT2_WITH_CUDA_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_VT_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_VAAPI_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_TURBOJPEG_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT +#define LIBFREENECT2_TEGRAJPEG_LIBRARY "@TegraJPEG_LIBRARIES@" + +#cmakedefine LIBFREENECT2_THREADING_STDLIB + +#cmakedefine LIBFREENECT2_THREADING_TINYTHREAD + +#cmakedefine LIBFREENECT2_WITH_CXX11_SUPPORT + +#cmakedefine LIBFREENECT2_WITH_PROFILING + +#endif // LIBFREENECT2_CONFIG_H diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener.hpp new file mode 100644 index 0000000..1b0bda1 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener.hpp @@ -0,0 +1,109 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file frame_listener.hpp Classes for frame listeners. */ + +#ifndef FRAME_LISTENER_HPP_ +#define FRAME_LISTENER_HPP_ + +#include +#include +#include + +namespace libfreenect2 +{ + +/** @defgroup frame Frame Listeners + * Receive decoded image frames, and the frame format. + */ + +/** Frame format and metadata. @ingroup frame */ +class LIBFREENECT2_API Frame +{ + public: + /** Available types of frames. */ + enum Type + { + Color = 1, ///< 1920x1080. BGRX or RGBX. + Ir = 2, ///< 512x424 float. Range is [0.0, 65535.0]. + Depth = 4 ///< 512x424 float, unit: millimeter. Non-positive, NaN, and infinity are invalid or missing data. + }; + + /** Pixel format. */ + enum Format + { + Invalid = 0, ///< Invalid format. + Raw = 1, ///< Raw bitstream. 'bytes_per_pixel' defines the number of bytes + Float = 2, ///< A 4-byte float per pixel + BGRX = 4, ///< 4 bytes of B, G, R, and unused per pixel + RGBX = 5, ///< 4 bytes of R, G, B, and unused per pixel + Gray = 6, ///< 1 byte of gray per pixel + }; + + size_t width; ///< Length of a line (in pixels). + size_t height; ///< Number of lines in the frame. + size_t bytes_per_pixel; ///< Number of bytes in a pixel. If frame format is 'Raw' this is the buffer size. + unsigned char* data; ///< Data of the frame (aligned). @see See Frame::Type for pixel format. + uint32_t timestamp; ///< Unit: 0.125 millisecond. Usually incrementing by 266 (30Hz) or 533 (15Hz). + uint32_t sequence; ///< Increasing frame sequence number + float exposure; ///< From 0.5 (very bright) to ~60.0 (fully covered) + float gain; ///< From 1.0 (bright) to 1.5 (covered) + float gamma; ///< From 1.0 (bright) to 6.4 (covered) + uint32_t status; ///< zero if ok; non-zero for errors. + Format format; ///< Byte format. Informative only, doesn't indicate errors. + + /** Construct a new frame. + * @param width Width in pixel + * @param height Height in pixel + * @param bytes_per_pixel Bytes per pixel + * @param data_ Memory to store frame data. If `NULL`, new memory is allocated. + */ + Frame(size_t width, size_t height, size_t bytes_per_pixel, unsigned char *data_ = NULL); + virtual ~Frame(); + + protected: + unsigned char* rawdata; ///< Unaligned start of #data. +}; + +/** Callback interface to receive new frames. @ingroup frame + * You can inherit from FrameListener and define your own listener. + */ +class LIBFREENECT2_API FrameListener +{ +public: + virtual ~FrameListener(); + + /** + * libfreenect2 calls this function when a new frame is decoded. + * @param type Type of the new frame. + * @param frame Data of the frame. + * @return true if you want to take ownership of the frame, i.e. reuse/delete it. Will be reused/deleted by caller otherwise. + */ + virtual bool onNewFrame(Frame::Type type, Frame *frame) = 0; +}; + +} /* namespace libfreenect2 */ +#endif /* FRAME_LISTENER_HPP_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener_impl.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener_impl.h new file mode 100644 index 0000000..d4610dc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/frame_listener_impl.h @@ -0,0 +1,86 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file frame_listener_impl.h Implementation of the frame listener classes. */ + +#ifndef FRAME_LISTENER_IMPL_H_ +#define FRAME_LISTENER_IMPL_H_ + +#include + +#include +#include + +namespace libfreenect2 +{ +///@addtogroup frame +///@{ + +/** Storage of multiple different types of frames. */ +typedef std::map FrameMap; + +class SyncMultiFrameListenerImpl; + +/** Collect multiple types of frames. */ +class LIBFREENECT2_API SyncMultiFrameListener : public FrameListener +{ +public: + /** + * @param frame_types Use bitwise or to combine multiple types, e.g. `Frame::Ir | Frame::Depth`. + */ + SyncMultiFrameListener(unsigned int frame_types); + virtual ~SyncMultiFrameListener(); + + /** Test if there are new frames. Non-blocking. */ + bool hasNewFrame() const; + + /** Wait milliseconds for new frames. + * @param[out] frame Caller is responsible to release the frames in `frame`. + * @param milliseconds Timeout. This parameter is ignored if not built with C++11 threading support. + * @return true if a frame is received; false if not. + */ + bool waitForNewFrame(FrameMap &frame, int milliseconds); + + /** Wait indefinitely for new frames. + * @param[out] frame Caller is responsible to release the frames in `frame`. + */ + void waitForNewFrame(FrameMap &frame); + + /** Shortcut to delete all frames in `frame`. */ + void release(FrameMap &frame); + + virtual bool onNewFrame(Frame::Type type, Frame *frame); +private: + SyncMultiFrameListenerImpl *impl_; + + /* Disable copy and assignment constructors */ + SyncMultiFrameListener(const SyncMultiFrameListener&); + SyncMultiFrameListener& operator=(const SyncMultiFrameListener&); +}; + +///@} +} /* namespace libfreenect2 */ +#endif /* FRAME_LISTENER_IMPL_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/led_settings.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/led_settings.h new file mode 100644 index 0000000..e6ae312 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/led_settings.h @@ -0,0 +1,48 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef LED_SETTINGS_H_ +#define LED_SETTINGS_H_ + +namespace libfreenect2 +{ + +// The following information was found by using the library released by Microsoft under MIT license, +// https://github.com/Microsoft/MixedRealityCompanionKit/tree/master/KinectIPD/NuiSensor +// Debugging the library assembly shows the original struct name was _PETRA_LED_STATE. +struct LedSettings +{ + uint16_t LedId; // LED index [0, 1] + uint16_t Mode; // 0 = constant, 1 = blink between StartLevel, StopLevel every IntervalInMs ms + uint16_t StartLevel; // LED intensity [0, 1000] + uint16_t StopLevel; // LED intensity [0, 1000] + uint32_t IntervalInMs; // Blink interval for Mode=1 in milliseconds + uint32_t Reserved; // 0 +}; + +} /* namespace libfreenect2 */ + +#endif /* LED_SETTINGS_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/libfreenect2.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/libfreenect2.hpp new file mode 100644 index 0000000..5c45656 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/libfreenect2.hpp @@ -0,0 +1,370 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file libfreenect2.hpp Header file of the Freenect2 library. */ + +#ifndef LIBFREENECT2_HPP_ +#define LIBFREENECT2_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ + +/** @defgroup device Initialization and Device Control + * Find, open, and control Kinect v2 devices. */ +///@{ + +/** Device control. */ +class LIBFREENECT2_API Freenect2Device +{ +public: + static const unsigned int VendorId = 0x045E; + static const unsigned int ProductId = 0x02D8; + static const unsigned int ProductIdPreview = 0x02C4; + + /** Color camera calibration parameters. + * Kinect v2 includes factory preset values for these parameters. They are used in Registration. + */ + struct ColorCameraParams + { + /** @name Intrinsic parameters */ + ///@{ + float fx; ///< Focal length x (pixel) + float fy; ///< Focal length y (pixel) + float cx; ///< Principal point x (pixel) + float cy; ///< Principal point y (pixel) + ///@} + + /** @name Extrinsic parameters + * These parameters are used in [a formula](https://github.com/OpenKinect/libfreenect2/issues/41#issuecomment-72022111) to map coordinates in the + * depth camera to the color camera. + * + * They cannot be used for matrix transformation. + */ + ///@{ + float shift_d, shift_m; + + float mx_x3y0; // xxx + float mx_x0y3; // yyy + float mx_x2y1; // xxy + float mx_x1y2; // yyx + float mx_x2y0; // xx + float mx_x0y2; // yy + float mx_x1y1; // xy + float mx_x1y0; // x + float mx_x0y1; // y + float mx_x0y0; // 1 + + float my_x3y0; // xxx + float my_x0y3; // yyy + float my_x2y1; // xxy + float my_x1y2; // yyx + float my_x2y0; // xx + float my_x0y2; // yy + float my_x1y1; // xy + float my_x1y0; // x + float my_x0y1; // y + float my_x0y0; // 1 + ///@} + }; + + /** IR camera intrinsic calibration parameters. + * Kinect v2 includes factory preset values for these parameters. They are used in depth image decoding, and Registration. + */ + struct IrCameraParams + { + float fx; ///< Focal length x (pixel) + float fy; ///< Focal length y (pixel) + float cx; ///< Principal point x (pixel) + float cy; ///< Principal point y (pixel) + float k1; ///< Radial distortion coefficient, 1st-order + float k2; ///< Radial distortion coefficient, 2nd-order + float k3; ///< Radial distortion coefficient, 3rd-order + float p1; ///< Tangential distortion coefficient + float p2; ///< Tangential distortion coefficient + }; + + /** Configuration of depth processing. */ + struct Config + { + float MinDepth; ///< Clip at this minimum distance (meter). + float MaxDepth; ///< Clip at this maximum distance (meter). + + bool EnableBilateralFilter; ///< Remove some "flying pixels". + bool EnableEdgeAwareFilter; ///< Remove pixels on edges because ToF cameras produce noisy edges. + + /** Default is 0.5, 4.5, true, true */ + LIBFREENECT2_API Config(); + }; + + virtual ~Freenect2Device(); + + virtual std::string getSerialNumber() = 0; + virtual std::string getFirmwareVersion() = 0; + + /** Get current color parameters. + * @copydetails ColorCameraParams + */ + virtual ColorCameraParams getColorCameraParams() = 0; + + /** Get current depth parameters. + * @copydetails IrCameraParams + */ + virtual IrCameraParams getIrCameraParams() = 0; + + /** Replace factory preset color camera parameters. + * We do not have a clear understanding of the meaning of the parameters right now. + * You probably want to leave it as it is. + */ + virtual void setColorCameraParams(const ColorCameraParams ¶ms) = 0; + + /** Replace factory preset depth camera parameters. + * This decides accuracy in depth images. You are recommended to provide calibrated values. + */ + virtual void setIrCameraParams(const IrCameraParams ¶ms) = 0; + + /** Configure depth processing. */ + virtual void setConfiguration(const Config &config) = 0; + + /** Provide your listener to receive color frames. */ + virtual void setColorFrameListener(FrameListener* rgb_frame_listener) = 0; + + /** Provide your listener to receive IR and depth frames. */ + virtual void setIrAndDepthFrameListener(FrameListener* ir_frame_listener) = 0; + + /** Sets the RGB camera to fully automatic exposure setting. + * Exposure compensation: negative value gives an underexposed image, + * positive gives an overexposed image. + * + * @param exposure_compensation Exposure compensation, range [-2.0, 2.0] + */ + virtual void setColorAutoExposure(float exposure_compensation = 0) = 0; + + /** Sets a flicker-free exposure time of the RGB camera in pseudo-ms, value in range [0.0, 640] ms. + * The actual frame integration time is set to a multiple of fluorescent light period + * that is shorter than the requested time e.g. requesting 16 ms will set 10 ms + * in Australia (100Hz light flicker), 8.33 ms in USA (120Hz light flicker). + * The gain is automatically set to compensate for the reduced integration time, + * as if the gain was set to 1.0 and the integration time was the requested value. + * + * Requesting less than a single fluorescent light period will set the integration time + * to the requested value, so the image brightness will flicker. + * + * To set the shortest non-flickering integration period for any country, simply set + * a pseudo-exposure time of between (10.0, 16.667) ms, which will automatically drop + * the integration time to 10 or 8.3 ms depending on country, while setting the analog + * gain control to a brighter value. + * + * @param pseudo_exposure_time_ms Pseudo-exposure time in milliseconds, range (0.0, 66.0+] + */ + virtual void setColorSemiAutoExposure(float pseudo_exposure_time_ms) = 0; + + /** Manually set true exposure time and analog gain of the RGB camera. + * @param integration_time_ms True shutter time in milliseconds, range (0.0, 66.0] + * @param analog_gain Analog gain, range [1.0, 4.0] + */ + virtual void setColorManualExposure(float integration_time_ms, float analog_gain) = 0; + + /** Set/get an individual setting value of the RGB camera. */ + virtual void setColorSetting(ColorSettingCommandType cmd, uint32_t value) = 0; + virtual void setColorSetting(ColorSettingCommandType cmd, float value) = 0; + virtual uint32_t getColorSetting(ColorSettingCommandType cmd) = 0; + virtual float getColorSettingFloat(ColorSettingCommandType cmd) = 0; + + /** Set the settings of a Kinect LED. + * @param led Settings for a single LED. + */ + virtual void setLedStatus(LedSettings led) = 0; + + /** Start data processing with both RGB and depth streams. + * All above configuration must only be called before start() or after stop(). + * + * FrameListener will receive frames when the device is running. + * + * @return true if ok, false if error. + */ + virtual bool start() = 0; + + /** Start data processing with or without some streams. + * FrameListener will receive enabled frames when the device is running. + * + * @param rgb Whether to enable RGB stream. + * @param depth Whether to enable depth stream. + * @return true if ok, false if error. + */ + virtual bool startStreams(bool rgb, bool depth) = 0; + + /** Stop data processing. + * + * @return true if ok, false if error. + */ + virtual bool stop() = 0; + + /** Shut down the device. + * + * @return true if ok, false if error. + */ + virtual bool close() = 0; +}; + +class Freenect2Impl; + +/** + * Library context to find and open devices. + * + * You will first find existing devices by calling enumerateDevices(). + * + * Then you can openDevice() and control the devices with returned Freenect2Device object. + * + * You may open devices with custom PacketPipeline. + * After passing a PacketPipeline object to libfreenect2 do not use or free the object, + * libfreenect2 will take care. If openDevice() fails the PacketPipeline object will get + * deleted. A new PacketPipeline object has to be created each time a device is opened. + */ +class LIBFREENECT2_API Freenect2 +{ +public: + /** + * @param usb_context If the libusb context is provided, + * Freenect2 will use it instead of creating one. + */ + Freenect2(void *usb_context = 0); + virtual ~Freenect2(); + + /** Must be called before doing anything else. + * @return Number of devices, 0 if none + */ + int enumerateDevices(); + + /** + * @param idx Device index + * @return Device serial number, or empty if the index is invalid. + */ + std::string getDeviceSerialNumber(int idx); + + /** + * @return Device serial number, or empty if no device exists. + */ + std::string getDefaultDeviceSerialNumber(); + + /** Open device by index with default pipeline. + * @param idx Index number. Index numbers are not determinstic during enumeration. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDevice(int idx); + + /** Open device by index. + * @param idx Index number. Index numbers are not determinstic during enumeration. + * @param factory New PacketPipeline instance. This is always automatically freed. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDevice(int idx, const PacketPipeline *factory); + + /** Open device by serial number with default pipeline. + * @param serial Serial number + * @return New device object, or NULL on failure + */ + Freenect2Device *openDevice(const std::string &serial); + + /** Open device by serial number. + * @param serial Serial number + * @param factory New PacketPipeline instance. This is always automatically freed. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDevice(const std::string &serial, const PacketPipeline *factory); + + /** Open the first device with default pipeline. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDefaultDevice(); + + /** Open the first device. + * @param factory New PacketPipeline instance. This is always automatically freed. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDefaultDevice(const PacketPipeline *factory); +private: + Freenect2Impl *impl_; + + /* Disable copy and assignment constructors */ + Freenect2(const Freenect2&); + Freenect2& operator=(const Freenect2&); +}; + +class Freenect2ReplayImpl; + +/** + * Library context to create and open replay devices. + * + * Call openDevice() and control the device with the returned Freenect2ReplayDevice object. + */ +class LIBFREENECT2_API Freenect2Replay +{ +public: + /** + * Creates the context. + */ + Freenect2Replay(); + virtual ~Freenect2Replay(); + + /** Open a device by a collection of stored frame filenames with default pipeline. + * See filename format below. + * @param frame_filenames A list of filenames for stored frames. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDevice(const std::vector& frame_filenames); + + /** Open device by a collection of stored frame filenames with the specified pipeline. + * File names non-compliant with the filename format will be skipped. + * Filename format: __. + * - a string of the filename, anything + * -- packet timestamp as in pipeline packets + * -- frame sequence number in the packet + * -- .depth, .jpg, or .jpeg (case sensitive) + * @param frame_filenames A list of filenames for stored frames. + * @param factory New PacketPipeline instance. This is always automatically freed. + * @return New device object, or NULL on failure + */ + Freenect2Device *openDevice(const std::vector& frame_filenames, const PacketPipeline *factory); + +private: + Freenect2ReplayImpl *impl_; + + /* Disable copy and assignment constructors */ + Freenect2Replay(const Freenect2Replay&); + Freenect2Replay& operator=(const Freenect2Replay&); +}; + +///@} +} /* namespace libfreenect2 */ +#endif /* LIBFREENECT2_HPP_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/logger.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/logger.h new file mode 100644 index 0000000..576aafc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/logger.h @@ -0,0 +1,100 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file logger.h Declaration of logging classes. */ + +#ifndef LIBFREENECT2_LOGGER_H_ +#define LIBFREENECT2_LOGGER_H_ + +#include + +#include + +namespace libfreenect2 +{ + +/** @defgroup logging Logging utilities + * Specify logging level and custom logging destination. */ +///@{ + +/** Provide interfaces to receive log messages. + * You can inherit this class and implement your custom logger. */ +class LIBFREENECT2_API Logger +{ +public: + /** Available levels of logging, higher is more output. */ + enum Level + { + None = 0, + Error = 1, + Warning = 2, + Info = 3, + Debug = 4, + }; + + /** Default is Info, or overridden by environment variable `LIBFREENECT2_LOGGER_LEVEL`. + * `LIBFREENECT2_LOGGER_LEVEL` can contain a case-insensitive name of level. + */ + static Level getDefaultLevel(); + + /** Convert logging level to a human-readable name. + */ + static std::string level2str(Level level); + + virtual ~Logger(); + + /** Get the level of the logger; the level is immutable. */ + virtual Level level() const; + + /** libfreenect2 calls this function to output all log messages. */ + virtual void log(Level level, const std::string &message) = 0; +protected: + Level level_; +}; + +/** Allocate a Logger instance that outputs log to standard input/output */ +LIBFREENECT2_API Logger *createConsoleLogger(Logger::Level level); + +/** @copybrief Logger::getDefaultLevel + * + * %libfreenect2 will have an initial global logger created with createConsoleLoggerWithDefaultLevel(). + * You do not have to explicitly call this if the default is already what you want. + */ +LIBFREENECT2_API Logger *createConsoleLoggerWithDefaultLevel(); + +/** Get the pointer to the current logger. + * @return Pointer to the logger. This is purely informational. You should not free the pointer. + */ +LIBFREENECT2_API Logger *getGlobalLogger(); + +/** Set the logger for all log output in this library. + * @param logger Pointer to your logger, or `NULL` to disable logging. The memory will be freed automatically. You should not free the pointer. + */ +LIBFREENECT2_API void setGlobalLogger(Logger *logger); + +///@} +} /* namespace libfreenect2 */ +#endif /* LIBFREENECT2_LOGGER_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/packet_pipeline.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/packet_pipeline.h new file mode 100644 index 0000000..08d6540 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/packet_pipeline.h @@ -0,0 +1,161 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file packet_pipeline.h Packet pipe line definitions. */ + +#ifndef PACKET_PIPELINE_H_ +#define PACKET_PIPELINE_H_ + +#include + +#include + +namespace libfreenect2 +{ + +class DataCallback; +class RgbPacketProcessor; +class DepthPacketProcessor; +class PacketPipelineComponents; + +/** @defgroup pipeline Packet Pipelines + * Implement various methods to decode color and depth images with different performance and platform support + * + * You can construct a specific PacketPipeline object and provide it to Freenect2::openDevice(). + */ +///@{ + +/** Base class for other pipeline classes. + * Methods in this class are reserved for internal use. + */ +class LIBFREENECT2_API PacketPipeline +{ +public: + typedef DataCallback PacketParser; + + PacketPipeline(); + virtual ~PacketPipeline(); + + virtual PacketParser *getRgbPacketParser() const; + virtual PacketParser *getIrPacketParser() const; + + virtual RgbPacketProcessor *getRgbPacketProcessor() const; + virtual DepthPacketProcessor *getDepthPacketProcessor() const; +protected: + PacketPipelineComponents *comp_; +}; + + class LIBFREENECT2_API DumpPacketPipeline: public PacketPipeline + { + public: + DumpPacketPipeline(); + virtual ~DumpPacketPipeline(); + + // These are all required to decode depth data + const unsigned char* getDepthP0Tables(size_t* length); + + const float* getDepthXTable(size_t* length); + const float* getDepthZTable(size_t* length); + const short* getDepthLookupTable(size_t* length); + }; + +/** Pipeline with CPU depth processing. */ +class LIBFREENECT2_API CpuPacketPipeline : public PacketPipeline +{ +public: + CpuPacketPipeline(); + virtual ~CpuPacketPipeline(); +}; + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +/** Pipeline with OpenGL depth processing. */ +class LIBFREENECT2_API OpenGLPacketPipeline : public PacketPipeline +{ +protected: + void *parent_opengl_context_; + bool debug_; +public: + OpenGLPacketPipeline(void *parent_opengl_context = 0, bool debug = false); + virtual ~OpenGLPacketPipeline(); +}; +#endif // LIBFREENECT2_WITH_OPENGL_SUPPORT + +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT +/** Pipeline with OpenCL depth processing. */ +class LIBFREENECT2_API OpenCLPacketPipeline : public PacketPipeline +{ +protected: + const int deviceId; +public: + OpenCLPacketPipeline(const int deviceId = -1); + virtual ~OpenCLPacketPipeline(); +}; + +/* + * The class below implement a depth packet processor using the phase unwrapping + * algorithm described in the paper "Efficient Phase Unwrapping using Kernel + * Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ +class LIBFREENECT2_API OpenCLKdePacketPipeline : public PacketPipeline +{ +protected: + const int deviceId; +public: + OpenCLKdePacketPipeline(const int deviceId = -1); + virtual ~OpenCLKdePacketPipeline(); +}; +#endif // LIBFREENECT2_WITH_OPENCL_SUPPORT + +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT +class LIBFREENECT2_API CudaPacketPipeline : public PacketPipeline +{ +protected: + const int deviceId; +public: + CudaPacketPipeline(const int deviceId = -1); + virtual ~CudaPacketPipeline(); +}; + +/* + * The class below implement a depth packet processor using the phase unwrapping + * algorithm described in the paper "Efficient Phase Unwrapping using Kernel + * Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ +class LIBFREENECT2_API CudaKdePacketPipeline : public PacketPipeline +{ +protected: + const int deviceId; +public: + CudaKdePacketPipeline(const int deviceId = -1); + virtual ~CudaKdePacketPipeline(); +}; +#endif // LIBFREENECT2_WITH_CUDA_SUPPORT + +///@} +} /* namespace libfreenect2 */ +#endif /* PACKET_PIPELINE_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/registration.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/registration.h new file mode 100644 index 0000000..6638919 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/include/libfreenect2/registration.h @@ -0,0 +1,126 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file registration.h Class for merging depth and color frames. */ + +#ifndef REGISTRATION_H_ +#define REGISTRATION_H_ + +#include +#include +#include +#include + +namespace libfreenect2 +{ + +class RegistrationImpl; + +/** @defgroup registration Registration and Geometry + * Register depth to color, create point clouds. */ + +/** Combine frames of depth and color camera. @ingroup registration + * Right now this class uses a reverse engineered formula that uses factory + * preset extrinsic parameters. We do not have a clear understanding of these + * particular extrinsic parameters and do not know how to calibrate them by + * hand. + * + * If you want to perform registration with standard camera extrinsic matrix, + * you probably need something else. + */ +class LIBFREENECT2_API Registration +{ +public: + /** + * @param depth_p Depth camera parameters. You can use the factory values, or use your own. + * @param rgb_p Color camera parameters. Probably use the factory values for now. + */ + Registration(Freenect2Device::IrCameraParams depth_p, Freenect2Device::ColorCameraParams rgb_p); + ~Registration(); + + /** Undistort and register a single depth point to color camera. + * @param dx Distorted depth coordinate x (pixel) + * @param dy Distorted depth coordinate y (pixel) + * @param dz Depth value (millimeter) + * @param[out] cx Undistorted color coordinate x (normalized) + * @param[out] cy Undistorted color coordinate y (normalized) + */ + void apply(int dx, int dy, float dz, float& cx, float &cy) const; + + /** Map color images onto depth images + * @param rgb Color image (1920x1080 BGRX) + * @param depth Depth image (512x424 float) + * @param[out] undistorted Undistorted depth image + * @param[out] registered Color image for the depth image (512x424) + * @param enable_filter Filter out pixels not visible to both cameras. + * @param[out] bigdepth If not `NULL`, return mapping of depth onto colors (1920x1082 float). **1082** not 1080, with a blank top and bottom row. + * @param[out] color_depth_map Index of mapped color pixel for each depth pixel (512x424). + */ + void apply(const Frame* rgb, const Frame* depth, Frame* undistorted, Frame* registered, const bool enable_filter = true, Frame* bigdepth = 0, int* color_depth_map = 0) const; + + /** Undistort depth + * @param depth Depth image (512x424 float) + * @param[out] undistorted Undistorted depth image + */ + void undistortDepth(const Frame* depth, Frame* undistorted) const; + + /** Construct a 3-D point with color in a point cloud. + * @param undistorted Undistorted depth frame from apply(). + * @param registered Registered color frame from apply(). + * @param r Row (y) index in depth image. + * @param c Column (x) index in depth image. + * @param[out] x X coordinate of the 3-D point (meter). + * @param[out] y Y coordinate of the 3-D point (meter). + * @param[out] z Z coordinate of the 3-D point (meter). + * @param[out] rgb Color of the 3-D point (BGRX). To unpack the data, use + * + * const uint8_t *p = reinterpret_cast(&rgb); + * uint8_t b = p[0]; + * uint8_t g = p[1]; + * uint8_t r = p[2]; + */ + void getPointXYZRGB (const Frame* undistorted, const Frame* registered, int r, int c, float& x, float& y, float& z, float& rgb) const; + + /** Construct a 3-D point in a point cloud. + * @param undistorted Undistorted depth frame from apply(). + * @param r Row (y) index in depth image. + * @param c Column (x) index in depth image. + * @param[out] x X coordinate of the 3-D point (meter). + * @param[out] y Y coordinate of the 3-D point (meter). + * @param[out] z Z coordinate of the 3-D point (meter). + */ + void getPointXYZ (const Frame* undistorted, int r, int c, float& x, float& y, float& z) const; + +private: + RegistrationImpl *impl_; + + /* Disable copy and assignment constructors */ + Registration(const Registration&); + Registration& operator=(const Registration&); +}; + +} /* namespace libfreenect2 */ +#endif /* REGISTRATION_H_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/README.md b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/README.md new file mode 100644 index 0000000..4f410b3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/README.md @@ -0,0 +1,42 @@ +# Build libfreenect2 for Android + +## 1. Requirements + +* A latest release of Android NDK. +* A rooted Android device with USB3.0 host. + +## 2. Build libusb + +* See the [official documentation](https://github.com/libusb/libusb/blob/master/android/README) for instructions to build libusb for Android. +* Due to [certain modifications](https://github.com/libusb/libusb/commit/2f3bc98b0d0f4766496df53c855685a5f0e5e7cf), libusb can no longer be used directly on Android. Grab a latest available [release](https://github.com/libusb/libusb/releases/tag/v1.0.22) instead. +* The arm64-v8a build of libusb segfaults, use an armeabi-v7a build instead if you are running Android on arm64. + +## 3. Build libturbojpeg + +* See the [official documentation](https://github.com/libjpeg-turbo/libjpeg-turbo/blob/master/BUILDING.md) for instructions to build libturbojpeg for Android. +* May encounter problems when using the master branch of libturbojpeg with libfreenect2. However, [2.0.1 release](https://github.com/libjpeg-turbo/libjpeg-turbo/releases/tag/2.0.1) and older versions work well. + +## 4. Build libfreenect2 + +* Grab libfreenect2 and change into Android build directory. + +```bash +git clone https://github.com/OpenKinect/libfreenect2.git +cd libfreenect2/platform/android/jni +``` + +* Build libfreenect2 with Android NDK. + +```bash +/path/to/ndk-build \ + LIBUSB_ROOT=/path/to/libusb/root \ + LIBUSB_SHARED_REL=relative/path/to/libusb1.0.so \ + LIBTURBOJPEG_ROOT=/path/to/libturbojpeg \ + LIBTURBOJPEG_SHARED_REL=relative/path/to/libturbojpeg.so +``` + +* You will find the built binaries in platform/android/libs. + +## 5. Notes + +* Now we can only use CPU for depth packet processing. OpenGL ES on Android should work, but it's not yet supported. \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Android.mk b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Android.mk new file mode 100644 index 0000000..7bc9514 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Android.mk @@ -0,0 +1,5 @@ + +LOCAL_PATH := $(call my-dir) + +include $(LOCAL_PATH)/libfreenect2.mk +include $(LOCAL_PATH)/examples.mk diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Application.mk b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Application.mk new file mode 100644 index 0000000..dbadc36 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/Application.mk @@ -0,0 +1,5 @@ + +APP_ABI := armeabi-v7a +APP_PLATFORM := android-21 +APP_STL := c++_shared +APP_CPPFLAGS := -fexceptions -std=c++11 diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/examples.mk b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/examples.mk new file mode 100644 index 0000000..79460dc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/examples.mk @@ -0,0 +1,16 @@ + +include $(CLEAR_VARS) + +LIBFREENECT2_ROOT := ../../.. + +LOCAL_SRC_FILES := $(LIBFREENECT2_ROOT)/examples/Protonect.cpp + +LOCAL_C_INCLUDES += \ + $(LIBFREENECT2_ROOT)/include \ + $(LIBFREENECT2_ROOT)/platform/android + +LOCAL_SHARED_LIBRARIES += libfreenect2 + +LOCAL_MODULE := Protonect + +include $(BUILD_EXECUTABLE) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/libfreenect2.mk b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/libfreenect2.mk new file mode 100644 index 0000000..9cfca23 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/jni/libfreenect2.mk @@ -0,0 +1,50 @@ + +LIBFREENECT2_ROOT := ../../.. + +include $(CLEAR_VARS) +LOCAL_MODULE := libusb +LOCAL_SRC_FILES := $(LIBUSB_ROOT)/$(LIBUSB_SHARED_REL) +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libturbojpeg +LOCAL_SRC_FILES := $(LIBTURBOJPEG_ROOT)/$(LIBTURBOJPEG_SHARED_REL) +include $(PREBUILT_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +LIBFREENECT2_SRC := $(LIBFREENECT2_ROOT)/src + +LOCAL_C_INCLUDES += \ + $(LIBUSB_ROOT)/libusb \ + $(LIBTURBOJPEG_ROOT) \ + $(LIBFREENECT2_ROOT)/include \ + $(LIBFREENECT2_ROOT)/include/internal \ + $(LIBFREENECT2_SRC)/tinythread \ + $(LIBFREENECT2_ROOT)/platform/android + +LOCAL_SRC_FILES := \ + $(LIBFREENECT2_SRC)/tinythread/tinythread.cpp \ + $(LIBFREENECT2_SRC)/allocator.cpp \ + $(LIBFREENECT2_SRC)/command_transaction.cpp \ + $(LIBFREENECT2_SRC)/cpu_depth_packet_processor.cpp \ + $(LIBFREENECT2_SRC)/depth_packet_processor.cpp \ + $(LIBFREENECT2_SRC)/depth_packet_stream_parser.cpp \ + $(LIBFREENECT2_SRC)/event_loop.cpp \ + $(LIBFREENECT2_SRC)/frame_listener_impl.cpp \ + $(LIBFREENECT2_SRC)/libfreenect2.cpp \ + $(LIBFREENECT2_SRC)/logging.cpp \ + $(LIBFREENECT2_SRC)/packet_pipeline.cpp \ + $(LIBFREENECT2_SRC)/registration.cpp \ + $(LIBFREENECT2_SRC)/resource.cpp \ + $(LIBFREENECT2_SRC)/rgb_packet_processor.cpp \ + $(LIBFREENECT2_SRC)/rgb_packet_stream_parser.cpp \ + $(LIBFREENECT2_SRC)/transfer_pool.cpp \ + $(LIBFREENECT2_SRC)/turbo_jpeg_rgb_packet_processor.cpp \ + $(LIBFREENECT2_SRC)/usb_control.cpp + +LOCAL_SHARED_LIBRARIES += libusb libturbojpeg + +LOCAL_MODULE := libfreenect2 + +include $(BUILD_SHARED_LIBRARY) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/libfreenect2/config.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/libfreenect2/config.h new file mode 100644 index 0000000..2488969 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/android/libfreenect2/config.h @@ -0,0 +1,15 @@ +#ifndef LIBFREENECT2_CONFIG_H +#define LIBFREENECT2_CONFIG_H + +#define LIBFREENECT2_VERSION "0.2.0" +#define LIBFREENECT2_API_VERSION ((0 << 16) | 2) + +#define LIBFREENECT2_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) + +#define LIBFREENECT2_API __attribute__((visibility("default"))) + +#define LIBFREENECT2_WITH_TURBOJPEG_SUPPORT +#define LIBFREENECT2_THREADING_STDLIB +#define LIBFREENECT2_WITH_CXX11_SUPPORT + +#endif // LIBFREENECT2_CONFIG_H diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/linux/udev/90-kinect2.rules b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/linux/udev/90-kinect2.rules new file mode 100644 index 0000000..55936e3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/linux/udev/90-kinect2.rules @@ -0,0 +1,5 @@ +# this file belongs in /etc/udev/rules.d/ +# ATTR{product}=="Kinect2" +SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02c4", MODE="0666" +SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02d8", MODE="0666" +SUBSYSTEM=="usb", ATTR{idVendor}=="045e", ATTR{idProduct}=="02d9", MODE="0666" diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/Readme.tracing.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/Readme.tracing.txt new file mode 100644 index 0000000..b1997e3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/Readme.tracing.txt @@ -0,0 +1,13 @@ +Use these convenience scripts if you want to create USB 3 traces as described in this blog: + +http://blogs.msdn.com/b/usbcoreblog/archive/2012/08/07/how-to-trace-usb-3-activity.aspx + +Requires Windows 8.1 and software installed as described in the link. + +1. Open command prompt as administrator +2. Run starttrace.bat. +3. When the bat file completes, do something USB-y. Try to keep it short as the trace logs can take up a lot of space. +4. When you are done, run stoptrace.bat as soon as possible. +5. Check c:\Windows\tracing for the log file, and rename it to describe what you were tracing. + +Logs (.etl) are viewable in NetMon on Windows, per the link above. \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/starttrace.bat b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/starttrace.bat new file mode 100644 index 0000000..36021cc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/starttrace.bat @@ -0,0 +1,12 @@ +@echo off +echo Initializing USB 3 tracing... +logman create trace -n usbtrace -o %SystemRoot%\Tracing\usbtrace.etl -nb 128 640 -bs 128 +logman update trace -n usbtrace -p Microsoft-Windows-USB-USBXHCI (Default,PartialDataBusTrace) +logman update trace -n usbtrace -p Microsoft-Windows-USB-UCX (Default,PartialDataBusTrace) +logman update trace -n usbtrace -p Microsoft-Windows-USB-USBHUB3 (Default,PartialDataBusTrace) +REM uncomment below for usb 2 devices as well (not needed for k4w2) +REM logman update trace -n usbtrace -p Microsoft-Windows-USB-USBPORT +REM logman update trace -n usbtrace -p Microsoft-Windows-USB-USBHUB +logman update trace -n usbtrace -p Microsoft-Windows-Kernel-IoTrace 0 2 +logman start -n usbtrace +echo Tracing started. Perform USB tasks now. \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/stoptrace.bat b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/stoptrace.bat new file mode 100644 index 0000000..2f54695 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/stoptrace.bat @@ -0,0 +1,6 @@ +@echo off +echo Stopping tracing... +logman stop -n usbtrace +logman delete -n usbtrace +timestamp.bat %SystemRoot%\Tracing\usbtrace_000001.etl +echo Tracing completed. See C:\Windows\tracing for the file. \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/timestamp.bat b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/timestamp.bat new file mode 100644 index 0000000..ab15bbe --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/platform/windows/tracing/timestamp.bat @@ -0,0 +1,56 @@ +@ECHO off + SETLOCAL + IF [%1] NEQ [] goto s_start + + :: Author - Simon Sheppard, Nov 2012 + :: Tested for Windows XP, Windows 2008 + Echo StampMe.cmd + Echo Rename a file with the DATE/Time + Echo: + Echo Syntax + Echo STAMPME TestFile.txt + Echo: + Echo STAMPME "Test File.txt" + Echo: + Echo STAMPME "c:\docs\Test File.txt" + Echo: + Echo Will rename the file in the format "Test File-2009-12-30@16-55.txt" + Echo: + Echo In a batch file use CALL STAMPME ... + GOTO :eof + + :s_start + Set _file=%~n1% + Set _pathname=%~f1% + Set _ext=%~x1% + + ::Get the date + For /f "tokens=1-4 delims=/-. " %%G in ('Date /t') Do (Call :s_fixdate %%G %%H %%I %%J) + Goto :s_time + + :s_fixdate + Set _yr=%1 + if "%_yr:~0,1%" GTR "9" Shift + For /f "skip=1 tokens=2-4 delims=(-)" %%G in ('Echo.^|Date') Do ( + Set %%G=%1&Set %%H=%2&Set %%I=%3) + goto :eof + + :s_time + :: Get the time + For /f "tokens=1-3 delims=1234567890 " %%a in ("%time%") Do Set "delims=%%a%%b%%c" + For /f "tokens=1-4 delims=%delims%" %%G in ("%time%") Do ( + Set _hh=%%G + Set _min=%%H + Set _ss=%%I + Set _ms=%%J + ) + :: Strip any leading spaces + Set _hh=%_hh: =% + + :: Ensure the hours have a leading zero + if 1%_hh% LSS 20 Set _hh=0%_hh% + +REM Echo Year-Month-Day@Hour-Min-Sec +REM Echo %yy%-%mm%-%dd% @ %_hh%-%_min%-%_ss% + REN "%_pathname%" "%_file% - %yy%-%mm%-%dd%@%_hh%-%_min%-%_ss%%_ext%" + Echo File created %_file% - %yy%-%mm%-%dd%@%_hh%-%_min%-%_ss%%_ext% \ No newline at end of file diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/allocator.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/allocator.cpp new file mode 100644 index 0000000..13aa76d --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/allocator.cpp @@ -0,0 +1,137 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file packet_processor.h Packet processor definitions. */ + +#include "libfreenect2/allocator.h" +#include "libfreenect2/threading.h" + +namespace libfreenect2 +{ +class NewAllocator: public Allocator +{ +public: + virtual Buffer *allocate(size_t size) + { + Buffer *b = new Buffer; + b->data = new unsigned char[size]; + b->length = 0; + b->capacity = size; + b->allocator = this; + return b; + } + + virtual void free(Buffer *b) + { + if (b == NULL) + return; + delete[] b->data; + delete b; + } +}; + +class PoolAllocatorImpl: public Allocator +{ +private: + Allocator *allocator; + Buffer *buffers[2]; + bool used[2]; + mutex used_lock; + condition_variable available_cond; +public: + PoolAllocatorImpl(Allocator *a): allocator(a), buffers(), used() {} + + Buffer *allocate(size_t size) + { + unique_lock guard(used_lock); + while (used[0] && used[1]) + WAIT_CONDITION(available_cond, used_lock, guard); + + if (!used[0]) { + if (buffers[0] == NULL) + buffers[0] = allocator->allocate(size); + buffers[0]->length = 0; + buffers[0]->allocator = this; + used[0] = true; + return buffers[0]; + } else if (!used[1]) { + if (buffers[1] == NULL) + buffers[1] = allocator->allocate(size); + buffers[1]->length = 0; + buffers[1]->allocator = this; + used[1] = true; + return buffers[1]; + } else { + // should never happen + return NULL; + } + } + + void free(Buffer *b) + { + lock_guard guard(used_lock); + if (b == buffers[0]) { + used[0] = false; + available_cond.notify_one(); + } else if (b == buffers[1]) { + used[1] = false; + available_cond.notify_one(); + } + } + + ~PoolAllocatorImpl() + { + allocator->free(buffers[0]); + allocator->free(buffers[1]); + delete allocator; + } +}; + +PoolAllocator::PoolAllocator(): + impl_(new PoolAllocatorImpl(new NewAllocator)) +{ +} + +PoolAllocator::PoolAllocator(Allocator *a): + impl_(new PoolAllocatorImpl(a)) +{ +} + +PoolAllocator::~PoolAllocator() +{ + delete impl_; +} + +Buffer *PoolAllocator::allocate(size_t size) +{ + return impl_->allocate(size); +} + +void PoolAllocator::free(Buffer *b) +{ + impl_->free(b); +} +} // namespace libfreenect2 diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/command_transaction.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/command_transaction.cpp new file mode 100644 index 0000000..e3dc9b0 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/command_transaction.cpp @@ -0,0 +1,146 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file command_transaction.cpp Protocol transactions for device. */ + +#include +#include + +#include + +#define WRITE_LIBUSB_ERROR(__RESULT) libusb_error_name(__RESULT) << " " << libusb_strerror((libusb_error)__RESULT) + +namespace libfreenect2 +{ +namespace protocol +{ +CommandTransaction::CommandTransaction(libusb_device_handle *handle, int inbound_endpoint, int outbound_endpoint) : + handle_(handle), + inbound_endpoint_(inbound_endpoint), + outbound_endpoint_(outbound_endpoint), + timeout_(1000) +{ +} + +CommandTransaction::~CommandTransaction() {} + +bool CommandTransaction::execute(const CommandBase& command, Result& result) +{ + result.resize(command.maxResponseLength()); + response_complete_result_.resize(ResponseCompleteLength); + + // send command + if (!send(command)) + return false; + + // receive response data + if(command.maxResponseLength() > 0) + { + if (!receive(result, command.minResponseLength())) + return false; + if (isResponseCompleteResult(result, command.sequence())) + { + LOG_ERROR << "received premature response complete!"; + return false; + } + } + + // receive response complete + if (!receive(response_complete_result_, ResponseCompleteLength)) + return false; + if (!isResponseCompleteResult(response_complete_result_, command.sequence())) + { + LOG_ERROR << "missing response complete!"; + return false; + } + + return true; +} + +bool CommandTransaction::send(const CommandBase& command) +{ + int transferred_bytes = 0; + int r = libusb_bulk_transfer(handle_, outbound_endpoint_, const_cast(command.data()), command.size(), &transferred_bytes, timeout_); + + if(r != LIBUSB_SUCCESS) + { + LOG_ERROR << "bulk transfer failed: " << WRITE_LIBUSB_ERROR(r); + return false; + } + + if((size_t)transferred_bytes != command.size()) + { + LOG_ERROR << "sent number of bytes differs from expected number! expected: " << command.size() << " got: " << transferred_bytes; + return false; + } + + return true; +} + +bool CommandTransaction::receive(CommandTransaction::Result& result, uint32_t min_length) +{ + int length = 0; + + int r = libusb_bulk_transfer(handle_, inbound_endpoint_, &result[0], result.size(), &length, timeout_); + result.resize(length); + + if(r != LIBUSB_SUCCESS) + { + LOG_ERROR << "bulk transfer failed: " << WRITE_LIBUSB_ERROR(r); + return false; + } + + if ((uint32_t)length < min_length) + { + LOG_ERROR << "bulk transfer too short! expected at least: " << min_length << " got : " << length; + return false; + } + + return true; +} + +bool CommandTransaction::isResponseCompleteResult(CommandTransaction::Result& result, uint32_t sequence) +{ + if(result.size() == ResponseCompleteLength) + { + uint32_t *data = reinterpret_cast(&result[0]); + + if(data[0] == ResponseCompleteMagic) + { + if(data[1] != sequence) + { + LOG_ERROR << "response complete with wrong sequence number! expected: " << sequence << " got: " << data[1]; + } + return true; + } + } + + return false; +} + + +} /* namespace protocol */ +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cpu_depth_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cpu_depth_packet_processor.cpp new file mode 100644 index 0000000..85966b7 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cpu_depth_packet_processor.cpp @@ -0,0 +1,979 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file cpu_depth_packet_processor.cpp Depth processor implementation for the CPU. */ + +#include +#include +#include +#include + +#include + +#include + +#define _USE_MATH_DEFINES +#include + +#include +#include + +/** + * Vector class. + * @tparam ScalarT Type of the elements. + * @tparam Size Number of elements in the vector. + */ +template +struct Vec +{ + ScalarT val[Size]; +}; + +/** + * Matrix class. + * @tparam ScalarT Eelement type of the matrix. + */ +template +struct Mat +{ +private: + bool owns_buffer; ///< Whether the matrix owns the data buffer (and should dispose it when deleted). + unsigned char *buffer_; ///< Data buffer of the matrix (row major). + unsigned char *buffer_end_; ///< End of the buffer (just after the last element). + int width_; ///< Number of elements in the matrix. + int height_; ///< Number of rows in the matrix. + int x_step; ///< Number of bytes in one element. + int y_step; ///< Number of bytes in one row. + + /** + * Allocate a buffer. + * @param width Width of the matrix. + * @param height Height of the matrix. + * @param external_buffer If not \c null, use the provided buffer, else make a new one. + */ + void allocate(int width, int height, unsigned char *external_buffer = 0) + { + this->width_ = width; + this->height_ = height; + x_step = sizeof(ScalarT); + y_step = width * x_step; + + owns_buffer = external_buffer == 0; + + if(owns_buffer) + { + buffer_ = new unsigned char[y_step * height]; + } + else + { + buffer_ = external_buffer; + } + buffer_end_ = buffer_ + (y_step * height); + } + + void deallocate() + { + if(owns_buffer && buffer_ != 0) + { + delete[] buffer_; + owns_buffer = false; + buffer_ = 0; + buffer_end_ = 0; + } + } + +public: + /** Default constructor. */ + Mat():buffer_(0), buffer_end_(0) + { + } + + /** + * Constructor with locally allocated buffer. + * @param height Height of the image. + * @param width Width of the image. + */ + Mat(int height, int width) : owns_buffer(false), buffer_(0) + { + create(height, width); + } + + /** + * Constructor with external buffer. + * @tparam DataT Type of data of the buffer. + * @param height Height of the image. + * @param width Width of the image. + * @param external_buffer Provided buffer. + */ + template + Mat(int height, int width, DataT *external_buffer) + { + allocate(width, height, reinterpret_cast(external_buffer)); + } + + /** Destructor. */ + ~Mat() + { + deallocate(); + } + + /** + * Get the width of the image. + * @return Width of the image. + */ + int width() const + { + return width_; + } + + /** + * Get the height of the image. + * @return height of the image. + */ + int height() const + { + return height_; + } + + /** + * Construct a new image buffer + * @param height Height of the new image. + * @param width Width of the new image. + */ + void create(int height, int width) + { + deallocate(); + allocate(width, height); + } + + /** + * Copy image data to the provided matrix. + * @param other Destination to copy to. + */ + void copyTo(Mat &other) const + { + other.create(height(), width()); + std::copy(buffer_, buffer_end_, other.buffer_); + } + + /** + * Get the image data at the requested point \a x, \a y. + * @param y Vertical (row) position. + * @param x Horizontal position. + * @return Data at the given position. + */ + const ScalarT &at(int y, int x) const + { + return *ptr(y, x); + } + + /** + * Get a reference to the image data at the requested point \a x, \a y. + * @param y Vertical (row) position. + * @param x Horizontal position. + * @return Reference to the data at the given position. + */ + ScalarT &at(int y, int x) + { + return *ptr(y, x); + } + + const ScalarT *ptr(int y, int x) const + { + return reinterpret_cast(buffer_ + y_step * y + x_step * x); + } + + ScalarT *ptr(int y, int x) + { + return reinterpret_cast(buffer_ + y_step * y + x_step * x); + } + + /** + * Get the buffer. + * @return The buffer. + */ + unsigned char* buffer() + { + return buffer_; + } + + /** + * Get the size of the buffer. + * @return Number of bytes in the buffer. + */ + int sizeInBytes() const + { + return buffer_end_ - buffer_; + } +}; + +/** + * Copy and flip buffer upside-down (upper part to bottom, bottom part to top). + * @tparam ScalarT Type of the element of the buffer. + * @param in Source buffer. + * @param [out] out Destination buffer to be filled with flipped \a in data. + */ +template +void flipHorizontal(const Mat &in, Mat& out) +{ + in.copyTo(out); + + typedef unsigned char type; + + int linestep = out.sizeInBytes() / out.height() / sizeof(type); + + type *first_line = reinterpret_cast(out.buffer()), *last_line = reinterpret_cast(out.buffer()) + (out.height() - 1) * linestep; + + + for(int y = 0; y < out.height() / 2; ++y) + { + for(int x = 0; x < linestep; ++x, ++first_line, ++last_line) + { + std::swap(*first_line, *last_line); + } + last_line -= 2 * linestep; + } +} + +namespace libfreenect2 +{ + +inline int bfi(int width, int offset, int src2, int src3) +{ + int bitmask = (((1 << width)-1) << offset) & 0xffffffff; + return ((src2 << offset) & bitmask) | (src3 & ~bitmask); +} + +class CpuDepthPacketProcessorImpl: public WithPerfLogging +{ +public: + Mat p0_table0, p0_table1, p0_table2; + Mat x_table, z_table; + + int16_t lut11to16[2048]; + + float trig_table0[512*424][6]; + float trig_table1[512*424][6]; + float trig_table2[512*424][6]; + + bool enable_bilateral_filter, enable_edge_filter; + DepthPacketProcessor::Parameters params; + + Frame *ir_frame, *depth_frame; + + bool flip_ptables; + + CpuDepthPacketProcessorImpl() + { + newIrFrame(); + newDepthFrame(); + + enable_bilateral_filter = true; + enable_edge_filter = true; + + flip_ptables = true; + } + + /** Allocate a new IR frame. */ + void newIrFrame() + { + ir_frame = new Frame(512, 424, 4); + ir_frame->format = Frame::Float; + //ir_frame = new Frame(512, 424, 12); + } + + ~CpuDepthPacketProcessorImpl() + { + delete ir_frame; + delete depth_frame; + } + + /** Allocate a new depth frame. */ + void newDepthFrame() + { + depth_frame = new Frame(512, 424, 4); + depth_frame->format = Frame::Float; + } + + int32_t decodePixelMeasurement(unsigned char* data, int sub, int x, int y) + { + if (x < 1 || y < 0 || 510 < x || 423 < y) + { + return lut11to16[0]; + } + + int r1zi = (x >> 2) + ((x & 0x3) << 7); // Range 1..510 + r1zi = r1zi * 11L; // Range 11..5610 + + // 298496 = 512 * 424 * 11 / 8 = number of bytes per sub image + uint16_t *ptr = reinterpret_cast(data + 298496 * sub); + int i = y < 212 ? y + 212 : 423 - y; + ptr += 352*i; + + int r1yi = r1zi >> 4; // Range 0..350 + r1zi = r1zi & 15; + + int i1 = ptr[r1yi]; + int i2 = ptr[r1yi + 1]; + i1 = i1 >> r1zi; + i2 = i2 << (16 - r1zi); + + return lut11to16[((i1 | i2) & 2047)]; + } + + /** + * Initialize cos and sin trigonometry tables for each of the three #phase_in_rad parameters. + * @param p0table Angle at every (x, y) position. + * @param [out] trig_tables (3 cos tables, followed by 3 sin tables for the three phases. + */ + void fillTrigTable(Mat &p0table, float trig_table[512*424][6]) + { + int i = 0; + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, ++i) + { + float p0 = -((float)p0table.at(y, x)) * 0.000031 * M_PI; + + float tmp0 = p0 + params.phase_in_rad[0]; + float tmp1 = p0 + params.phase_in_rad[1]; + float tmp2 = p0 + params.phase_in_rad[2]; + + trig_table[i][0] = std::cos(tmp0); + trig_table[i][1] = std::cos(tmp1); + trig_table[i][2] = std::cos(tmp2); + + trig_table[i][3] = std::sin(-tmp0); + trig_table[i][4] = std::sin(-tmp1); + trig_table[i][5] = std::sin(-tmp2); + } + } + + /** + * Process measurement (all three layers). + * @param [in] trig_table Trigonometry tables. + * @param abMultiplierPerFrq Multiplier. + * @param x X position in the image. + * @param y Y position in the image. + * @param m Measurement. + * @param [out] m_out Processed measurement (IR a, IR b, IR amplitude). + */ + void processMeasurementTriple(float trig_table[512*424][6], float abMultiplierPerFrq, int x, int y, const int32_t* m, float* m_out) + { + float zmultiplier = z_table.at(y, x); + if (0 < zmultiplier) + { + bool saturated = (m[0] == 32767 || m[1] == 32767 || m[2] == 32767); + if (!saturated) + { + int offset = y * 512 + x; + float cos_tmp0 = trig_table[offset][0]; + float cos_tmp1 = trig_table[offset][1]; + float cos_tmp2 = trig_table[offset][2]; + + float sin_negtmp0 = trig_table[offset][3]; + float sin_negtmp1 = trig_table[offset][4]; + float sin_negtmp2 = trig_table[offset][5]; + + // formula given in Patent US 8,587,771 B2 + float ir_image_a = cos_tmp0 * m[0] + cos_tmp1 * m[1] + cos_tmp2 * m[2]; + float ir_image_b = sin_negtmp0 * m[0] + sin_negtmp1 * m[1] + sin_negtmp2 * m[2]; + + // only if modeMask & 32 != 0; + if(true)//(modeMask & 32) != 0) + { + ir_image_a *= abMultiplierPerFrq; + ir_image_b *= abMultiplierPerFrq; + } + float ir_amplitude = std::sqrt(ir_image_a * ir_image_a + ir_image_b * ir_image_b) * params.ab_multiplier; + + m_out[0] = ir_image_a; + m_out[1] = ir_image_b; + m_out[2] = ir_amplitude; + } + else + { + // Saturated pixel. + m_out[0] = 0; + m_out[1] = 0; + m_out[2] = 65535.0; + } + } + else + { + // Invalid pixel. + m_out[0] = 0; + m_out[1] = 0; + m_out[2] = 0; + } + } + + /** + * Transform measurement. + * @param [in, out] m Measurement. + */ + void transformMeasurements(float* m) + { + float tmp0 = std::atan2((m[1]), (m[0])); + tmp0 = tmp0 < 0 ? tmp0 + M_PI * 2.0f : tmp0; + tmp0 = (tmp0 != tmp0) ? 0 : tmp0; + + float tmp1 = std::sqrt(m[0] * m[0] + m[1] * m[1]) * params.ab_multiplier; + + m[0] = tmp0; // phase + m[1] = tmp1; // ir amplitude - (possibly bilateral filtered) + } + + /** + * Process first pixel stage. + * @param x Horizontal position. + * @param y Vertical position. + * @param data + * @param [out] m0_out First layer output. + * @param [out] m1_out Second layer output. + * @param [out] m2_out Third layer output. + */ + void processPixelStage1(int x, int y, unsigned char* data, float *m0_out, float *m1_out, float *m2_out) + { + int32_t m0_raw[3], m1_raw[3], m2_raw[3]; + + m0_raw[0] = decodePixelMeasurement(data, 0, x, y); + m0_raw[1] = decodePixelMeasurement(data, 1, x, y); + m0_raw[2] = decodePixelMeasurement(data, 2, x, y); + m1_raw[0] = decodePixelMeasurement(data, 3, x, y); + m1_raw[1] = decodePixelMeasurement(data, 4, x, y); + m1_raw[2] = decodePixelMeasurement(data, 5, x, y); + m2_raw[0] = decodePixelMeasurement(data, 6, x, y); + m2_raw[1] = decodePixelMeasurement(data, 7, x, y); + m2_raw[2] = decodePixelMeasurement(data, 8, x, y); + + processMeasurementTriple(trig_table0, params.ab_multiplier_per_frq[0], x, y, m0_raw, m0_out); + processMeasurementTriple(trig_table1, params.ab_multiplier_per_frq[1], x, y, m1_raw, m1_out); + processMeasurementTriple(trig_table2, params.ab_multiplier_per_frq[2], x, y, m2_raw, m2_out); + } + + /** + * Filter pixels in stage 1. + * @param x Horizontal position. + * @param y Vertical position. + * @param m Input data? + * @param [out] Output data. + * @param [out] bilateral_max_edge_test Whether the accumulated distance of each image stayed within limits. + */ + void filterPixelStage1(int x, int y, const Mat >& m, float* m_out, bool& bilateral_max_edge_test) + { + const float *m_ptr = (m.ptr(y, x)->val); + bilateral_max_edge_test = true; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + for(int i = 0; i < 9; ++i) + m_out[i] = m_ptr[i]; + } + else + { + float m_normalized[2]; + float other_m_normalized[2]; + + int offset = 0; + + for(int i = 0; i < 3; ++i, m_ptr += 3, m_out += 3, offset += 3) + { + float norm2 = m_ptr[0] * m_ptr[0] + m_ptr[1] * m_ptr[1]; + float inv_norm = 1.0f / std::sqrt(norm2); + inv_norm = (inv_norm == inv_norm) ? inv_norm : std::numeric_limits::infinity(); + + m_normalized[0] = m_ptr[0] * inv_norm; + m_normalized[1] = m_ptr[1] * inv_norm; + + int j = 0; + + float weight_acc = 0.0f; + float weighted_m_acc[2] = {0.0f, 0.0f}; + + float threshold = (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier); + float joint_bilateral_exp = params.joint_bilateral_exp; + + if(norm2 < threshold) + { + threshold = 0.0f; + joint_bilateral_exp = 0.0f; + } + + float dist_acc = 0.0f; + + for(int yi = -1; yi < 2; ++yi) + { + for(int xi = -1; xi < 2; ++xi, ++j) + { + if(yi == 0 && xi == 0) + { + weight_acc += params.gaussian_kernel[j]; + + weighted_m_acc[0] += params.gaussian_kernel[j] * m_ptr[0]; + weighted_m_acc[1] += params.gaussian_kernel[j] * m_ptr[1]; + continue; + } + + const float *other_m_ptr = (m.ptr(y + yi, x + xi)->val) + offset; + float other_norm2 = other_m_ptr[0] * other_m_ptr[0] + other_m_ptr[1] * other_m_ptr[1]; + // TODO: maybe fix numeric problems when norm = 0 - original code uses reciprocal square root, which returns +inf for +0 + float other_inv_norm = 1.0f / std::sqrt(other_norm2); + other_inv_norm = (other_inv_norm == other_inv_norm) ? other_inv_norm : std::numeric_limits::infinity(); + + other_m_normalized[0] = other_m_ptr[0] * other_inv_norm; + other_m_normalized[1] = other_m_ptr[1] * other_inv_norm; + + float dist = -(other_m_normalized[0] * m_normalized[0] + other_m_normalized[1] * m_normalized[1]); + dist += 1.0f; + dist *= 0.5f; + + float weight = 0.0f; + + if(other_norm2 >= threshold) + { + weight = (params.gaussian_kernel[j] * std::exp(-1.442695f * joint_bilateral_exp * dist)); + dist_acc += dist; + } + + weighted_m_acc[0] += weight * other_m_ptr[0]; + weighted_m_acc[1] += weight * other_m_ptr[1]; + + weight_acc += weight; + } + } + + bilateral_max_edge_test = bilateral_max_edge_test && dist_acc < params.joint_bilateral_max_edge; + + m_out[0] = 0.0f < weight_acc ? weighted_m_acc[0] / weight_acc : 0.0f; + m_out[1] = 0.0f < weight_acc ? weighted_m_acc[1] / weight_acc : 0.0f; + m_out[2] = m_ptr[2]; + } + } + } + + void processPixelStage2(int x, int y, float *m0, float *m1, float *m2, float *ir_out, float *depth_out, float *ir_sum_out) + { + //// 10th measurement + //float m9 = 1; // decodePixelMeasurement(data, 9, x, y); + // + //// WTF? + //bool cond0 = zmultiplier == 0 || (m9 >= 0 && m9 < 32767); + //m9 = std::max(-m9, m9); + //// if m9 is positive or pixel is invalid (zmultiplier) we set it to 0 otherwise to its absolute value O.o + //m9 = cond0 ? 0 : m9; + + transformMeasurements(m0); + transformMeasurements(m1); + transformMeasurements(m2); + + float ir_sum = m0[1] + m1[1] + m2[1]; + + float phase; + // if(DISABLE_DISAMBIGUATION) + if(false) + { +#if 0 + //r0.yz = r3.zx + r4.zx // add + //r0.yz = r5.xz + r0.zy // add + float phase = m0[0] + m1[0] + m2[0]; // r0.y + float tmp1 = m0[2] + m1[2] + m2[2]; // r0.z + + //r7.xyz = r3.zxy + r4.zxy // add + //r4.xyz = r5.zyx + r7.xzy // add + float tmp2 = m0[0] + m1[0] + m2[0]; // r4.z + //r3.zw = r4.xy // mov + float tmp3 = m0[2] + m1[2] + m2[2]; // r3.z + float tmp4 = m0[1] + m1[1] + m2[1]; // r3.w +#endif + } + else + { + float ir_min = std::min(std::min(m0[1], m1[1]), m2[1]); + + if (ir_min < params.individual_ab_threshold || ir_sum < params.ab_threshold) + { + phase = 0; + } + else + { + float t0 = m0[0] / (2.0f * M_PI) * 3.0f; + float t1 = m1[0] / (2.0f * M_PI) * 15.0f; + float t2 = m2[0] / (2.0f * M_PI) * 2.0f; + + float t5 = (std::floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - std::floor(t3)) * f1; + + bool c2 = 0.5f < std::abs(t3) && std::abs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (std::floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI; + t7 *= 2.0f * M_PI; + t8 *= 2.0f * M_PI; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < params.ab_confidence_slope; + + float ir_min_ = std::min(std::min(m0[1], m1[1]), m2[1]); + float ir_max_ = std::max(std::max(m0[1], m1[1]), m2[1]); + + float ir_x = slope_positive ? ir_min_ : ir_max_; + + ir_x = std::log(ir_x); + ir_x = (ir_x * params.ab_confidence_slope * 0.301030f + params.ab_confidence_offset) * 3.321928f; + ir_x = std::exp(ir_x); + ir_x = std::min(params.max_dealias_confidence, std::max(params.min_dealias_confidence, ir_x)); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = params.max_dealias_confidence * params.max_dealias_confidence >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + } + + // this seems to be the phase to depth mapping :) + float zmultiplier = z_table.at(y, x); + float xmultiplier = x_table.at(y, x); + + phase = 0 < phase ? phase + params.phase_offset : phase; + + float depth_linear = zmultiplier * phase; + float max_depth = phase * params.unambigious_dist * 2; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0 < depth_linear && 0 < max_depth; + + xmultiplier = (xmultiplier * 90) / (max_depth * max_depth * 8192.0); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + + depth_fit = depth_fit < 0 ? 0 : depth_fit; + float depth = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + + // depth + *depth_out = depth; + if(ir_sum_out != 0) + { + *ir_sum_out = ir_sum; + } + + // ir + //*ir_out = std::min((m1[2]) * ab_output_multiplier, 65535.0f); + // ir avg + *ir_out = std::min((m0[2] + m1[2] + m2[2]) * 0.3333333f * params.ab_output_multiplier, 65535.0f); + //ir_out[0] = std::min(m0[2] * ab_output_multiplier, 65535.0f); + //ir_out[1] = std::min(m1[2] * ab_output_multiplier, 65535.0f); + //ir_out[2] = std::min(m2[2] * ab_output_multiplier, 65535.0f); + } + + void filterPixelStage2(int x, int y, Mat > &m, bool max_edge_test_ok, float *depth_out) + { + Vec &depth_and_ir_sum = m.at(y, x); + float &raw_depth = depth_and_ir_sum.val[0], &ir_sum = depth_and_ir_sum.val[2]; + + if(raw_depth >= params.min_depth && raw_depth <= params.max_depth) + { + if(x < 1 || y < 1 || x > 510 || y > 422) + { + *depth_out = raw_depth; + } + else + { + float ir_sum_acc = ir_sum, squared_ir_sum_acc = ir_sum * ir_sum, min_depth = raw_depth, max_depth = raw_depth; + + for(int yi = -1; yi < 2; ++yi) + { + for(int xi = -1; xi < 2; ++xi) + { + if(yi == 0 && xi == 0) continue; + + Vec &other = m.at(y + yi, x + xi); + + ir_sum_acc += other.val[2]; + squared_ir_sum_acc += other.val[2] * other.val[2]; + + if(0.0f < other.val[1]) + { + min_depth = std::min(min_depth, other.val[1]); + max_depth = std::max(max_depth, other.val[1]); + } + } + } + + float tmp0 = std::sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = std::max(ir_sum_acc / 9.0f, params.edge_ab_avg_min_value); + tmp0 /= edge_avg; + + float abs_min_diff = std::abs(raw_depth - min_depth); + float abs_max_diff = std::abs(raw_depth - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = std::max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < raw_depth && + tmp0 >= params.edge_ab_std_dev_threshold && + params.edge_close_delta_threshold < abs_min_diff && + params.edge_far_delta_threshold < abs_max_diff && + params.edge_max_delta_threshold < max_abs_diff && + params.edge_avg_delta_threshold < avg_diff; + + *depth_out = cond0 ? 0.0f : raw_depth; + + if(!cond0) + { + if(max_edge_test_ok) + { + //float tmp1 = 1500.0f > raw_depth ? 30.0f : 0.02f * raw_depth; + float edge_count = 0.0f; + + *depth_out = edge_count > params.max_edge_count ? 0.0f : raw_depth; + } + else + { + *depth_out = !max_edge_test_ok ? 0.0f : raw_depth; + *depth_out = true ? *depth_out : raw_depth; + } + } + } + } + else + { + *depth_out = 0.0f; + } + + // override raw depth + depth_and_ir_sum.val[0] = depth_and_ir_sum.val[1]; + } +}; + +CpuDepthPacketProcessor::CpuDepthPacketProcessor() : + impl_(new CpuDepthPacketProcessorImpl()) +{ +} + +CpuDepthPacketProcessor::~CpuDepthPacketProcessor() +{ + delete impl_; +} + +void CpuDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + + impl_->params.min_depth = config.MinDepth * 1000.0f; + impl_->params.max_depth = config.MaxDepth * 1000.0f; + impl_->enable_bilateral_filter = config.EnableBilateralFilter; + impl_->enable_edge_filter = config.EnableEdgeAwareFilter; +} + +/** + * Load p0 tables from a command response, + * @param buffer Buffer containing the response. + * @param buffer_length Length of the response data. + */ +void CpuDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) +{ + // TODO: check known header fields (headersize, tablesize) + libfreenect2::protocol::P0TablesResponse* p0table = (libfreenect2::protocol::P0TablesResponse*)buffer; + + if(buffer_length < sizeof(libfreenect2::protocol::P0TablesResponse)) + { + LOG_ERROR << "P0Table response too short!"; + return; + } + + if(impl_->flip_ptables) + { + flipHorizontal(Mat(424, 512, p0table->p0table0), impl_->p0_table0); + flipHorizontal(Mat(424, 512, p0table->p0table1), impl_->p0_table1); + flipHorizontal(Mat(424, 512, p0table->p0table2), impl_->p0_table2); + } + else + { + Mat p00(424, 512, p0table->p0table0); + p00.copyTo(impl_->p0_table0); + Mat(424, 512, p0table->p0table1).copyTo(impl_->p0_table1); + Mat(424, 512, p0table->p0table2).copyTo(impl_->p0_table2); + } + + impl_->fillTrigTable(impl_->p0_table0, impl_->trig_table0); + impl_->fillTrigTable(impl_->p0_table1, impl_->trig_table1); + impl_->fillTrigTable(impl_->p0_table2, impl_->trig_table2); +} + +void CpuDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) +{ + impl_->x_table.create(424, 512); + std::copy(xtable, xtable + TABLE_SIZE, impl_->x_table.ptr(0,0)); + + impl_->z_table.create(424, 512); + std::copy(ztable, ztable + TABLE_SIZE, impl_->z_table.ptr(0,0)); +} + +void CpuDepthPacketProcessor::loadLookupTable(const short *lut) +{ + std::copy(lut, lut + LUT_SIZE, impl_->lut11to16); +} + +/** + * Process a packet. + * @param packet Packet to process. + */ +void CpuDepthPacketProcessor::process(const DepthPacket &packet) +{ + if(listener_ == 0) return; + + impl_->startTiming(); + + impl_->ir_frame->timestamp = packet.timestamp; + impl_->depth_frame->timestamp = packet.timestamp; + impl_->ir_frame->sequence = packet.sequence; + impl_->depth_frame->sequence = packet.sequence; + + Mat > + m(424, 512), + m_filtered(424, 512) + ; + Mat m_max_edge_test(424, 512); + + float *m_ptr = (m.ptr(0, 0)->val); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_ptr += 9) + { + impl_->processPixelStage1(x, y, packet.buffer, m_ptr + 0, m_ptr + 3, m_ptr + 6); + } + + // bilateral filtering + if(impl_->enable_bilateral_filter) + { + float *m_filtered_ptr = (m_filtered.ptr(0, 0)->val); + unsigned char *m_max_edge_test_ptr = m_max_edge_test.ptr(0, 0); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_filtered_ptr += 9, ++m_max_edge_test_ptr) + { + bool max_edge_test_val = true; + impl_->filterPixelStage1(x, y, m, m_filtered_ptr, max_edge_test_val); + *m_max_edge_test_ptr = max_edge_test_val ? 1 : 0; + } + + m_ptr = (m_filtered.ptr(0, 0)->val); + } + else + { + m_ptr = (m.ptr(0, 0)->val); + } + + Mat out_ir(424, 512, impl_->ir_frame->data), out_depth(424, 512, impl_->depth_frame->data); + + if(impl_->enable_edge_filter) + { + Mat > depth_ir_sum(424, 512); + Vec *depth_ir_sum_ptr = depth_ir_sum.ptr(0, 0); + unsigned char *m_max_edge_test_ptr = m_max_edge_test.ptr(0, 0); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_ptr += 9, ++m_max_edge_test_ptr, ++depth_ir_sum_ptr) + { + float raw_depth, ir_sum; + + impl_->processPixelStage2(x, y, m_ptr + 0, m_ptr + 3, m_ptr + 6, out_ir.ptr(423 - y, x), &raw_depth, &ir_sum); + + depth_ir_sum_ptr->val[0] = raw_depth; + depth_ir_sum_ptr->val[1] = *m_max_edge_test_ptr == 1 ? raw_depth : 0; + depth_ir_sum_ptr->val[2] = ir_sum; + } + + m_max_edge_test_ptr = m_max_edge_test.ptr(0, 0); + + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, ++m_max_edge_test_ptr) + { + impl_->filterPixelStage2(x, y, depth_ir_sum, *m_max_edge_test_ptr == 1, out_depth.ptr(423 - y, x)); + } + } + else + { + for(int y = 0; y < 424; ++y) + for(int x = 0; x < 512; ++x, m_ptr += 9) + { + impl_->processPixelStage2(x, y, m_ptr + 0, m_ptr + 3, m_ptr + 6, out_ir.ptr(423 - y, x), out_depth.ptr(423 - y, x), 0); + } + } + + impl_->stopTiming(LOG_INFO); + + if (listener_ != 0 ){ + if(listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + { + impl_->newIrFrame(); + } + + if(listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + { + impl_->newDepthFrame(); + } + } + +} + +} /* namespace libfreenect2 */ + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_depth_packet_processor.cu b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_depth_packet_processor.cu new file mode 100644 index 0000000..7ca5974 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_depth_packet_processor.cu @@ -0,0 +1,966 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include "libfreenect2/logging.h" + +#include +#include + +__constant__ static unsigned int BFI_BITMASK; +__constant__ static float AB_MULTIPLIER; +__constant__ static float AB_MULTIPLIER_PER_FRQ0; +__constant__ static float AB_MULTIPLIER_PER_FRQ1; +__constant__ static float AB_MULTIPLIER_PER_FRQ2; +__constant__ static float AB_OUTPUT_MULTIPLIER; +; +__constant__ static float PHASE_IN_RAD0; +__constant__ static float PHASE_IN_RAD1; +__constant__ static float PHASE_IN_RAD2; +; +__constant__ static float JOINT_BILATERAL_AB_THRESHOLD; +__constant__ static float JOINT_BILATERAL_MAX_EDGE; +__constant__ static float JOINT_BILATERAL_EXP; +__constant__ static float JOINT_BILATERAL_THRESHOLD; +; +__constant__ static float GAUSSIAN_KERNEL_0; +__constant__ static float GAUSSIAN_KERNEL_1; +__constant__ static float GAUSSIAN_KERNEL_2; +__constant__ static float GAUSSIAN_KERNEL_3; +__constant__ static float GAUSSIAN_KERNEL_4; +__constant__ static float GAUSSIAN_KERNEL_5; +__constant__ static float GAUSSIAN_KERNEL_6; +__constant__ static float GAUSSIAN_KERNEL_7; +__constant__ static float GAUSSIAN_KERNEL_8; +; +__constant__ static float PHASE_OFFSET; +__constant__ static float UNAMBIGIOUS_DIST; +__constant__ static float INDIVIDUAL_AB_THRESHOLD; +__constant__ static float AB_THRESHOLD; +__constant__ static float AB_CONFIDENCE_SLOPE; +__constant__ static float AB_CONFIDENCE_OFFSET; +__constant__ static float MIN_DEALIAS_CONFIDENCE; +__constant__ static float MAX_DEALIAS_CONFIDENCE; +; +__constant__ static float EDGE_AB_AVG_MIN_VALUE; +__constant__ static float EDGE_AB_STD_DEV_THRESHOLD; +__constant__ static float EDGE_CLOSE_DELTA_THRESHOLD; +__constant__ static float EDGE_FAR_DELTA_THRESHOLD; +__constant__ static float EDGE_MAX_DELTA_THRESHOLD; +__constant__ static float EDGE_AVG_DELTA_THRESHOLD; +__constant__ static float MAX_EDGE_COUNT; +; +__constant__ static float MIN_DEPTH; +__constant__ static float MAX_DEPTH; + +#define sqrt(x) sqrtf(x) +#define sincos(x, a, b) sincosf(x, a, b) +#define atan2(a, b) atan2f(a, b) +#define log(x) logf(x) +#define exp(x) expf(x) +#define max(x, y) fmaxf(x, y) +#define min(x, y) fminf(x, y) +#define M_PI_F CUDART_PI_F +#ifndef M_PI +#define M_PI CUDART_PI +#endif + +typedef unsigned char uchar; + +inline __device__ uint get_global_id(uint i) +{ + if (i == 0) + return blockIdx.x*blockDim.x + threadIdx.x; + // NOT IMPLEMENTED for i > 0 + return 0; +} + +static inline __device__ int3 isnan(float3 v) +{ + return make_int3(isnan(v.x) ? -1 : 0, isnan(v.y) ? -1 : 0, isnan(v.z) ? -1 : 0); +} +static inline __device__ float3 sqrtf(float3 v) +{ + return make_float3(sqrtf(v.x), sqrtf(v.y), sqrtf(v.z)); +} +static inline __device__ void sincosf(float3 v, float3 *a, float3 *b) +{ + sincosf(v.x, &a->x, &b->x); + sincosf(v.y, &a->y, &b->y); + sincosf(v.z, &a->z, &b->z); +} +static inline __device__ float3 atan2f(float3 a, float3 b) +{ + return make_float3(atan2f(a.x, b.x), atan2f(a.y, b.y), atan2f(a.z, b.z)); +} +static inline __device__ float3 expf(float3 v) +{ + return make_float3(expf(v.x), expf(v.y), expf(v.z)); +} +static inline __device__ float3 select(float3 a, float3 b, int3 c) +{ + return make_float3(c.x < 0 ? b.x : a.x, c.y < 0 ? b.y : a.y, c.z < 0 ? b.z : a.z); +} +static inline __device__ int3 isless(float3 a, float3 b) +{ + return make_int3(a.x < b.x ? -1 : 0, a.y < b.y ? -1 : 0, a.z < b.z ? -1 : 0); +} +static inline __device__ int3 isequal(float3 a, float3 b) +{ + return make_int3(a.x == b.x ? -1 : 0, a.y == b.y ? -1 : 0, a.z == b.z ? -1 : 0); +} +static inline __device__ int any(int3 v) +{ + return (v.x | v.y | v.z) < 0; +} +static inline __device__ int all(int3 v) +{ + return (v.x & v.y & v.z) < 0; +} + +/******************************************************************************* + * Process pixel stage 1 + ******************************************************************************/ + +static __device__ +float decodePixelMeasurement(const ushort* __restrict__ data, const short* __restrict__ lut11to16, const uint sub, const uint x, const uint y) +{ + uint row_idx = (424 * sub + (y < 212 ? y + 212 : 423 - y)) * 352; + uint idx = (((x >> 2) + ((x << 7) & BFI_BITMASK)) * 11) & (uint)0xffffffff; + + uint col_idx = idx >> 4; + uint upper_bytes = idx & 15; + uint lower_bytes = 16 - upper_bytes; + + uint data_idx0 = row_idx + col_idx; + uint data_idx1 = row_idx + col_idx + 1; + + return (float)lut11to16[(x < 1 || 510 < x || col_idx > 352) ? 0 : ((data[data_idx0] >> upper_bytes) | (data[data_idx1] << lower_bytes)) & 2047]; +} + +static __device__ +float2 processMeasurementTriple(const float ab_multiplier_per_frq, const float p0, const float3 v, int *invalid) +{ + float3 p0vec = make_float3(p0 + PHASE_IN_RAD0, p0 + PHASE_IN_RAD1, p0 + PHASE_IN_RAD2); + float3 p0sin, p0cos; + sincos(p0vec, &p0sin, &p0cos); + + *invalid = *invalid && any(isequal(v, make_float3(32767.0f))); + + return make_float2(dot(v, p0cos), -dot(v, p0sin)) * ab_multiplier_per_frq; +} + +static __global__ +void processPixelStage1(const short* __restrict__ lut11to16, const float* __restrict__ z_table, const float4* __restrict__ p0_table, const ushort* __restrict__ data, + float4 *a_out, float4 *b_out, float4 *n_out, float *ir_out) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const uint y_in = (423 - y); + + const float zmultiplier = z_table[i]; + int valid = (int)(0.0f < zmultiplier); + int saturatedX = valid; + int saturatedY = valid; + int saturatedZ = valid; + int3 invalid_pixel = make_int3((int)(!valid)); + const float3 p0 = make_float3(p0_table[i]); + + const float3 v0 = make_float3(decodePixelMeasurement(data, lut11to16, 0, x, y_in), + decodePixelMeasurement(data, lut11to16, 1, x, y_in), + decodePixelMeasurement(data, lut11to16, 2, x, y_in)); + const float2 ab0 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ0, p0.x, v0, &saturatedX); + + const float3 v1 = make_float3(decodePixelMeasurement(data, lut11to16, 3, x, y_in), + decodePixelMeasurement(data, lut11to16, 4, x, y_in), + decodePixelMeasurement(data, lut11to16, 5, x, y_in)); + const float2 ab1 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ1, p0.y, v1, &saturatedY); + + const float3 v2 = make_float3(decodePixelMeasurement(data, lut11to16, 6, x, y_in), + decodePixelMeasurement(data, lut11to16, 7, x, y_in), + decodePixelMeasurement(data, lut11to16, 8, x, y_in)); + const float2 ab2 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ2, p0.z, v2, &saturatedZ); + + float3 a = select(make_float3(ab0.x, ab1.x, ab2.x), make_float3(0.0f), invalid_pixel); + float3 b = select(make_float3(ab0.y, ab1.y, ab2.y), make_float3(0.0f), invalid_pixel); + float3 n = sqrt(a * a + b * b); + + int3 saturated = make_int3(saturatedX, saturatedY, saturatedZ); + a = select(a, make_float3(0.0f), saturated); + b = select(b, make_float3(0.0f), saturated); + + a_out[i] = make_float4(a); + b_out[i] = make_float4(b); + n_out[i] = make_float4(n); + ir_out[i] = min(dot(select(n, make_float3(65535.0f), saturated), make_float3(0.333333333f * AB_MULTIPLIER * AB_OUTPUT_MULTIPLIER)), 65535.0f); +} + +/******************************************************************************* + * Filter pixel stage 1 + ******************************************************************************/ +static __global__ +void filterPixelStage1(const float4* __restrict__ a, const float4* __restrict__ b, const float4* __restrict__ n, + float4 *a_out, float4 *b_out, uchar *max_edge_test) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float3 self_a = make_float3(a[i]); + const float3 self_b = make_float3(b[i]); + + const float gaussian[9] = {GAUSSIAN_KERNEL_0, GAUSSIAN_KERNEL_1, GAUSSIAN_KERNEL_2, GAUSSIAN_KERNEL_3, GAUSSIAN_KERNEL_4, GAUSSIAN_KERNEL_5, GAUSSIAN_KERNEL_6, GAUSSIAN_KERNEL_7, GAUSSIAN_KERNEL_8}; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + a_out[i] = make_float4(self_a); + b_out[i] = make_float4(self_b); + max_edge_test[i] = 1; + } + else + { + float3 threshold = make_float3(sqrt(JOINT_BILATERAL_THRESHOLD)); + float3 joint_bilateral_exp = make_float3(JOINT_BILATERAL_EXP); + + const float3 self_norm = make_float3(n[i]); + const float3 self_normalized_a = self_a / self_norm; + const float3 self_normalized_b = self_b / self_norm; + + float3 weight_acc = make_float3(0.0f); + float3 weighted_a_acc = make_float3(0.0f); + float3 weighted_b_acc = make_float3(0.0f); + float3 dist_acc = make_float3(0.0f); + + const int3 c0 = isless(self_norm, threshold); + + threshold = select(threshold, make_float3(0.0f), c0); + joint_bilateral_exp = select(joint_bilateral_exp, make_float3(0.0f), c0); + + for(int yi = -1, j = 0; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++j, ++i_other) + { + const float3 other_a = make_float3(a[i_other]); + const float3 other_b = make_float3(b[i_other]); + const float3 other_norm = make_float3(n[i_other]); + const float3 other_normalized_a = other_a / other_norm; + const float3 other_normalized_b = other_b / other_norm; + + const int3 c1 = isless(other_norm, threshold); + + const float3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + const float3 weight = select(gaussian[j] * exp(-1.442695f * joint_bilateral_exp * dist), make_float3(0.0f), c1); + + weighted_a_acc += weight * other_a; + weighted_b_acc += weight * other_b; + weight_acc += weight; + dist_acc += select(dist, make_float3(0.0f), c1); + } + } + + const int3 c2 = isless(make_float3(0.0f), weight_acc); + a_out[i] = make_float4(select(make_float3(0.0f), weighted_a_acc / weight_acc, c2)); + b_out[i] = make_float4(select(make_float3(0.0f), weighted_b_acc / weight_acc, c2)); + + max_edge_test[i] = all(isless(dist_acc, make_float3(JOINT_BILATERAL_MAX_EDGE))); + } +} + +/******************************************************************************* + * Process pixel stage 2 + ******************************************************************************/ +static __global__ +void processPixelStage2(const float4* __restrict__ a_in, const float4* __restrict__ b_in, const float* __restrict__ x_table, const float* __restrict__ z_table, + float *depth, float *ir_sums) +{ + const uint i = get_global_id(0); + float3 a = make_float3(a_in[i]); + float3 b = make_float3(b_in[i]); + + float3 phase = atan2(b, a); + phase = select(phase, phase + 2.0f * M_PI_F, isless(phase, make_float3(0.0f))); + phase = select(phase, make_float3(0.0f), isnan(phase)); + float3 ir = sqrt(a * a + b * b) * AB_MULTIPLIER; + + float ir_sum = ir.x + ir.y + ir.z; + float ir_min = min(ir.x, min(ir.y, ir.z)); + float ir_max = max(ir.x, max(ir.y, ir.z)); + + float phase_final = 0; + + if(ir_min >= INDIVIDUAL_AB_THRESHOLD && ir_sum >= AB_THRESHOLD) + { + float3 t = phase / (2.0f * M_PI_F) * make_float3(3.0f, 15.0f, 2.0f); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + float t5 = (floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - floor(t3)) * f1; + + bool c2 = 0.5f < fabs(t3) && fabs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI_F; + t7 *= 2.0f * M_PI_F; + t8 *= 2.0f * M_PI_F; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < AB_CONFIDENCE_SLOPE; + + float ir_x = slope_positive ? ir_min : ir_max; + + ir_x = log(ir_x); + ir_x = (ir_x * AB_CONFIDENCE_SLOPE * 0.301030f + AB_CONFIDENCE_OFFSET) * 3.321928f; + ir_x = exp(ir_x); + ir_x = clamp(ir_x, MIN_DEALIAS_CONFIDENCE, MAX_DEALIAS_CONFIDENCE); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = MAX_DEALIAS_CONFIDENCE * MAX_DEALIAS_CONFIDENCE >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase_final = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + phase_final = 0.0f < phase_final ? phase_final + PHASE_OFFSET : phase_final; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0) / (max_depth * max_depth * 8192.0); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + depth[i] = d; + ir_sums[i] = ir_sum; +} + +/******************************************************************************* + * Filter pixel stage 2 + ******************************************************************************/ +static __global__ +void filterPixelStage2(const float* __restrict__ depth, const float* __restrict__ ir_sums, const uchar* __restrict__ max_edge_test, float *filtered) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float raw_depth = depth[i]; + const float ir_sum = ir_sums[i]; + const uchar edge_test = max_edge_test[i]; + + if(raw_depth >= MIN_DEPTH && raw_depth <= MAX_DEPTH) + { + if(x < 1 || y < 1 || x > 510 || y > 422) + { + filtered[i] = raw_depth; + } + else + { + float ir_sum_acc = ir_sum; + float squared_ir_sum_acc = ir_sum * ir_sum; + float min_depth = raw_depth; + float max_depth = raw_depth; + + for(int yi = -1; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++i_other) + { + if(i_other == i) + { + continue; + } + + const float raw_depth_other = depth[i_other]; + const float ir_sum_other = ir_sums[i_other]; + + ir_sum_acc += ir_sum_other; + squared_ir_sum_acc += ir_sum_other * ir_sum_other; + + if(0.0f < raw_depth_other) + { + min_depth = min(min_depth, raw_depth_other); + max_depth = max(max_depth, raw_depth_other); + } + } + } + + float tmp0 = sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = max(ir_sum_acc / 9.0f, EDGE_AB_AVG_MIN_VALUE); + tmp0 /= edge_avg; + + float abs_min_diff = fabs(raw_depth - min_depth); + float abs_max_diff = fabs(raw_depth - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < raw_depth && + tmp0 >= EDGE_AB_STD_DEV_THRESHOLD && + EDGE_CLOSE_DELTA_THRESHOLD < abs_min_diff && + EDGE_FAR_DELTA_THRESHOLD < abs_max_diff && + EDGE_MAX_DELTA_THRESHOLD < max_abs_diff && + EDGE_AVG_DELTA_THRESHOLD < avg_diff; + + if(!cond0) + { + if(edge_test != 0) + { + //float tmp1 = 1500.0f > raw_depth ? 30.0f : 0.02f * raw_depth; + float edge_count = 0.0f; + + filtered[i] = edge_count > MAX_EDGE_COUNT ? 0.0f : raw_depth; + } + else + { + filtered[i] = 0.0f; + } + } + else + { + filtered[i] = 0.0f; + } + } + } + else + { + filtered[i] = 0.0f; + } +} + +#define CHECK_CUDA(expr) do { cudaError_t err = (expr); if (err != cudaSuccess) { LOG_ERROR << #expr ": " << cudaGetErrorString(err); return false; } } while(0) +#define CALL_CUDA(expr) do { cudaError_t err = (expr); if (err != cudaSuccess) { LOG_ERROR << #expr ": " << cudaGetErrorString(err); } } while(0) + +namespace libfreenect2 +{ + +class CudaFrame: public Frame +{ +public: + CudaFrame(Buffer *buffer): + Frame(512, 424, 4, (unsigned char*)-1) + { + data = buffer->data; + rawdata = reinterpret_cast(buffer); + } + + virtual ~CudaFrame() + { + Buffer *buffer = reinterpret_cast(rawdata); + buffer->allocator->free(buffer); + rawdata = NULL; + } +}; + +class CudaAllocator: public Allocator +{ +private: + const bool input; + + bool allocate_cuda(Buffer *b, size_t size) + { + unsigned int flags = cudaHostAllocPortable; + if (input) + flags |= cudaHostAllocWriteCombined; + CHECK_CUDA(cudaHostAlloc(&b->data, size, flags)); + b->length = 0; + b->capacity = size; + return true; + } + +public: + CudaAllocator(bool input): input(input) {} + + virtual Buffer *allocate(size_t size) + { + Buffer *b = new Buffer(); + if (!allocate_cuda(b, size)) + b->data = NULL; + return b; + } + + virtual void free(Buffer *b) + { + if (b == NULL) + return; + if (b->data) + CALL_CUDA(cudaFreeHost(b->data)); + delete b; + } +}; + +class CudaDepthPacketProcessorImpl: public WithPerfLogging +{ +public: + static const size_t IMAGE_SIZE = 512*424; + static const size_t LUT_SIZE = 2048; + + size_t d_lut_size; + size_t d_xtable_size; + size_t d_ztable_size; + size_t d_p0table_size; + + short *d_lut; + float *d_xtable; + float *d_ztable; + float4 *d_p0table; + float4 h_p0table[IMAGE_SIZE]; + + size_t d_packet_size; + unsigned short *d_packet; + + float4 *d_a; + float4 *d_b; + float4 *d_n; + float *d_ir; + float4 *d_a_filtered; + float4 *d_b_filtered; + unsigned char *d_edge_test; + float *d_depth; + float *d_ir_sum; + float *d_filtered; + + size_t block_size; + size_t grid_size; + + DepthPacketProcessor::Config config; + DepthPacketProcessor::Parameters params; + + Frame *ir_frame, *depth_frame; + + Allocator *input_allocator; + Allocator *ir_allocator; + Allocator *depth_allocator; + + bool good; + + CudaDepthPacketProcessorImpl(const int deviceId): + block_size(128), + grid_size(IMAGE_SIZE/block_size), + config(), + params(), + ir_frame(NULL), + depth_frame(NULL), + input_allocator(NULL), + ir_allocator(NULL), + depth_allocator(NULL) + { + good = initDevice(deviceId); + if (!good) + return; + + input_allocator = new PoolAllocator(new CudaAllocator(true)); + ir_allocator = new PoolAllocator(new CudaAllocator(false)); + depth_allocator = new PoolAllocator(new CudaAllocator(false)); + + newIrFrame(); + newDepthFrame(); + } + + ~CudaDepthPacketProcessorImpl() + { + delete ir_frame; + delete depth_frame; + delete input_allocator; + delete ir_allocator; + delete depth_allocator; + if (good) + freeDeviceMemory(); + } + + bool setParameters(const DepthPacketProcessor::Parameters ¶ms) + { + unsigned int bfi_bitmask = 0x180; + cudaMemcpyToSymbolAsync(BFI_BITMASK, &bfi_bitmask, sizeof(int)); + + #define COPY(upper, lower) cudaMemcpyToSymbolAsync(upper, ¶ms.lower, sizeof(params.lower)); + COPY(AB_MULTIPLIER, ab_multiplier) + COPY(AB_MULTIPLIER_PER_FRQ0, ab_multiplier_per_frq[0]) + COPY(AB_MULTIPLIER_PER_FRQ1, ab_multiplier_per_frq[1]) + COPY(AB_MULTIPLIER_PER_FRQ2, ab_multiplier_per_frq[2]) + COPY(AB_OUTPUT_MULTIPLIER, ab_output_multiplier) + + COPY(PHASE_IN_RAD0, phase_in_rad[0]) + COPY(PHASE_IN_RAD1, phase_in_rad[1]) + COPY(PHASE_IN_RAD2, phase_in_rad[2]) + + COPY(JOINT_BILATERAL_AB_THRESHOLD, joint_bilateral_ab_threshold) + COPY(JOINT_BILATERAL_MAX_EDGE, joint_bilateral_max_edge) + COPY(JOINT_BILATERAL_EXP, joint_bilateral_exp) + float joint_bilateral_threshold; + joint_bilateral_threshold = (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier); + cudaMemcpyToSymbolAsync(JOINT_BILATERAL_THRESHOLD, &joint_bilateral_threshold, sizeof(float)); + + COPY(GAUSSIAN_KERNEL_0, gaussian_kernel[0]) + COPY(GAUSSIAN_KERNEL_1, gaussian_kernel[1]) + COPY(GAUSSIAN_KERNEL_2, gaussian_kernel[2]) + COPY(GAUSSIAN_KERNEL_3, gaussian_kernel[3]) + COPY(GAUSSIAN_KERNEL_4, gaussian_kernel[4]) + COPY(GAUSSIAN_KERNEL_5, gaussian_kernel[5]) + COPY(GAUSSIAN_KERNEL_6, gaussian_kernel[6]) + COPY(GAUSSIAN_KERNEL_7, gaussian_kernel[7]) + COPY(GAUSSIAN_KERNEL_8, gaussian_kernel[8]) + + COPY(PHASE_OFFSET, phase_offset) + COPY(UNAMBIGIOUS_DIST, unambigious_dist) + COPY(INDIVIDUAL_AB_THRESHOLD, individual_ab_threshold) + COPY(AB_THRESHOLD, ab_threshold) + COPY(AB_CONFIDENCE_SLOPE, ab_confidence_slope) + COPY(AB_CONFIDENCE_OFFSET, ab_confidence_offset) + COPY(MIN_DEALIAS_CONFIDENCE, min_dealias_confidence) + COPY(MAX_DEALIAS_CONFIDENCE, max_dealias_confidence) + + COPY(EDGE_AB_AVG_MIN_VALUE, edge_ab_avg_min_value) + COPY(EDGE_AB_STD_DEV_THRESHOLD, edge_ab_std_dev_threshold) + COPY(EDGE_CLOSE_DELTA_THRESHOLD, edge_close_delta_threshold) + COPY(EDGE_FAR_DELTA_THRESHOLD, edge_far_delta_threshold) + COPY(EDGE_MAX_DELTA_THRESHOLD, edge_max_delta_threshold) + COPY(EDGE_AVG_DELTA_THRESHOLD, edge_avg_delta_threshold) + COPY(MAX_EDGE_COUNT, max_edge_count) + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + bool allocateDeviceMemory() + { + //Read only + d_p0table_size = IMAGE_SIZE * sizeof(float4); + d_xtable_size = IMAGE_SIZE * sizeof(float); + d_ztable_size = IMAGE_SIZE * sizeof(float); + d_lut_size = LUT_SIZE * sizeof(short); + + CHECK_CUDA(cudaMalloc(&d_p0table, d_p0table_size)); + CHECK_CUDA(cudaMalloc(&d_xtable, d_xtable_size)); + CHECK_CUDA(cudaMalloc(&d_ztable, d_ztable_size)); + CHECK_CUDA(cudaMalloc(&d_lut, d_lut_size)); + + d_packet_size = (IMAGE_SIZE * 11 / 8) * 10; + + CHECK_CUDA(cudaMalloc(&d_packet, d_packet_size)); + + //Read-Write + size_t d_a_size = IMAGE_SIZE * sizeof(float4); + size_t d_b_size = IMAGE_SIZE * sizeof(float4); + size_t d_n_size = IMAGE_SIZE * sizeof(float4); + size_t d_ir_size = IMAGE_SIZE * sizeof(float); + size_t d_a_filtered_size = IMAGE_SIZE * sizeof(float4); + size_t d_b_filtered_size = IMAGE_SIZE * sizeof(float4); + size_t d_edge_test_size = IMAGE_SIZE * sizeof(char); + size_t d_depth_size = IMAGE_SIZE * sizeof(float); + size_t d_ir_sum_size = IMAGE_SIZE * sizeof(float); + size_t d_filtered_size = IMAGE_SIZE * sizeof(float); + + CHECK_CUDA(cudaMalloc(&d_a, d_a_size)); + CHECK_CUDA(cudaMalloc(&d_b, d_b_size)); + CHECK_CUDA(cudaMalloc(&d_n, d_n_size)); + CHECK_CUDA(cudaMalloc(&d_ir, d_ir_size)); + CHECK_CUDA(cudaMalloc(&d_a_filtered, d_a_filtered_size)); + CHECK_CUDA(cudaMalloc(&d_b_filtered, d_b_filtered_size)); + CHECK_CUDA(cudaMalloc(&d_edge_test, d_edge_test_size)); + CHECK_CUDA(cudaMalloc(&d_depth, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_ir_sum, d_ir_sum_size)); + CHECK_CUDA(cudaMalloc(&d_filtered, d_filtered_size)); + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + void freeDeviceMemory() + { + CALL_CUDA(cudaFree(d_p0table)); + CALL_CUDA(cudaFree(d_xtable)); + CALL_CUDA(cudaFree(d_ztable)); + CALL_CUDA(cudaFree(d_lut)); + + CALL_CUDA(cudaFree(d_packet)); + + CALL_CUDA(cudaFree(d_a)); + CALL_CUDA(cudaFree(d_b)); + CALL_CUDA(cudaFree(d_n)); + CALL_CUDA(cudaFree(d_ir)); + CALL_CUDA(cudaFree(d_a_filtered)); + CALL_CUDA(cudaFree(d_b_filtered)); + CALL_CUDA(cudaFree(d_edge_test)); + CALL_CUDA(cudaFree(d_depth)); + CALL_CUDA(cudaFree(d_ir_sum)); + CALL_CUDA(cudaFree(d_filtered)); + } + + bool initDevice(const int deviceId) + { + int deviceCount = 0; + + CHECK_CUDA(cudaGetDeviceCount(&deviceCount)); + + int devId = -1; + for (int i = 0; i < deviceCount; i++) { + if (deviceId != -1 && i != deviceId) + continue; + + cudaDeviceProp prop; + CHECK_CUDA(cudaGetDeviceProperties(&prop, i)); + LOG_INFO << "device " << i << ": " << prop.name << " @ " << (prop.clockRate / 1000) << "MHz Memory " << (prop.totalGlobalMem >> 20) << "MB"; + + if (prop.computeMode == cudaComputeModeProhibited) { + LOG_INFO << " Compute Mode Prohibited"; + continue; + } + + if (prop.major < 1) { + LOG_INFO << " does not support CUDA"; + continue; + } + + devId = i; + break; + } + + if (devId == -1) { + LOG_ERROR << "No CUDA device found"; + return false; + } + + CHECK_CUDA(cudaSetDevice(devId)); + LOG_INFO << "selected device " << devId; + + if (!setParameters(params)) + return false; + + if (!setConfiguration(config)) + return false; + + if (!allocateDeviceMemory()) + return false; + + return true; + } + + bool setConfiguration(const DepthPacketProcessor::Config &cfg) + { + config = cfg; + float tmpf; + + tmpf = cfg.MinDepth * 1000.0f; + cudaMemcpyToSymbolAsync(MIN_DEPTH, &tmpf, sizeof(tmpf)); + + tmpf = cfg.MaxDepth * 1000.0f; + cudaMemcpyToSymbolAsync(MAX_DEPTH, &tmpf, sizeof(tmpf)); + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + bool run(const DepthPacket &packet) + { + size_t ir_frame_size = ir_frame->width * ir_frame->height * ir_frame->bytes_per_pixel; + size_t depth_frame_size = depth_frame->width * depth_frame->height * depth_frame->bytes_per_pixel; + + cudaMemcpyAsync(d_packet, packet.buffer, packet.buffer_length, cudaMemcpyHostToDevice); + + processPixelStage1<<>>(d_lut, d_ztable, d_p0table, d_packet, d_a, d_b, d_n, d_ir); + + cudaMemcpyAsync(ir_frame->data, d_ir, ir_frame_size, cudaMemcpyDeviceToHost); + + if (config.EnableBilateralFilter) { + filterPixelStage1<<>>(d_a, d_b, d_n, d_a_filtered, d_b_filtered, d_edge_test); + } + + processPixelStage2<<>>( + config.EnableBilateralFilter ? d_a_filtered : d_a, + config.EnableBilateralFilter ? d_b_filtered : d_b, + d_xtable, d_ztable, d_depth, d_ir_sum); + + if (config.EnableEdgeAwareFilter) { + filterPixelStage2<<>>(d_depth, d_ir_sum, d_edge_test, d_filtered); + } + + cudaMemcpyAsync(depth_frame->data, config.EnableEdgeAwareFilter ? d_filtered : d_depth, depth_frame_size, cudaMemcpyDeviceToHost); + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + void newIrFrame() + { + ir_frame = new CudaFrame(ir_allocator->allocate(IMAGE_SIZE*sizeof(float))); + ir_frame->format = Frame::Float; + } + + void newDepthFrame() + { + depth_frame = new CudaFrame(depth_allocator->allocate(IMAGE_SIZE*sizeof(float))); + depth_frame->format = Frame::Float; + } + + void fill_trig_table(const protocol::P0TablesResponse *p0table) + { + for (int r = 0; r < 424; ++r) { + float4 *it = &h_p0table[r * 512]; + const uint16_t *it0 = &p0table->p0table0[r * 512]; + const uint16_t *it1 = &p0table->p0table1[r * 512]; + const uint16_t *it2 = &p0table->p0table2[r * 512]; + for (int c = 0; c < 512; ++c, ++it, ++it0, ++it1, ++it2) { + it->x = -((float) * it0) * 0.000031 * M_PI; + it->y = -((float) * it1) * 0.000031 * M_PI; + it->z = -((float) * it2) * 0.000031 * M_PI; + it->w = 0.0f; + } + } + } +}; + +CudaDepthPacketProcessor::CudaDepthPacketProcessor(const int deviceId): + impl_(new CudaDepthPacketProcessorImpl(deviceId)) +{ +} + +CudaDepthPacketProcessor::~CudaDepthPacketProcessor() +{ + delete impl_; +} + +void CudaDepthPacketProcessor::setConfiguration(const DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + + impl_->good = impl_->setConfiguration(config); +} + +void CudaDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char *buffer, size_t buffer_length) +{ + impl_->fill_trig_table((protocol::P0TablesResponse *)buffer); + cudaMemcpy(impl_->d_p0table, impl_->h_p0table, impl_->d_p0table_size, cudaMemcpyHostToDevice); +} + +void CudaDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) +{ + cudaMemcpy(impl_->d_xtable, xtable, impl_->d_xtable_size, cudaMemcpyHostToDevice); + cudaMemcpy(impl_->d_ztable, ztable, impl_->d_ztable_size, cudaMemcpyHostToDevice); +} + +void CudaDepthPacketProcessor::loadLookupTable(const short *lut) +{ + cudaMemcpy(impl_->d_lut, lut, impl_->d_lut_size, cudaMemcpyHostToDevice); +} + +bool CudaDepthPacketProcessor::good() +{ + return impl_->good; +} + +void CudaDepthPacketProcessor::process(const DepthPacket &packet) +{ + if (listener_ == NULL) + return; + + impl_->startTiming(); + + impl_->ir_frame->timestamp = packet.timestamp; + impl_->depth_frame->timestamp = packet.timestamp; + impl_->ir_frame->sequence = packet.sequence; + impl_->depth_frame->sequence = packet.sequence; + + impl_->good = impl_->run(packet); + + impl_->stopTiming(LOG_INFO); + + if (!impl_->good) { + impl_->ir_frame->status = 1; + impl_->depth_frame->status = 1; + } + + if (listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + impl_->newIrFrame(); + if (listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + impl_->newDepthFrame(); +} + +Allocator *CudaDepthPacketProcessor::getAllocator() +{ + return impl_->input_allocator; +} +} // namespace libfreenect2 diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_kde_depth_packet_processor.cu b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_kde_depth_packet_processor.cu new file mode 100644 index 0000000..0a16f55 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/cuda_kde_depth_packet_processor.cu @@ -0,0 +1,1419 @@ +/* + * This code implements a depth packet processor using the phase unwrapping + * algorithm described in the paper "Efficient Phase Unwrapping using Kernel + * Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ + + +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include "libfreenect2/logging.h" + +#include +#include + +__constant__ static unsigned int BFI_BITMASK; +__constant__ static float AB_MULTIPLIER; +__constant__ static float AB_MULTIPLIER_PER_FRQ0; +__constant__ static float AB_MULTIPLIER_PER_FRQ1; +__constant__ static float AB_MULTIPLIER_PER_FRQ2; +__constant__ static float AB_OUTPUT_MULTIPLIER; +; +__constant__ static float PHASE_IN_RAD0; +__constant__ static float PHASE_IN_RAD1; +__constant__ static float PHASE_IN_RAD2; +; +__constant__ static float JOINT_BILATERAL_AB_THRESHOLD; +__constant__ static float JOINT_BILATERAL_MAX_EDGE; +__constant__ static float JOINT_BILATERAL_EXP; +__constant__ static float JOINT_BILATERAL_THRESHOLD; +; +__constant__ static float GAUSSIAN_KERNEL_0; +__constant__ static float GAUSSIAN_KERNEL_1; +__constant__ static float GAUSSIAN_KERNEL_2; +__constant__ static float GAUSSIAN_KERNEL_3; +__constant__ static float GAUSSIAN_KERNEL_4; +__constant__ static float GAUSSIAN_KERNEL_5; +__constant__ static float GAUSSIAN_KERNEL_6; +__constant__ static float GAUSSIAN_KERNEL_7; +__constant__ static float GAUSSIAN_KERNEL_8; +; +__constant__ static float PHASE_OFFSET; +__constant__ static float UNAMBIGIOUS_DIST; +__constant__ static float INDIVIDUAL_AB_THRESHOLD; +__constant__ static float AB_THRESHOLD; +__constant__ static float AB_CONFIDENCE_SLOPE; +__constant__ static float AB_CONFIDENCE_OFFSET; +__constant__ static float MIN_DEALIAS_CONFIDENCE; +__constant__ static float MAX_DEALIAS_CONFIDENCE; +; +__constant__ static float EDGE_AB_AVG_MIN_VALUE; +__constant__ static float EDGE_AB_STD_DEV_THRESHOLD; +__constant__ static float EDGE_CLOSE_DELTA_THRESHOLD; +__constant__ static float EDGE_FAR_DELTA_THRESHOLD; +__constant__ static float EDGE_MAX_DELTA_THRESHOLD; +__constant__ static float EDGE_AVG_DELTA_THRESHOLD; +__constant__ static float MAX_EDGE_COUNT; +; + +__constant__ static float KDE_SIGMA_SQR; +__constant__ static unsigned int KDE_NEIGBORHOOD_SIZE; +__constant__ static float UNWRAPPING_LIKELIHOOD_SCALE; +__constant__ static float PHASE_CONFIDENCE_SCALE; +__constant__ static float KDE_THRESHOLD; + +__constant__ static float MIN_DEPTH; +__constant__ static float MAX_DEPTH; + +#define sqrt(x) sqrtf(x) +#define sincos(x, a, b) sincosf(x, a, b) +#define atan2(a, b) atan2f(a, b) +#define log(x) logf(x) +#define exp(x) expf(x) +#define max(x, y) fmaxf(x, y) +#define min(x, y) fminf(x, y) +#define M_PI_F CUDART_PI_F +#ifndef M_PI +#define M_PI CUDART_PI +#endif +#define NUM_HYPOTHESES 30 + +typedef unsigned char uchar; + +inline __device__ uint get_global_id(uint i) +{ + if (i == 0) + return blockIdx.x*blockDim.x + threadIdx.x; + // NOT IMPLEMENTED for i > 0 + return 0; +} + +static inline __device__ int3 isnan(float3 v) +{ + return make_int3(isnan(v.x) ? -1 : 0, isnan(v.y) ? -1 : 0, isnan(v.z) ? -1 : 0); +} +static inline __device__ float3 sqrtf(float3 v) +{ + return make_float3(sqrtf(v.x), sqrtf(v.y), sqrtf(v.z)); +} +static inline __device__ void sincosf(float3 v, float3 *a, float3 *b) +{ + sincosf(v.x, &a->x, &b->x); + sincosf(v.y, &a->y, &b->y); + sincosf(v.z, &a->z, &b->z); +} +static inline __device__ float3 atan2f(float3 a, float3 b) +{ + return make_float3(atan2f(a.x, b.x), atan2f(a.y, b.y), atan2f(a.z, b.z)); +} +static inline __device__ float3 expf(float3 v) +{ + return make_float3(expf(v.x), expf(v.y), expf(v.z)); +} +static inline __device__ float3 select(float3 a, float3 b, int3 c) +{ + return make_float3(c.x < 0 ? b.x : a.x, c.y < 0 ? b.y : a.y, c.z < 0 ? b.z : a.z); +} +static inline __device__ int3 isless(float3 a, float3 b) +{ + return make_int3(a.x < b.x ? -1 : 0, a.y < b.y ? -1 : 0, a.z < b.z ? -1 : 0); +} +static inline __device__ int3 isequal(float3 a, float3 b) +{ + return make_int3(a.x == b.x ? -1 : 0, a.y == b.y ? -1 : 0, a.z == b.z ? -1 : 0); +} +static inline __device__ int any(int3 v) +{ + return (v.x | v.y | v.z) < 0; +} +static inline __device__ int all(int3 v) +{ + return (v.x & v.y & v.z) < 0; +} + +/******************************************************************************* + * Process pixel stage 1 + ******************************************************************************/ + +static __device__ +float decodePixelMeasurement(const ushort* __restrict__ data, const short* __restrict__ lut11to16, const uint sub, const uint x, const uint y) +{ + uint row_idx = (424 * sub + (y < 212 ? y + 212 : 423 - y)) * 352; + uint idx = (((x >> 2) + ((x << 7) & BFI_BITMASK)) * 11) & (uint)0xffffffff; + + uint col_idx = idx >> 4; + uint upper_bytes = idx & 15; + uint lower_bytes = 16 - upper_bytes; + + uint data_idx0 = row_idx + col_idx; + uint data_idx1 = row_idx + col_idx + 1; + + return (float)lut11to16[(x < 1 || 510 < x || col_idx > 352) ? 0 : ((data[data_idx0] >> upper_bytes) | (data[data_idx1] << lower_bytes)) & 2047]; +} + +static __device__ +float2 processMeasurementTriple(const float ab_multiplier_per_frq, const float p0, const float3 v, int *invalid) +{ + float3 p0vec = make_float3(p0 + PHASE_IN_RAD0, p0 + PHASE_IN_RAD1, p0 + PHASE_IN_RAD2); + float3 p0sin, p0cos; + sincos(p0vec, &p0sin, &p0cos); + + *invalid = *invalid && any(isequal(v, make_float3(32767.0f))); + + return make_float2(dot(v, p0cos), -dot(v, p0sin)) * ab_multiplier_per_frq; +} + +static __global__ +void processPixelStage1(const short* __restrict__ lut11to16, const float* __restrict__ z_table, const float4* __restrict__ p0_table, const ushort* __restrict__ data, + float4 *a_out, float4 *b_out, float4 *n_out, float *ir_out) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const uint y_in = (423 - y); + + const float zmultiplier = z_table[i]; + int valid = (int)(0.0f < zmultiplier); + int saturatedX = valid; + int saturatedY = valid; + int saturatedZ = valid; + int3 invalid_pixel = make_int3((int)(!valid)); + const float3 p0 = make_float3(p0_table[i]); + + const float3 v0 = make_float3(decodePixelMeasurement(data, lut11to16, 0, x, y_in), + decodePixelMeasurement(data, lut11to16, 1, x, y_in), + decodePixelMeasurement(data, lut11to16, 2, x, y_in)); + const float2 ab0 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ0, p0.x, v0, &saturatedX); + + const float3 v1 = make_float3(decodePixelMeasurement(data, lut11to16, 3, x, y_in), + decodePixelMeasurement(data, lut11to16, 4, x, y_in), + decodePixelMeasurement(data, lut11to16, 5, x, y_in)); + const float2 ab1 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ1, p0.y, v1, &saturatedY); + + const float3 v2 = make_float3(decodePixelMeasurement(data, lut11to16, 6, x, y_in), + decodePixelMeasurement(data, lut11to16, 7, x, y_in), + decodePixelMeasurement(data, lut11to16, 8, x, y_in)); + const float2 ab2 = processMeasurementTriple(AB_MULTIPLIER_PER_FRQ2, p0.z, v2, &saturatedZ); + + float3 a = select(make_float3(ab0.x, ab1.x, ab2.x), make_float3(0.0f), invalid_pixel); + float3 b = select(make_float3(ab0.y, ab1.y, ab2.y), make_float3(0.0f), invalid_pixel); + float3 n = sqrt(a * a + b * b); + + int3 saturated = make_int3(saturatedX, saturatedY, saturatedZ); + a = select(a, make_float3(0.0f), saturated); + b = select(b, make_float3(0.0f), saturated); + + a_out[i] = make_float4(a); + b_out[i] = make_float4(b); + n_out[i] = make_float4(n); + ir_out[i] = min(dot(select(n, make_float3(65535.0f), saturated), make_float3(0.333333333f * AB_MULTIPLIER * AB_OUTPUT_MULTIPLIER)), 65535.0f); +} + +/******************************************************************************* + * Filter pixel stage 1 + ******************************************************************************/ +static __global__ +void filterPixelStage1(const float4* __restrict__ a, const float4* __restrict__ b, const float4* __restrict__ n, + float4 *a_out, float4 *b_out, uchar *max_edge_test) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float3 self_a = make_float3(a[i]); + const float3 self_b = make_float3(b[i]); + + const float gaussian[9] = {GAUSSIAN_KERNEL_0, GAUSSIAN_KERNEL_1, GAUSSIAN_KERNEL_2, GAUSSIAN_KERNEL_3, GAUSSIAN_KERNEL_4, GAUSSIAN_KERNEL_5, GAUSSIAN_KERNEL_6, GAUSSIAN_KERNEL_7, GAUSSIAN_KERNEL_8}; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + a_out[i] = make_float4(self_a); + b_out[i] = make_float4(self_b); + max_edge_test[i] = 1; + } + else + { + float3 threshold = make_float3(sqrt(JOINT_BILATERAL_THRESHOLD)); + float3 joint_bilateral_exp = make_float3(JOINT_BILATERAL_EXP); + + const float3 self_norm = make_float3(n[i]); + const float3 self_normalized_a = self_a / self_norm; + const float3 self_normalized_b = self_b / self_norm; + + float3 weight_acc = make_float3(0.0f); + float3 weighted_a_acc = make_float3(0.0f); + float3 weighted_b_acc = make_float3(0.0f); + float3 dist_acc = make_float3(0.0f); + + const int3 c0 = isless(self_norm, threshold); + + threshold = select(threshold, make_float3(0.0f), c0); + joint_bilateral_exp = select(joint_bilateral_exp, make_float3(0.0f), c0); + + for(int yi = -1, j = 0; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++j, ++i_other) + { + const float3 other_a = make_float3(a[i_other]); + const float3 other_b = make_float3(b[i_other]); + const float3 other_norm = make_float3(n[i_other]); + const float3 other_normalized_a = other_a / other_norm; + const float3 other_normalized_b = other_b / other_norm; + + const int3 c1 = isless(other_norm, threshold); + + const float3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + const float3 weight = select(gaussian[j] * exp(-1.442695f * joint_bilateral_exp * dist), make_float3(0.0f), c1); + + weighted_a_acc += weight * other_a; + weighted_b_acc += weight * other_b; + weight_acc += weight; + dist_acc += select(dist, make_float3(0.0f), c1); + } + } + + const int3 c2 = isless(make_float3(0.0f), weight_acc); + a_out[i] = make_float4(select(make_float3(0.0f), weighted_a_acc / weight_acc, c2)); + b_out[i] = make_float4(select(make_float3(0.0f), weighted_b_acc / weight_acc, c2)); + + max_edge_test[i] = all(isless(dist_acc, make_float3(JOINT_BILATERAL_MAX_EDGE))); + } +} + +/******************************************************************************* + * KDE phase unwrapping + ******************************************************************************/ + +//arrays for hypotheses +__device__ float k_list[NUM_HYPOTHESES] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; +__device__ float n_list[NUM_HYPOTHESES] = {0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 5.0f, 6.0f, 5.0f, 6.0f, 6.0f, 7.0f, 7.0f, 8.0f, 8.0f, 7.0f, 8.0f, 9.0f, 9.0f}; +__device__ float m_list[NUM_HYPOTHESES] = {0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 8.0f, 8.0f, 9.0f, 9.0f, 10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f, 13.0f, 13.0f, 14.0f}; + +static __device__ +void calcErr(const float k, const float n, const float m, const float t0, const float t1, const float t2, float* err1, float* err2, float* err3) +{ + //phase unwrapping equation residuals. + //The coefficients 2.0, 15.0 and 3.0 are the smallest common multiples of the sequence of modulation frequencies 16, 80 and 120 MHz + *err1 = 3.0f*n - 15.0f*k - (t1 - t0); + *err2 = 3.0f*n - 2.0f*m - (t2 - t0); + *err3 = 15.0f*k - 2.0f*m - (t2 - t1); +} + +/******************************************************************************** + * Rank all 30 phase hypothses and returns the two most likley + ********************************************************************************/ +static __device__ +void phaseUnWrapper(float t0, float t1,float t2, float* phase_first, float* phase_second, float* err_w1, float* err_w2) +{ + float err; + float err1, err2, err3; + + //unwrapping weight for cost function + float w1 = 1.0f; + float w2 = 10.0f; + float w3 = 1.0218f; + + //initialize residuals with som large numbers + float err_min = 100000.0f; + float err_min_second = 200000.0f; + unsigned int ind_min, ind_second; + + float k, n, m; + + for(int i = 0; i < NUM_HYPOTHESES; i++) + { + m = m_list[i]; + n = n_list[i]; + k = k_list[i]; + calcErr(k, n, m, t0, t1, t2, &err1, &err2, &err3); + err = w1 * err1 * err1 + w2 * err2 * err2 + w3 * err3 * err3; + if(err < err_min) + { + err_min_second = err_min; + ind_second = ind_min; + err_min = err; + ind_min = i; + + } + else if(err < err_min_second) + { + err_min_second = err; + ind_second = i; + } + + } + + //decode ind_min + float mvals = m_list[ind_min]; + float nvals = n_list[ind_min]; + float kvals = k_list[ind_min]; + + //Weighted phases for phase fusion weighted average + float phi2_out = (t2 / 2.0f + mvals); + float phi1_out = (t1 / 15.0f + kvals); + float phi0_out = (t0 / 3.0f + nvals); + + *err_w1 = err_min; + + //phase fusion + *phase_first = (phi2_out + phi1_out + phi0_out) / 3.0f; + + mvals = m_list[ind_second]; + nvals = n_list[ind_second]; + kvals = k_list[ind_second]; + + //Weighted phases for phase fusion weighted average + phi2_out = (t2 / 2.0f + mvals); + phi1_out = (t1 / 15.0f + kvals); + phi0_out = (t0 / 3.0f + nvals); + + *err_w2 = err_min_second; + + //phase fusion + *phase_second = (phi2_out + phi1_out + phi0_out) / 3.0f; + +} + +/******************************************************************************* + * Predict phase variance from amplitude direct quadratic model + ******************************************************************************/ +static __device__ +void calculatePhaseUnwrappingVarDirect(float3 ir, float3* var) +{ + //Model: sigma = 1/(gamma0*a+gamma1*a^2+gamma2). Possibly better than calculatePhaseUnwrappingVar + //The gammas are optimized using lsqnonlin in matlab. + //For more details see the paper "Efficient Phase Unwrapping using Kernel Density Estimation" + //section 3.3 and 4.4. + float sigma_max = 0.5f * M_PI_F; + + //Set sigma = pi/2 as a maximum standard deviation of the phase. Cut off function after root + float q0 = ir.x > 5.244404f ? 0.7919451669f * ir.x - 0.002363097609f * ir.x * ir.x - 3.088285897f : 1.0f / sigma_max; + float q1 = ir.y > 4.084835f ? 1.214266794f * ir.y - 0.00581082634f * ir.y * ir.y - 3.863119924f : 1.0f / sigma_max; + float q2 = ir.z > 6.379475f ? 0.6101457464f * ir.z - 0.00113679233f * ir.z * ir.z - 2.84614442f : 1.0f / sigma_max; + float3 q = make_float3(q0, q1, q2); + float3 roots = make_float3(5.244404f, 4.084835f, 6.379475f); + float3 sigma = make_float3(1.0f)/q; + sigma = select(sigma, make_float3(sigma_max), isless(make_float3(sigma_max), sigma)); + *var = sigma; +} + + +/******************************************************************************* + * Predict phase variance from amplitude (quadratic atan model) + ******************************************************************************/ +static __device__ +void calculatePhaseUnwrappingVar(float3 ir, float3 *var) +{ + //Model: sigma = atan(sqrt(1/(gamma0*a+gamma1*a^2+gamma2)-1)). The gammas are optimized using lsqnonlin in matlab. + //For more details see the paper "Efficient Phase Unwrapping using Kernel Density Estimation", + //section 3.3 and 4.4. + float q0 = 0.8211288451f * ir.x - 0.002601348899f * ir.x * ir.x - 3.549793908f; + float q1 = 1.259642407f * ir.y - 0.005478390508f * ir.y * ir.y - 4.335841127f; + float q2 = 0.6447928035f * ir.z - 0.0009627273649f * ir.z * ir.z - 3.368205575f; + float3 q = make_float3(q0, q1, q2); + q *= q; + float3 roots = make_float3(5.64173671f, 4.31705182f, 6.84453530f); + float3 asdf = atan2(make_float3(0.5f), make_float3(1.0f)); + float3 sigma = select(select(make_float3(0.5f * M_PI_F), roots * 0.5f * M_PI_F / ir, isless(roots,ir)), atan2(sqrt(make_float3(1.0f) / (q - make_float3(1.0f))), make_float3(1.0f)), isless(make_float3(1.0f), q)); + sigma = select(sigma, make_float3(0.001f), isless(sigma, make_float3(0.001f))); + *var = sigma*sigma; +} + +static __global__ +void processPixelStage2_phase(const float4* __restrict__ a_in, const float4* __restrict__ b_in, float4 *phase_conf_vec) +{ + const uint i = get_global_id(0); + + //read complex number real (a) and imaginary part (b) + float3 a = make_float3(a_in[i]); + float3 b = make_float3(b_in[i]); + + //calculate complex argument + float3 phase = atan2(b, a); + phase = select(phase, make_float3(0.0f), isnan(phase)); + phase = select(phase, phase + 2.0f * M_PI_F, isless(phase, make_float3(0.0f))); + + //calculate amplitude or the absolute value + float3 ir = sqrt(a * a + b * b) * AB_MULTIPLIER; + + float ir_sum = ir.x + ir.y + ir.z; + float ir_min = min(ir.x, min(ir.y, ir.z)); + float ir_max = max(ir.x, max(ir.y, ir.z)); + + float phase_first = 0.0f; + float phase_second = 0.0f; + + float J_1, J_2, unwrapping_likelihood1, unwrapping_likelihood2; + + //scale with least common multiples of modulation frequencies + float3 t = phase / (2.0f * M_PI_F) * make_float3(3.0f, 15.0f, 2.0f); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + //rank and extract two most likely phase hypothises + phaseUnWrapper(t0, t1, t2, &phase_first, &phase_second, &J_1, &J_2); + + float phase_likelihood; + + //check if near saturation + if(ir_sum < 0.4f * 65535.0f) + { + //calculate phase likelihood from amplitude + float3 var; + calculatePhaseUnwrappingVar(ir, &var); + phase_likelihood = exp(-(var.x + var.y + var.z) / (2.0f * PHASE_CONFIDENCE_SCALE)); + phase_likelihood = isnan(phase_likelihood) ? 0.0f : phase_likelihood; + } + else + { + phase_likelihood = 0.0f; + } + + //merge phase likelihood with phase likelihood + unwrapping_likelihood1 = phase_likelihood*exp(-J_1 / (2 * UNWRAPPING_LIKELIHOOD_SCALE)); + unwrapping_likelihood2 = phase_likelihood*exp(-J_2 / (2 * UNWRAPPING_LIKELIHOOD_SCALE)); + + //suppress confidence if phase is beyond allowed range + unwrapping_likelihood1 = phase_first > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood1; + unwrapping_likelihood2 = phase_second > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood2; + + phase_conf_vec[i] = make_float4(phase_first,phase_second, unwrapping_likelihood1, unwrapping_likelihood2); + +} + +static __global__ +void filter_kde(const float4 *phase_conf_vec, const float* gauss_filt_array, const float* __restrict__ x_table, const float* __restrict__ z_table, float* depth) +{ + const uint i = get_global_id(0); + float kde_val_1, kde_val_2; + + const int loadX = i % 512; + const int loadY = i / 512; + + int k, l; + float sum_1, sum_2; + + //initialize neighborhood boundaries + int from_x = (loadX > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadX + 1); + int from_y = (loadY > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadY + 1); + int to_x = (loadX < 511 - KDE_NEIGBORHOOD_SIZE - 1 ? KDE_NEIGBORHOOD_SIZE: 511 - loadX - 1); + int to_y = (loadY < 423 - KDE_NEIGBORHOOD_SIZE ? KDE_NEIGBORHOOD_SIZE: 423 - loadY); + + kde_val_1 = 0.0f; + kde_val_2 = 0.0f; + float4 phase_local = phase_conf_vec[i]; + if(loadX >= 1 && loadX < 511 && loadY >= 0 && loadY<424) + { + sum_1 = 0.0f; + sum_2 = 0.0f; + float gauss; + float sum_gauss = 0.0f; + + float phase_1_local; + float phase_2_local; + float conf1_local; + float conf2_local; + float4 phase_conf_local; + uint ind; + float diff11, diff21, diff12, diff22; + //calculate KDE for all hypothesis within the neigborhood + for(k = from_y; k <= to_y; k++) + for(l = from_x; l <= to_x; l++) + { + ind = (loadY + k) * 512 + (loadX + l); + + phase_conf_local = phase_conf_vec[ind]; + conf1_local = phase_conf_local.z; + conf2_local = phase_conf_local.w; + phase_1_local = phase_conf_local.x; + phase_2_local = phase_conf_local.y; + + gauss = gauss_filt_array[k + KDE_NEIGBORHOOD_SIZE] * gauss_filt_array[l + KDE_NEIGBORHOOD_SIZE]; + sum_gauss += gauss * (conf1_local + conf2_local); + diff11 = phase_1_local - phase_local.x; + diff21 = phase_2_local - phase_local.x; + diff12 = phase_1_local - phase_local.y; + diff22 = phase_2_local - phase_local.y; + sum_1 += gauss * (conf1_local * exp(-diff11 * diff11 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff21 * diff21 / (2 * KDE_SIGMA_SQR))); + sum_2 += gauss * (conf1_local * exp(-diff12 * diff12 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff22 * diff22 / (2 * KDE_SIGMA_SQR))); + } + kde_val_1 = sum_gauss > 0.5f ? sum_1/sum_gauss : sum_1 * 2.0f; + kde_val_2 = sum_gauss > 0.5f ? sum_2/sum_gauss : sum_2 * 2.0f; + } + + //select hypothesis + int val_ind = kde_val_2 <= kde_val_1 ? 1: 0; + + float phase_final = val_ind ? phase_local.x: phase_local.y; + float max_val = val_ind ? kde_val_1: kde_val_2; + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0f; + + bool cond1 = true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0f) / (max_depth * max_depth * 8192.0f); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + + max_val = d < MIN_DEPTH || d > MAX_DEPTH ? 0.0f: max_val; + + depth[i] = max_val >= KDE_THRESHOLD ? d: 0.0f; +} + + +/***************************************************************** + * THREE HYPOTHESIS + *****************************************************************/ +static __device__ +void phaseUnWrapper3(float t0, float t1,float t2, float* phase_first, float* phase_second, float* phase_third, float* err_w1, float* err_w2, float* err_w3) +{ + float err; + float err1, err2, err3; + + //unwrapping weight for cost function + float w1 = 1.0f; + float w2 = 10.0f; + float w3 = 1.0218f; + + //initialize residuals with som large numbers + float err_min = 100000.0f; + float err_min_second = 200000.0f; + float err_min_third = 300000.0f; + unsigned int ind_min, ind_second, ind_third; + + float k, n, m; + + for(int i = 0; i < NUM_HYPOTHESES; i++) + { + m = m_list[i]; + n = n_list[i]; + k = k_list[i]; + calcErr(k, n, m, t0, t1, t2, &err1, &err2, &err3); + err = w1 * err1 * err1 + w2 * err2 * err2 + w3 * err3 * err3; + if(err < err_min) + { + err_min_third = err_min_second; + ind_third = ind_second; + err_min_second = err_min; + ind_second = ind_min; + err_min = err; + ind_min = i; + + } + else if(err MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood1; + unwrapping_likelihood2 = phase_second > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood2; + unwrapping_likelihood3 = phase_third > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood3; + + conf1[i] = unwrapping_likelihood1; + conf2[i] = unwrapping_likelihood2; + conf3[i] = unwrapping_likelihood3; +} + + +static __global__ +void filter_kde3(const float *phase_1, const float *phase_2, const float *phase_3, const float* conf1, const float* conf2, const float* conf3, const float* gauss_filt_array, const float* __restrict__ x_table, const float* __restrict__ z_table, float* depth) +{ + const uint i = get_global_id(0); + float kde_val_1, kde_val_2, kde_val_3; + + const int loadX = i % 512; + const int loadY = i / 512; + int k, l; + float sum_1, sum_2, sum_3; + + //initialize neighborhood boundaries + int from_x = (loadX > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadX + 1); + int from_y = (loadY > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadY + 1); + int to_x = (loadX < 511 - KDE_NEIGBORHOOD_SIZE-1 ? KDE_NEIGBORHOOD_SIZE: 511 - loadX - 1); + int to_y = (loadY < 423 - KDE_NEIGBORHOOD_SIZE ? KDE_NEIGBORHOOD_SIZE: 423 - loadY); + + kde_val_1 = 0.0f; + kde_val_2 = 0.0f; + kde_val_3 = 0.0f; + float phase_first = phase_1[i]; + float phase_second = phase_2[i]; + float phase_third = phase_3[i]; + if(loadX >= 1 && loadX < 511 && loadY >= 0 && loadY<424) + { + //Filter kernel + sum_1 = 0.0f; + sum_2 = 0.0f; + sum_3 = 0.0f; + float gauss; + float sum_gauss = 0.0f; + + float phase_1_local; + float phase_2_local; + float phase_3_local; + float conf1_local; + float conf2_local; + float conf3_local; + float diff11, diff12, diff13, diff21, diff22, diff23, diff31, diff32, diff33; + uint ind; + + //calculate KDE for all hypothesis within the neigborhood + for(k = from_y; k <= to_y; k++) + for(l = from_x; l <= to_x; l++) + { + ind = (loadY + k) * 512+ (loadX + l); + conf1_local = conf1[ind]; + conf2_local = conf2[ind]; + conf3_local = conf3[ind]; + phase_1_local = phase_1[ind]; + phase_2_local = phase_2[ind]; + phase_3_local = phase_3[ind]; + diff11 = phase_1_local - phase_first; + diff12 = phase_1_local - phase_second; + diff13 = phase_1_local - phase_third; + diff21 = phase_2_local - phase_first; + diff22 = phase_2_local - phase_second; + diff23 = phase_2_local - phase_third; + diff31 = phase_3_local - phase_first; + diff32 = phase_3_local - phase_second; + diff33 = phase_3_local - phase_third; + gauss = gauss_filt_array[k + KDE_NEIGBORHOOD_SIZE] * gauss_filt_array[l + KDE_NEIGBORHOOD_SIZE]; + sum_gauss += gauss * (conf1_local + conf2_local+conf3_local); + sum_1 += gauss*(conf1_local * exp(-diff11 * diff11 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff21 * diff21 / (2 * KDE_SIGMA_SQR)) + conf3_local * exp(-diff31 * diff31 /(2 * KDE_SIGMA_SQR))); + sum_2 += gauss * (conf1_local * exp(-diff12 * diff12 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff22 * diff22 / (2 * KDE_SIGMA_SQR)) + conf3_local * exp(-diff32 * diff32 / (2 * KDE_SIGMA_SQR))); + sum_3 += gauss * (conf1_local * exp(-diff13 * diff13 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff23 * diff23 / (2 * KDE_SIGMA_SQR)) + conf3_local * exp(-diff33 * diff33 / (2 * KDE_SIGMA_SQR))); + } + kde_val_1 = sum_gauss > 0.5f ? sum_1 / sum_gauss : sum_1 * 2.0f; + kde_val_2 = sum_gauss > 0.5f ? sum_2 / sum_gauss : sum_2 * 2.0f; + kde_val_3 = sum_gauss > 0.5f ? sum_3 / sum_gauss : sum_3 * 2.0f; + } + + //select hypothesis + float phase_final, max_val; + if(kde_val_2 > kde_val_1 || kde_val_3 > kde_val_1) + { + if(kde_val_3 > kde_val_2) + { + phase_final = phase_third; + max_val = kde_val_3; + } + else + { + phase_final = phase_second; + max_val = kde_val_2; + } + } + else + { + phase_final = phase_first; + max_val = kde_val_1; + } + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0f; + + bool cond1 = true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0f) / (max_depth * max_depth * 8192.0f); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + + max_val = depth_linear < MIN_DEPTH || depth_linear > MAX_DEPTH ? 0.0f: max_val; + + //set to zero if confidence is low + depth[i] = max_val >= KDE_THRESHOLD ? d: 0.0f; +} + + +#define CHECK_CUDA(expr) do { cudaError_t err = (expr); if (err != cudaSuccess) { LOG_ERROR << #expr ": " << cudaGetErrorString(err); return false; } } while(0) +#define CALL_CUDA(expr) do { cudaError_t err = (expr); if (err != cudaSuccess) { LOG_ERROR << #expr ": " << cudaGetErrorString(err); } } while(0) + +namespace libfreenect2 +{ + +class CudaKdeFrame: public Frame +{ +public: + CudaKdeFrame(Buffer *buffer): + Frame(512, 424, 4, (unsigned char*)-1) + { + data = buffer->data; + rawdata = reinterpret_cast(buffer); + } + + virtual ~CudaKdeFrame() + { + Buffer *buffer = reinterpret_cast(rawdata); + buffer->allocator->free(buffer); + rawdata = NULL; + } +}; + +class CudaKdeAllocator: public Allocator +{ +private: + const bool input; + + bool allocate_cuda(Buffer *b, size_t size) + { + unsigned int flags = cudaHostAllocPortable; + if (input) + flags |= cudaHostAllocWriteCombined; + CHECK_CUDA(cudaHostAlloc(&b->data, size, flags)); + b->length = 0; + b->capacity = size; + return true; + } + +public: + CudaKdeAllocator(bool input): input(input) {} + + virtual Buffer *allocate(size_t size) + { + Buffer *b = new Buffer(); + if (!allocate_cuda(b, size)) + b->data = NULL; + return b; + } + + virtual void free(Buffer *b) + { + if (b == NULL) + return; + if (b->data) + CALL_CUDA(cudaFreeHost(b->data)); + delete b; + } +}; + +class CudaKdeDepthPacketProcessorImpl: public WithPerfLogging +{ +public: + static const size_t IMAGE_SIZE = 512*424; + static const size_t LUT_SIZE = 2048; + + size_t d_lut_size; + size_t d_xtable_size; + size_t d_ztable_size; + size_t d_p0table_size; + size_t d_gauss_kernel_size; + + short *d_lut; + float *d_xtable; + float *d_ztable; + float4 *d_p0table; + float4 h_p0table[IMAGE_SIZE]; + float* d_gauss_kernel; + + size_t d_packet_size; + unsigned short *d_packet; + + float4 *d_a; + float4 *d_b; + float4 *d_n; + float *d_ir; + float4 *d_a_filtered; + float4 *d_b_filtered; + unsigned char *d_edge_test; + float *d_depth; + //float *d_ir_sum; + float *d_phase_1; + float *d_phase_2; + float *d_phase_3; + float *d_conf_1; + float *d_conf_2; + float *d_conf_3; + float4 *d_phase_conf_vec; + + size_t block_size; + size_t grid_size; + + DepthPacketProcessor::Config config; + DepthPacketProcessor::Parameters params; + + Frame *ir_frame, *depth_frame; + + Allocator *input_allocator; + Allocator *ir_allocator; + Allocator *depth_allocator; + + bool good; + + CudaKdeDepthPacketProcessorImpl(const int deviceId): + block_size(128), + grid_size(IMAGE_SIZE/block_size), + config(), + params(), + ir_frame(NULL), + depth_frame(NULL), + input_allocator(NULL), + ir_allocator(NULL), + depth_allocator(NULL) + { + + good = initDevice(deviceId); + if (!good) + return; + + input_allocator = new PoolAllocator(new CudaKdeAllocator(true)); + ir_allocator = new PoolAllocator(new CudaKdeAllocator(false)); + depth_allocator = new PoolAllocator(new CudaKdeAllocator(false)); + + newIrFrame(); + newDepthFrame(); + } + + ~CudaKdeDepthPacketProcessorImpl() + { + delete ir_frame; + delete depth_frame; + delete input_allocator; + delete ir_allocator; + delete depth_allocator; + if (good) + freeDeviceMemory(); + } + + bool setParameters(const DepthPacketProcessor::Parameters ¶ms) + { + unsigned int bfi_bitmask = 0x180; + cudaMemcpyToSymbolAsync(BFI_BITMASK, &bfi_bitmask, sizeof(int)); + + #define COPY(upper, lower) cudaMemcpyToSymbolAsync(upper, ¶ms.lower, sizeof(params.lower)); + COPY(AB_MULTIPLIER, ab_multiplier) + COPY(AB_MULTIPLIER_PER_FRQ0, ab_multiplier_per_frq[0]) + COPY(AB_MULTIPLIER_PER_FRQ1, ab_multiplier_per_frq[1]) + COPY(AB_MULTIPLIER_PER_FRQ2, ab_multiplier_per_frq[2]) + COPY(AB_OUTPUT_MULTIPLIER, ab_output_multiplier) + + COPY(PHASE_IN_RAD0, phase_in_rad[0]) + COPY(PHASE_IN_RAD1, phase_in_rad[1]) + COPY(PHASE_IN_RAD2, phase_in_rad[2]) + + COPY(JOINT_BILATERAL_AB_THRESHOLD, joint_bilateral_ab_threshold) + COPY(JOINT_BILATERAL_MAX_EDGE, joint_bilateral_max_edge) + COPY(JOINT_BILATERAL_EXP, joint_bilateral_exp) + float joint_bilateral_threshold; + joint_bilateral_threshold = (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier); + cudaMemcpyToSymbolAsync(JOINT_BILATERAL_THRESHOLD, &joint_bilateral_threshold, sizeof(float)); + + COPY(GAUSSIAN_KERNEL_0, gaussian_kernel[0]) + COPY(GAUSSIAN_KERNEL_1, gaussian_kernel[1]) + COPY(GAUSSIAN_KERNEL_2, gaussian_kernel[2]) + COPY(GAUSSIAN_KERNEL_3, gaussian_kernel[3]) + COPY(GAUSSIAN_KERNEL_4, gaussian_kernel[4]) + COPY(GAUSSIAN_KERNEL_5, gaussian_kernel[5]) + COPY(GAUSSIAN_KERNEL_6, gaussian_kernel[6]) + COPY(GAUSSIAN_KERNEL_7, gaussian_kernel[7]) + COPY(GAUSSIAN_KERNEL_8, gaussian_kernel[8]) + + COPY(PHASE_OFFSET, phase_offset) + COPY(UNAMBIGIOUS_DIST, unambigious_dist) + COPY(INDIVIDUAL_AB_THRESHOLD, individual_ab_threshold) + COPY(AB_THRESHOLD, ab_threshold) + COPY(AB_CONFIDENCE_SLOPE, ab_confidence_slope) + COPY(AB_CONFIDENCE_OFFSET, ab_confidence_offset) + COPY(MIN_DEALIAS_CONFIDENCE, min_dealias_confidence) + COPY(MAX_DEALIAS_CONFIDENCE, max_dealias_confidence) + + COPY(EDGE_AB_AVG_MIN_VALUE, edge_ab_avg_min_value) + COPY(EDGE_AB_STD_DEV_THRESHOLD, edge_ab_std_dev_threshold) + COPY(EDGE_CLOSE_DELTA_THRESHOLD, edge_close_delta_threshold) + COPY(EDGE_FAR_DELTA_THRESHOLD, edge_far_delta_threshold) + COPY(EDGE_MAX_DELTA_THRESHOLD, edge_max_delta_threshold) + COPY(EDGE_AVG_DELTA_THRESHOLD, edge_avg_delta_threshold) + COPY(MAX_EDGE_COUNT, max_edge_count) + + + COPY(KDE_SIGMA_SQR, kde_sigma_sqr); + COPY(KDE_NEIGBORHOOD_SIZE, kde_neigborhood_size); + COPY(UNWRAPPING_LIKELIHOOD_SCALE, unwrapping_likelihood_scale); + COPY(PHASE_CONFIDENCE_SCALE, phase_confidence_scale); + COPY(KDE_THRESHOLD, kde_threshold); + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + bool allocateDeviceMemory() + { + //Read only + d_p0table_size = IMAGE_SIZE * sizeof(float4); + d_xtable_size = IMAGE_SIZE * sizeof(float); + d_ztable_size = IMAGE_SIZE * sizeof(float); + d_lut_size = LUT_SIZE * sizeof(short); + d_gauss_kernel_size = (2*params.kde_neigborhood_size+1)*sizeof(float); + + CHECK_CUDA(cudaMalloc(&d_p0table, d_p0table_size)); + CHECK_CUDA(cudaMalloc(&d_xtable, d_xtable_size)); + CHECK_CUDA(cudaMalloc(&d_ztable, d_ztable_size)); + CHECK_CUDA(cudaMalloc(&d_lut, d_lut_size)); + CHECK_CUDA(cudaMalloc(&d_gauss_kernel, d_gauss_kernel_size)); + + d_packet_size = (IMAGE_SIZE * 11 / 8) * 10; + + CHECK_CUDA(cudaMalloc(&d_packet, d_packet_size)); + + //Read-Write + size_t d_a_size = IMAGE_SIZE * sizeof(float4); + size_t d_b_size = IMAGE_SIZE * sizeof(float4); + size_t d_n_size = IMAGE_SIZE * sizeof(float4); + size_t d_ir_size = IMAGE_SIZE * sizeof(float); + size_t d_a_filtered_size = IMAGE_SIZE * sizeof(float4); + size_t d_b_filtered_size = IMAGE_SIZE * sizeof(float4); + size_t d_edge_test_size = IMAGE_SIZE * sizeof(char); + size_t d_depth_size = IMAGE_SIZE * sizeof(float); + size_t d_phase_conf_vec_size = IMAGE_SIZE * sizeof(float4); + + CHECK_CUDA(cudaMalloc(&d_a, d_a_size)); + CHECK_CUDA(cudaMalloc(&d_b, d_b_size)); + CHECK_CUDA(cudaMalloc(&d_n, d_n_size)); + CHECK_CUDA(cudaMalloc(&d_ir, d_ir_size)); + CHECK_CUDA(cudaMalloc(&d_a_filtered, d_a_filtered_size)); + CHECK_CUDA(cudaMalloc(&d_b_filtered, d_b_filtered_size)); + CHECK_CUDA(cudaMalloc(&d_edge_test, d_edge_test_size)); + CHECK_CUDA(cudaMalloc(&d_depth, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_phase_1, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_phase_2, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_conf_1, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_conf_2, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_phase_conf_vec, d_phase_conf_vec_size)); + + if(params.num_hyps == 3) + { + CHECK_CUDA(cudaMalloc(&d_phase_3, d_depth_size)); + CHECK_CUDA(cudaMalloc(&d_conf_3, d_depth_size)); + } + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + void freeDeviceMemory() + { + CALL_CUDA(cudaFree(d_p0table)); + CALL_CUDA(cudaFree(d_xtable)); + CALL_CUDA(cudaFree(d_ztable)); + CALL_CUDA(cudaFree(d_lut)); + CALL_CUDA(cudaFree(d_gauss_kernel)); + + CALL_CUDA(cudaFree(d_packet)); + + CALL_CUDA(cudaFree(d_a)); + CALL_CUDA(cudaFree(d_b)); + CALL_CUDA(cudaFree(d_n)); + CALL_CUDA(cudaFree(d_ir)); + CALL_CUDA(cudaFree(d_a_filtered)); + CALL_CUDA(cudaFree(d_b_filtered)); + CALL_CUDA(cudaFree(d_edge_test)); + CALL_CUDA(cudaFree(d_depth)); + //CALL_CUDA(cudaFree(d_ir_sum)); + CALL_CUDA(cudaFree(d_phase_1)); + CALL_CUDA(cudaFree(d_phase_2)); + CALL_CUDA(cudaFree(d_conf_1)); + CALL_CUDA(cudaFree(d_conf_2)); + CALL_CUDA(cudaFree(d_phase_conf_vec)); + + if(params.num_hyps == 3) + { + CALL_CUDA(cudaFree(d_phase_3)); + CALL_CUDA(cudaFree(d_conf_3)); + } + } + + bool initDevice(const int deviceId) + { + int deviceCount = 0; + + CHECK_CUDA(cudaGetDeviceCount(&deviceCount)); + + int devId = -1; + for (int i = 0; i < deviceCount; i++) { + if (deviceId != -1 && i != deviceId) + continue; + + cudaDeviceProp prop; + CHECK_CUDA(cudaGetDeviceProperties(&prop, i)); + LOG_INFO << "device " << i << ": " << prop.name << " @ " << (prop.clockRate / 1000) << "MHz Memory " << (prop.totalGlobalMem >> 20) << "MB"; + + if (prop.computeMode == cudaComputeModeProhibited) { + LOG_INFO << " Compute Mode Prohibited"; + continue; + } + + if (prop.major < 1) { + LOG_INFO << " does not support CUDA"; + continue; + } + + devId = i; + break; + } + + if (devId == -1) { + LOG_ERROR << "No CUDA device found"; + return false; + } + + CHECK_CUDA(cudaSetDevice(devId)); + LOG_INFO << "selected device " << devId; + + if (!setParameters(params)) + return false; + + if (!setConfiguration(config)) + return false; + + if (!allocateDeviceMemory()) + return false; + + return true; + } + + bool setConfiguration(const DepthPacketProcessor::Config &cfg) + { + config = cfg; + float tmpf; + + tmpf = cfg.MinDepth * 1000.0f; + cudaMemcpyToSymbolAsync(MIN_DEPTH, &tmpf, sizeof(tmpf)); + + tmpf = cfg.MaxDepth * 1000.0f; + cudaMemcpyToSymbolAsync(MAX_DEPTH, &tmpf, sizeof(tmpf)); + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + bool run(const DepthPacket &packet) + { + size_t ir_frame_size = ir_frame->width * ir_frame->height * ir_frame->bytes_per_pixel; + size_t depth_frame_size = depth_frame->width * depth_frame->height * depth_frame->bytes_per_pixel; + + cudaMemcpyAsync(d_packet, packet.buffer, packet.buffer_length, cudaMemcpyHostToDevice); + + processPixelStage1<<>>(d_lut, d_ztable, d_p0table, d_packet, d_a, d_b, d_n, d_ir); + + cudaMemcpyAsync(ir_frame->data, d_ir, ir_frame_size, cudaMemcpyDeviceToHost); + + if (config.EnableBilateralFilter) { + filterPixelStage1<<>>(d_a, d_b, d_n, d_a_filtered, d_b_filtered, d_edge_test); + } + + if(params.num_hyps == 3) + { + processPixelStage2_phase3<<>>( + config.EnableBilateralFilter ? d_a_filtered : d_a, + config.EnableBilateralFilter ? d_b_filtered : d_b, + d_phase_1, d_phase_2, d_phase_3, d_conf_1, d_conf_2, d_conf_3); + + filter_kde3<<>>( + d_phase_1, + d_phase_2, + d_phase_3, + d_conf_1, + d_conf_2, + d_conf_3, + d_gauss_kernel, + d_xtable, + d_ztable, + d_depth); + } + else + { + processPixelStage2_phase<<>>( + config.EnableBilateralFilter ? d_a_filtered : d_a, + config.EnableBilateralFilter ? d_b_filtered : d_b, + d_phase_conf_vec); + + filter_kde<<>>( + d_phase_conf_vec, + d_gauss_kernel, + d_xtable, + d_ztable, + d_depth); + } + + cudaMemcpyAsync(depth_frame->data, d_depth, depth_frame_size, cudaMemcpyDeviceToHost); + + cudaDeviceSynchronize(); + + CHECK_CUDA(cudaGetLastError()); + return true; + } + + void newIrFrame() + { + ir_frame = new CudaKdeFrame(ir_allocator->allocate(IMAGE_SIZE*sizeof(float))); + ir_frame->format = Frame::Float; + } + + void newDepthFrame() + { + depth_frame = new CudaKdeFrame(depth_allocator->allocate(IMAGE_SIZE*sizeof(float))); + depth_frame->format = Frame::Float; + } + + void fill_trig_table(const protocol::P0TablesResponse *p0table) + { + for (int r = 0; r < 424; ++r) { + float4 *it = &h_p0table[r * 512]; + const uint16_t *it0 = &p0table->p0table0[r * 512]; + const uint16_t *it1 = &p0table->p0table1[r * 512]; + const uint16_t *it2 = &p0table->p0table2[r * 512]; + for (int c = 0; c < 512; ++c, ++it, ++it0, ++it1, ++it2) { + it->x = -((float) * it0) * 0.000031 * M_PI; + it->y = -((float) * it1) * 0.000031 * M_PI; + it->z = -((float) * it2) * 0.000031 * M_PI; + it->w = 0.0f; + } + } + } + + //initialize spatial weights + void createGaussianKernel(float** kernel, int size) + { + *kernel = new float[2*size+1]; + float sigma = 0.5f*(float)size; + + for(int i = -size; i <= size; i++) + { + (*kernel)[i+size] = exp(-0.5f*i*i/(sigma*sigma)); + } + } +}; + +CudaKdeDepthPacketProcessor::CudaKdeDepthPacketProcessor(const int deviceId): + impl_(new CudaKdeDepthPacketProcessorImpl(deviceId)) +{ +} + +CudaKdeDepthPacketProcessor::~CudaKdeDepthPacketProcessor() +{ + delete impl_; +} + +void CudaKdeDepthPacketProcessor::setConfiguration(const DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + + impl_->good = impl_->setConfiguration(config); +} + +void CudaKdeDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char *buffer, size_t buffer_length) +{ + impl_->fill_trig_table((protocol::P0TablesResponse *)buffer); + cudaMemcpy(impl_->d_p0table, impl_->h_p0table, impl_->d_p0table_size, cudaMemcpyHostToDevice); +} + +void CudaKdeDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) +{ + cudaMemcpy(impl_->d_xtable, xtable, impl_->d_xtable_size, cudaMemcpyHostToDevice); + cudaMemcpy(impl_->d_ztable, ztable, impl_->d_ztable_size, cudaMemcpyHostToDevice); + float* gauss_kernel; + impl_->createGaussianKernel(&gauss_kernel, impl_->params.kde_neigborhood_size); + cudaMemcpy(impl_->d_gauss_kernel, gauss_kernel, impl_->d_gauss_kernel_size, cudaMemcpyHostToDevice); +} + +void CudaKdeDepthPacketProcessor::loadLookupTable(const short *lut) +{ + cudaMemcpy(impl_->d_lut, lut, impl_->d_lut_size, cudaMemcpyHostToDevice); +} + +bool CudaKdeDepthPacketProcessor::good() +{ + return impl_->good; +} + +void CudaKdeDepthPacketProcessor::process(const DepthPacket &packet) +{ + if (listener_ == NULL) + return; + + impl_->startTiming(); + + impl_->ir_frame->timestamp = packet.timestamp; + impl_->depth_frame->timestamp = packet.timestamp; + impl_->ir_frame->sequence = packet.sequence; + impl_->depth_frame->sequence = packet.sequence; + + impl_->good = impl_->run(packet); + + impl_->stopTiming(LOG_INFO); + + if (!impl_->good) { + impl_->ir_frame->status = 1; + impl_->depth_frame->status = 1; + } + + if (listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + impl_->newIrFrame(); + if (listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + impl_->newDepthFrame(); +} + +Allocator *CudaKdeDepthPacketProcessor::getAllocator() +{ + return impl_->input_allocator; +} +} // namespace libfreenect2 diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_processor.cpp new file mode 100644 index 0000000..abb5bc7 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_processor.cpp @@ -0,0 +1,182 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file depth_packet_processor.cpp Generic part of the depth processors (configuration and parameters). */ + +#include +#include + +#include + +namespace libfreenect2 +{ + +DepthPacketProcessor::Parameters::Parameters() +{ + ab_multiplier = 0.6666667f; + ab_multiplier_per_frq[0] = 1.322581f; + ab_multiplier_per_frq[1] = 1.0f; + ab_multiplier_per_frq[2] = 1.612903f; + ab_output_multiplier = 16.0f; + + phase_in_rad[0] = 0.0f; + phase_in_rad[1] = 2.094395f; + phase_in_rad[2] = 4.18879f; + + joint_bilateral_ab_threshold = 3.0f; + joint_bilateral_max_edge = 2.5f; + joint_bilateral_exp = 5.0f; + + gaussian_kernel[0] = 0.1069973f; + gaussian_kernel[1] = 0.1131098f; + gaussian_kernel[2] = 0.1069973f; + gaussian_kernel[3] = 0.1131098f; + gaussian_kernel[4] = 0.1195716f; + gaussian_kernel[5] = 0.1131098f; + gaussian_kernel[6] = 0.1069973f; + gaussian_kernel[7] = 0.1131098f; + gaussian_kernel[8] = 0.1069973f; + + phase_offset = 0.0f; + unambigious_dist = 2083.333f; + individual_ab_threshold = 3.0f; + ab_threshold = 10.0f; + ab_confidence_slope = -0.5330578f; + ab_confidence_offset = 0.7694894f; + min_dealias_confidence = 0.3490659f; + max_dealias_confidence = 0.6108653f; + + edge_ab_avg_min_value = 50.0f; + edge_ab_std_dev_threshold = 0.05f; + edge_close_delta_threshold = 50.0f; + edge_far_delta_threshold = 30.0f; + edge_max_delta_threshold = 100.0f; + edge_avg_delta_threshold = 0.0f; + max_edge_count = 5.0f; + +/* + * These are parameters for the method described in "Efficient Phase Unwrapping + * using Kernel Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ + + kde_sigma_sqr = 0.0239282226563f; //the scale of the kernel in the KDE, h in eq (13). + unwrapping_likelihood_scale = 2.0f; //scale parameter for the unwrapping likelihood, s_1^2 in eq (15). + phase_confidence_scale = 3.0f; //scale parameter for the phase likelihood, s_2^2 in eq (23) + kde_threshold = 0.5f; //threshold on the KDE output in eq (25), defines the inlier/outlier rate trade-off + + kde_neigborhood_size = 5; //spatial support of the KDE, defines a filter size of (2*kde_neigborhood_size+1 x 2*kde_neigborhood_size+1) + num_hyps = 2; //number of phase unwrapping hypothesis considered by the KDE in each pixel. Implemented values are 2 and 3. + //a large kde_neigborhood_size improves performance but may remove fine structures and makes the processing slower. + //setting num_hyp to 3 improves the performance slightly but makes processing slower + + min_depth = 500.0f; + max_depth = 4500.0f; //set to > 8000 for best performance when using the kde pipeline +} + +DepthPacketProcessor::DepthPacketProcessor() : + listener_(0) +{ +} + +DepthPacketProcessor::~DepthPacketProcessor() +{ +} + +void DepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + config_ = config; +} + +void DepthPacketProcessor::setFrameListener(libfreenect2::FrameListener *listener) +{ + listener_ = listener; +} + +DumpDepthPacketProcessor::DumpDepthPacketProcessor() + : p0table_(NULL), xtable_(NULL), ztable_(NULL), lut_(NULL) { +} + +DumpDepthPacketProcessor::~DumpDepthPacketProcessor(){ + delete[] p0table_; + delete[] xtable_; + delete[] ztable_; + delete[] lut_; +} + +void DumpDepthPacketProcessor::process(const DepthPacket &packet) { + Frame* depth_frame = new Frame(1, 1, packet.buffer_length); + + depth_frame->timestamp = packet.timestamp; + depth_frame->sequence = packet.sequence; + depth_frame->format = Frame::Raw; + std::memcpy(depth_frame->data, packet.buffer, packet.buffer_length); + + Frame* ir_frame = new Frame(1, 1, packet.buffer_length, depth_frame->data); + ir_frame->timestamp = packet.timestamp; + ir_frame->sequence = packet.sequence; + ir_frame->data = packet.buffer; + ir_frame->format = Frame::Raw; + + if (!listener_->onNewFrame(Frame::Ir, ir_frame)) { + delete ir_frame; + } + ir_frame = NULL; + if (!listener_->onNewFrame(Frame::Depth, depth_frame)) { + delete depth_frame; + } + depth_frame = NULL; +} + +const unsigned char* DumpDepthPacketProcessor::getP0Tables() { return p0table_; } + +const float* DumpDepthPacketProcessor::getXTable() { return xtable_; } +const float* DumpDepthPacketProcessor::getZTable() { return ztable_; } + +const short* DumpDepthPacketProcessor::getLookupTable() { return lut_; } + +void DumpDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) { + delete[] p0table_; + p0table_ = new unsigned char[buffer_length]; + std::memcpy(p0table_, buffer, buffer_length); +} + +void DumpDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) { + delete[] xtable_; + xtable_ = new float[TABLE_SIZE]; + std::memcpy(xtable_, xtable, TABLE_SIZE * sizeof(float)); + + delete[] ztable_; + ztable_ = new float[TABLE_SIZE]; + std::memcpy(ztable_, ztable, TABLE_SIZE * sizeof(float)); +} + +void DumpDepthPacketProcessor::loadLookupTable(const short *lut) { + delete[] lut_; + lut_ = new short[LUT_SIZE]; + std::memcpy(lut_, lut, LUT_SIZE * sizeof(short)); +} +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_stream_parser.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_stream_parser.cpp new file mode 100644 index 0000000..db0a2dc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/depth_packet_stream_parser.cpp @@ -0,0 +1,169 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file depth_packet_stream_parser.cpp Parser for getting packets from the depth stream. */ + +#include +#include +#include + +namespace libfreenect2 +{ + +DepthPacketStreamParser::DepthPacketStreamParser() : + processor_(noopProcessor()), + processed_packets_(-1), + current_sequence_(0), + current_subsequence_(0) +{ + size_t single_image = 512*424*11/8; + buffer_size_ = 10 * single_image; + + processor_->allocateBuffer(packet_, buffer_size_); + + work_buffer_.data = new unsigned char[single_image]; + work_buffer_.capacity = single_image; + work_buffer_.length = 0; +} + +DepthPacketStreamParser::~DepthPacketStreamParser() +{ + delete[] work_buffer_.data; +} + +void DepthPacketStreamParser::setPacketProcessor(libfreenect2::BaseDepthPacketProcessor *processor) +{ + processor_->releaseBuffer(packet_); + processor_ = (processor != 0) ? processor : noopProcessor(); + processor_->allocateBuffer(packet_, buffer_size_); +} + +void DepthPacketStreamParser::onDataReceived(unsigned char* buffer, size_t in_length) +{ + if (packet_.memory == NULL || packet_.memory->data == NULL) + { + LOG_ERROR << "Packet buffer is NULL"; + return; + } + Buffer &wb = work_buffer_; + + if(in_length == 0) + { + //synchronize to subpacket boundary + wb.length = 0; + } + else + { + DepthSubPacketFooter *footer = 0; + bool footer_found = false; + + if(wb.length + in_length == wb.capacity + sizeof(DepthSubPacketFooter)) + { + in_length -= sizeof(DepthSubPacketFooter); + footer = reinterpret_cast(&buffer[in_length]); + footer_found = true; + } + + if(wb.length + in_length > wb.capacity) + { + LOG_DEBUG << "subpacket too large"; + wb.length = 0; + return; + } + + memcpy(wb.data + wb.length, buffer, in_length); + wb.length += in_length; + + if(footer_found) + { + if(footer->length != wb.length) + { + LOG_DEBUG << "image data too short!"; + } + else + { + if(current_sequence_ != footer->sequence) + { + if(current_subsequence_ == 0x3ff) + { + if(processor_->ready()) + { + DepthPacket &packet = packet_; + packet.sequence = current_sequence_; + packet.timestamp = footer->timestamp; + packet.buffer = packet_.memory->data; + packet.buffer_length = packet_.memory->capacity; + + processor_->process(packet); + processor_->allocateBuffer(packet_, buffer_size_); + + processed_packets_++; + if (processed_packets_ == 0) + processed_packets_ = current_sequence_; + int diff = current_sequence_ - processed_packets_; + const int interval = 30; + if ((current_sequence_ % interval == 0 && diff != 0) || diff >= interval) + { + LOG_INFO << diff << " packets were lost"; + processed_packets_ = current_sequence_; + } + } + else + { + LOG_DEBUG << "skipping depth packet"; + } + } + else + { + LOG_DEBUG << "not all subsequences received " << current_subsequence_; + } + + current_sequence_ = footer->sequence; + current_subsequence_ = 0; + } + + Buffer &fb = *packet_.memory; + + // set the bit corresponding to the subsequence number to 1 + current_subsequence_ |= 1 << footer->subsequence; + + if(footer->subsequence * footer->length > fb.capacity) + { + LOG_DEBUG << "front buffer too short! subsequence number is " << footer->subsequence; + } + else + { + memcpy(fb.data + (footer->subsequence * footer->length), wb.data + (wb.length - footer->length), footer->length); + } + } + + // reset working buffer + wb.length = 0; + } + } +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/event_loop.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/event_loop.cpp new file mode 100644 index 0000000..a7ac1dd --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/event_loop.cpp @@ -0,0 +1,106 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file event_loop.cpp Event handling. */ + +#include + +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +namespace libfreenect2 +{ +namespace usb +{ + +/** + * Execute the given event loop. + * @param cookie Event loop to run. + */ +void EventLoop::static_execute(void *cookie) +{ + static_cast(cookie)->execute(); +} + +EventLoop::EventLoop() : + shutdown_(false), + thread_(0), + usb_context_(0) +{ +} + +EventLoop::~EventLoop() +{ + stop(); +} + +/** + * Start the event-loop thread. + * @param usb_context Context. + */ +void EventLoop::start(void *usb_context) +{ + if(thread_ == 0) + { + shutdown_ = false; + usb_context_ = usb_context; + thread_ = new libfreenect2::thread(&EventLoop::static_execute, this); + } +} + +/** Stop the thread. */ +void EventLoop::stop() +{ + if(thread_ != 0) + { + shutdown_ = true; + thread_->join(); + delete thread_; + thread_ = 0; + usb_context_ = 0; + } +} + +/** Execute the job, until shut down. */ +void EventLoop::execute() +{ + this_thread::set_name("USB"); + timeval t; + t.tv_sec = 0; + t.tv_usec = 100000; + + while(!shutdown_) + { + libusb_handle_events_timeout_completed(reinterpret_cast(usb_context_), &t, 0); + } +} + +} /* namespace usb */ +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.cpp new file mode 100644 index 0000000..5828eff --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.cpp @@ -0,0 +1,279 @@ +#include "flextGL.h" +#include "GLFW/glfw3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void flextInit(OpenGLBindings *bindings) +{ + /* --- Function pointer loading --- */ + + + /* GL_VERSION_1_2 */ + + bindings->glDrawRangeElements = (PFNGLDRAWRANGEELEMENTS_PROC*)glfwGetProcAddress("glDrawRangeElements"); + bindings->glTexImage3D = (PFNGLTEXIMAGE3D_PROC*)glfwGetProcAddress("glTexImage3D"); + bindings->glTexSubImage3D = (PFNGLTEXSUBIMAGE3D_PROC*)glfwGetProcAddress("glTexSubImage3D"); + bindings->glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3D_PROC*)glfwGetProcAddress("glCopyTexSubImage3D"); + + /* GL_VERSION_1_3 */ + + bindings->glActiveTexture = (PFNGLACTIVETEXTURE_PROC*)glfwGetProcAddress("glActiveTexture"); + bindings->glSampleCoverage = (PFNGLSAMPLECOVERAGE_PROC*)glfwGetProcAddress("glSampleCoverage"); + bindings->glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3D_PROC*)glfwGetProcAddress("glCompressedTexImage3D"); + bindings->glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2D_PROC*)glfwGetProcAddress("glCompressedTexImage2D"); + bindings->glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1D_PROC*)glfwGetProcAddress("glCompressedTexImage1D"); + bindings->glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC*)glfwGetProcAddress("glCompressedTexSubImage3D"); + bindings->glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC*)glfwGetProcAddress("glCompressedTexSubImage2D"); + bindings->glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC*)glfwGetProcAddress("glCompressedTexSubImage1D"); + bindings->glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGE_PROC*)glfwGetProcAddress("glGetCompressedTexImage"); + + /* GL_VERSION_1_4 */ + + bindings->glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATE_PROC*)glfwGetProcAddress("glBlendFuncSeparate"); + bindings->glMultiDrawArrays = (PFNGLMULTIDRAWARRAYS_PROC*)glfwGetProcAddress("glMultiDrawArrays"); + bindings->glMultiDrawElements = (PFNGLMULTIDRAWELEMENTS_PROC*)glfwGetProcAddress("glMultiDrawElements"); + bindings->glPointParameterf = (PFNGLPOINTPARAMETERF_PROC*)glfwGetProcAddress("glPointParameterf"); + bindings->glPointParameterfv = (PFNGLPOINTPARAMETERFV_PROC*)glfwGetProcAddress("glPointParameterfv"); + bindings->glPointParameteri = (PFNGLPOINTPARAMETERI_PROC*)glfwGetProcAddress("glPointParameteri"); + bindings->glPointParameteriv = (PFNGLPOINTPARAMETERIV_PROC*)glfwGetProcAddress("glPointParameteriv"); + bindings->glBlendColor = (PFNGLBLENDCOLOR_PROC*)glfwGetProcAddress("glBlendColor"); + bindings->glBlendEquation = (PFNGLBLENDEQUATION_PROC*)glfwGetProcAddress("glBlendEquation"); + + /* GL_VERSION_1_5 */ + + bindings->glGenQueries = (PFNGLGENQUERIES_PROC*)glfwGetProcAddress("glGenQueries"); + bindings->glDeleteQueries = (PFNGLDELETEQUERIES_PROC*)glfwGetProcAddress("glDeleteQueries"); + bindings->glIsQuery = (PFNGLISQUERY_PROC*)glfwGetProcAddress("glIsQuery"); + bindings->glBeginQuery = (PFNGLBEGINQUERY_PROC*)glfwGetProcAddress("glBeginQuery"); + bindings->glEndQuery = (PFNGLENDQUERY_PROC*)glfwGetProcAddress("glEndQuery"); + bindings->glGetQueryiv = (PFNGLGETQUERYIV_PROC*)glfwGetProcAddress("glGetQueryiv"); + bindings->glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIV_PROC*)glfwGetProcAddress("glGetQueryObjectiv"); + bindings->glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIV_PROC*)glfwGetProcAddress("glGetQueryObjectuiv"); + bindings->glBindBuffer = (PFNGLBINDBUFFER_PROC*)glfwGetProcAddress("glBindBuffer"); + bindings->glDeleteBuffers = (PFNGLDELETEBUFFERS_PROC*)glfwGetProcAddress("glDeleteBuffers"); + bindings->glGenBuffers = (PFNGLGENBUFFERS_PROC*)glfwGetProcAddress("glGenBuffers"); + bindings->glIsBuffer = (PFNGLISBUFFER_PROC*)glfwGetProcAddress("glIsBuffer"); + bindings->glBufferData = (PFNGLBUFFERDATA_PROC*)glfwGetProcAddress("glBufferData"); + bindings->glBufferSubData = (PFNGLBUFFERSUBDATA_PROC*)glfwGetProcAddress("glBufferSubData"); + bindings->glGetBufferSubData = (PFNGLGETBUFFERSUBDATA_PROC*)glfwGetProcAddress("glGetBufferSubData"); + bindings->glMapBuffer = (PFNGLMAPBUFFER_PROC*)glfwGetProcAddress("glMapBuffer"); + bindings->glUnmapBuffer = (PFNGLUNMAPBUFFER_PROC*)glfwGetProcAddress("glUnmapBuffer"); + bindings->glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIV_PROC*)glfwGetProcAddress("glGetBufferParameteriv"); + bindings->glGetBufferPointerv = (PFNGLGETBUFFERPOINTERV_PROC*)glfwGetProcAddress("glGetBufferPointerv"); + + /* GL_VERSION_2_0 */ + + bindings->glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATE_PROC*)glfwGetProcAddress("glBlendEquationSeparate"); + bindings->glDrawBuffers = (PFNGLDRAWBUFFERS_PROC*)glfwGetProcAddress("glDrawBuffers"); + bindings->glStencilOpSeparate = (PFNGLSTENCILOPSEPARATE_PROC*)glfwGetProcAddress("glStencilOpSeparate"); + bindings->glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATE_PROC*)glfwGetProcAddress("glStencilFuncSeparate"); + bindings->glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATE_PROC*)glfwGetProcAddress("glStencilMaskSeparate"); + bindings->glAttachShader = (PFNGLATTACHSHADER_PROC*)glfwGetProcAddress("glAttachShader"); + bindings->glBindAttribLocation = (PFNGLBINDATTRIBLOCATION_PROC*)glfwGetProcAddress("glBindAttribLocation"); + bindings->glCompileShader = (PFNGLCOMPILESHADER_PROC*)glfwGetProcAddress("glCompileShader"); + bindings->glCreateProgram = (PFNGLCREATEPROGRAM_PROC*)glfwGetProcAddress("glCreateProgram"); + bindings->glCreateShader = (PFNGLCREATESHADER_PROC*)glfwGetProcAddress("glCreateShader"); + bindings->glDeleteProgram = (PFNGLDELETEPROGRAM_PROC*)glfwGetProcAddress("glDeleteProgram"); + bindings->glDeleteShader = (PFNGLDELETESHADER_PROC*)glfwGetProcAddress("glDeleteShader"); + bindings->glDetachShader = (PFNGLDETACHSHADER_PROC*)glfwGetProcAddress("glDetachShader"); + bindings->glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAY_PROC*)glfwGetProcAddress("glDisableVertexAttribArray"); + bindings->glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAY_PROC*)glfwGetProcAddress("glEnableVertexAttribArray"); + bindings->glGetActiveAttrib = (PFNGLGETACTIVEATTRIB_PROC*)glfwGetProcAddress("glGetActiveAttrib"); + bindings->glGetActiveUniform = (PFNGLGETACTIVEUNIFORM_PROC*)glfwGetProcAddress("glGetActiveUniform"); + bindings->glGetAttachedShaders = (PFNGLGETATTACHEDSHADERS_PROC*)glfwGetProcAddress("glGetAttachedShaders"); + bindings->glGetAttribLocation = (PFNGLGETATTRIBLOCATION_PROC*)glfwGetProcAddress("glGetAttribLocation"); + bindings->glGetProgramiv = (PFNGLGETPROGRAMIV_PROC*)glfwGetProcAddress("glGetProgramiv"); + bindings->glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOG_PROC*)glfwGetProcAddress("glGetProgramInfoLog"); + bindings->glGetShaderiv = (PFNGLGETSHADERIV_PROC*)glfwGetProcAddress("glGetShaderiv"); + bindings->glGetShaderInfoLog = (PFNGLGETSHADERINFOLOG_PROC*)glfwGetProcAddress("glGetShaderInfoLog"); + bindings->glGetShaderSource = (PFNGLGETSHADERSOURCE_PROC*)glfwGetProcAddress("glGetShaderSource"); + bindings->glGetUniformLocation = (PFNGLGETUNIFORMLOCATION_PROC*)glfwGetProcAddress("glGetUniformLocation"); + bindings->glGetUniformfv = (PFNGLGETUNIFORMFV_PROC*)glfwGetProcAddress("glGetUniformfv"); + bindings->glGetUniformiv = (PFNGLGETUNIFORMIV_PROC*)glfwGetProcAddress("glGetUniformiv"); + bindings->glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDV_PROC*)glfwGetProcAddress("glGetVertexAttribdv"); + bindings->glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFV_PROC*)glfwGetProcAddress("glGetVertexAttribfv"); + bindings->glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIV_PROC*)glfwGetProcAddress("glGetVertexAttribiv"); + bindings->glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERV_PROC*)glfwGetProcAddress("glGetVertexAttribPointerv"); + bindings->glIsProgram = (PFNGLISPROGRAM_PROC*)glfwGetProcAddress("glIsProgram"); + bindings->glIsShader = (PFNGLISSHADER_PROC*)glfwGetProcAddress("glIsShader"); + bindings->glLinkProgram = (PFNGLLINKPROGRAM_PROC*)glfwGetProcAddress("glLinkProgram"); + bindings->glShaderSource = (PFNGLSHADERSOURCE_PROC*)glfwGetProcAddress("glShaderSource"); + bindings->glUseProgram = (PFNGLUSEPROGRAM_PROC*)glfwGetProcAddress("glUseProgram"); + bindings->glUniform1f = (PFNGLUNIFORM1F_PROC*)glfwGetProcAddress("glUniform1f"); + bindings->glUniform2f = (PFNGLUNIFORM2F_PROC*)glfwGetProcAddress("glUniform2f"); + bindings->glUniform3f = (PFNGLUNIFORM3F_PROC*)glfwGetProcAddress("glUniform3f"); + bindings->glUniform4f = (PFNGLUNIFORM4F_PROC*)glfwGetProcAddress("glUniform4f"); + bindings->glUniform1i = (PFNGLUNIFORM1I_PROC*)glfwGetProcAddress("glUniform1i"); + bindings->glUniform2i = (PFNGLUNIFORM2I_PROC*)glfwGetProcAddress("glUniform2i"); + bindings->glUniform3i = (PFNGLUNIFORM3I_PROC*)glfwGetProcAddress("glUniform3i"); + bindings->glUniform4i = (PFNGLUNIFORM4I_PROC*)glfwGetProcAddress("glUniform4i"); + bindings->glUniform1fv = (PFNGLUNIFORM1FV_PROC*)glfwGetProcAddress("glUniform1fv"); + bindings->glUniform2fv = (PFNGLUNIFORM2FV_PROC*)glfwGetProcAddress("glUniform2fv"); + bindings->glUniform3fv = (PFNGLUNIFORM3FV_PROC*)glfwGetProcAddress("glUniform3fv"); + bindings->glUniform4fv = (PFNGLUNIFORM4FV_PROC*)glfwGetProcAddress("glUniform4fv"); + bindings->glUniform1iv = (PFNGLUNIFORM1IV_PROC*)glfwGetProcAddress("glUniform1iv"); + bindings->glUniform2iv = (PFNGLUNIFORM2IV_PROC*)glfwGetProcAddress("glUniform2iv"); + bindings->glUniform3iv = (PFNGLUNIFORM3IV_PROC*)glfwGetProcAddress("glUniform3iv"); + bindings->glUniform4iv = (PFNGLUNIFORM4IV_PROC*)glfwGetProcAddress("glUniform4iv"); + bindings->glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FV_PROC*)glfwGetProcAddress("glUniformMatrix2fv"); + bindings->glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FV_PROC*)glfwGetProcAddress("glUniformMatrix3fv"); + bindings->glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FV_PROC*)glfwGetProcAddress("glUniformMatrix4fv"); + bindings->glValidateProgram = (PFNGLVALIDATEPROGRAM_PROC*)glfwGetProcAddress("glValidateProgram"); + bindings->glVertexAttrib1d = (PFNGLVERTEXATTRIB1D_PROC*)glfwGetProcAddress("glVertexAttrib1d"); + bindings->glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DV_PROC*)glfwGetProcAddress("glVertexAttrib1dv"); + bindings->glVertexAttrib1f = (PFNGLVERTEXATTRIB1F_PROC*)glfwGetProcAddress("glVertexAttrib1f"); + bindings->glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FV_PROC*)glfwGetProcAddress("glVertexAttrib1fv"); + bindings->glVertexAttrib1s = (PFNGLVERTEXATTRIB1S_PROC*)glfwGetProcAddress("glVertexAttrib1s"); + bindings->glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SV_PROC*)glfwGetProcAddress("glVertexAttrib1sv"); + bindings->glVertexAttrib2d = (PFNGLVERTEXATTRIB2D_PROC*)glfwGetProcAddress("glVertexAttrib2d"); + bindings->glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DV_PROC*)glfwGetProcAddress("glVertexAttrib2dv"); + bindings->glVertexAttrib2f = (PFNGLVERTEXATTRIB2F_PROC*)glfwGetProcAddress("glVertexAttrib2f"); + bindings->glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FV_PROC*)glfwGetProcAddress("glVertexAttrib2fv"); + bindings->glVertexAttrib2s = (PFNGLVERTEXATTRIB2S_PROC*)glfwGetProcAddress("glVertexAttrib2s"); + bindings->glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SV_PROC*)glfwGetProcAddress("glVertexAttrib2sv"); + bindings->glVertexAttrib3d = (PFNGLVERTEXATTRIB3D_PROC*)glfwGetProcAddress("glVertexAttrib3d"); + bindings->glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DV_PROC*)glfwGetProcAddress("glVertexAttrib3dv"); + bindings->glVertexAttrib3f = (PFNGLVERTEXATTRIB3F_PROC*)glfwGetProcAddress("glVertexAttrib3f"); + bindings->glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FV_PROC*)glfwGetProcAddress("glVertexAttrib3fv"); + bindings->glVertexAttrib3s = (PFNGLVERTEXATTRIB3S_PROC*)glfwGetProcAddress("glVertexAttrib3s"); + bindings->glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SV_PROC*)glfwGetProcAddress("glVertexAttrib3sv"); + bindings->glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBV_PROC*)glfwGetProcAddress("glVertexAttrib4Nbv"); + bindings->glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIV_PROC*)glfwGetProcAddress("glVertexAttrib4Niv"); + bindings->glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSV_PROC*)glfwGetProcAddress("glVertexAttrib4Nsv"); + bindings->glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUB_PROC*)glfwGetProcAddress("glVertexAttrib4Nub"); + bindings->glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBV_PROC*)glfwGetProcAddress("glVertexAttrib4Nubv"); + bindings->glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIV_PROC*)glfwGetProcAddress("glVertexAttrib4Nuiv"); + bindings->glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSV_PROC*)glfwGetProcAddress("glVertexAttrib4Nusv"); + bindings->glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BV_PROC*)glfwGetProcAddress("glVertexAttrib4bv"); + bindings->glVertexAttrib4d = (PFNGLVERTEXATTRIB4D_PROC*)glfwGetProcAddress("glVertexAttrib4d"); + bindings->glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DV_PROC*)glfwGetProcAddress("glVertexAttrib4dv"); + bindings->glVertexAttrib4f = (PFNGLVERTEXATTRIB4F_PROC*)glfwGetProcAddress("glVertexAttrib4f"); + bindings->glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FV_PROC*)glfwGetProcAddress("glVertexAttrib4fv"); + bindings->glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IV_PROC*)glfwGetProcAddress("glVertexAttrib4iv"); + bindings->glVertexAttrib4s = (PFNGLVERTEXATTRIB4S_PROC*)glfwGetProcAddress("glVertexAttrib4s"); + bindings->glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SV_PROC*)glfwGetProcAddress("glVertexAttrib4sv"); + bindings->glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBV_PROC*)glfwGetProcAddress("glVertexAttrib4ubv"); + bindings->glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIV_PROC*)glfwGetProcAddress("glVertexAttrib4uiv"); + bindings->glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USV_PROC*)glfwGetProcAddress("glVertexAttrib4usv"); + bindings->glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTER_PROC*)glfwGetProcAddress("glVertexAttribPointer"); + + /* GL_VERSION_2_1 */ + + bindings->glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FV_PROC*)glfwGetProcAddress("glUniformMatrix2x3fv"); + bindings->glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FV_PROC*)glfwGetProcAddress("glUniformMatrix3x2fv"); + bindings->glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FV_PROC*)glfwGetProcAddress("glUniformMatrix2x4fv"); + bindings->glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FV_PROC*)glfwGetProcAddress("glUniformMatrix4x2fv"); + bindings->glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FV_PROC*)glfwGetProcAddress("glUniformMatrix3x4fv"); + bindings->glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FV_PROC*)glfwGetProcAddress("glUniformMatrix4x3fv"); + + /* GL_VERSION_3_0 */ + + bindings->glColorMaski = (PFNGLCOLORMASKI_PROC*)glfwGetProcAddress("glColorMaski"); + bindings->glGetBooleani_v = (PFNGLGETBOOLEANI_V_PROC*)glfwGetProcAddress("glGetBooleani_v"); + bindings->glGetIntegeri_v = (PFNGLGETINTEGERI_V_PROC*)glfwGetProcAddress("glGetIntegeri_v"); + bindings->glEnablei = (PFNGLENABLEI_PROC*)glfwGetProcAddress("glEnablei"); + bindings->glDisablei = (PFNGLDISABLEI_PROC*)glfwGetProcAddress("glDisablei"); + bindings->glIsEnabledi = (PFNGLISENABLEDI_PROC*)glfwGetProcAddress("glIsEnabledi"); + bindings->glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACK_PROC*)glfwGetProcAddress("glBeginTransformFeedback"); + bindings->glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACK_PROC*)glfwGetProcAddress("glEndTransformFeedback"); + bindings->glBindBufferRange = (PFNGLBINDBUFFERRANGE_PROC*)glfwGetProcAddress("glBindBufferRange"); + bindings->glBindBufferBase = (PFNGLBINDBUFFERBASE_PROC*)glfwGetProcAddress("glBindBufferBase"); + bindings->glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGS_PROC*)glfwGetProcAddress("glTransformFeedbackVaryings"); + bindings->glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYING_PROC*)glfwGetProcAddress("glGetTransformFeedbackVarying"); + bindings->glClampColor = (PFNGLCLAMPCOLOR_PROC*)glfwGetProcAddress("glClampColor"); + bindings->glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDER_PROC*)glfwGetProcAddress("glBeginConditionalRender"); + bindings->glEndConditionalRender = (PFNGLENDCONDITIONALRENDER_PROC*)glfwGetProcAddress("glEndConditionalRender"); + bindings->glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTER_PROC*)glfwGetProcAddress("glVertexAttribIPointer"); + bindings->glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIV_PROC*)glfwGetProcAddress("glGetVertexAttribIiv"); + bindings->glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIV_PROC*)glfwGetProcAddress("glGetVertexAttribIuiv"); + bindings->glVertexAttribI1i = (PFNGLVERTEXATTRIBI1I_PROC*)glfwGetProcAddress("glVertexAttribI1i"); + bindings->glVertexAttribI2i = (PFNGLVERTEXATTRIBI2I_PROC*)glfwGetProcAddress("glVertexAttribI2i"); + bindings->glVertexAttribI3i = (PFNGLVERTEXATTRIBI3I_PROC*)glfwGetProcAddress("glVertexAttribI3i"); + bindings->glVertexAttribI4i = (PFNGLVERTEXATTRIBI4I_PROC*)glfwGetProcAddress("glVertexAttribI4i"); + bindings->glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UI_PROC*)glfwGetProcAddress("glVertexAttribI1ui"); + bindings->glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UI_PROC*)glfwGetProcAddress("glVertexAttribI2ui"); + bindings->glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UI_PROC*)glfwGetProcAddress("glVertexAttribI3ui"); + bindings->glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UI_PROC*)glfwGetProcAddress("glVertexAttribI4ui"); + bindings->glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IV_PROC*)glfwGetProcAddress("glVertexAttribI1iv"); + bindings->glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IV_PROC*)glfwGetProcAddress("glVertexAttribI2iv"); + bindings->glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IV_PROC*)glfwGetProcAddress("glVertexAttribI3iv"); + bindings->glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IV_PROC*)glfwGetProcAddress("glVertexAttribI4iv"); + bindings->glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIV_PROC*)glfwGetProcAddress("glVertexAttribI1uiv"); + bindings->glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIV_PROC*)glfwGetProcAddress("glVertexAttribI2uiv"); + bindings->glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIV_PROC*)glfwGetProcAddress("glVertexAttribI3uiv"); + bindings->glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIV_PROC*)glfwGetProcAddress("glVertexAttribI4uiv"); + bindings->glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BV_PROC*)glfwGetProcAddress("glVertexAttribI4bv"); + bindings->glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SV_PROC*)glfwGetProcAddress("glVertexAttribI4sv"); + bindings->glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBV_PROC*)glfwGetProcAddress("glVertexAttribI4ubv"); + bindings->glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USV_PROC*)glfwGetProcAddress("glVertexAttribI4usv"); + bindings->glGetUniformuiv = (PFNGLGETUNIFORMUIV_PROC*)glfwGetProcAddress("glGetUniformuiv"); + bindings->glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATION_PROC*)glfwGetProcAddress("glBindFragDataLocation"); + bindings->glGetFragDataLocation = (PFNGLGETFRAGDATALOCATION_PROC*)glfwGetProcAddress("glGetFragDataLocation"); + bindings->glUniform1ui = (PFNGLUNIFORM1UI_PROC*)glfwGetProcAddress("glUniform1ui"); + bindings->glUniform2ui = (PFNGLUNIFORM2UI_PROC*)glfwGetProcAddress("glUniform2ui"); + bindings->glUniform3ui = (PFNGLUNIFORM3UI_PROC*)glfwGetProcAddress("glUniform3ui"); + bindings->glUniform4ui = (PFNGLUNIFORM4UI_PROC*)glfwGetProcAddress("glUniform4ui"); + bindings->glUniform1uiv = (PFNGLUNIFORM1UIV_PROC*)glfwGetProcAddress("glUniform1uiv"); + bindings->glUniform2uiv = (PFNGLUNIFORM2UIV_PROC*)glfwGetProcAddress("glUniform2uiv"); + bindings->glUniform3uiv = (PFNGLUNIFORM3UIV_PROC*)glfwGetProcAddress("glUniform3uiv"); + bindings->glUniform4uiv = (PFNGLUNIFORM4UIV_PROC*)glfwGetProcAddress("glUniform4uiv"); + bindings->glTexParameterIiv = (PFNGLTEXPARAMETERIIV_PROC*)glfwGetProcAddress("glTexParameterIiv"); + bindings->glTexParameterIuiv = (PFNGLTEXPARAMETERIUIV_PROC*)glfwGetProcAddress("glTexParameterIuiv"); + bindings->glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIV_PROC*)glfwGetProcAddress("glGetTexParameterIiv"); + bindings->glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIV_PROC*)glfwGetProcAddress("glGetTexParameterIuiv"); + bindings->glClearBufferiv = (PFNGLCLEARBUFFERIV_PROC*)glfwGetProcAddress("glClearBufferiv"); + bindings->glClearBufferuiv = (PFNGLCLEARBUFFERUIV_PROC*)glfwGetProcAddress("glClearBufferuiv"); + bindings->glClearBufferfv = (PFNGLCLEARBUFFERFV_PROC*)glfwGetProcAddress("glClearBufferfv"); + bindings->glClearBufferfi = (PFNGLCLEARBUFFERFI_PROC*)glfwGetProcAddress("glClearBufferfi"); + bindings->glGetStringi = (PFNGLGETSTRINGI_PROC*)glfwGetProcAddress("glGetStringi"); + bindings->glIsRenderbuffer = (PFNGLISRENDERBUFFER_PROC*)glfwGetProcAddress("glIsRenderbuffer"); + bindings->glBindRenderbuffer = (PFNGLBINDRENDERBUFFER_PROC*)glfwGetProcAddress("glBindRenderbuffer"); + bindings->glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERS_PROC*)glfwGetProcAddress("glDeleteRenderbuffers"); + bindings->glGenRenderbuffers = (PFNGLGENRENDERBUFFERS_PROC*)glfwGetProcAddress("glGenRenderbuffers"); + bindings->glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGE_PROC*)glfwGetProcAddress("glRenderbufferStorage"); + bindings->glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIV_PROC*)glfwGetProcAddress("glGetRenderbufferParameteriv"); + bindings->glIsFramebuffer = (PFNGLISFRAMEBUFFER_PROC*)glfwGetProcAddress("glIsFramebuffer"); + bindings->glBindFramebuffer = (PFNGLBINDFRAMEBUFFER_PROC*)glfwGetProcAddress("glBindFramebuffer"); + bindings->glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERS_PROC*)glfwGetProcAddress("glDeleteFramebuffers"); + bindings->glGenFramebuffers = (PFNGLGENFRAMEBUFFERS_PROC*)glfwGetProcAddress("glGenFramebuffers"); + bindings->glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUS_PROC*)glfwGetProcAddress("glCheckFramebufferStatus"); + bindings->glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1D_PROC*)glfwGetProcAddress("glFramebufferTexture1D"); + bindings->glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2D_PROC*)glfwGetProcAddress("glFramebufferTexture2D"); + bindings->glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3D_PROC*)glfwGetProcAddress("glFramebufferTexture3D"); + bindings->glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFER_PROC*)glfwGetProcAddress("glFramebufferRenderbuffer"); + bindings->glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC*)glfwGetProcAddress("glGetFramebufferAttachmentParameteriv"); + bindings->glGenerateMipmap = (PFNGLGENERATEMIPMAP_PROC*)glfwGetProcAddress("glGenerateMipmap"); + bindings->glBlitFramebuffer = (PFNGLBLITFRAMEBUFFER_PROC*)glfwGetProcAddress("glBlitFramebuffer"); + bindings->glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC*)glfwGetProcAddress("glRenderbufferStorageMultisample"); + bindings->glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYER_PROC*)glfwGetProcAddress("glFramebufferTextureLayer"); + bindings->glMapBufferRange = (PFNGLMAPBUFFERRANGE_PROC*)glfwGetProcAddress("glMapBufferRange"); + bindings->glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGE_PROC*)glfwGetProcAddress("glFlushMappedBufferRange"); + bindings->glBindVertexArray = (PFNGLBINDVERTEXARRAY_PROC*)glfwGetProcAddress("glBindVertexArray"); + bindings->glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYS_PROC*)glfwGetProcAddress("glDeleteVertexArrays"); + bindings->glGenVertexArrays = (PFNGLGENVERTEXARRAYS_PROC*)glfwGetProcAddress("glGenVertexArrays"); + bindings->glIsVertexArray = (PFNGLISVERTEXARRAY_PROC*)glfwGetProcAddress("glIsVertexArray"); + + /* GL_VERSION_3_1 */ + + bindings->glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCED_PROC*)glfwGetProcAddress("glDrawArraysInstanced"); + bindings->glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCED_PROC*)glfwGetProcAddress("glDrawElementsInstanced"); + bindings->glTexBuffer = (PFNGLTEXBUFFER_PROC*)glfwGetProcAddress("glTexBuffer"); + bindings->glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEX_PROC*)glfwGetProcAddress("glPrimitiveRestartIndex"); + bindings->glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATA_PROC*)glfwGetProcAddress("glCopyBufferSubData"); + bindings->glGetUniformIndices = (PFNGLGETUNIFORMINDICES_PROC*)glfwGetProcAddress("glGetUniformIndices"); + bindings->glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIV_PROC*)glfwGetProcAddress("glGetActiveUniformsiv"); + bindings->glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAME_PROC*)glfwGetProcAddress("glGetActiveUniformName"); + bindings->glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEX_PROC*)glfwGetProcAddress("glGetUniformBlockIndex"); + bindings->glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIV_PROC*)glfwGetProcAddress("glGetActiveUniformBlockiv"); + bindings->glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC*)glfwGetProcAddress("glGetActiveUniformBlockName"); + bindings->glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDING_PROC*)glfwGetProcAddress("glUniformBlockBinding"); + +} + +/* ----------------------- Extension flag definitions ---------------------- */ + +#ifdef __cplusplus +} +#endif diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.h new file mode 100644 index 0000000..807d742 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/flextGL.h @@ -0,0 +1,1463 @@ +#ifndef __gl_h_ +#define __gl_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Function declaration macros - to move into glplatform.h */ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#ifndef WINAPI +#define WINAPI __stdcall +#endif +#define APIENTRY WINAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/* -------------------------------- DATA TYPES ------------------------------- */ + +#include +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glxext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GL_EXT_timer_query extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef signed char GLbyte; +typedef short GLshort; +typedef int GLint; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef int GLsizei; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef char GLchar; +typedef unsigned short GLhalf; +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +/* ----------------------------------- ENUMS --------------------------------- */ + +/* GL_VERSION_1_1 */ + +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_VIEWPORT 0x0BA2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_DOUBLE 0x140A +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_REPEAT 0x2901 +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B + +/* GL_VERSION_1_2 */ + +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +/* GL_VERSION_1_3 */ + +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D + +/* GL_VERSION_1_4 */ + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 + +/* GL_VERSION_1_5 */ + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 + +/* GL_VERSION_2_0 */ + +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +/* GL_VERSION_2_1 */ + +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 + +/* GL_VERSION_3_0 */ + +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 + +/* GL_VERSION_3_1 */ + +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu + +/* --------------------------- FUNCTION PROTOTYPES --------------------------- */ + + +/* GL_VERSION_1_0 */ + +GLAPI void APIENTRY glCullFace (GLenum mode); +GLAPI void APIENTRY glFrontFace (GLenum mode); +GLAPI void APIENTRY glHint (GLenum target, GLenum mode); +GLAPI void APIENTRY glLineWidth (GLfloat width); +GLAPI void APIENTRY glPointSize (GLfloat size); +GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); +GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GLAPI void APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat * params); +GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint * params); +GLAPI void APIENTRY glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glDrawBuffer (GLenum buf); +GLAPI void APIENTRY glClear (GLbitfield mask); +GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI void APIENTRY glClearStencil (GLint s); +GLAPI void APIENTRY glClearDepth (GLdouble depth); +GLAPI void APIENTRY glStencilMask (GLuint mask); +GLAPI void APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI void APIENTRY glDepthMask (GLboolean flag); +GLAPI void APIENTRY glDisable (GLenum cap); +GLAPI void APIENTRY glEnable (GLenum cap); +GLAPI void APIENTRY glFinish (void); +GLAPI void APIENTRY glFlush (void); +GLAPI void APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GLAPI void APIENTRY glLogicOp (GLenum opcode); +GLAPI void APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GLAPI void APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GLAPI void APIENTRY glDepthFunc (GLenum func); +GLAPI void APIENTRY glPixelStoref (GLenum pname, GLfloat param); +GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); +GLAPI void APIENTRY glReadBuffer (GLenum src); +GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +GLAPI void APIENTRY glGetBooleanv (GLenum pname, GLboolean * data); +GLAPI void APIENTRY glGetDoublev (GLenum pname, GLdouble * data); +GLAPI GLenum APIENTRY glGetError (void); +GLAPI void APIENTRY glGetFloatv (GLenum pname, GLfloat * data); +GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint * data); +GLAPI const GLubyte * APIENTRY glGetString (GLenum name); +GLAPI void APIENTRY glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +GLAPI void APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat * params); +GLAPI void APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint * params); +GLAPI void APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat * params); +GLAPI void APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint * params); +GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); +GLAPI void APIENTRY glDepthRange (GLdouble near, GLdouble far); +GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +/* GL_VERSION_1_1 */ + +GLAPI void APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void * indices); +GLAPI void APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GLAPI void APIENTRY glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI void APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI void APIENTRY glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI void APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); +GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint * textures); +GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint * textures); +GLAPI GLboolean APIENTRY glIsTexture (GLuint texture); + + +/* GL_VERSION_1_2 */ + +typedef void (APIENTRY PFNGLDRAWRANGEELEMENTS_PROC (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices)); +typedef void (APIENTRY PFNGLTEXIMAGE3D_PROC (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels)); +typedef void (APIENTRY PFNGLTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels)); +typedef void (APIENTRY PFNGLCOPYTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)); + +/* GL_VERSION_1_3 */ + +typedef void (APIENTRY PFNGLACTIVETEXTURE_PROC (GLenum texture)); +typedef void (APIENTRY PFNGLSAMPLECOVERAGE_PROC (GLfloat value, GLboolean invert)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE3D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE2D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXIMAGE1D_PROC (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data)); +typedef void (APIENTRY PFNGLGETCOMPRESSEDTEXIMAGE_PROC (GLenum target, GLint level, void * img)); + +/* GL_VERSION_1_4 */ + +typedef void (APIENTRY PFNGLBLENDFUNCSEPARATE_PROC (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)); +typedef void (APIENTRY PFNGLMULTIDRAWARRAYS_PROC (GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount)); +typedef void (APIENTRY PFNGLMULTIDRAWELEMENTS_PROC (GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount)); +typedef void (APIENTRY PFNGLPOINTPARAMETERF_PROC (GLenum pname, GLfloat param)); +typedef void (APIENTRY PFNGLPOINTPARAMETERFV_PROC (GLenum pname, const GLfloat * params)); +typedef void (APIENTRY PFNGLPOINTPARAMETERI_PROC (GLenum pname, GLint param)); +typedef void (APIENTRY PFNGLPOINTPARAMETERIV_PROC (GLenum pname, const GLint * params)); +typedef void (APIENTRY PFNGLBLENDCOLOR_PROC (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)); +typedef void (APIENTRY PFNGLBLENDEQUATION_PROC (GLenum mode)); + +/* GL_VERSION_1_5 */ + +typedef void (APIENTRY PFNGLGENQUERIES_PROC (GLsizei n, GLuint * ids)); +typedef void (APIENTRY PFNGLDELETEQUERIES_PROC (GLsizei n, const GLuint * ids)); +typedef GLboolean (APIENTRY PFNGLISQUERY_PROC (GLuint id)); +typedef void (APIENTRY PFNGLBEGINQUERY_PROC (GLenum target, GLuint id)); +typedef void (APIENTRY PFNGLENDQUERY_PROC (GLenum target)); +typedef void (APIENTRY PFNGLGETQUERYIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTIV_PROC (GLuint id, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETQUERYOBJECTUIV_PROC (GLuint id, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLBINDBUFFER_PROC (GLenum target, GLuint buffer)); +typedef void (APIENTRY PFNGLDELETEBUFFERS_PROC (GLsizei n, const GLuint * buffers)); +typedef void (APIENTRY PFNGLGENBUFFERS_PROC (GLsizei n, GLuint * buffers)); +typedef GLboolean (APIENTRY PFNGLISBUFFER_PROC (GLuint buffer)); +typedef void (APIENTRY PFNGLBUFFERDATA_PROC (GLenum target, GLsizeiptr size, const void * data, GLenum usage)); +typedef void (APIENTRY PFNGLBUFFERSUBDATA_PROC (GLenum target, GLintptr offset, GLsizeiptr size, const void * data)); +typedef void (APIENTRY PFNGLGETBUFFERSUBDATA_PROC (GLenum target, GLintptr offset, GLsizeiptr size, void * data)); +typedef void * (APIENTRY PFNGLMAPBUFFER_PROC (GLenum target, GLenum access)); +typedef GLboolean (APIENTRY PFNGLUNMAPBUFFER_PROC (GLenum target)); +typedef void (APIENTRY PFNGLGETBUFFERPARAMETERIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETBUFFERPOINTERV_PROC (GLenum target, GLenum pname, void ** params)); + +/* GL_VERSION_2_0 */ + +typedef void (APIENTRY PFNGLBLENDEQUATIONSEPARATE_PROC (GLenum modeRGB, GLenum modeAlpha)); +typedef void (APIENTRY PFNGLDRAWBUFFERS_PROC (GLsizei n, const GLenum * bufs)); +typedef void (APIENTRY PFNGLSTENCILOPSEPARATE_PROC (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)); +typedef void (APIENTRY PFNGLSTENCILFUNCSEPARATE_PROC (GLenum face, GLenum func, GLint ref, GLuint mask)); +typedef void (APIENTRY PFNGLSTENCILMASKSEPARATE_PROC (GLenum face, GLuint mask)); +typedef void (APIENTRY PFNGLATTACHSHADER_PROC (GLuint program, GLuint shader)); +typedef void (APIENTRY PFNGLBINDATTRIBLOCATION_PROC (GLuint program, GLuint index, const GLchar * name)); +typedef void (APIENTRY PFNGLCOMPILESHADER_PROC (GLuint shader)); +typedef GLuint (APIENTRY PFNGLCREATEPROGRAM_PROC (void)); +typedef GLuint (APIENTRY PFNGLCREATESHADER_PROC (GLenum type)); +typedef void (APIENTRY PFNGLDELETEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLDELETESHADER_PROC (GLuint shader)); +typedef void (APIENTRY PFNGLDETACHSHADER_PROC (GLuint program, GLuint shader)); +typedef void (APIENTRY PFNGLDISABLEVERTEXATTRIBARRAY_PROC (GLuint index)); +typedef void (APIENTRY PFNGLENABLEVERTEXATTRIBARRAY_PROC (GLuint index)); +typedef void (APIENTRY PFNGLGETACTIVEATTRIB_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORM_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLGETATTACHEDSHADERS_PROC (GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders)); +typedef GLint (APIENTRY PFNGLGETATTRIBLOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGETPROGRAMIV_PROC (GLuint program, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETPROGRAMINFOLOG_PROC (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog)); +typedef void (APIENTRY PFNGLGETSHADERIV_PROC (GLuint shader, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETSHADERINFOLOG_PROC (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog)); +typedef void (APIENTRY PFNGLGETSHADERSOURCE_PROC (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source)); +typedef GLint (APIENTRY PFNGLGETUNIFORMLOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLGETUNIFORMFV_PROC (GLuint program, GLint location, GLfloat * params)); +typedef void (APIENTRY PFNGLGETUNIFORMIV_PROC (GLuint program, GLint location, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBDV_PROC (GLuint index, GLenum pname, GLdouble * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBFV_PROC (GLuint index, GLenum pname, GLfloat * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIV_PROC (GLuint index, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBPOINTERV_PROC (GLuint index, GLenum pname, void ** pointer)); +typedef GLboolean (APIENTRY PFNGLISPROGRAM_PROC (GLuint program)); +typedef GLboolean (APIENTRY PFNGLISSHADER_PROC (GLuint shader)); +typedef void (APIENTRY PFNGLLINKPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLSHADERSOURCE_PROC (GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length)); +typedef void (APIENTRY PFNGLUSEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLUNIFORM1F_PROC (GLint location, GLfloat v0)); +typedef void (APIENTRY PFNGLUNIFORM2F_PROC (GLint location, GLfloat v0, GLfloat v1)); +typedef void (APIENTRY PFNGLUNIFORM3F_PROC (GLint location, GLfloat v0, GLfloat v1, GLfloat v2)); +typedef void (APIENTRY PFNGLUNIFORM4F_PROC (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)); +typedef void (APIENTRY PFNGLUNIFORM1I_PROC (GLint location, GLint v0)); +typedef void (APIENTRY PFNGLUNIFORM2I_PROC (GLint location, GLint v0, GLint v1)); +typedef void (APIENTRY PFNGLUNIFORM3I_PROC (GLint location, GLint v0, GLint v1, GLint v2)); +typedef void (APIENTRY PFNGLUNIFORM4I_PROC (GLint location, GLint v0, GLint v1, GLint v2, GLint v3)); +typedef void (APIENTRY PFNGLUNIFORM1FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM2FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM3FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM4FV_PROC (GLint location, GLsizei count, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORM1IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM2IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM3IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORM4IV_PROC (GLint location, GLsizei count, const GLint * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLVALIDATEPROGRAM_PROC (GLuint program)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1D_PROC (GLuint index, GLdouble x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1F_PROC (GLuint index, GLfloat x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1S_PROC (GLuint index, GLshort x)); +typedef void (APIENTRY PFNGLVERTEXATTRIB1SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2D_PROC (GLuint index, GLdouble x, GLdouble y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2F_PROC (GLuint index, GLfloat x, GLfloat y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2S_PROC (GLuint index, GLshort x, GLshort y)); +typedef void (APIENTRY PFNGLVERTEXATTRIB2SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3D_PROC (GLuint index, GLdouble x, GLdouble y, GLdouble z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3F_PROC (GLuint index, GLfloat x, GLfloat y, GLfloat z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3S_PROC (GLuint index, GLshort x, GLshort y, GLshort z)); +typedef void (APIENTRY PFNGLVERTEXATTRIB3SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NBV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NIV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NSV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUB_PROC (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4NUSV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4BV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4D_PROC (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4DV_PROC (GLuint index, const GLdouble * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4F_PROC (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4FV_PROC (GLuint index, const GLfloat * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4S_PROC (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4UBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIB4USV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBPOINTER_PROC (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)); + +/* GL_VERSION_2_1 */ + +typedef void (APIENTRY PFNGLUNIFORMMATRIX2X3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3X2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX2X4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4X2FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX3X4FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); +typedef void (APIENTRY PFNGLUNIFORMMATRIX4X3FV_PROC (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)); + +/* GL_VERSION_3_0 */ + +typedef void (APIENTRY PFNGLCOLORMASKI_PROC (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)); +typedef void (APIENTRY PFNGLGETBOOLEANI_V_PROC (GLenum target, GLuint index, GLboolean * data)); +typedef void (APIENTRY PFNGLGETINTEGERI_V_PROC (GLenum target, GLuint index, GLint * data)); +typedef void (APIENTRY PFNGLENABLEI_PROC (GLenum target, GLuint index)); +typedef void (APIENTRY PFNGLDISABLEI_PROC (GLenum target, GLuint index)); +typedef GLboolean (APIENTRY PFNGLISENABLEDI_PROC (GLenum target, GLuint index)); +typedef void (APIENTRY PFNGLBEGINTRANSFORMFEEDBACK_PROC (GLenum primitiveMode)); +typedef void (APIENTRY PFNGLENDTRANSFORMFEEDBACK_PROC (void)); +typedef void (APIENTRY PFNGLBINDBUFFERRANGE_PROC (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)); +typedef void (APIENTRY PFNGLBINDBUFFERBASE_PROC (GLenum target, GLuint index, GLuint buffer)); +typedef void (APIENTRY PFNGLTRANSFORMFEEDBACKVARYINGS_PROC (GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode)); +typedef void (APIENTRY PFNGLGETTRANSFORMFEEDBACKVARYING_PROC (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name)); +typedef void (APIENTRY PFNGLCLAMPCOLOR_PROC (GLenum target, GLenum clamp)); +typedef void (APIENTRY PFNGLBEGINCONDITIONALRENDER_PROC (GLuint id, GLenum mode)); +typedef void (APIENTRY PFNGLENDCONDITIONALRENDER_PROC (void)); +typedef void (APIENTRY PFNGLVERTEXATTRIBIPOINTER_PROC (GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIIV_PROC (GLuint index, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETVERTEXATTRIBIUIV_PROC (GLuint index, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1I_PROC (GLuint index, GLint x)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2I_PROC (GLuint index, GLint x, GLint y)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3I_PROC (GLuint index, GLint x, GLint y, GLint z)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4I_PROC (GLuint index, GLint x, GLint y, GLint z, GLint w)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1UI_PROC (GLuint index, GLuint x)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2UI_PROC (GLuint index, GLuint x, GLuint y)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3UI_PROC (GLuint index, GLuint x, GLuint y, GLuint z)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UI_PROC (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4IV_PROC (GLuint index, const GLint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI1UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI2UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI3UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UIV_PROC (GLuint index, const GLuint * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4BV_PROC (GLuint index, const GLbyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4SV_PROC (GLuint index, const GLshort * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4UBV_PROC (GLuint index, const GLubyte * v)); +typedef void (APIENTRY PFNGLVERTEXATTRIBI4USV_PROC (GLuint index, const GLushort * v)); +typedef void (APIENTRY PFNGLGETUNIFORMUIV_PROC (GLuint program, GLint location, GLuint * params)); +typedef void (APIENTRY PFNGLBINDFRAGDATALOCATION_PROC (GLuint program, GLuint color, const GLchar * name)); +typedef GLint (APIENTRY PFNGLGETFRAGDATALOCATION_PROC (GLuint program, const GLchar * name)); +typedef void (APIENTRY PFNGLUNIFORM1UI_PROC (GLint location, GLuint v0)); +typedef void (APIENTRY PFNGLUNIFORM2UI_PROC (GLint location, GLuint v0, GLuint v1)); +typedef void (APIENTRY PFNGLUNIFORM3UI_PROC (GLint location, GLuint v0, GLuint v1, GLuint v2)); +typedef void (APIENTRY PFNGLUNIFORM4UI_PROC (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)); +typedef void (APIENTRY PFNGLUNIFORM1UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM2UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM3UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLUNIFORM4UIV_PROC (GLint location, GLsizei count, const GLuint * value)); +typedef void (APIENTRY PFNGLTEXPARAMETERIIV_PROC (GLenum target, GLenum pname, const GLint * params)); +typedef void (APIENTRY PFNGLTEXPARAMETERIUIV_PROC (GLenum target, GLenum pname, const GLuint * params)); +typedef void (APIENTRY PFNGLGETTEXPARAMETERIIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETTEXPARAMETERIUIV_PROC (GLenum target, GLenum pname, GLuint * params)); +typedef void (APIENTRY PFNGLCLEARBUFFERIV_PROC (GLenum buffer, GLint drawbuffer, const GLint * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERUIV_PROC (GLenum buffer, GLint drawbuffer, const GLuint * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERFV_PROC (GLenum buffer, GLint drawbuffer, const GLfloat * value)); +typedef void (APIENTRY PFNGLCLEARBUFFERFI_PROC (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)); +typedef const GLubyte * (APIENTRY PFNGLGETSTRINGI_PROC (GLenum name, GLuint index)); +typedef GLboolean (APIENTRY PFNGLISRENDERBUFFER_PROC (GLuint renderbuffer)); +typedef void (APIENTRY PFNGLBINDRENDERBUFFER_PROC (GLenum target, GLuint renderbuffer)); +typedef void (APIENTRY PFNGLDELETERENDERBUFFERS_PROC (GLsizei n, const GLuint * renderbuffers)); +typedef void (APIENTRY PFNGLGENRENDERBUFFERS_PROC (GLsizei n, GLuint * renderbuffers)); +typedef void (APIENTRY PFNGLRENDERBUFFERSTORAGE_PROC (GLenum target, GLenum internalformat, GLsizei width, GLsizei height)); +typedef void (APIENTRY PFNGLGETRENDERBUFFERPARAMETERIV_PROC (GLenum target, GLenum pname, GLint * params)); +typedef GLboolean (APIENTRY PFNGLISFRAMEBUFFER_PROC (GLuint framebuffer)); +typedef void (APIENTRY PFNGLBINDFRAMEBUFFER_PROC (GLenum target, GLuint framebuffer)); +typedef void (APIENTRY PFNGLDELETEFRAMEBUFFERS_PROC (GLsizei n, const GLuint * framebuffers)); +typedef void (APIENTRY PFNGLGENFRAMEBUFFERS_PROC (GLsizei n, GLuint * framebuffers)); +typedef GLenum (APIENTRY PFNGLCHECKFRAMEBUFFERSTATUS_PROC (GLenum target)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE1D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE2D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURE3D_PROC (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)); +typedef void (APIENTRY PFNGLFRAMEBUFFERRENDERBUFFER_PROC (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)); +typedef void (APIENTRY PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC (GLenum target, GLenum attachment, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGENERATEMIPMAP_PROC (GLenum target)); +typedef void (APIENTRY PFNGLBLITFRAMEBUFFER_PROC (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)); +typedef void (APIENTRY PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)); +typedef void (APIENTRY PFNGLFRAMEBUFFERTEXTURELAYER_PROC (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)); +typedef void * (APIENTRY PFNGLMAPBUFFERRANGE_PROC (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)); +typedef void (APIENTRY PFNGLFLUSHMAPPEDBUFFERRANGE_PROC (GLenum target, GLintptr offset, GLsizeiptr length)); +typedef void (APIENTRY PFNGLBINDVERTEXARRAY_PROC (GLuint array)); +typedef void (APIENTRY PFNGLDELETEVERTEXARRAYS_PROC (GLsizei n, const GLuint * arrays)); +typedef void (APIENTRY PFNGLGENVERTEXARRAYS_PROC (GLsizei n, GLuint * arrays)); +typedef GLboolean (APIENTRY PFNGLISVERTEXARRAY_PROC (GLuint array)); + +/* GL_VERSION_3_1 */ + +typedef void (APIENTRY PFNGLDRAWARRAYSINSTANCED_PROC (GLenum mode, GLint first, GLsizei count, GLsizei instancecount)); +typedef void (APIENTRY PFNGLDRAWELEMENTSINSTANCED_PROC (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount)); +typedef void (APIENTRY PFNGLTEXBUFFER_PROC (GLenum target, GLenum internalformat, GLuint buffer)); +typedef void (APIENTRY PFNGLPRIMITIVERESTARTINDEX_PROC (GLuint index)); +typedef void (APIENTRY PFNGLCOPYBUFFERSUBDATA_PROC (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)); +typedef void (APIENTRY PFNGLGETUNIFORMINDICES_PROC (GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMSIV_PROC (GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMNAME_PROC (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName)); +typedef GLuint (APIENTRY PFNGLGETUNIFORMBLOCKINDEX_PROC (GLuint program, const GLchar * uniformBlockName)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMBLOCKIV_PROC (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params)); +typedef void (APIENTRY PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName)); +typedef void (APIENTRY PFNGLUNIFORMBLOCKBINDING_PROC (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)); + +struct OpenGLBindings +{ + + /* GL_VERSION_1_2 */ + + PFNGLDRAWRANGEELEMENTS_PROC* glDrawRangeElements; + PFNGLTEXIMAGE3D_PROC* glTexImage3D; + PFNGLTEXSUBIMAGE3D_PROC* glTexSubImage3D; + PFNGLCOPYTEXSUBIMAGE3D_PROC* glCopyTexSubImage3D; + + /* GL_VERSION_1_3 */ + + PFNGLACTIVETEXTURE_PROC* glActiveTexture; + PFNGLSAMPLECOVERAGE_PROC* glSampleCoverage; + PFNGLCOMPRESSEDTEXIMAGE3D_PROC* glCompressedTexImage3D; + PFNGLCOMPRESSEDTEXIMAGE2D_PROC* glCompressedTexImage2D; + PFNGLCOMPRESSEDTEXIMAGE1D_PROC* glCompressedTexImage1D; + PFNGLCOMPRESSEDTEXSUBIMAGE3D_PROC* glCompressedTexSubImage3D; + PFNGLCOMPRESSEDTEXSUBIMAGE2D_PROC* glCompressedTexSubImage2D; + PFNGLCOMPRESSEDTEXSUBIMAGE1D_PROC* glCompressedTexSubImage1D; + PFNGLGETCOMPRESSEDTEXIMAGE_PROC* glGetCompressedTexImage; + + /* GL_VERSION_1_4 */ + + PFNGLBLENDFUNCSEPARATE_PROC* glBlendFuncSeparate; + PFNGLMULTIDRAWARRAYS_PROC* glMultiDrawArrays; + PFNGLMULTIDRAWELEMENTS_PROC* glMultiDrawElements; + PFNGLPOINTPARAMETERF_PROC* glPointParameterf; + PFNGLPOINTPARAMETERFV_PROC* glPointParameterfv; + PFNGLPOINTPARAMETERI_PROC* glPointParameteri; + PFNGLPOINTPARAMETERIV_PROC* glPointParameteriv; + PFNGLBLENDCOLOR_PROC* glBlendColor; + PFNGLBLENDEQUATION_PROC* glBlendEquation; + + /* GL_VERSION_1_5 */ + + PFNGLGENQUERIES_PROC* glGenQueries; + PFNGLDELETEQUERIES_PROC* glDeleteQueries; + PFNGLISQUERY_PROC* glIsQuery; + PFNGLBEGINQUERY_PROC* glBeginQuery; + PFNGLENDQUERY_PROC* glEndQuery; + PFNGLGETQUERYIV_PROC* glGetQueryiv; + PFNGLGETQUERYOBJECTIV_PROC* glGetQueryObjectiv; + PFNGLGETQUERYOBJECTUIV_PROC* glGetQueryObjectuiv; + PFNGLBINDBUFFER_PROC* glBindBuffer; + PFNGLDELETEBUFFERS_PROC* glDeleteBuffers; + PFNGLGENBUFFERS_PROC* glGenBuffers; + PFNGLISBUFFER_PROC* glIsBuffer; + PFNGLBUFFERDATA_PROC* glBufferData; + PFNGLBUFFERSUBDATA_PROC* glBufferSubData; + PFNGLGETBUFFERSUBDATA_PROC* glGetBufferSubData; + PFNGLMAPBUFFER_PROC* glMapBuffer; + PFNGLUNMAPBUFFER_PROC* glUnmapBuffer; + PFNGLGETBUFFERPARAMETERIV_PROC* glGetBufferParameteriv; + PFNGLGETBUFFERPOINTERV_PROC* glGetBufferPointerv; + + /* GL_VERSION_2_0 */ + + PFNGLBLENDEQUATIONSEPARATE_PROC* glBlendEquationSeparate; + PFNGLDRAWBUFFERS_PROC* glDrawBuffers; + PFNGLSTENCILOPSEPARATE_PROC* glStencilOpSeparate; + PFNGLSTENCILFUNCSEPARATE_PROC* glStencilFuncSeparate; + PFNGLSTENCILMASKSEPARATE_PROC* glStencilMaskSeparate; + PFNGLATTACHSHADER_PROC* glAttachShader; + PFNGLBINDATTRIBLOCATION_PROC* glBindAttribLocation; + PFNGLCOMPILESHADER_PROC* glCompileShader; + PFNGLCREATEPROGRAM_PROC* glCreateProgram; + PFNGLCREATESHADER_PROC* glCreateShader; + PFNGLDELETEPROGRAM_PROC* glDeleteProgram; + PFNGLDELETESHADER_PROC* glDeleteShader; + PFNGLDETACHSHADER_PROC* glDetachShader; + PFNGLDISABLEVERTEXATTRIBARRAY_PROC* glDisableVertexAttribArray; + PFNGLENABLEVERTEXATTRIBARRAY_PROC* glEnableVertexAttribArray; + PFNGLGETACTIVEATTRIB_PROC* glGetActiveAttrib; + PFNGLGETACTIVEUNIFORM_PROC* glGetActiveUniform; + PFNGLGETATTACHEDSHADERS_PROC* glGetAttachedShaders; + PFNGLGETATTRIBLOCATION_PROC* glGetAttribLocation; + PFNGLGETPROGRAMIV_PROC* glGetProgramiv; + PFNGLGETPROGRAMINFOLOG_PROC* glGetProgramInfoLog; + PFNGLGETSHADERIV_PROC* glGetShaderiv; + PFNGLGETSHADERINFOLOG_PROC* glGetShaderInfoLog; + PFNGLGETSHADERSOURCE_PROC* glGetShaderSource; + PFNGLGETUNIFORMLOCATION_PROC* glGetUniformLocation; + PFNGLGETUNIFORMFV_PROC* glGetUniformfv; + PFNGLGETUNIFORMIV_PROC* glGetUniformiv; + PFNGLGETVERTEXATTRIBDV_PROC* glGetVertexAttribdv; + PFNGLGETVERTEXATTRIBFV_PROC* glGetVertexAttribfv; + PFNGLGETVERTEXATTRIBIV_PROC* glGetVertexAttribiv; + PFNGLGETVERTEXATTRIBPOINTERV_PROC* glGetVertexAttribPointerv; + PFNGLISPROGRAM_PROC* glIsProgram; + PFNGLISSHADER_PROC* glIsShader; + PFNGLLINKPROGRAM_PROC* glLinkProgram; + PFNGLSHADERSOURCE_PROC* glShaderSource; + PFNGLUSEPROGRAM_PROC* glUseProgram; + PFNGLUNIFORM1F_PROC* glUniform1f; + PFNGLUNIFORM2F_PROC* glUniform2f; + PFNGLUNIFORM3F_PROC* glUniform3f; + PFNGLUNIFORM4F_PROC* glUniform4f; + PFNGLUNIFORM1I_PROC* glUniform1i; + PFNGLUNIFORM2I_PROC* glUniform2i; + PFNGLUNIFORM3I_PROC* glUniform3i; + PFNGLUNIFORM4I_PROC* glUniform4i; + PFNGLUNIFORM1FV_PROC* glUniform1fv; + PFNGLUNIFORM2FV_PROC* glUniform2fv; + PFNGLUNIFORM3FV_PROC* glUniform3fv; + PFNGLUNIFORM4FV_PROC* glUniform4fv; + PFNGLUNIFORM1IV_PROC* glUniform1iv; + PFNGLUNIFORM2IV_PROC* glUniform2iv; + PFNGLUNIFORM3IV_PROC* glUniform3iv; + PFNGLUNIFORM4IV_PROC* glUniform4iv; + PFNGLUNIFORMMATRIX2FV_PROC* glUniformMatrix2fv; + PFNGLUNIFORMMATRIX3FV_PROC* glUniformMatrix3fv; + PFNGLUNIFORMMATRIX4FV_PROC* glUniformMatrix4fv; + PFNGLVALIDATEPROGRAM_PROC* glValidateProgram; + PFNGLVERTEXATTRIB1D_PROC* glVertexAttrib1d; + PFNGLVERTEXATTRIB1DV_PROC* glVertexAttrib1dv; + PFNGLVERTEXATTRIB1F_PROC* glVertexAttrib1f; + PFNGLVERTEXATTRIB1FV_PROC* glVertexAttrib1fv; + PFNGLVERTEXATTRIB1S_PROC* glVertexAttrib1s; + PFNGLVERTEXATTRIB1SV_PROC* glVertexAttrib1sv; + PFNGLVERTEXATTRIB2D_PROC* glVertexAttrib2d; + PFNGLVERTEXATTRIB2DV_PROC* glVertexAttrib2dv; + PFNGLVERTEXATTRIB2F_PROC* glVertexAttrib2f; + PFNGLVERTEXATTRIB2FV_PROC* glVertexAttrib2fv; + PFNGLVERTEXATTRIB2S_PROC* glVertexAttrib2s; + PFNGLVERTEXATTRIB2SV_PROC* glVertexAttrib2sv; + PFNGLVERTEXATTRIB3D_PROC* glVertexAttrib3d; + PFNGLVERTEXATTRIB3DV_PROC* glVertexAttrib3dv; + PFNGLVERTEXATTRIB3F_PROC* glVertexAttrib3f; + PFNGLVERTEXATTRIB3FV_PROC* glVertexAttrib3fv; + PFNGLVERTEXATTRIB3S_PROC* glVertexAttrib3s; + PFNGLVERTEXATTRIB3SV_PROC* glVertexAttrib3sv; + PFNGLVERTEXATTRIB4NBV_PROC* glVertexAttrib4Nbv; + PFNGLVERTEXATTRIB4NIV_PROC* glVertexAttrib4Niv; + PFNGLVERTEXATTRIB4NSV_PROC* glVertexAttrib4Nsv; + PFNGLVERTEXATTRIB4NUB_PROC* glVertexAttrib4Nub; + PFNGLVERTEXATTRIB4NUBV_PROC* glVertexAttrib4Nubv; + PFNGLVERTEXATTRIB4NUIV_PROC* glVertexAttrib4Nuiv; + PFNGLVERTEXATTRIB4NUSV_PROC* glVertexAttrib4Nusv; + PFNGLVERTEXATTRIB4BV_PROC* glVertexAttrib4bv; + PFNGLVERTEXATTRIB4D_PROC* glVertexAttrib4d; + PFNGLVERTEXATTRIB4DV_PROC* glVertexAttrib4dv; + PFNGLVERTEXATTRIB4F_PROC* glVertexAttrib4f; + PFNGLVERTEXATTRIB4FV_PROC* glVertexAttrib4fv; + PFNGLVERTEXATTRIB4IV_PROC* glVertexAttrib4iv; + PFNGLVERTEXATTRIB4S_PROC* glVertexAttrib4s; + PFNGLVERTEXATTRIB4SV_PROC* glVertexAttrib4sv; + PFNGLVERTEXATTRIB4UBV_PROC* glVertexAttrib4ubv; + PFNGLVERTEXATTRIB4UIV_PROC* glVertexAttrib4uiv; + PFNGLVERTEXATTRIB4USV_PROC* glVertexAttrib4usv; + PFNGLVERTEXATTRIBPOINTER_PROC* glVertexAttribPointer; + + /* GL_VERSION_2_1 */ + + PFNGLUNIFORMMATRIX2X3FV_PROC* glUniformMatrix2x3fv; + PFNGLUNIFORMMATRIX3X2FV_PROC* glUniformMatrix3x2fv; + PFNGLUNIFORMMATRIX2X4FV_PROC* glUniformMatrix2x4fv; + PFNGLUNIFORMMATRIX4X2FV_PROC* glUniformMatrix4x2fv; + PFNGLUNIFORMMATRIX3X4FV_PROC* glUniformMatrix3x4fv; + PFNGLUNIFORMMATRIX4X3FV_PROC* glUniformMatrix4x3fv; + + /* GL_VERSION_3_0 */ + + PFNGLCOLORMASKI_PROC* glColorMaski; + PFNGLGETBOOLEANI_V_PROC* glGetBooleani_v; + PFNGLGETINTEGERI_V_PROC* glGetIntegeri_v; + PFNGLENABLEI_PROC* glEnablei; + PFNGLDISABLEI_PROC* glDisablei; + PFNGLISENABLEDI_PROC* glIsEnabledi; + PFNGLBEGINTRANSFORMFEEDBACK_PROC* glBeginTransformFeedback; + PFNGLENDTRANSFORMFEEDBACK_PROC* glEndTransformFeedback; + PFNGLBINDBUFFERRANGE_PROC* glBindBufferRange; + PFNGLBINDBUFFERBASE_PROC* glBindBufferBase; + PFNGLTRANSFORMFEEDBACKVARYINGS_PROC* glTransformFeedbackVaryings; + PFNGLGETTRANSFORMFEEDBACKVARYING_PROC* glGetTransformFeedbackVarying; + PFNGLCLAMPCOLOR_PROC* glClampColor; + PFNGLBEGINCONDITIONALRENDER_PROC* glBeginConditionalRender; + PFNGLENDCONDITIONALRENDER_PROC* glEndConditionalRender; + PFNGLVERTEXATTRIBIPOINTER_PROC* glVertexAttribIPointer; + PFNGLGETVERTEXATTRIBIIV_PROC* glGetVertexAttribIiv; + PFNGLGETVERTEXATTRIBIUIV_PROC* glGetVertexAttribIuiv; + PFNGLVERTEXATTRIBI1I_PROC* glVertexAttribI1i; + PFNGLVERTEXATTRIBI2I_PROC* glVertexAttribI2i; + PFNGLVERTEXATTRIBI3I_PROC* glVertexAttribI3i; + PFNGLVERTEXATTRIBI4I_PROC* glVertexAttribI4i; + PFNGLVERTEXATTRIBI1UI_PROC* glVertexAttribI1ui; + PFNGLVERTEXATTRIBI2UI_PROC* glVertexAttribI2ui; + PFNGLVERTEXATTRIBI3UI_PROC* glVertexAttribI3ui; + PFNGLVERTEXATTRIBI4UI_PROC* glVertexAttribI4ui; + PFNGLVERTEXATTRIBI1IV_PROC* glVertexAttribI1iv; + PFNGLVERTEXATTRIBI2IV_PROC* glVertexAttribI2iv; + PFNGLVERTEXATTRIBI3IV_PROC* glVertexAttribI3iv; + PFNGLVERTEXATTRIBI4IV_PROC* glVertexAttribI4iv; + PFNGLVERTEXATTRIBI1UIV_PROC* glVertexAttribI1uiv; + PFNGLVERTEXATTRIBI2UIV_PROC* glVertexAttribI2uiv; + PFNGLVERTEXATTRIBI3UIV_PROC* glVertexAttribI3uiv; + PFNGLVERTEXATTRIBI4UIV_PROC* glVertexAttribI4uiv; + PFNGLVERTEXATTRIBI4BV_PROC* glVertexAttribI4bv; + PFNGLVERTEXATTRIBI4SV_PROC* glVertexAttribI4sv; + PFNGLVERTEXATTRIBI4UBV_PROC* glVertexAttribI4ubv; + PFNGLVERTEXATTRIBI4USV_PROC* glVertexAttribI4usv; + PFNGLGETUNIFORMUIV_PROC* glGetUniformuiv; + PFNGLBINDFRAGDATALOCATION_PROC* glBindFragDataLocation; + PFNGLGETFRAGDATALOCATION_PROC* glGetFragDataLocation; + PFNGLUNIFORM1UI_PROC* glUniform1ui; + PFNGLUNIFORM2UI_PROC* glUniform2ui; + PFNGLUNIFORM3UI_PROC* glUniform3ui; + PFNGLUNIFORM4UI_PROC* glUniform4ui; + PFNGLUNIFORM1UIV_PROC* glUniform1uiv; + PFNGLUNIFORM2UIV_PROC* glUniform2uiv; + PFNGLUNIFORM3UIV_PROC* glUniform3uiv; + PFNGLUNIFORM4UIV_PROC* glUniform4uiv; + PFNGLTEXPARAMETERIIV_PROC* glTexParameterIiv; + PFNGLTEXPARAMETERIUIV_PROC* glTexParameterIuiv; + PFNGLGETTEXPARAMETERIIV_PROC* glGetTexParameterIiv; + PFNGLGETTEXPARAMETERIUIV_PROC* glGetTexParameterIuiv; + PFNGLCLEARBUFFERIV_PROC* glClearBufferiv; + PFNGLCLEARBUFFERUIV_PROC* glClearBufferuiv; + PFNGLCLEARBUFFERFV_PROC* glClearBufferfv; + PFNGLCLEARBUFFERFI_PROC* glClearBufferfi; + PFNGLGETSTRINGI_PROC* glGetStringi; + PFNGLISRENDERBUFFER_PROC* glIsRenderbuffer; + PFNGLBINDRENDERBUFFER_PROC* glBindRenderbuffer; + PFNGLDELETERENDERBUFFERS_PROC* glDeleteRenderbuffers; + PFNGLGENRENDERBUFFERS_PROC* glGenRenderbuffers; + PFNGLRENDERBUFFERSTORAGE_PROC* glRenderbufferStorage; + PFNGLGETRENDERBUFFERPARAMETERIV_PROC* glGetRenderbufferParameteriv; + PFNGLISFRAMEBUFFER_PROC* glIsFramebuffer; + PFNGLBINDFRAMEBUFFER_PROC* glBindFramebuffer; + PFNGLDELETEFRAMEBUFFERS_PROC* glDeleteFramebuffers; + PFNGLGENFRAMEBUFFERS_PROC* glGenFramebuffers; + PFNGLCHECKFRAMEBUFFERSTATUS_PROC* glCheckFramebufferStatus; + PFNGLFRAMEBUFFERTEXTURE1D_PROC* glFramebufferTexture1D; + PFNGLFRAMEBUFFERTEXTURE2D_PROC* glFramebufferTexture2D; + PFNGLFRAMEBUFFERTEXTURE3D_PROC* glFramebufferTexture3D; + PFNGLFRAMEBUFFERRENDERBUFFER_PROC* glFramebufferRenderbuffer; + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV_PROC* glGetFramebufferAttachmentParameteriv; + PFNGLGENERATEMIPMAP_PROC* glGenerateMipmap; + PFNGLBLITFRAMEBUFFER_PROC* glBlitFramebuffer; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLE_PROC* glRenderbufferStorageMultisample; + PFNGLFRAMEBUFFERTEXTURELAYER_PROC* glFramebufferTextureLayer; + PFNGLMAPBUFFERRANGE_PROC* glMapBufferRange; + PFNGLFLUSHMAPPEDBUFFERRANGE_PROC* glFlushMappedBufferRange; + PFNGLBINDVERTEXARRAY_PROC* glBindVertexArray; + PFNGLDELETEVERTEXARRAYS_PROC* glDeleteVertexArrays; + PFNGLGENVERTEXARRAYS_PROC* glGenVertexArrays; + PFNGLISVERTEXARRAY_PROC* glIsVertexArray; + + /* GL_VERSION_3_1 */ + + PFNGLDRAWARRAYSINSTANCED_PROC* glDrawArraysInstanced; + PFNGLDRAWELEMENTSINSTANCED_PROC* glDrawElementsInstanced; + PFNGLTEXBUFFER_PROC* glTexBuffer; + PFNGLPRIMITIVERESTARTINDEX_PROC* glPrimitiveRestartIndex; + PFNGLCOPYBUFFERSUBDATA_PROC* glCopyBufferSubData; + PFNGLGETUNIFORMINDICES_PROC* glGetUniformIndices; + PFNGLGETACTIVEUNIFORMSIV_PROC* glGetActiveUniformsiv; + PFNGLGETACTIVEUNIFORMNAME_PROC* glGetActiveUniformName; + PFNGLGETUNIFORMBLOCKINDEX_PROC* glGetUniformBlockIndex; + PFNGLGETACTIVEUNIFORMBLOCKIV_PROC* glGetActiveUniformBlockiv; + PFNGLGETACTIVEUNIFORMBLOCKNAME_PROC* glGetActiveUniformBlockName; + PFNGLUNIFORMBLOCKBINDING_PROC* glUniformBlockBinding; + +}; + +typedef struct OpenGLBindings OpenGLBindings; + +/* --------------------------- CATEGORY DEFINES ------------------------------ */ + +#define GL_VERSION_1_0 +#define GL_VERSION_1_1 +#define GL_VERSION_1_2 +#define GL_VERSION_1_3 +#define GL_VERSION_1_4 +#define GL_VERSION_1_5 +#define GL_VERSION_2_0 +#define GL_VERSION_2_1 +#define GL_VERSION_3_0 +#define GL_VERSION_3_1 + +/* ---------------------- Flags for optional extensions ---------------------- */ + +void flextInit(OpenGLBindings *bindings); + +#define FLEXT_MAJOR_VERSION 3 +#define FLEXT_MINOR_VERSION 1 +#define FLEXT_CORE_PROFILE 1 + +#ifdef __cplusplus +} +#endif + +#endif /* _gl_h_ */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/frame_listener_impl.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/frame_listener_impl.cpp new file mode 100644 index 0000000..45224e8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/frame_listener_impl.cpp @@ -0,0 +1,194 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file frame_listener_impl.cpp Implementation classes for frame listeners. */ + +#include +#include + +namespace libfreenect2 +{ + +Frame::Frame(size_t width, size_t height, size_t bytes_per_pixel, unsigned char *data_) : + width(width), + height(height), + bytes_per_pixel(bytes_per_pixel), + data(data_), + exposure(0.f), + gain(0.f), + gamma(0.f), + status(0), + format(Frame::Invalid), + rawdata(NULL) +{ + if (data_) + return; + const size_t alignment = 64; + size_t space = width * height * bytes_per_pixel + alignment; + rawdata = new unsigned char[space]; + uintptr_t ptr = reinterpret_cast(rawdata); + uintptr_t aligned = (ptr - 1u + alignment) & -alignment; + data = reinterpret_cast(aligned); +} + +Frame::~Frame() +{ + delete[] rawdata; +} + +FrameListener::~FrameListener() {} + +/** Implementation class for synchronizing different types of frames. */ +class SyncMultiFrameListenerImpl +{ +public: + libfreenect2::mutex mutex_; + libfreenect2::condition_variable condition_; + FrameMap next_frame_; + + const unsigned int subscribed_frame_types_; + unsigned int ready_frame_types_; + bool current_frame_released_; + + SyncMultiFrameListenerImpl(unsigned int frame_types) : + subscribed_frame_types_(frame_types), + ready_frame_types_(0), + current_frame_released_(true) + { + } + + bool hasNewFrame() const + { + return ready_frame_types_ == subscribed_frame_types_; + } +}; + +SyncMultiFrameListener::SyncMultiFrameListener(unsigned int frame_types) : + impl_(new SyncMultiFrameListenerImpl(frame_types)) +{ +} + +SyncMultiFrameListener::~SyncMultiFrameListener() +{ + release(impl_->next_frame_); + delete impl_; +} + +bool SyncMultiFrameListener::hasNewFrame() const +{ + libfreenect2::unique_lock l(impl_->mutex_); + + return impl_->hasNewFrame(); +} + +bool SyncMultiFrameListener::waitForNewFrame(FrameMap &frame, int milliseconds) +{ +#ifdef LIBFREENECT2_THREADING_STDLIB + libfreenect2::unique_lock l(impl_->mutex_); + + auto predicate = [this]{ return impl_->hasNewFrame(); }; + + if(impl_->condition_.wait_for(l, std::chrono::milliseconds(milliseconds), predicate)) + { + frame = impl_->next_frame_; + impl_->next_frame_.clear(); + impl_->ready_frame_types_ = 0; + + return true; + } + else + { + return false; + } +#else + waitForNewFrame(frame); + return true; +#endif // LIBFREENECT2_THREADING_STDLIB +} + +void SyncMultiFrameListener::waitForNewFrame(FrameMap &frame) +{ + libfreenect2::unique_lock l(impl_->mutex_); + + while(!impl_->hasNewFrame()) + { + WAIT_CONDITION(impl_->condition_, impl_->mutex_, l) + } + + frame = impl_->next_frame_; + impl_->next_frame_.clear(); + impl_->ready_frame_types_ = 0; + impl_->current_frame_released_ = false; +} + +void SyncMultiFrameListener::release(FrameMap &frame) +{ + for(FrameMap::iterator it = frame.begin(); it != frame.end(); ++it) + { + delete it->second; + it->second = 0; + } + + frame.clear(); + + { + libfreenect2::lock_guard l(impl_->mutex_); + impl_->current_frame_released_ = true; + } +} + +bool SyncMultiFrameListener::onNewFrame(Frame::Type type, Frame *frame) +{ + if((impl_->subscribed_frame_types_ & type) == 0) return false; + + { + libfreenect2::lock_guard l(impl_->mutex_); + + if (!impl_->current_frame_released_) + return false; + + FrameMap::iterator it = impl_->next_frame_.find(type); + + if(it != impl_->next_frame_.end()) + { + // replace frame + delete it->second; + it->second = frame; + } + else + { + impl_->next_frame_[type] = frame; + } + + impl_->ready_frame_types_ |= type; + } + + impl_->condition_.notify_one(); + + return true; +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/libfreenect2.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/libfreenect2.cpp new file mode 100644 index 0000000..631a578 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/libfreenect2.cpp @@ -0,0 +1,1650 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file libfreenect2.cpp Freenect2 devices and processing implementation. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WRITE_LIBUSB_ERROR(__RESULT) libusb_error_name(__RESULT) << " " << libusb_strerror((libusb_error)__RESULT) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ +using namespace libfreenect2; +using namespace libfreenect2::usb; +using namespace libfreenect2::protocol; + +/* +For detailed analysis see https://github.com/OpenKinect/libfreenect2/issues/144 + +The following discussion is in no way authoritative. It is the current best +explanation considering the hardcoded parameters and decompiled code. + +p0 tables are the "initial shift" of phase values, as in US8587771 B2. + +Three p0 tables are used for "disamgibuation" in the first half of stage 2 +processing. + +At the end of stage 2 processing: + +phase_final is the phase shift used to compute the travel distance. + +What is being measured is max_depth (d), the total travel distance of the +reflected ray. + +But what we want is depth_fit (z), the distance from reflection to the XY +plane. There are two issues: the distance before reflection is not needed; +and the measured ray is not normal to the XY plane. + +Suppose L is the distance between the light source and the focal point (a +fixed constant), and xu,yu is the undistorted and normalized coordinates for +each measured pixel at unit depth. + +Through some derivation, we have + + z = (d*d - L*L)/(d*sqrt(xu*xu + yu*yu + 1) - xu*L)/2. + +The expression in stage 2 processing is a variant of this, with the term +`-L*L` removed. Detailed derivation can be found in the above issue. + +Here, the two terms `sqrt(xu*xu + yu*yu + 1)` and `xu` requires undistorted +coordinates, which is hard to compute in real-time because the inverse of +radial and tangential distortion has no analytical solutions and requires +numeric methods to solve. Thus these two terms are precomputed once and +their variants are stored as ztable and xtable respectively. + +Even though x/ztable is derived with undistortion, they are only used to +correct the effect of distortion on the z value. Image warping is needed for +correcting distortion on x-y value, which happens in registration.cpp. +*/ +struct IrCameraTables: Freenect2Device::IrCameraParams +{ + std::vector xtable; + std::vector ztable; + std::vector lut; + + IrCameraTables(const Freenect2Device::IrCameraParams &parent): + Freenect2Device::IrCameraParams(parent), + xtable(DepthPacketProcessor::TABLE_SIZE), + ztable(DepthPacketProcessor::TABLE_SIZE), + lut(DepthPacketProcessor::LUT_SIZE) + { + const double scaling_factor = 8192; + const double unambigious_dist = 6250.0/3; + size_t divergence = 0; + for (size_t i = 0; i < DepthPacketProcessor::TABLE_SIZE; i++) + { + size_t xi = i % 512; + size_t yi = i / 512; + double xd = (xi + 0.5 - cx)/fx; + double yd = (yi + 0.5 - cy)/fy; + double xu, yu; + divergence += !undistort(xd, yd, xu, yu); + xtable[i] = scaling_factor*xu; + ztable[i] = unambigious_dist/sqrt(xu*xu + yu*yu + 1); + } + + if (divergence > 0) + LOG_ERROR << divergence << " pixels in x/ztable have incorrect undistortion."; + + short y = 0; + for (int x = 0; x < 1024; x++) + { + unsigned inc = 1 << (x/128 - (x>=128)); + lut[x] = y; + lut[1024 + x] = -y; + y += inc; + } + lut[1024] = 32767; + } + + //x,y: undistorted, normalized coordinates + //xd,yd: distorted, normalized coordinates + void distort(double x, double y, double &xd, double &yd) const + { + double x2 = x * x; + double y2 = y * y; + double r2 = x2 + y2; + double xy = x * y; + double kr = ((k3 * r2 + k2) * r2 + k1) * r2 + 1.0; + xd = x*kr + p2*(r2 + 2*x2) + 2*p1*xy; + yd = y*kr + p1*(r2 + 2*y2) + 2*p2*xy; + } + + //The inverse of distort() using Newton's method + //Return true if converged correctly + //This function considers tangential distortion with double precision. + bool undistort(double x, double y, double &xu, double &yu) const + { + double x0 = x; + double y0 = y; + + double last_x = x; + double last_y = y; + const int max_iterations = 100; + int iter; + for (iter = 0; iter < max_iterations; iter++) { + double x2 = x*x; + double y2 = y*y; + double x2y2 = x2 + y2; + double x2y22 = x2y2*x2y2; + double x2y23 = x2y2*x2y22; + + //Jacobian matrix + double Ja = k3*x2y23 + (k2+6*k3*x2)*x2y22 + (k1+4*k2*x2)*x2y2 + 2*k1*x2 + 6*p2*x + 2*p1*y + 1; + double Jb = 6*k3*x*y*x2y22 + 4*k2*x*y*x2y2 + 2*k1*x*y + 2*p1*x + 2*p2*y; + double Jc = Jb; + double Jd = k3*x2y23 + (k2+6*k3*y2)*x2y22 + (k1+4*k2*y2)*x2y2 + 2*k1*y2 + 2*p2*x + 6*p1*y + 1; + + //Inverse Jacobian + double Jdet = 1/(Ja*Jd - Jb*Jc); + double a = Jd*Jdet; + double b = -Jb*Jdet; + double c = -Jc*Jdet; + double d = Ja*Jdet; + + double f, g; + distort(x, y, f, g); + f -= x0; + g -= y0; + + x -= a*f + b*g; + y -= c*f + d*g; + const double eps = std::numeric_limits::epsilon()*16; + if (fabs(x - last_x) <= eps && fabs(y - last_y) <= eps) + break; + last_x = x; + last_y = y; + } + xu = x; + yu = y; + return iter < max_iterations; + } +}; + +/** Freenect2 device implementation. */ +class Freenect2DeviceImpl : public Freenect2Device +{ +private: + enum State + { + Created, + Open, + Streaming, + Closed + }; + + State state_; + bool has_usb_interfaces_; + + Freenect2Impl *context_; + libusb_device *usb_device_; + libusb_device_handle *usb_device_handle_; + + BulkTransferPool rgb_transfer_pool_; + IsoTransferPool ir_transfer_pool_; + + UsbControl usb_control_; + CommandTransaction command_tx_; + int command_seq_; + + const PacketPipeline *pipeline_; + std::string serial_, firmware_; + Freenect2Device::IrCameraParams ir_camera_params_; + Freenect2Device::ColorCameraParams rgb_camera_params_; +public: + Freenect2DeviceImpl(Freenect2Impl *context, const PacketPipeline *pipeline, libusb_device *usb_device, libusb_device_handle *usb_device_handle, const std::string &serial); + virtual ~Freenect2DeviceImpl(); + + bool isSameUsbDevice(libusb_device* other); + + virtual std::string getSerialNumber(); + virtual std::string getFirmwareVersion(); + + virtual Freenect2Device::ColorCameraParams getColorCameraParams(); + virtual Freenect2Device::IrCameraParams getIrCameraParams(); + virtual void setColorCameraParams(const Freenect2Device::ColorCameraParams ¶ms); + virtual void setIrCameraParams(const Freenect2Device::IrCameraParams ¶ms); + virtual void setConfiguration(const Freenect2Device::Config &config); + + int nextCommandSeq(); + + bool open(); + + virtual void setColorFrameListener(libfreenect2::FrameListener* rgb_frame_listener); + virtual void setIrAndDepthFrameListener(libfreenect2::FrameListener* ir_frame_listener); + virtual void setColorAutoExposure(float exposure_compensation = 0); + virtual void setColorSemiAutoExposure(float pseudo_exposure_time_ms); + virtual void setColorManualExposure(float integration_time_ms, float analog_gain); + virtual void setColorSetting(ColorSettingCommandType cmd, uint32_t value); + virtual void setColorSetting(ColorSettingCommandType cmd, float value); + virtual uint32_t getColorSetting(ColorSettingCommandType cmd); + virtual float getColorSettingFloat(ColorSettingCommandType cmd); + virtual void setLedStatus(LedSettings led); + virtual bool start(); + virtual bool startStreams(bool rgb, bool depth); + virtual bool stop(); + virtual bool close(); +}; + +class Freenect2ReplayDevice : public Freenect2Device +{ +public: + Freenect2ReplayDevice(Freenect2ReplayImpl *context_, const std::vector& frame_filenames, const PacketPipeline* pipeline); + virtual ~Freenect2ReplayDevice(); + + virtual std::string getSerialNumber(); + virtual std::string getFirmwareVersion(); + + virtual ColorCameraParams getColorCameraParams(); + virtual IrCameraParams getIrCameraParams(); + virtual void setColorCameraParams(const ColorCameraParams ¶ms); + virtual void setIrCameraParams(const IrCameraParams ¶ms); + virtual void setConfiguration(const Config &config); + + virtual void setColorFrameListener(FrameListener* listener); + virtual void setIrAndDepthFrameListener(FrameListener* listener); + + virtual void setColorAutoExposure(float exposure_compensation) {} + virtual void setColorSemiAutoExposure(float pseudo_exposure_time_ms) {} + virtual void setColorManualExposure(float integration_time_ms, float analog_gain) {} + virtual void setColorSetting(ColorSettingCommandType cmd, uint32_t value) {} + virtual void setColorSetting(ColorSettingCommandType cmd, float value) {} + virtual uint32_t getColorSetting(ColorSettingCommandType cmd) { return 0u; } + virtual float getColorSettingFloat(ColorSettingCommandType cmd) { return 0.0f; } + virtual void setLedStatus(LedSettings led) {} + + bool open(); + + virtual bool start(); + virtual bool startStreams(bool rgb, bool depth); + virtual bool stop(); + virtual bool close(); + + // X, Z, LUT tables are generated in setIrCameraParams(). + void loadP0Tables(unsigned char* buffer, size_t buffer_length); + +private: + bool processRawFrame(Frame::Type type, Frame* frame); + void processRgbFrame(Frame* frame); + void processDepthFrame(Frame* frame); + + void run(); + static void static_execute(void* arg); + + Freenect2ReplayImpl *context_; + const PacketPipeline* pipeline_; + size_t buffer_size_; + DepthPacket packet_; + + std::vector frame_filenames_; + libfreenect2::thread* t_; + bool running_; + + Freenect2Device::IrCameraParams ir_camera_params_; + Freenect2Device::ColorCameraParams rgb_camera_params_; +}; + +struct PrintBusAndDevice +{ + libusb_device *dev_; + int status_; + + PrintBusAndDevice(libusb_device *dev, int status = 0) : dev_(dev), status_(status) {} +}; + +std::ostream &operator<<(std::ostream &out, const PrintBusAndDevice& dev) +{ + out << "@" << int(libusb_get_bus_number(dev.dev_)) << ":" << int(libusb_get_device_address(dev.dev_)); + if (dev.status_) + out << " " << WRITE_LIBUSB_ERROR(dev.status_); + return out; +} + +/** Freenect2 device storage and control. */ +class Freenect2Impl +{ +private: + bool managed_usb_context_; + libusb_context *usb_context_; + EventLoop usb_event_loop_; +public: + struct UsbDeviceWithSerial + { + libusb_device *dev; + std::string serial; + }; + typedef std::vector UsbDeviceVector; + typedef std::vector DeviceVector; + + bool has_device_enumeration_; + UsbDeviceVector enumerated_devices_; + DeviceVector devices_; + + bool initialized; + + Freenect2Impl(void *usb_context) : + managed_usb_context_(usb_context == 0), + usb_context_(reinterpret_cast(usb_context)), + has_device_enumeration_(false), + initialized(false) + { +#ifdef __linux__ + if (libusb_get_version()->nano < 10952) + { + LOG_ERROR << "Your libusb does not support large iso buffer!"; + return; + } +#endif + + if(managed_usb_context_) + { + int r = libusb_init(&usb_context_); + if(r != 0) + { + LOG_ERROR << "failed to create usb context: " << WRITE_LIBUSB_ERROR(r); + return; + } + +#if defined(_WIN32) || defined (__WIN32__) || defined(__WINDOWS__) + (void)libusb_set_option(usb_context_, LIBUSB_OPTION_USE_USBDK); +#endif + } + + usb_event_loop_.start(usb_context_); + initialized = true; + } + + ~Freenect2Impl() + { + if (!initialized) + return; + + clearDevices(); + clearDeviceEnumeration(); + + usb_event_loop_.stop(); + + if(managed_usb_context_ && usb_context_ != 0) + { + libusb_exit(usb_context_); + usb_context_ = 0; + } + } + + void addDevice(Freenect2DeviceImpl *device) + { + if (!initialized) + return; + + devices_.push_back(device); + } + + void removeDevice(Freenect2DeviceImpl *device) + { + if (!initialized) + return; + + DeviceVector::iterator it = std::find(devices_.begin(), devices_.end(), device); + + if(it != devices_.end()) + { + devices_.erase(it); + } + else + { + LOG_WARNING << "tried to remove device, which is not in the internal device list!"; + } + } + + bool tryGetDevice(libusb_device *usb_device, Freenect2DeviceImpl **device) + { + if (!initialized) + return false; + + for(DeviceVector::iterator it = devices_.begin(); it != devices_.end(); ++it) + { + if((*it)->isSameUsbDevice(usb_device)) + { + *device = *it; + return true; + } + } + + return false; + } + + void clearDevices() + { + if (!initialized) + return; + + DeviceVector devices(devices_.begin(), devices_.end()); + + for(DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) + { + delete (*it); + } + + if(!devices_.empty()) + { + LOG_WARNING << "after deleting all devices the internal device list should be empty!"; + } + } + + void clearDeviceEnumeration() + { + if (!initialized) + return; + + // free enumerated device pointers, this should not affect opened devices + for(UsbDeviceVector::iterator it = enumerated_devices_.begin(); it != enumerated_devices_.end(); ++it) + { + libusb_unref_device(it->dev); + } + + enumerated_devices_.clear(); + has_device_enumeration_ = false; + } + + void enumerateDevices() + { + if (!initialized) + return; + + LOG_INFO << "enumerating devices..."; + libusb_device **device_list; + int num_devices = libusb_get_device_list(usb_context_, &device_list); + + LOG_INFO << num_devices << " usb devices connected"; + + if(num_devices > 0) + { + for(int idx = 0; idx < num_devices; ++idx) + { + libusb_device *dev = device_list[idx]; + libusb_device_descriptor dev_desc; + + int r = libusb_get_device_descriptor(dev, &dev_desc); // this is always successful + + if(dev_desc.idVendor == Freenect2Device::VendorId && (dev_desc.idProduct == Freenect2Device::ProductId || dev_desc.idProduct == Freenect2Device::ProductIdPreview)) + { + Freenect2DeviceImpl *freenect2_dev; + + // prevent error if device is already open + if(tryGetDevice(dev, &freenect2_dev)) + { + UsbDeviceWithSerial dev_with_serial; + dev_with_serial.dev = dev; + dev_with_serial.serial = freenect2_dev->getSerialNumber(); + + enumerated_devices_.push_back(dev_with_serial); + continue; + } + else + { + libusb_device_handle *dev_handle; + r = libusb_open(dev, &dev_handle); + + if(r == LIBUSB_SUCCESS) + { + unsigned char buffer[1024]; + r = libusb_get_string_descriptor_ascii(dev_handle, dev_desc.iSerialNumber, buffer, sizeof(buffer)); + // keep the ref until determined not kinect + libusb_ref_device(dev); + libusb_close(dev_handle); + + if(r > LIBUSB_SUCCESS) + { + UsbDeviceWithSerial dev_with_serial; + dev_with_serial.dev = dev; + dev_with_serial.serial = std::string(reinterpret_cast(buffer), size_t(r)); + + LOG_INFO << "found valid Kinect v2 " << PrintBusAndDevice(dev) << " with serial " << dev_with_serial.serial; + // valid Kinect v2 + enumerated_devices_.push_back(dev_with_serial); + continue; + } + else + { + libusb_unref_device(dev); + LOG_ERROR << "failed to get serial number of Kinect v2: " << PrintBusAndDevice(dev, r); + } + } + else + { + LOG_ERROR << "failed to open Kinect v2: " << PrintBusAndDevice(dev, r); + } + } + } + libusb_unref_device(dev); + } + } + + libusb_free_device_list(device_list, 0); + has_device_enumeration_ = true; + + LOG_INFO << "found " << enumerated_devices_.size() << " devices"; + } + + int getNumDevices() + { + if (!initialized) + return 0; + + if(!has_device_enumeration_) + { + enumerateDevices(); + } + return enumerated_devices_.size(); + } + + Freenect2Device *openDevice(int idx, const PacketPipeline *factory, bool attempting_reset); +}; + +class Freenect2ReplayImpl +{ +private: + typedef std::vector DeviceVector; + DeviceVector devices_; + +public: + ~Freenect2ReplayImpl() + { + clearDevices(); + } + + void addDevice(Freenect2ReplayDevice *device) + { + devices_.push_back(device); + } + + void removeDevice(Freenect2ReplayDevice *device) + { + DeviceVector::iterator it = std::find(devices_.begin(), devices_.end(), device); + + if(it != devices_.end()) + { + devices_.erase(it); + } + else + { + LOG_WARNING << "tried to remove a REPLAY device, which is not in the internal device list!"; + } + } + + void clearDevices() + { + DeviceVector devices(devices_.begin(), devices_.end()); + + for(DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) + { + delete (*it); + } + + // Should never happen + if(!devices_.empty()) + { + LOG_WARNING << "after deleting all REPLAY devices the internal device list should be empty!"; + } + } + + Freenect2Device *openDevice(const std::vector& frame_filenames, const PacketPipeline *pipeline); +}; + +Freenect2Device::~Freenect2Device() +{ +} + +Freenect2DeviceImpl::Freenect2DeviceImpl(Freenect2Impl *context, const PacketPipeline *pipeline, libusb_device *usb_device, libusb_device_handle *usb_device_handle, const std::string &serial) : + state_(Created), + has_usb_interfaces_(false), + context_(context), + usb_device_(usb_device), + usb_device_handle_(usb_device_handle), + rgb_transfer_pool_(usb_device_handle, 0x83), + ir_transfer_pool_(usb_device_handle, 0x84), + usb_control_(usb_device_handle_), + command_tx_(usb_device_handle_, 0x81, 0x02), + command_seq_(0), + pipeline_(pipeline), + serial_(serial), + firmware_("") +{ + rgb_transfer_pool_.setCallback(pipeline_->getRgbPacketParser()); + ir_transfer_pool_.setCallback(pipeline_->getIrPacketParser()); +} + +Freenect2DeviceImpl::~Freenect2DeviceImpl() +{ + close(); + context_->removeDevice(this); + + delete pipeline_; +} + +int Freenect2DeviceImpl::nextCommandSeq() +{ + return command_seq_++; +} + +bool Freenect2DeviceImpl::isSameUsbDevice(libusb_device* other) +{ + bool result = false; + + if(state_ != Closed && usb_device_ != 0) + { + unsigned char bus = libusb_get_bus_number(usb_device_); + unsigned char address = libusb_get_device_address(usb_device_); + + unsigned char other_bus = libusb_get_bus_number(other); + unsigned char other_address = libusb_get_device_address(other); + + result = (bus == other_bus) && (address == other_address); + } + + return result; +} + +std::string Freenect2DeviceImpl::getSerialNumber() +{ + return serial_; +} + +std::string Freenect2DeviceImpl::getFirmwareVersion() +{ + return firmware_; +} + +Freenect2Device::ColorCameraParams Freenect2DeviceImpl::getColorCameraParams() +{ + return rgb_camera_params_; +} + + +Freenect2Device::IrCameraParams Freenect2DeviceImpl::getIrCameraParams() +{ + return ir_camera_params_; +} + +void Freenect2DeviceImpl::setColorCameraParams(const Freenect2Device::ColorCameraParams ¶ms) +{ + rgb_camera_params_ = params; +} + +void Freenect2DeviceImpl::setIrCameraParams(const Freenect2Device::IrCameraParams ¶ms) +{ + ir_camera_params_ = params; + DepthPacketProcessor *proc = pipeline_->getDepthPacketProcessor(); + if (proc != 0) + { + IrCameraTables tables(params); + proc->loadXZTables(&tables.xtable[0], &tables.ztable[0]); + proc->loadLookupTable(&tables.lut[0]); + } +} + +Freenect2Device::Config::Config() : + MinDepth(0.5f), + MaxDepth(4.5f), //set to > 8000 for best performance when using the kde pipeline + EnableBilateralFilter(true), + EnableEdgeAwareFilter(true) {} + +void Freenect2DeviceImpl::setConfiguration(const Freenect2Device::Config &config) +{ + DepthPacketProcessor *proc = pipeline_->getDepthPacketProcessor(); + if (proc != 0) + proc->setConfiguration(config); +} + +void Freenect2DeviceImpl::setColorFrameListener(libfreenect2::FrameListener* rgb_frame_listener) +{ + // TODO: should only be possible, if not started + if(pipeline_->getRgbPacketProcessor() != 0) + pipeline_->getRgbPacketProcessor()->setFrameListener(rgb_frame_listener); +} + +void Freenect2DeviceImpl::setIrAndDepthFrameListener(libfreenect2::FrameListener* ir_frame_listener) +{ + // TODO: should only be possible, if not started + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->setFrameListener(ir_frame_listener); +} + +void Freenect2DeviceImpl::setColorAutoExposure(float exposure_compensation) +{ + CommandTransaction::Result result; + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ACS, 0u), result); + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_MODE, 0u), result); // 0 == Fully auto + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_COMPENSATION, exposure_compensation), result); +} + +void Freenect2DeviceImpl::setColorSemiAutoExposure(float pseudo_exposure_time_ms) +{ + CommandTransaction::Result result; + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ACS, 0u), result); + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_MODE, 3u), result); // 3 == Semi-auto + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_TIME_MS, pseudo_exposure_time_ms), result); +} + +void Freenect2DeviceImpl::setColorManualExposure(float integration_time_ms, float analog_gain) +{ + CommandTransaction::Result result; + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ACS, 0u), result); + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_EXPOSURE_MODE, 4u), result); // 4 == Fully manual + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_INTEGRATION_TIME, integration_time_ms), result); + command_tx_.execute(ColorSettingCommand(COLOR_SETTING_SET_ANALOG_GAIN, analog_gain), result); +} + +void Freenect2DeviceImpl::setColorSetting(ColorSettingCommandType cmd, uint32_t value) +{ + CommandTransaction::Result result; + command_tx_.execute(ColorSettingCommand(cmd, value), result); +} + +void Freenect2DeviceImpl::setColorSetting(ColorSettingCommandType cmd, float value) +{ + CommandTransaction::Result result; + command_tx_.execute(ColorSettingCommand(cmd, value), result); +} + +uint32_t Freenect2DeviceImpl::getColorSetting(ColorSettingCommandType cmd) +{ + CommandTransaction::Result result; + command_tx_.execute(ColorSettingCommand(cmd), result); + if (result.size() < sizeof(ColorSettingResponse)) + { + LOG_WARNING << "failed to get color setting, response size " << result.size() << " too small, expected " << sizeof(ColorSettingResponse); + return 0u; + } + ColorSettingResponse const* data = reinterpret_cast(&result[0]); + return data->Data; +} + +float Freenect2DeviceImpl::getColorSettingFloat(ColorSettingCommandType cmd) +{ + uint32_t data = getColorSetting(cmd); + float out; + memcpy(&out, &data, sizeof(out)); + return out; +} + +void Freenect2DeviceImpl::setLedStatus(LedSettings led) +{ + CommandTransaction::Result result; + command_tx_.execute(LedSettingCommand(led), result); +} + +bool Freenect2DeviceImpl::open() +{ + LOG_INFO << "opening..."; + + if(state_ != Created) return false; + + if(usb_control_.setConfiguration() != UsbControl::Success) return false; + if(!has_usb_interfaces_ && usb_control_.claimInterfaces() != UsbControl::Success) return false; + has_usb_interfaces_ = true; + + if(usb_control_.setIsochronousDelay() != UsbControl::Success) return false; + // TODO: always fails right now with error 6 - TRANSFER_OVERFLOW! + //if(usb_control_.setPowerStateLatencies() != UsbControl::Success) return false; + if(usb_control_.setIrInterfaceState(UsbControl::Disabled) != UsbControl::Success) return false; + if(usb_control_.enablePowerStates() != UsbControl::Success) return false; + if(usb_control_.setVideoTransferFunctionState(UsbControl::Disabled) != UsbControl::Success) return false; + + int max_iso_packet_size; + if(usb_control_.getIrMaxIsoPacketSize(max_iso_packet_size) != UsbControl::Success) return false; + + if(max_iso_packet_size < 0x8400) + { + LOG_ERROR << "max iso packet size for endpoint 0x84 too small! (expected: " << 0x8400 << " got: " << max_iso_packet_size << ")"; + return false; + } + + unsigned rgb_xfer_size = 0x4000; + unsigned rgb_num_xfers = 20; + unsigned ir_pkts_per_xfer = 8; + unsigned ir_num_xfers = 60; + +#if defined(__APPLE__) + ir_pkts_per_xfer = 128; + ir_num_xfers = 4; +#elif defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + // For multi-Kinect setup, there is a 64 fd limit on poll(). + rgb_xfer_size = 1048576; + rgb_num_xfers = 3; + ir_pkts_per_xfer = 64; + ir_num_xfers = 8; +#endif + + const char *xfer_str; + xfer_str = std::getenv("LIBFREENECT2_RGB_TRANSFER_SIZE"); + if(xfer_str) rgb_xfer_size = std::atoi(xfer_str); + xfer_str = std::getenv("LIBFREENECT2_RGB_TRANSFERS"); + if(xfer_str) rgb_num_xfers = std::atoi(xfer_str); + xfer_str = std::getenv("LIBFREENECT2_IR_PACKETS"); + if(xfer_str) ir_pkts_per_xfer = std::atoi(xfer_str); + xfer_str = std::getenv("LIBFREENECT2_IR_TRANSFERS"); + if(xfer_str) ir_num_xfers = std::atoi(xfer_str); + + LOG_INFO << "transfer pool sizes" + << " rgb: " << rgb_num_xfers << "*" << rgb_xfer_size + << " ir: " << ir_num_xfers << "*" << ir_pkts_per_xfer << "*" << max_iso_packet_size; + rgb_transfer_pool_.allocate(rgb_num_xfers, rgb_xfer_size); + ir_transfer_pool_.allocate(ir_num_xfers, ir_pkts_per_xfer, max_iso_packet_size); + + state_ = Open; + + LOG_INFO << "opened"; + + return true; +} + +bool Freenect2DeviceImpl::start() +{ + return startStreams(true, true); +} + +bool Freenect2DeviceImpl::startStreams(bool enable_rgb, bool enable_depth) +{ + LOG_INFO << "starting..."; + if(state_ != Open) return false; + + CommandTransaction::Result serial_result, firmware_result, result; + + if (usb_control_.setVideoTransferFunctionState(UsbControl::Enabled) != UsbControl::Success) return false; + + if (!command_tx_.execute(ReadFirmwareVersionsCommand(nextCommandSeq()), firmware_result)) return false; + firmware_ = FirmwareVersionResponse(firmware_result).toString(); + + if (!command_tx_.execute(ReadHardwareInfoCommand(nextCommandSeq()), result)) return false; + //The hardware version is currently useless. It is only used to select the + //IR normalization table, but we don't have that. + + if (!command_tx_.execute(ReadSerialNumberCommand(nextCommandSeq()), serial_result)) return false; + std::string new_serial = SerialNumberResponse(serial_result).toString(); + + if(serial_ != new_serial) + { + LOG_WARNING << "serial number reported by libusb " << serial_ << " differs from serial number " << new_serial << " in device protocol! "; + } + + if (!command_tx_.execute(ReadDepthCameraParametersCommand(nextCommandSeq()), result)) return false; + setIrCameraParams(DepthCameraParamsResponse(result).toIrCameraParams()); + + if (!command_tx_.execute(ReadP0TablesCommand(nextCommandSeq()), result)) return false; + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->loadP0TablesFromCommandResponse(&result[0], result.size()); + + if (!command_tx_.execute(ReadRgbCameraParametersCommand(nextCommandSeq()), result)) return false; + setColorCameraParams(RgbCameraParamsResponse(result).toColorCameraParams()); + + if (!command_tx_.execute(SetModeEnabledWith0x00640064Command(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result)) return false; + + int timeout = 50; // about 5 seconds (100ms x 50) + for (uint32_t status = 0, last = 0; (status & 1) == 0 && 0 < timeout; last = status, timeout--) + { + if (!command_tx_.execute(ReadStatus0x090000Command(nextCommandSeq()), result)) return false; + status = Status0x090000Response(result).toNumber(); + if (status != last) + LOG_DEBUG << "status 0x090000: " << status; + if ((status & 1) == 0) + this_thread::sleep_for(chrono::milliseconds(100)); + } + if (timeout == 0) { + LOG_DEBUG << "status 0x090000: timeout"; + } + + if (!command_tx_.execute(InitStreamsCommand(nextCommandSeq()), result)) return false; + + if (usb_control_.setIrInterfaceState(UsbControl::Enabled) != UsbControl::Success) return false; + + if (!command_tx_.execute(ReadStatus0x090000Command(nextCommandSeq()), result)) return false; + LOG_DEBUG << "status 0x090000: " << Status0x090000Response(result).toNumber(); + + if (!command_tx_.execute(SetStreamEnabledCommand(nextCommandSeq()), result)) return false; + + //command_tx_.execute(Unknown0x47Command(nextCommandSeq()), result); + //command_tx_.execute(Unknown0x46Command(nextCommandSeq()), result); +/* + command_tx_.execute(SetModeEnabledCommand(nextCommandSeq()), result); + command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result); + + usb_control_.setIrInterfaceState(UsbControl::Enabled); + + command_tx_.execute(SetModeEnabledWith0x00640064Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); + command_tx_.execute(ReadStatus0x100007Command(nextCommandSeq()), result); + command_tx_.execute(SetModeEnabledWith0x00500050Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); + command_tx_.execute(ReadStatus0x100007Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); + command_tx_.execute(ReadData0x26Command(nextCommandSeq()), result); +*/ + if (enable_rgb) + { + LOG_INFO << "submitting rgb transfers..."; + rgb_transfer_pool_.enableSubmission(); + if (!rgb_transfer_pool_.submit()) return false; + } + + if (enable_depth) + { + LOG_INFO << "submitting depth transfers..."; + ir_transfer_pool_.enableSubmission(); + if (!ir_transfer_pool_.submit()) return false; + } + + state_ = Streaming; + LOG_INFO << "started"; + return true; +} + +bool Freenect2DeviceImpl::stop() +{ + LOG_INFO << "stopping..."; + + if(state_ != Streaming) + { + LOG_INFO << "already stopped, doing nothing"; + return false; + } + + if (rgb_transfer_pool_.enabled()) + { + LOG_INFO << "canceling rgb transfers..."; + rgb_transfer_pool_.disableSubmission(); + rgb_transfer_pool_.cancel(); + } + + if (ir_transfer_pool_.enabled()) + { + LOG_INFO << "canceling depth transfers..."; + ir_transfer_pool_.disableSubmission(); + ir_transfer_pool_.cancel(); + } + + if (usb_control_.setIrInterfaceState(UsbControl::Disabled) != UsbControl::Success) return false; + + CommandTransaction::Result result; + if (!command_tx_.execute(SetModeEnabledWith0x00640064Command(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(StopCommand(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetStreamDisabledCommand(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetModeEnabledCommand(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetModeEnabledCommand(nextCommandSeq()), result)) return false; + if (!command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result)) return false; + + if (usb_control_.setVideoTransferFunctionState(UsbControl::Disabled) != UsbControl::Success) return false; + + state_ = Open; + LOG_INFO << "stopped"; + return true; +} + +bool Freenect2DeviceImpl::close() +{ + LOG_INFO << "closing..."; + + if(state_ == Closed) + { + LOG_INFO << "already closed, doing nothing"; + return true; + } + + if(state_ == Streaming) + { + stop(); + } + + CommandTransaction::Result result; + command_tx_.execute(SetModeEnabledWith0x00640064Command(nextCommandSeq()), result); + command_tx_.execute(SetModeDisabledCommand(nextCommandSeq()), result); + /* This command actually reboots the device and makes it disappear for 3 seconds. + * Protonect can restart instantly without it. + */ +#ifdef __APPLE__ + /* Kinect will disappear on Mac OS X regardless during close(). + * Painstaking effort could not determine the root cause. + * See https://github.com/OpenKinect/libfreenect2/issues/539 + * + * Shut down Kinect explicitly on Mac and wait a fixed time. + */ + command_tx_.execute(ShutdownCommand(nextCommandSeq()), result); + libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(4*1000)); +#endif + + if(pipeline_->getRgbPacketProcessor() != 0) + pipeline_->getRgbPacketProcessor()->setFrameListener(0); + + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->setFrameListener(0); + + if(has_usb_interfaces_) + { + LOG_INFO << "releasing usb interfaces..."; + + usb_control_.releaseInterfaces(); + has_usb_interfaces_ = false; + } + + LOG_INFO << "deallocating usb transfer pools..."; + rgb_transfer_pool_.deallocate(); + ir_transfer_pool_.deallocate(); + + LOG_INFO << "closing usb device..."; + + libusb_close(usb_device_handle_); + usb_device_handle_ = 0; + usb_device_ = 0; + + state_ = Closed; + LOG_INFO << "closed"; + return true; +} + +PacketPipeline *createPacketPipelineByName(std::string name) +{ +#if defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) + if (name == "gl") + return new OpenGLPacketPipeline(); +#endif +#if defined(LIBFREENECT2_WITH_CUDA_SUPPORT) + if (name == "cuda") + return new CudaPacketPipeline(); +#endif +#if defined(LIBFREENECT2_WITH_OPENCL_SUPPORT) + if (name == "cl") + return new OpenCLPacketPipeline(); +#endif + if (name == "cpu") + return new CpuPacketPipeline(); + return NULL; +} + +PacketPipeline *createDefaultPacketPipeline() +{ + const char *pipeline_env = std::getenv("LIBFREENECT2_PIPELINE"); + if (pipeline_env) + { + PacketPipeline *pipeline = createPacketPipelineByName(pipeline_env); + if (pipeline) + return pipeline; + else + LOG_WARNING << "`" << pipeline_env << "' pipeline is not available."; + } + +#if defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) + return new OpenGLPacketPipeline(); +#elif defined(LIBFREENECT2_WITH_CUDA_SUPPORT) + return new CudaPacketPipeline(); +#elif defined(LIBFREENECT2_WITH_OPENCL_SUPPORT) + return new OpenCLPacketPipeline(); +#else + return new CpuPacketPipeline(); +#endif +} + +Freenect2::Freenect2(void *usb_context) : + impl_(new Freenect2Impl(usb_context)) +{ +} + +Freenect2::~Freenect2() +{ + delete impl_; +} + +int Freenect2::enumerateDevices() +{ + impl_->clearDeviceEnumeration(); + return impl_->getNumDevices(); +} + +std::string Freenect2::getDeviceSerialNumber(int idx) +{ + if (!impl_->initialized) + return std::string(); + if (idx >= impl_->getNumDevices() || idx < 0) + return std::string(); + + return impl_->enumerated_devices_[idx].serial; +} + +std::string Freenect2::getDefaultDeviceSerialNumber() +{ + return getDeviceSerialNumber(0); +} + +Freenect2Device *Freenect2::openDevice(int idx) +{ + return openDevice(idx, createDefaultPacketPipeline()); +} + +Freenect2Device *Freenect2::openDevice(int idx, const PacketPipeline *pipeline) +{ + return impl_->openDevice(idx, pipeline, true); +} + +Freenect2Device *Freenect2Impl::openDevice(int idx, const PacketPipeline *pipeline, bool attempting_reset) +{ + int num_devices = getNumDevices(); + Freenect2DeviceImpl *device = 0; + + if(idx >= num_devices) + { + LOG_ERROR << "requested device " << idx << " is not connected!"; + delete pipeline; + + return device; + } + + Freenect2Impl::UsbDeviceWithSerial &dev = enumerated_devices_[idx]; + libusb_device_handle *dev_handle; + + if(tryGetDevice(dev.dev, &device)) + { + LOG_WARNING << "device " << PrintBusAndDevice(dev.dev) + << " is already be open!"; + delete pipeline; + + return device; + } + + int r; + for (int i = 0; i < 10; i++) + { + r = libusb_open(dev.dev, &dev_handle); + if(r == LIBUSB_SUCCESS) + { + break; + } + LOG_INFO << "device unavailable right now, retrying"; + this_thread::sleep_for(chrono::milliseconds(100)); + } + + if(r != LIBUSB_SUCCESS) + { + LOG_ERROR << "failed to open Kinect v2: " << PrintBusAndDevice(dev.dev, r); + delete pipeline; + + return device; + } + + if(attempting_reset) + { + r = libusb_reset_device(dev_handle); + + if(r == LIBUSB_ERROR_NOT_FOUND) + { + // From libusb documentation: + // "If the reset fails, the descriptors change, or the previous state + // cannot be restored, the device will appear to be disconnected and + // reconnected. This means that the device handle is no longer valid (you + // should close it) and rediscover the device. A return code of + // LIBUSB_ERROR_NOT_FOUND indicates when this is the case." + + // be a good citizen + libusb_close(dev_handle); + + // HACK: wait for the planets to align... (When the reset fails it may + // take a short while for the device to show up on the bus again. In the + // absence of hotplug support, we just wait a little. If this code path + // is followed there will already be a delay opening the device fully so + // adding a little more is tolerable.) + libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(1000)); + + // reenumerate devices + LOG_INFO << "re-enumerating devices after reset"; + clearDeviceEnumeration(); + enumerateDevices(); + + // re-open without reset + return openDevice(idx, pipeline, false); + } + else if(r != LIBUSB_SUCCESS) + { + LOG_ERROR << "failed to reset Kinect v2: " << PrintBusAndDevice(dev.dev, r); + delete pipeline; + + return device; + } + } + + device = new Freenect2DeviceImpl(this, pipeline, dev.dev, dev_handle, dev.serial); + addDevice(device); + + if(!device->open()) + { + delete device; + device = 0; + + LOG_ERROR << "failed to open Kinect v2: " << PrintBusAndDevice(dev.dev); + } + + return device; +} + +Freenect2Device *Freenect2::openDevice(const std::string &serial) +{ + return openDevice(serial, createDefaultPacketPipeline()); +} + +Freenect2Device *Freenect2::openDevice(const std::string &serial, const PacketPipeline *pipeline) +{ + Freenect2Device *device = 0; + int num_devices = impl_->getNumDevices(); + + for(int idx = 0; idx < num_devices; ++idx) + { + if(impl_->enumerated_devices_[idx].serial == serial) + { + return openDevice(idx, pipeline); + } + } + + delete pipeline; + return device; +} + +Freenect2Device *Freenect2::openDefaultDevice() +{ + return openDevice(0); +} + +Freenect2Device *Freenect2::openDefaultDevice(const PacketPipeline *pipeline) +{ + return openDevice(0, pipeline); +} + +Freenect2ReplayDevice::Freenect2ReplayDevice(Freenect2ReplayImpl *context, const std::vector& frame_filenames, const PacketPipeline* pipeline) + :context_(context), pipeline_(pipeline), frame_filenames_(frame_filenames), running_(false) +{ + size_t single_image = 512*424*11/8; + buffer_size_ = 10 * single_image; + pipeline_->getDepthPacketProcessor()->allocateBuffer(packet_, buffer_size_); +} + +Freenect2ReplayDevice::~Freenect2ReplayDevice() +{ + close(); + context_->removeDevice(this); + delete pipeline_; +} + +std::string Freenect2ReplayDevice::getSerialNumber() +{ + // Reasonable assumption given it is a software serial for apps that display this + return LIBFREENECT2_VERSION; +} + +std::string Freenect2ReplayDevice::getFirmwareVersion() +{ + // Reasonable assumption given it is a software serial for apps that display this + return LIBFREENECT2_VERSION; +} + +Freenect2Device::ColorCameraParams Freenect2ReplayDevice::getColorCameraParams() +{ + return rgb_camera_params_; +} + +Freenect2Device::IrCameraParams Freenect2ReplayDevice::getIrCameraParams() +{ + return ir_camera_params_; +} + +void Freenect2ReplayDevice::setColorCameraParams(const Freenect2Device::ColorCameraParams ¶ms) +{ + rgb_camera_params_ = params; +} + +void Freenect2ReplayDevice::setIrCameraParams(const Freenect2Device::IrCameraParams ¶ms) +{ + ir_camera_params_ = params; + DepthPacketProcessor *proc = pipeline_->getDepthPacketProcessor(); + if (proc != 0) + { + IrCameraTables tables(params); + proc->loadXZTables(&tables.xtable[0], &tables.ztable[0]); + proc->loadLookupTable(&tables.lut[0]); + } +} + +void Freenect2ReplayDevice::setConfiguration(const Freenect2Device::Config &config) +{ + DepthPacketProcessor *proc = pipeline_->getDepthPacketProcessor(); + if (proc != 0) + proc->setConfiguration(config); +} + +void Freenect2ReplayDevice::setColorFrameListener(FrameListener* listener) +{ + RgbPacketProcessor* proc = pipeline_->getRgbPacketProcessor(); + if (proc != NULL) + { + proc->setFrameListener(listener); + } +} + +void Freenect2ReplayDevice::setIrAndDepthFrameListener(FrameListener* listener) +{ + DepthPacketProcessor* proc = pipeline_->getDepthPacketProcessor(); + if (proc != NULL) + { + proc->setFrameListener(listener); + } +} + +bool Freenect2ReplayDevice::open() +{ + LOG_INFO << "opening..."; + + // May add file checking or params loading + + return true; +} + +bool Freenect2ReplayDevice::close() +{ + LOG_INFO << "closing..."; + + if(running_ == false) + { + LOG_INFO << "already closed, doing nothing"; + return true; + } + + if(running_ == true) + { + stop(); + } + + if(pipeline_->getRgbPacketProcessor() != 0) + pipeline_->getRgbPacketProcessor()->setFrameListener(0); + + if(pipeline_->getDepthPacketProcessor() != 0) + pipeline_->getDepthPacketProcessor()->setFrameListener(0); + + running_ = false; + LOG_INFO << "closed"; + return true; +} + +bool Freenect2ReplayDevice::processRawFrame(Frame::Type type, Frame* frame) +{ + if (frame->format != Frame::Raw) + { + return false; + } + switch (type) + { + case Frame::Color: + processRgbFrame(frame); + break; + case Frame::Depth: + processDepthFrame(frame); + break; + default: + return false; + } + return true; +} + +void Freenect2ReplayDevice::processRgbFrame(Frame* frame) +{ + RgbPacket packet; + + packet.timestamp = frame->timestamp; + packet.sequence = frame->sequence; + packet.jpeg_buffer = frame->data; + packet.jpeg_buffer_length = frame->bytes_per_pixel; + packet.exposure = frame->exposure; + packet.gain = frame->gain; + packet.gamma = frame->gamma; + + pipeline_->getRgbPacketProcessor()->process(packet); +} + +void Freenect2ReplayDevice::processDepthFrame(Frame* frame) +{ + DepthPacket packet; + + packet.timestamp = frame->timestamp; + packet.sequence = frame->sequence; + packet.buffer = frame->data; + packet.buffer_length = frame->bytes_per_pixel; + + pipeline_->getDepthPacketProcessor()->process(packet); +} + +void Freenect2ReplayDevice::loadP0Tables(unsigned char* buffer, size_t buffer_length) +{ + pipeline_->getDepthPacketProcessor()->loadP0TablesFromCommandResponse(buffer, buffer_length); +} + +void Freenect2ReplayDevice::static_execute(void* arg) +{ + static_cast(arg)->run(); +} + +bool Freenect2ReplayDevice::start() +{ + running_ = true; + t_ = new libfreenect2::thread(static_execute, this); + LOG_INFO << "replay started"; + return running_; +} + +bool Freenect2ReplayDevice::startStreams(bool enable_rgb, bool enable_depth) +{ + LOG_INFO << "Freenect2ReplayDevice: starting: rgb: " << enable_rgb << ", depth: " << enable_depth; + LOG_INFO << "Freenect2ReplayDevice: unimplemented"; + return false; +} + +bool Freenect2ReplayDevice::stop() +{ + running_ = false; + t_->join(); + delete t_; + t_ = NULL; + LOG_INFO << "replay stopped"; + return true; +} + +bool hasSuffix(const std::string& str, const std::string& suffix) +{ + if (str.length() < suffix.length()) + { + return false; + } + return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; +} + +bool parseFrameFilename(const std::string& frame_filename, size_t timestamp_sequence[2]) +{ + LOG_DEBUG << "parsing: " << frame_filename; + + if (!hasSuffix(frame_filename, ".depth") && + !hasSuffix(frame_filename, ".jpg") && + !hasSuffix(frame_filename, ".jpeg")) + { + LOG_ERROR << "wrong suffix in the filename; need .depth, .jpg, or .jpeg"; + return false; + } + + size_t ix1 = frame_filename.find("_"); + size_t ix2 = frame_filename.find("_", ix1 + 1); + size_t ix3 = frame_filename.find(".", ix2 + 1); + + std::string ts = frame_filename.substr(0, ix1); + std::string seq = frame_filename.substr(ix2 + 1, ix3); + + LOG_DEBUG << "ts: " << ts << ", seq: " << seq; + + if(ts.size() == 0 || seq.size() == 0) + { + LOG_ERROR << "could not extract timestamp or sequence"; + return false; + } + + timestamp_sequence[0] = atoi(ts.c_str()); + timestamp_sequence[1] = atoi(seq.c_str()); + + LOG_DEBUG << "ts: " << timestamp_sequence[0] << ", seq: " << timestamp_sequence[1]; + + if(timestamp_sequence[0] == 0) + { + LOG_WARNING << "invalid timestamp"; + return false; + } + + return true; +} + +void Freenect2ReplayDevice::run() +{ + size_t timestamp_sequence[2] = {0}; + + for (size_t i = 0; i < frame_filenames_.size() && running_; i++) + { + std::string frame = frame_filenames_[i]; + + if(parseFrameFilename(frame, timestamp_sequence) == false) + { + LOG_ERROR << "could not parse replay frame filename " << frame << ", skipping..."; + continue; + } + + if (hasSuffix(frame, ".depth")) + { + std::ifstream fd(frame.c_str()); + + if(!fd) + { + LOG_ERROR << "failed to open replay frame: " << frame << ", skipping..."; + continue; + } + + fd.seekg(0, fd.end); + size_t length = fd.tellg(); + fd.seekg(0, fd.beg); + + if(length != buffer_size_) + { + LOG_ERROR << "file length: " << length + << "exceeds depth image buffer size: " + << buffer_size_ << "; skipping..."; + continue; + } + + fd.read(reinterpret_cast(packet_.memory->data), length); + if(!fd || (size_t)fd.gcount() != length) + { + LOG_ERROR << "failed to read replay frame: " << frame << ": " + << fd.gcount() << " vs. " << length << " bytes"; + continue; + } + + if(pipeline_->getDepthPacketProcessor()->ready()) + { + packet_.timestamp = timestamp_sequence[0]; + packet_.sequence = timestamp_sequence[1]; + packet_.buffer = packet_.memory->data; + packet_.buffer_length = length; + + pipeline_->getDepthPacketProcessor()->process(packet_); + pipeline_->getDepthPacketProcessor()->allocateBuffer(packet_, buffer_size_); + } + else + { + LOG_DEBUG + << "skipping a replay depth packet for " << frame + << " as depth processor is not ready"; + } + } + } +} + +Freenect2Replay::Freenect2Replay() : + impl_(new Freenect2ReplayImpl) +{ +} + +Freenect2Replay::~Freenect2Replay() +{ + delete impl_; +} + +Freenect2Device *Freenect2Replay::openDevice(const std::vector& frame_filenames) +{ + return openDevice(frame_filenames, createDefaultPacketPipeline()); +} + +Freenect2Device *Freenect2Replay::openDevice(const std::vector& frame_filenames, const PacketPipeline *pipeline) +{ + return impl_->openDevice(frame_filenames, pipeline); +} + +Freenect2Device *Freenect2ReplayImpl::openDevice(const std::vector& frame_filenames, const PacketPipeline *pipeline) +{ + Freenect2ReplayDevice *device = new Freenect2ReplayDevice(this, frame_filenames, pipeline); + addDevice(device); + + if(!device->open()) + { + delete device; + device = 0; + LOG_ERROR << "failed to instantiate a replay device!"; + } + + return device; +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/logging.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/logging.cpp new file mode 100644 index 0000000..71a1135 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/logging.cpp @@ -0,0 +1,334 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2015 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file logging.cpp Logging message handler classes. */ + +#include +#include +#include +#include +#include + +#ifdef LIBFREENECT2_WITH_PROFILING +#include +#include +#include +#endif + +#ifdef LIBFREENECT2_WITH_CXX11_SUPPORT +#include +#endif + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +#include +#endif + +namespace libfreenect2 +{ +Logger::~Logger() {} + + +Logger::Level Logger::getDefaultLevel() +{ + Logger::Level l = Logger::Info; + + char *env_logger_level_c_str = getenv("LIBFREENECT2_LOGGER_LEVEL"); + + if(env_logger_level_c_str != 0) + { + std::string env_logger_level_str(env_logger_level_c_str); + std::transform(env_logger_level_str.begin(), env_logger_level_str.end(), env_logger_level_str.begin(), ::tolower); + + if(env_logger_level_str == "debug") + l = Logger::Debug; + else if(env_logger_level_str == "info") + l = Logger::Info; + else if(env_logger_level_str == "warning") + l = Logger::Warning; + else if(env_logger_level_str == "error") + l = Logger::Error; + else if(env_logger_level_str == "none") + l = Logger::None; + } + + return l; +} + +Logger::Level Logger::level() const +{ + return level_; +} + +std::string Logger::level2str(Level l) +{ + switch(l) + { + case Logger::Debug: + return "Debug"; + case Logger::Info: + return "Info"; + case Logger::Warning: + return "Warning"; + case Logger::Error: + return "Error"; + default: + return ""; + } +} + +/** Logger class to the console (stderr). */ +class ConsoleLogger : public Logger +{ +public: + ConsoleLogger(Level level) + { + level_ = level; + //std::ios_base::unitbuf causes automatic flushing which access + //thread local variable via std::uncaught_exception(). + //This causes deadlock with ocl-icd until its recent update. + //Accessing TLS has a slight performance penalty. + //log() always flush the ostream so unitbuf is unnecessary anyway. + std::nounitbuf(std::cerr); + } + virtual ~ConsoleLogger() {} + virtual void log(Level level, const std::string &message) + { + if(level > level_) return; + + (level <= Warning ? std::cerr : std::cout) << "[" << level2str(level) << "] " << message << std::endl; + } +}; + +Logger *createConsoleLogger(Logger::Level level) +{ + return new ConsoleLogger(level); +} + +Logger *createConsoleLoggerWithDefaultLevel() +{ + return new ConsoleLogger(Logger::getDefaultLevel()); +} + +LogMessage::LogMessage(Logger *logger, Logger::Level level) : logger_(logger), level_(level) +{ + +} + +std::string getShortName(const char *func) +{ + std::string src(func); + size_t end = src.rfind('('); + if (end == std::string::npos) + end = src.size(); + size_t begin = 1 + src.rfind(' ', end); + size_t first_ns = src.find("::", begin); + if (first_ns != std::string::npos) + begin = first_ns + 2; + size_t last_ns = src.rfind("::", end); + if (last_ns != std::string::npos) + end = last_ns; + return src.substr(begin, end - begin); +} + +LogMessage::LogMessage(Logger *logger, Logger::Level level, const char *source): + logger_(logger), level_(level) +{ + stream_ << "[" << getShortName(source) << "] "; +} + +LogMessage::~LogMessage() +{ + if(logger_ != 0 && stream_.good()) + { + const std::string &message = stream_.str(); + if (message.size()) + logger_->log(level_, message); + } +} + +std::ostream &LogMessage::stream() +{ + return stream_; +} + +static ConsoleLogger defaultLogger_(Logger::getDefaultLevel()); +static Logger *userLogger_ = &defaultLogger_; + +Logger *getGlobalLogger() +{ + return userLogger_; +} + +void setGlobalLogger(Logger *logger) +{ + if (userLogger_ != &defaultLogger_) + delete userLogger_; + userLogger_ = logger; +} + +/** Timer for measuring performance. */ +class Timer +{ + public: + double duration; + size_t count; + + Timer() + { +#if defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) + glfwInit(); +#endif + reset(); + } + + void reset() + { + duration = 0; + count = 0; + } + +#ifdef LIBFREENECT2_WITH_CXX11_SUPPORT + std::chrono::time_point time_start; + + void start() + { + time_start = std::chrono::high_resolution_clock::now(); + } + + double stop() + { + auto time_diff = std::chrono::high_resolution_clock::now() - time_start; + double this_duration = std::chrono::duration_cast>(time_diff).count(); + duration += this_duration; + count++; + return this_duration; + } +#elif defined(LIBFREENECT2_WITH_OPENGL_SUPPORT) + double time_start; + + void start() + { + time_start = glfwGetTime(); + } + + double stop() + { + double this_duration = glfwGetTime() - time_start; + duration += this_duration; + count++; + return this_duration; + } +#else + void start() + { + } + + double stop() + { + return 0; + } +#endif +}; + +class WithPerfLoggingImpl: public Timer +{ +public: +#ifdef LIBFREENECT2_WITH_PROFILING + std::vector stats; + std::string name; + + WithPerfLoggingImpl() + { + stats.reserve(30*100); + } + + ~WithPerfLoggingImpl() + { + if (stats.size() < 2) + return; + std::vector &v = stats; + std::sort(v.begin(), v.end()); + double sum = std::accumulate(v.begin(), v.end(), 0.0); + size_t n = v.size(); + double mean = sum / n; + std::vector diff(n); + for (size_t i = 0; i < n; ++i) + { + diff[i] = v[i] - mean; + } + double sqsum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); + double std = std::sqrt(sqsum / (n-1)); + + std::cout << name << v[0] << " " << v[n/20] << " " << v[n/2] << " " << v[n - (n+19)/20] << " " << v[n-1] << " mean=" << mean << " std=" << std << " n=" << n << std::endl; + } +#endif + + std::ostream &stop(std::ostream &stream) + { +#ifndef LIBFREENECT2_WITH_PROFILING + Timer::stop(); +#else + double this_duration = Timer::stop(); + if (name.empty()) + { + std::stringstream &ss = static_cast(stream); + name = ss.str(); + } + stats.push_back(this_duration*1e3); +#endif + if (count < 100) + { + stream.setstate(std::ios::eofbit); + return stream; + } + double avg = duration / count; + reset(); + stream << "avg. time: " << (avg * 1000) << "ms -> ~" << (1.0/avg) << "Hz"; + return stream; + } +}; + +WithPerfLogging::WithPerfLogging() + :impl_(new WithPerfLoggingImpl) +{ +} + +WithPerfLogging::~WithPerfLogging() +{ + delete impl_; +} + +void WithPerfLogging::startTiming() +{ + impl_->start(); +} + +std::ostream &WithPerfLogging::stopTiming(std::ostream &stream) +{ + return impl_->stop(stream); +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cl b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cl new file mode 100644 index 0000000..bdce0a4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cl @@ -0,0 +1,378 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#define PHASE (float3)(PHASE_IN_RAD0, PHASE_IN_RAD1, PHASE_IN_RAD2) +#define AB_MULTIPLIER_PER_FRQ (float3)(AB_MULTIPLIER_PER_FRQ0, AB_MULTIPLIER_PER_FRQ1, AB_MULTIPLIER_PER_FRQ2) + +/******************************************************************************* + * Process pixel stage 1 + ******************************************************************************/ + +float decodePixelMeasurement(global const ushort *data, global const short *lut11to16, const uint sub, const uint x, const uint y) +{ + uint row_idx = (424 * sub + y) * 352; + uint idx = (((x >> 2) + ((x << 7) & BFI_BITMASK)) * 11) & (uint)0xffffffff; + + uint col_idx = idx >> 4; + uint upper_bytes = idx & 15; + uint lower_bytes = 16 - upper_bytes; + + uint data_idx0 = row_idx + col_idx; + uint data_idx1 = row_idx + col_idx + 1; + + return (float)lut11to16[(x < 1 || 510 < x || col_idx > 352) ? 0 : ((data[data_idx0] >> upper_bytes) | (data[data_idx1] << lower_bytes)) & 2047]; +} + +void kernel processPixelStage1(global const short *lut11to16, global const float *z_table, global const float3 *p0_table, global const ushort *data, + global float3 *a_out, global float3 *b_out, global float3 *n_out, global float *ir_out) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const uint y_tmp = (423 - y); + const uint y_in = (y_tmp < 212 ? y_tmp + 212 : 423 - y_tmp); + + const int3 invalid = (int)(0.0f >= z_table[i]); + const float3 p0 = p0_table[i]; + float3 p0x_sin, p0y_sin, p0z_sin; + float3 p0x_cos, p0y_cos, p0z_cos; + + p0x_sin = -sincos(PHASE + p0.x, &p0x_cos); + p0y_sin = -sincos(PHASE + p0.y, &p0y_cos); + p0z_sin = -sincos(PHASE + p0.z, &p0z_cos); + + int3 invalid_pixel = (int3)(invalid); + + const float3 v0 = (float3)(decodePixelMeasurement(data, lut11to16, 0, x, y_in), + decodePixelMeasurement(data, lut11to16, 1, x, y_in), + decodePixelMeasurement(data, lut11to16, 2, x, y_in)); + const float3 v1 = (float3)(decodePixelMeasurement(data, lut11to16, 3, x, y_in), + decodePixelMeasurement(data, lut11to16, 4, x, y_in), + decodePixelMeasurement(data, lut11to16, 5, x, y_in)); + const float3 v2 = (float3)(decodePixelMeasurement(data, lut11to16, 6, x, y_in), + decodePixelMeasurement(data, lut11to16, 7, x, y_in), + decodePixelMeasurement(data, lut11to16, 8, x, y_in)); + + float3 a = (float3)(dot(v0, p0x_cos), + dot(v1, p0y_cos), + dot(v2, p0z_cos)) * AB_MULTIPLIER_PER_FRQ; + float3 b = (float3)(dot(v0, p0x_sin), + dot(v1, p0y_sin), + dot(v2, p0z_sin)) * AB_MULTIPLIER_PER_FRQ; + + a = select(a, (float3)(0.0f), invalid_pixel); + b = select(b, (float3)(0.0f), invalid_pixel); + float3 n = sqrt(a * a + b * b); + + int3 saturated = (int3)(any(isequal(v0, (float3)(32767.0f))), + any(isequal(v1, (float3)(32767.0f))), + any(isequal(v2, (float3)(32767.0f)))); + + a_out[i] = select(a, (float3)(0.0f), saturated); + b_out[i] = select(b, (float3)(0.0f), saturated); + n_out[i] = n; + ir_out[i] = min(dot(select(n, (float3)(65535.0f), saturated), (float3)(0.333333333f * AB_MULTIPLIER * AB_OUTPUT_MULTIPLIER)), 65535.0f); +} + +/******************************************************************************* + * Filter pixel stage 1 + ******************************************************************************/ +void kernel filterPixelStage1(global const float3 *a, global const float3 *b, global const float3 *n, + global float3 *a_out, global float3 *b_out, global uchar *max_edge_test) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float3 self_a = a[i]; + const float3 self_b = b[i]; + + const float gaussian[9] = {GAUSSIAN_KERNEL_0, GAUSSIAN_KERNEL_1, GAUSSIAN_KERNEL_2, GAUSSIAN_KERNEL_3, GAUSSIAN_KERNEL_4, GAUSSIAN_KERNEL_5, GAUSSIAN_KERNEL_6, GAUSSIAN_KERNEL_7, GAUSSIAN_KERNEL_8}; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + a_out[i] = self_a; + b_out[i] = self_b; + max_edge_test[i] = 1; + } + else + { + float3 threshold = (float3)(JOINT_BILATERAL_THRESHOLD); + float3 joint_bilateral_exp = (float3)(JOINT_BILATERAL_EXP); + + const float3 self_norm = n[i]; + const float3 self_normalized_a = self_a / self_norm; + const float3 self_normalized_b = self_b / self_norm; + + float3 weight_acc = (float3)(0.0f); + float3 weighted_a_acc = (float3)(0.0f); + float3 weighted_b_acc = (float3)(0.0f); + float3 dist_acc = (float3)(0.0f); + + const int3 c0 = isless(self_norm * self_norm, threshold); + + threshold = select(threshold, (float3)(0.0f), c0); + joint_bilateral_exp = select(joint_bilateral_exp, (float3)(0.0f), c0); + + for(int yi = -1, j = 0; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++j, ++i_other) + { + const float3 other_a = a[i_other]; + const float3 other_b = b[i_other]; + const float3 other_norm = n[i_other]; + const float3 other_normalized_a = other_a / other_norm; + const float3 other_normalized_b = other_b / other_norm; + + const int3 c1 = isless(other_norm * other_norm, threshold); + + const float3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + const float3 weight = select(gaussian[j] * exp(-1.442695f * joint_bilateral_exp * dist), (float3)(0.0f), c1); + + weighted_a_acc += weight * other_a; + weighted_b_acc += weight * other_b; + weight_acc += weight; + dist_acc += select(dist, (float3)(0.0f), c1); + } + } + + const int3 c2 = isless((float3)(0.0f), weight_acc.xyz); + a_out[i] = select((float3)(0.0f), weighted_a_acc / weight_acc, c2); + b_out[i] = select((float3)(0.0f), weighted_b_acc / weight_acc, c2); + + max_edge_test[i] = all(isless(dist_acc, (float3)(JOINT_BILATERAL_MAX_EDGE))); + } +} + +/******************************************************************************* + * Process pixel stage 2 + ******************************************************************************/ +void kernel processPixelStage2(global const float3 *a_in, global const float3 *b_in, global const float *x_table, global const float *z_table, + global float *depth, global float *ir_sums) +{ + const uint i = get_global_id(0); + float3 a = a_in[i]; + float3 b = b_in[i]; + + float3 phase = atan2(b, a); + phase = select(phase, phase + 2.0f * M_PI_F, isless(phase, (float3)(0.0f))); + phase = select(phase, (float3)(0.0f), isnan(phase)); + float3 ir = sqrt(a * a + b * b) * AB_MULTIPLIER; + + float ir_sum = ir.x + ir.y + ir.z; + float ir_min = min(ir.x, min(ir.y, ir.z)); + float ir_max = max(ir.x, max(ir.y, ir.z)); + + float phase_final = 0.0f; + + if(ir_min >= INDIVIDUAL_AB_THRESHOLD && ir_sum >= AB_THRESHOLD) + { + float3 t = phase / (2.0f * M_PI_F) * (float3)(3.0f, 15.0f, 2.0f); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + float t5 = (floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - floor(t3)) * f1; + + bool c2 = 0.5f < fabs(t3) && fabs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI_F; + t7 *= 2.0f * M_PI_F; + t8 *= 2.0f * M_PI_F; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < AB_CONFIDENCE_SLOPE; + + float ir_x = slope_positive ? ir_min : ir_max; + + ir_x = log(ir_x); + ir_x = (ir_x * AB_CONFIDENCE_SLOPE * 0.301030f + AB_CONFIDENCE_OFFSET) * 3.321928f; + ir_x = exp(ir_x); + ir_x = clamp(ir_x, MIN_DEALIAS_CONFIDENCE, MAX_DEALIAS_CONFIDENCE); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = MAX_DEALIAS_CONFIDENCE * MAX_DEALIAS_CONFIDENCE >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase_final = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + phase_final = 0.0f < phase_final ? phase_final + PHASE_OFFSET : phase_final; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0f; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0f) / (max_depth * max_depth * 8192.0f); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + depth[i] = d; + ir_sums[i] = ir_sum; +} + +/******************************************************************************* + * Filter pixel stage 2 + ******************************************************************************/ +void kernel filterPixelStage2(global const float *depth, global const float *ir_sums, global const uchar *max_edge_test, global float *filtered) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float raw_depth = depth[i]; + const float ir_sum = ir_sums[i]; + const uchar edge_test = max_edge_test[i]; + + if(raw_depth >= MIN_DEPTH && raw_depth <= MAX_DEPTH) + { + if(x < 1 || y < 1 || x > 510 || y > 422) + { + filtered[i] = raw_depth; + } + else + { + float ir_sum_acc = ir_sum; + float squared_ir_sum_acc = ir_sum * ir_sum; + float min_depth = raw_depth; + float max_depth = raw_depth; + + for(int yi = -1; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++i_other) + { + if(i_other == i) + { + continue; + } + + const float raw_depth_other = depth[i_other]; + const float ir_sum_other = ir_sums[i_other]; + + ir_sum_acc += ir_sum_other; + squared_ir_sum_acc += ir_sum_other * ir_sum_other; + + if(0.0f < raw_depth_other) + { + min_depth = min(min_depth, raw_depth_other); + max_depth = max(max_depth, raw_depth_other); + } + } + } + + float tmp0 = sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = max(ir_sum_acc / 9.0f, EDGE_AB_AVG_MIN_VALUE); + tmp0 /= edge_avg; + + float abs_min_diff = fabs(raw_depth - min_depth); + float abs_max_diff = fabs(raw_depth - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < raw_depth && + tmp0 >= EDGE_AB_STD_DEV_THRESHOLD && + EDGE_CLOSE_DELTA_THRESHOLD < abs_min_diff && + EDGE_FAR_DELTA_THRESHOLD < abs_max_diff && + EDGE_MAX_DELTA_THRESHOLD < max_abs_diff && + EDGE_AVG_DELTA_THRESHOLD < avg_diff; + + if(!cond0) + { + if(edge_test != 0) + { + float tmp1 = 1500.0f > raw_depth ? 30.0f : 0.02f * raw_depth; + float edge_count = 0.0f; + + filtered[i] = edge_count > MAX_EDGE_COUNT ? 0.0f : raw_depth; + } + else + { + filtered[i] = 0.0f; + } + } + else + { + filtered[i] = 0.0f; + } + } + } + else + { + filtered[i] = 0.0f; + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cpp new file mode 100644 index 0000000..d8db14d --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_depth_packet_processor.cpp @@ -0,0 +1,821 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file opencl_depth_packet_processor.cl Implementation of the OpenCL depth packet processor. */ + +#include +#include +#include +#include + +#include + +#define _USE_MATH_DEFINES +#include + +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#define CL_USE_DEPRECATED_OPENCL_2_0_APIS + +#ifdef LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD +#define CL_USE_DEPRECATED_OPENCL_1_1_APIS +#include +#ifdef CL_VERSION_1_2 +#undef CL_VERSION_1_2 +#endif //CL_VERSION_1_2 +#endif //LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD + +#include + +#ifndef REG_OPENCL_FILE +#define REG_OPENCL_FILE "" +#endif + +#include + +#define CHECK_CL_PARAM(expr) do { cl_int err = CL_SUCCESS; (expr); if (err != CL_SUCCESS) { LOG_ERROR << #expr ": " << err; return false; } } while(0) +#define CHECK_CL_RETURN(expr) do { cl_int err = (expr); if (err != CL_SUCCESS) { LOG_ERROR << #expr ": " << err; return false; } } while(0) +#define CHECK_CL_ON_FAIL(expr, on_fail) do { cl_int err = (expr); if (err != CL_SUCCESS) { LOG_ERROR << #expr ": " << err; on_fail; return false; } } while(0) + +namespace libfreenect2 +{ + +std::string loadCLSource(const std::string &filename) +{ + const unsigned char *data; + size_t length = 0; + + if(!loadResource(filename, &data, &length)) + { + LOG_ERROR << "failed to load cl source!"; + return ""; + } + + return std::string(reinterpret_cast(data), length); +} + +class OpenCLDepthPacketProcessorImpl; + +class OpenCLBuffer: public Buffer +{ +public: + cl::Buffer buffer; +}; + +class OpenCLAllocator: public Allocator +{ +private: + cl::Context &context; + cl::CommandQueue &queue; + const bool isInputBuffer; + + bool allocate_opencl(OpenCLBuffer *b, size_t size) + { + if(isInputBuffer) + { + CHECK_CL_PARAM(b->buffer = cl::Buffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, size, NULL, &err)); + CHECK_CL_PARAM(b->data = (unsigned char*)queue.enqueueMapBuffer(b->buffer, CL_TRUE, CL_MAP_WRITE, 0, size, NULL, NULL, &err)); + } + else + { + CHECK_CL_PARAM(b->buffer = cl::Buffer(context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, size, NULL, &err)); + CHECK_CL_PARAM(b->data = (unsigned char*)queue.enqueueMapBuffer(b->buffer, CL_TRUE, CL_MAP_READ, 0, size, NULL, NULL, &err)); + } + + b->length = 0; + b->capacity = size; + return true; + } + + bool release_opencl(OpenCLBuffer *b) + { + cl::Event event; + CHECK_CL_RETURN(queue.enqueueUnmapMemObject(b->buffer, b->data, NULL, &event)); + CHECK_CL_RETURN(event.wait()); + return true; + } + +public: + OpenCLAllocator(cl::Context &context, cl::CommandQueue &queue, bool isInputBuffer) : context(context), queue(queue), isInputBuffer(isInputBuffer) + { + } + + virtual Buffer *allocate(size_t size) + { + OpenCLBuffer *b = new OpenCLBuffer(); + if(!allocate_opencl(b, size)) + b->data = NULL; + return b; + } + + virtual void free(Buffer *b) + { + if(b == NULL) + return; + release_opencl(static_cast(b)); + delete b; + } +}; + +class OpenCLFrame: public Frame +{ +private: + OpenCLBuffer *buffer; + +public: + OpenCLFrame(OpenCLBuffer *buffer) + : Frame(512, 424, 4, (unsigned char*)-1) + , buffer(buffer) + { + data = buffer->data; + } + + virtual ~OpenCLFrame() + { + buffer->allocator->free(buffer); + data = NULL; + } +}; + +class OpenCLDepthPacketProcessorImpl: public WithPerfLogging +{ +public: + static const size_t IMAGE_SIZE = 512*424; + static const size_t LUT_SIZE = 2048; + + libfreenect2::DepthPacketProcessor::Config config; + DepthPacketProcessor::Parameters params; + + Frame *ir_frame, *depth_frame; + Allocator *input_buffer_allocator; + Allocator *ir_buffer_allocator; + Allocator *depth_buffer_allocator; + + cl::Context context; + cl::Device device; + + cl::Program program; + cl::CommandQueue queue; + + cl::Kernel kernel_processPixelStage1; + cl::Kernel kernel_filterPixelStage1; + cl::Kernel kernel_processPixelStage2; + cl::Kernel kernel_filterPixelStage2; + + // Read only buffers + size_t buf_lut11to16_size; + size_t buf_p0_table_size; + size_t buf_x_table_size; + size_t buf_z_table_size; + size_t buf_packet_size; + + cl::Buffer buf_lut11to16; + cl::Buffer buf_p0_table; + cl::Buffer buf_x_table; + cl::Buffer buf_z_table; + cl::Buffer buf_packet; + + // Read-Write buffers + size_t buf_a_size; + size_t buf_b_size; + size_t buf_n_size; + size_t buf_ir_size; + size_t buf_a_filtered_size; + size_t buf_b_filtered_size; + size_t buf_edge_test_size; + size_t buf_depth_size; + size_t buf_ir_sum_size; + size_t buf_filtered_size; + + cl::Buffer buf_a; + cl::Buffer buf_b; + cl::Buffer buf_n; + cl::Buffer buf_ir; + cl::Buffer buf_a_filtered; + cl::Buffer buf_b_filtered; + cl::Buffer buf_edge_test; + cl::Buffer buf_depth; + cl::Buffer buf_ir_sum; + cl::Buffer buf_filtered; + + bool deviceInitialized; + bool programBuilt; + bool programInitialized; + bool runtimeOk; + std::string sourceCode; + +#ifdef LIBFREENECT2_WITH_PROFILING_CL + std::vector timings; + int count; +#endif + + OpenCLDepthPacketProcessorImpl(const int deviceId = -1) + : deviceInitialized(false) + , programBuilt(false) + , programInitialized(false) + , runtimeOk(true) + { +#if _BSD_SOURCE || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 + setenv("OCL_IGNORE_SELF_TEST", "1", 0); + setenv("OCL_STRICT_CONFORMANCE", "0", 0); +#endif + + deviceInitialized = initDevice(deviceId); + + input_buffer_allocator = new PoolAllocator(new OpenCLAllocator(context, queue, true)); + ir_buffer_allocator = new PoolAllocator(new OpenCLAllocator(context, queue, false)); + depth_buffer_allocator = new PoolAllocator(new OpenCLAllocator(context, queue, false)); + + newIrFrame(); + newDepthFrame(); + + const int CL_ICDL_VERSION = 2; + typedef cl_int (*icdloader_func)(int, size_t, void*, size_t*); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + icdloader_func clGetICDLoaderInfoOCLICD = (icdloader_func)clGetExtensionFunctionAddress("clGetICDLoaderInfoOCLICD"); +#ifdef _MSC_VER +#pragma warning(pop) +#else +#pragma GCC diagnostic pop +#endif + if (clGetICDLoaderInfoOCLICD != NULL) + { + char buf[16]; + if (clGetICDLoaderInfoOCLICD(CL_ICDL_VERSION, sizeof(buf), buf, NULL) == CL_SUCCESS) + { + if (strcmp(buf, "2.2.4") < 0 && strlen(buf) <= 5) + LOG_WARNING << "Your ocl-icd has deadlock bugs. Update to 2.2.4+ is recommended."; + } + } + } + + ~OpenCLDepthPacketProcessorImpl() + { + delete ir_frame; + delete depth_frame; + delete input_buffer_allocator; + delete ir_buffer_allocator; + delete depth_buffer_allocator; + } + + void generateOptions(std::string &options) const + { + std::ostringstream oss; + oss.precision(16); + oss << std::scientific; + oss << " -D BFI_BITMASK=" << "0x180"; + + oss << " -D AB_MULTIPLIER=" << params.ab_multiplier << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ0=" << params.ab_multiplier_per_frq[0] << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ1=" << params.ab_multiplier_per_frq[1] << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ2=" << params.ab_multiplier_per_frq[2] << "f"; + oss << " -D AB_OUTPUT_MULTIPLIER=" << params.ab_output_multiplier << "f"; + + oss << " -D PHASE_IN_RAD0=" << params.phase_in_rad[0] << "f"; + oss << " -D PHASE_IN_RAD1=" << params.phase_in_rad[1] << "f"; + oss << " -D PHASE_IN_RAD2=" << params.phase_in_rad[2] << "f"; + + oss << " -D JOINT_BILATERAL_AB_THRESHOLD=" << params.joint_bilateral_ab_threshold << "f"; + oss << " -D JOINT_BILATERAL_MAX_EDGE=" << params.joint_bilateral_max_edge << "f"; + oss << " -D JOINT_BILATERAL_EXP=" << params.joint_bilateral_exp << "f"; + oss << " -D JOINT_BILATERAL_THRESHOLD=" << (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier) << "f"; + oss << " -D GAUSSIAN_KERNEL_0=" << params.gaussian_kernel[0] << "f"; + oss << " -D GAUSSIAN_KERNEL_1=" << params.gaussian_kernel[1] << "f"; + oss << " -D GAUSSIAN_KERNEL_2=" << params.gaussian_kernel[2] << "f"; + oss << " -D GAUSSIAN_KERNEL_3=" << params.gaussian_kernel[3] << "f"; + oss << " -D GAUSSIAN_KERNEL_4=" << params.gaussian_kernel[4] << "f"; + oss << " -D GAUSSIAN_KERNEL_5=" << params.gaussian_kernel[5] << "f"; + oss << " -D GAUSSIAN_KERNEL_6=" << params.gaussian_kernel[6] << "f"; + oss << " -D GAUSSIAN_KERNEL_7=" << params.gaussian_kernel[7] << "f"; + oss << " -D GAUSSIAN_KERNEL_8=" << params.gaussian_kernel[8] << "f"; + + oss << " -D PHASE_OFFSET=" << params.phase_offset << "f"; + oss << " -D UNAMBIGIOUS_DIST=" << params.unambigious_dist << "f"; + oss << " -D INDIVIDUAL_AB_THRESHOLD=" << params.individual_ab_threshold << "f"; + oss << " -D AB_THRESHOLD=" << params.ab_threshold << "f"; + oss << " -D AB_CONFIDENCE_SLOPE=" << params.ab_confidence_slope << "f"; + oss << " -D AB_CONFIDENCE_OFFSET=" << params.ab_confidence_offset << "f"; + oss << " -D MIN_DEALIAS_CONFIDENCE=" << params.min_dealias_confidence << "f"; + oss << " -D MAX_DEALIAS_CONFIDENCE=" << params.max_dealias_confidence << "f"; + + oss << " -D EDGE_AB_AVG_MIN_VALUE=" << params.edge_ab_avg_min_value << "f"; + oss << " -D EDGE_AB_STD_DEV_THRESHOLD=" << params.edge_ab_std_dev_threshold << "f"; + oss << " -D EDGE_CLOSE_DELTA_THRESHOLD=" << params.edge_close_delta_threshold << "f"; + oss << " -D EDGE_FAR_DELTA_THRESHOLD=" << params.edge_far_delta_threshold << "f"; + oss << " -D EDGE_MAX_DELTA_THRESHOLD=" << params.edge_max_delta_threshold << "f"; + oss << " -D EDGE_AVG_DELTA_THRESHOLD=" << params.edge_avg_delta_threshold << "f"; + oss << " -D MAX_EDGE_COUNT=" << params.max_edge_count << "f"; + + oss << " -D MIN_DEPTH=" << config.MinDepth * 1000.0f << "f"; + oss << " -D MAX_DEPTH=" << config.MaxDepth * 1000.0f << "f"; + + oss << " -cl-mad-enable -cl-no-signed-zeros -cl-fast-relaxed-math"; + options = oss.str(); + } + + void getDevices(const std::vector &platforms, std::vector &devices) + { + devices.clear(); + for(size_t i = 0; i < platforms.size(); ++i) + { + const cl::Platform &platform = platforms[i]; + + std::vector devs; + if(platform.getDevices(CL_DEVICE_TYPE_ALL, &devs) != CL_SUCCESS) + { + continue; + } + + devices.insert(devices.end(), devs.begin(), devs.end()); + } + } + + std::string deviceString(cl::Device &dev) + { + std::string devName, devVendor, devType; + cl_device_type devTypeID; + dev.getInfo(CL_DEVICE_NAME, &devName); + dev.getInfo(CL_DEVICE_VENDOR, &devVendor); + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + switch(devTypeID) + { + case CL_DEVICE_TYPE_CPU: + devType = "CPU"; + break; + case CL_DEVICE_TYPE_GPU: + devType = "GPU"; + break; + case CL_DEVICE_TYPE_ACCELERATOR: + devType = "ACCELERATOR"; + break; + default: + devType = "CUSTOM/UNKNOWN"; + } + + return devName + " (" + devType + ")[" + devVendor + ']'; + } + + void listDevice(std::vector &devices) + { + LOG_INFO << " devices:"; + for(size_t i = 0; i < devices.size(); ++i) + { + LOG_INFO << " " << i << ": " << deviceString(devices[i]); + } + } + + bool selectDevice(std::vector &devices, const int deviceId) + { + if(deviceId != -1 && devices.size() > (size_t)deviceId) + { + device = devices[deviceId]; + return true; + } + + bool selected = false; + size_t selectedType = 0; + + for(size_t i = 0; i < devices.size(); ++i) + { + cl::Device &dev = devices[i]; + cl_device_type devTypeID = 0; + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + if(!selected || (selectedType != CL_DEVICE_TYPE_GPU && devTypeID == CL_DEVICE_TYPE_GPU)) + { + selectedType = devTypeID; + selected = true; + device = dev; + } + } + return selected; + } + + bool initDevice(const int deviceId) + { + if(!readProgram(sourceCode)) + { + return false; + } + + std::vector platforms; + CHECK_CL_RETURN(cl::Platform::get(&platforms)); + + if(platforms.empty()) + { + LOG_ERROR << "no opencl platforms found."; + return false; + } + + std::vector devices; + getDevices(platforms, devices); + listDevice(devices); + if(!selectDevice(devices, deviceId)) + { + LOG_ERROR << "could not find any suitable device"; + return false; + } + LOG_INFO << "selected device: " << deviceString(device); + + CHECK_CL_PARAM(context = cl::Context(device, NULL, NULL, NULL, &err)); + + if(!initBuffers()) + return false; + + return buildProgram(sourceCode); + } + + bool initBuffers() + { +#ifdef LIBFREENECT2_WITH_PROFILING_CL + count = 0; + CHECK_CL_PARAM(queue = cl::CommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &err)); +#else + CHECK_CL_PARAM(queue = cl::CommandQueue(context, device, 0, &err)); +#endif + + //Read only + buf_lut11to16_size = LUT_SIZE * sizeof(cl_short); + buf_p0_table_size = IMAGE_SIZE * sizeof(cl_float3); + buf_x_table_size = IMAGE_SIZE * sizeof(cl_float); + buf_z_table_size = IMAGE_SIZE * sizeof(cl_float); + buf_packet_size = ((IMAGE_SIZE * 11) / 16) * 10 * sizeof(cl_ushort); + + CHECK_CL_PARAM(buf_lut11to16 = cl::Buffer(context, CL_MEM_READ_ONLY, buf_lut11to16_size, NULL, &err)); + CHECK_CL_PARAM(buf_p0_table = cl::Buffer(context, CL_MEM_READ_ONLY, buf_p0_table_size, NULL, &err)); + CHECK_CL_PARAM(buf_x_table = cl::Buffer(context, CL_MEM_READ_ONLY, buf_x_table_size, NULL, &err)); + CHECK_CL_PARAM(buf_z_table = cl::Buffer(context, CL_MEM_READ_ONLY, buf_z_table_size, NULL, &err)); + CHECK_CL_PARAM(buf_packet = cl::Buffer(context, CL_MEM_READ_ONLY, buf_packet_size, NULL, &err)); + + //Read-Write + buf_a_size = IMAGE_SIZE * sizeof(cl_float3); + buf_b_size = IMAGE_SIZE * sizeof(cl_float3); + buf_n_size = IMAGE_SIZE * sizeof(cl_float3); + buf_ir_size = IMAGE_SIZE * sizeof(cl_float); + buf_a_filtered_size = IMAGE_SIZE * sizeof(cl_float3); + buf_b_filtered_size = IMAGE_SIZE * sizeof(cl_float3); + buf_edge_test_size = IMAGE_SIZE * sizeof(cl_uchar); + buf_depth_size = IMAGE_SIZE * sizeof(cl_float); + buf_ir_sum_size = IMAGE_SIZE * sizeof(cl_float); + buf_filtered_size = IMAGE_SIZE * sizeof(cl_float); + + CHECK_CL_PARAM(buf_a = cl::Buffer(context, CL_MEM_READ_WRITE, buf_a_size, NULL, &err)); + CHECK_CL_PARAM(buf_b = cl::Buffer(context, CL_MEM_READ_WRITE, buf_b_size, NULL, &err)); + CHECK_CL_PARAM(buf_n = cl::Buffer(context, CL_MEM_READ_WRITE, buf_n_size, NULL, &err)); + CHECK_CL_PARAM(buf_ir = cl::Buffer(context, CL_MEM_WRITE_ONLY, buf_ir_size, NULL, &err)); + CHECK_CL_PARAM(buf_a_filtered = cl::Buffer(context, CL_MEM_READ_WRITE, buf_a_filtered_size, NULL, &err)); + CHECK_CL_PARAM(buf_b_filtered = cl::Buffer(context, CL_MEM_READ_WRITE, buf_b_filtered_size, NULL, &err)); + CHECK_CL_PARAM(buf_edge_test = cl::Buffer(context, CL_MEM_READ_WRITE, buf_edge_test_size, NULL, &err)); + CHECK_CL_PARAM(buf_depth = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_ir_sum = cl::Buffer(context, CL_MEM_READ_WRITE, buf_ir_sum_size, NULL, &err)); + CHECK_CL_PARAM(buf_filtered = cl::Buffer(context, CL_MEM_WRITE_ONLY, buf_filtered_size, NULL, &err)); + + return true; + } + + bool initProgram() + { + if(!deviceInitialized) + { + return false; + } + + if (!programBuilt) + if (!buildProgram(sourceCode)) + return false; + + CHECK_CL_PARAM(kernel_processPixelStage1 = cl::Kernel(program, "processPixelStage1", &err)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(0, buf_lut11to16)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(1, buf_z_table)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(2, buf_p0_table)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(3, buf_packet)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(4, buf_a)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(5, buf_b)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(6, buf_n)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(7, buf_ir)); + + CHECK_CL_PARAM(kernel_filterPixelStage1 = cl::Kernel(program, "filterPixelStage1", &err)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(0, buf_a)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(1, buf_b)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(2, buf_n)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(3, buf_a_filtered)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(4, buf_b_filtered)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(5, buf_edge_test)); + + CHECK_CL_PARAM(kernel_processPixelStage2 = cl::Kernel(program, "processPixelStage2", &err)); + CHECK_CL_RETURN(kernel_processPixelStage2.setArg(0, config.EnableBilateralFilter ? buf_a_filtered : buf_a)); + CHECK_CL_RETURN(kernel_processPixelStage2.setArg(1, config.EnableBilateralFilter ? buf_b_filtered : buf_b)); + CHECK_CL_RETURN(kernel_processPixelStage2.setArg(2, buf_x_table)); + CHECK_CL_RETURN(kernel_processPixelStage2.setArg(3, buf_z_table)); + CHECK_CL_RETURN(kernel_processPixelStage2.setArg(4, buf_depth)); + CHECK_CL_RETURN(kernel_processPixelStage2.setArg(5, buf_ir_sum)); + + CHECK_CL_PARAM(kernel_filterPixelStage2 = cl::Kernel(program, "filterPixelStage2", &err)); + CHECK_CL_RETURN(kernel_filterPixelStage2.setArg(0, buf_depth)); + CHECK_CL_RETURN(kernel_filterPixelStage2.setArg(1, buf_ir_sum)); + CHECK_CL_RETURN(kernel_filterPixelStage2.setArg(2, buf_edge_test)); + CHECK_CL_RETURN(kernel_filterPixelStage2.setArg(3, buf_filtered)); + + programInitialized = true; + return true; + } + + bool run(const DepthPacket &packet) + { + std::vector eventWrite(1), eventPPS1(1), eventFPS1(1), eventPPS2(1), eventFPS2(1); + cl::Event eventReadIr, eventReadDepth; + + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_packet, CL_FALSE, 0, buf_packet_size, packet.buffer, NULL, &eventWrite[0])); + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_processPixelStage1, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventWrite, &eventPPS1[0])); + CHECK_CL_RETURN(queue.enqueueReadBuffer(buf_ir, CL_FALSE, 0, buf_ir_size, ir_frame->data, &eventPPS1, &eventReadIr)); + + if(config.EnableBilateralFilter) + { + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_filterPixelStage1, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventPPS1, &eventFPS1[0])); + } + else + { + eventFPS1[0] = eventPPS1[0]; + } + + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_processPixelStage2, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventFPS1, &eventPPS2[0])); + + if(config.EnableEdgeAwareFilter) + { + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_filterPixelStage2, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventPPS2, &eventFPS2[0])); + } + else + { + eventFPS2[0] = eventPPS2[0]; + } + + CHECK_CL_RETURN(queue.enqueueReadBuffer(config.EnableEdgeAwareFilter ? buf_filtered : buf_depth, CL_FALSE, 0, buf_depth_size, depth_frame->data, &eventFPS2, &eventReadDepth)); + CHECK_CL_RETURN(eventReadIr.wait()); + CHECK_CL_RETURN(eventReadDepth.wait()); + +#ifdef LIBFREENECT2_WITH_PROFILING_CL + if(count == 0) + { + timings.clear(); + timings.resize(7, 0.0); + } + + timings[0] += eventWrite[0].getProfilingInfo() - eventWrite[0].getProfilingInfo(); + timings[1] += eventPPS1[0].getProfilingInfo() - eventPPS1[0].getProfilingInfo(); + timings[2] += eventFPS1[0].getProfilingInfo() - eventFPS1[0].getProfilingInfo(); + timings[3] += eventPPS2[0].getProfilingInfo() - eventPPS2[0].getProfilingInfo(); + timings[4] += eventFPS2[0].getProfilingInfo() - eventFPS2[0].getProfilingInfo(); + timings[5] += eventReadIr.getProfilingInfo() - eventReadIr.getProfilingInfo(); + timings[6] += eventReadDepth.getProfilingInfo() - eventReadDepth.getProfilingInfo(); + + if(++count == 100) + { + double sum = timings[0] + timings[1] + timings[2] + timings[3] + timings[4] + timings[5] + timings[6]; + LOG_INFO << "writing package: " << timings[0] / 100000000.0 << " ms."; + LOG_INFO << "stage 1: " << timings[1] / 100000000.0 << " ms."; + LOG_INFO << "filter 1: " << timings[2] / 100000000.0 << " ms."; + LOG_INFO << "stage 2: " << timings[3] / 100000000.0 << " ms."; + LOG_INFO << "filter 2: " << timings[4] / 100000000.0 << " ms."; + LOG_INFO << "reading ir: " << timings[5] / 100000000.0 << " ms."; + LOG_INFO << "reading depth: " << timings[6] / 100000000.0 << " ms."; + LOG_INFO << "overall: " << sum / 100000000.0 << " ms."; + count = 0; + } +#endif + + return true; + } + + bool readProgram(std::string &source) const + { + source = loadCLSource("opencl_depth_packet_processor.cl"); + return !source.empty(); + } + + bool buildProgram(const std::string &sources) + { + LOG_INFO << "building OpenCL program..."; + + std::string options; + generateOptions(options); + + cl::Program::Sources source(1, std::make_pair(sources.c_str(), sources.length())); + CHECK_CL_PARAM(program = cl::Program(context, source, &err)); + + CHECK_CL_ON_FAIL(program.build(options.c_str()), + LOG_ERROR << "failed to build program: " << err; + LOG_ERROR << "Build Status: " << program.getBuildInfo(device); + LOG_ERROR << "Build Options:\t" << program.getBuildInfo(device); + LOG_ERROR << "Build Log:\t " << program.getBuildInfo(device)); + + LOG_INFO << "OpenCL program built successfully"; + programBuilt = true; + return true; + } + + void newIrFrame() + { + ir_frame = new OpenCLFrame(static_cast(ir_buffer_allocator->allocate(IMAGE_SIZE * sizeof(cl_float)))); + ir_frame->format = Frame::Float; + } + + void newDepthFrame() + { + depth_frame = new OpenCLFrame(static_cast(depth_buffer_allocator->allocate(IMAGE_SIZE * sizeof(cl_float)))); + depth_frame->format = Frame::Float; + } + + bool fill_trig_table(const libfreenect2::protocol::P0TablesResponse *p0table) + { + if(!deviceInitialized) + { + LOG_ERROR << "OpenCLDepthPacketProcessor is not initialized!"; + return false; + } + + cl_float3 *p0_table = new cl_float3[IMAGE_SIZE]; + + for(int r = 0; r < 424; ++r) + { + cl_float3 *it = &p0_table[r * 512]; + const uint16_t *it0 = &p0table->p0table0[r * 512]; + const uint16_t *it1 = &p0table->p0table1[r * 512]; + const uint16_t *it2 = &p0table->p0table2[r * 512]; + for(int c = 0; c < 512; ++c, ++it, ++it0, ++it1, ++it2) + { + it->s[0] = -((float)*it0) * 0.000031 * M_PI; + it->s[1] = -((float)*it1) * 0.000031 * M_PI; + it->s[2] = -((float)*it2) * 0.000031 * M_PI; + it->s[3] = 0.0f; + } + } + + cl::Event event; + CHECK_CL_ON_FAIL(queue.enqueueWriteBuffer(buf_p0_table, CL_FALSE, 0, buf_p0_table_size, p0_table, NULL, &event), delete[] p0_table); + CHECK_CL_ON_FAIL(event.wait(), delete[] p0_table); + delete[] p0_table; + return true; + } + + bool fill_xz_tables(const float *xtable, const float *ztable) + { + if(!deviceInitialized) + { + LOG_ERROR << "OpenCLDepthPacketProcessor is not initialized!"; + return false; + } + + cl::Event event0, event1; + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_x_table, CL_FALSE, 0, buf_x_table_size, xtable, NULL, &event0)); + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_z_table, CL_FALSE, 0, buf_z_table_size, ztable, NULL, &event1)); + CHECK_CL_RETURN(event0.wait()); + CHECK_CL_RETURN(event1.wait()); + return true; + } + + bool fill_lut(const short *lut) + { + if(!deviceInitialized) + { + LOG_ERROR << "OpenCLDepthPacketProcessor is not initialized!"; + return false; + } + + cl::Event event; + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_lut11to16, CL_FALSE, 0, buf_lut11to16_size, lut, NULL, &event)); + CHECK_CL_RETURN(event.wait()); + return true; + } +}; + +OpenCLDepthPacketProcessor::OpenCLDepthPacketProcessor(const int deviceId) : + impl_(new OpenCLDepthPacketProcessorImpl(deviceId)) +{ +} + +OpenCLDepthPacketProcessor::~OpenCLDepthPacketProcessor() +{ + delete impl_; +} + +void OpenCLDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + + if ( impl_->config.MaxDepth != config.MaxDepth + || impl_->config.MinDepth != config.MinDepth) + { + // OpenCL program needs to be rebuilt, then reinitialized + impl_->programBuilt = false; + impl_->programInitialized = false; + } + else if (impl_->config.EnableBilateralFilter != config.EnableBilateralFilter + || impl_->config.EnableEdgeAwareFilter != config.EnableEdgeAwareFilter) + { + // OpenCL program only needs to be reinitialized + impl_->programInitialized = false; + } + + impl_->config = config; + if (!impl_->programBuilt) + impl_->buildProgram(impl_->sourceCode); +} + +void OpenCLDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char *buffer, size_t buffer_length) +{ + libfreenect2::protocol::P0TablesResponse *p0table = (libfreenect2::protocol::P0TablesResponse *)buffer; + + if(buffer_length < sizeof(libfreenect2::protocol::P0TablesResponse)) + { + LOG_ERROR << "P0Table response too short!"; + return; + } + + impl_->fill_trig_table(p0table); +} + +void OpenCLDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) +{ + impl_->fill_xz_tables(xtable, ztable); +} + +void OpenCLDepthPacketProcessor::loadLookupTable(const short *lut) +{ + impl_->fill_lut(lut); +} + +bool OpenCLDepthPacketProcessor::good() +{ + return impl_->deviceInitialized && impl_->runtimeOk; +} + +void OpenCLDepthPacketProcessor::process(const DepthPacket &packet) +{ + if (!listener_) + return; + + if(!impl_->programInitialized && !impl_->initProgram()) + { + impl_->runtimeOk = false; + LOG_ERROR << "could not initialize OpenCLDepthPacketProcessor"; + return; + } + + impl_->startTiming(); + + impl_->ir_frame->timestamp = packet.timestamp; + impl_->depth_frame->timestamp = packet.timestamp; + impl_->ir_frame->sequence = packet.sequence; + impl_->depth_frame->sequence = packet.sequence; + + impl_->runtimeOk = impl_->run(packet); + + impl_->stopTiming(LOG_INFO); + + if (!impl_->runtimeOk) + { + impl_->ir_frame->status = 1; + impl_->depth_frame->status = 1; + } + + if(listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + impl_->newIrFrame(); + if(listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + impl_->newDepthFrame(); +} + +Allocator *OpenCLDepthPacketProcessor::getAllocator() +{ + return impl_->input_buffer_allocator; +} +} /* namespace libfreenect2 */ + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cl b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cl new file mode 100644 index 0000000..860ae74 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cl @@ -0,0 +1,746 @@ +/* + * This code implements a depth packet processor using the phase unwrapping + * algorithm described in the paper "Efficient Phase Unwrapping using Kernel + * Density Estimation", ECCV 2016, Felix Järemo Lawin, Per-Erik Forssen and + * Hannes Ovren, see http://www.cvl.isy.liu.se/research/datasets/kinect2-dataset/. + */ + + +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + + +/******************************************************************************* + * Process pixel stage 1 + ******************************************************************************/ + +#define PHASE (float3)(PHASE_IN_RAD0, PHASE_IN_RAD1, PHASE_IN_RAD2) +#define AB_MULTIPLIER_PER_FRQ (float3)(AB_MULTIPLIER_PER_FRQ0, AB_MULTIPLIER_PER_FRQ1, AB_MULTIPLIER_PER_FRQ2) +#define NUM_HYPOTHESES 30 + +float decodePixelMeasurement(global const ushort *data, global const short *lut11to16, const uint sub, const uint x, const uint y) +{ + uint row_idx = (424 * sub + y) * 352; + uint idx = (((x >> 2) + ((x << 7) & BFI_BITMASK)) * 11) & (uint)0xffffffff; + + uint col_idx = idx >> 4; + uint upper_bytes = idx & 15; + uint lower_bytes = 16 - upper_bytes; + + uint data_idx0 = row_idx + col_idx; + uint data_idx1 = row_idx + col_idx + 1; + + return (float)lut11to16[(x < 1 || 510 < x || col_idx > 352) ? 0 : ((data[data_idx0] >> upper_bytes) | (data[data_idx1] << lower_bytes)) & 2047]; +} + +void kernel processPixelStage1(global const short *lut11to16, global const float *z_table, global const float3 *p0_table, global const ushort *data, + global float3 *a_out, global float3 *b_out, global float3 *n_out, global float *ir_out) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const uint y_tmp = (423 - y); + const uint y_in = (y_tmp < 212 ? y_tmp + 212 : 423 - y_tmp); + + const int3 invalid = (int)(0.0f >= z_table[i]); + const float3 p0 = p0_table[i]; + float3 p0x_sin, p0y_sin, p0z_sin; + float3 p0x_cos, p0y_cos, p0z_cos; + + p0x_sin = -sincos(PHASE + p0.x, &p0x_cos); + p0y_sin = -sincos(PHASE + p0.y, &p0y_cos); + p0z_sin = -sincos(PHASE + p0.z, &p0z_cos); + + int3 invalid_pixel = (int3)(invalid); + + const float3 v0 = (float3)(decodePixelMeasurement(data, lut11to16, 0, x, y_in), + decodePixelMeasurement(data, lut11to16, 1, x, y_in), + decodePixelMeasurement(data, lut11to16, 2, x, y_in)); + const float3 v1 = (float3)(decodePixelMeasurement(data, lut11to16, 3, x, y_in), + decodePixelMeasurement(data, lut11to16, 4, x, y_in), + decodePixelMeasurement(data, lut11to16, 5, x, y_in)); + const float3 v2 = (float3)(decodePixelMeasurement(data, lut11to16, 6, x, y_in), + decodePixelMeasurement(data, lut11to16, 7, x, y_in), + decodePixelMeasurement(data, lut11to16, 8, x, y_in)); + + float3 a = (float3)(dot(v0, p0x_cos), + dot(v1, p0y_cos), + dot(v2, p0z_cos)) * AB_MULTIPLIER_PER_FRQ; + float3 b = (float3)(dot(v0, p0x_sin), + dot(v1, p0y_sin), + dot(v2, p0z_sin)) * AB_MULTIPLIER_PER_FRQ; + + a = select(a, (float3)(0.0f), invalid_pixel); + b = select(b, (float3)(0.0f), invalid_pixel); + float3 n = sqrt(a * a + b * b); + + int3 saturated = (int3)(any(isequal(v0, (float3)(32767.0f))), + any(isequal(v1, (float3)(32767.0f))), + any(isequal(v2, (float3)(32767.0f)))); + + a_out[i] = select(a, (float3)(0.0f), saturated); + b_out[i] = select(b, (float3)(0.0f), saturated); + n_out[i] = n; + ir_out[i] = min(dot(select(n, (float3)(65535.0f), saturated), (float3)(0.333333333f * AB_MULTIPLIER * AB_OUTPUT_MULTIPLIER)), 65535.0f); +} + +/******************************************************************************* + * Filter pixel stage 1 + ******************************************************************************/ +void kernel filterPixelStage1(global const float3 *a, global const float3 *b, global const float3 *n, + global float3 *a_out, global float3 *b_out, global uchar *max_edge_test) +{ + const uint i = get_global_id(0); + + const uint x = i % 512; + const uint y = i / 512; + + const float3 self_a = a[i]; + const float3 self_b = b[i]; + + const float gaussian[9] = {GAUSSIAN_KERNEL_0, GAUSSIAN_KERNEL_1, GAUSSIAN_KERNEL_2, GAUSSIAN_KERNEL_3, GAUSSIAN_KERNEL_4, GAUSSIAN_KERNEL_5, GAUSSIAN_KERNEL_6, GAUSSIAN_KERNEL_7, GAUSSIAN_KERNEL_8}; + + if(x < 1 || y < 1 || x > 510 || y > 422) + { + a_out[i] = self_a; + b_out[i] = self_b; + max_edge_test[i] = 1; + } + else + { + float3 threshold = (float3)(JOINT_BILATERAL_THRESHOLD); + float3 joint_bilateral_exp = (float3)(JOINT_BILATERAL_EXP); + + const float3 self_norm = n[i]; + const float3 self_normalized_a = self_a / self_norm; + const float3 self_normalized_b = self_b / self_norm; + + float3 weight_acc = (float3)(0.0f); + float3 weighted_a_acc = (float3)(0.0f); + float3 weighted_b_acc = (float3)(0.0f); + float3 dist_acc = (float3)(0.0f); + + const int3 c0 = isless(self_norm * self_norm, threshold); + + threshold = select(threshold, (float3)(0.0f), c0); + joint_bilateral_exp = select(joint_bilateral_exp, (float3)(0.0f), c0); + + for(int yi = -1, j = 0; yi < 2; ++yi) + { + uint i_other = (y + yi) * 512 + x - 1; + + for(int xi = -1; xi < 2; ++xi, ++j, ++i_other) + { + const float3 other_a = a[i_other]; + const float3 other_b = b[i_other]; + const float3 other_norm = n[i_other]; + const float3 other_normalized_a = other_a / other_norm; + const float3 other_normalized_b = other_b / other_norm; + + const int3 c1 = isless(other_norm * other_norm, threshold); + + const float3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + const float3 weight = select(gaussian[j] * exp(-1.442695f * joint_bilateral_exp * dist), (float3)(0.0f), c1); + + weighted_a_acc += weight * other_a; + weighted_b_acc += weight * other_b; + weight_acc += weight; + dist_acc += select(dist, (float3)(0.0f), c1); + } + } + + const int3 c2 = isless((float3)(0.0f), weight_acc.xyz); + a_out[i] = select((float3)(0.0f), weighted_a_acc / weight_acc, c2); + b_out[i] = select((float3)(0.0f), weighted_b_acc / weight_acc, c2); + + max_edge_test[i] = all(isless(dist_acc, (float3)(JOINT_BILATERAL_MAX_EDGE))); + } +} + + + +/******************************************************************************* + * KDE phase unwrapping + ******************************************************************************/ + +//arrays for hypotheses +float constant k_list[NUM_HYPOTHESES] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; +float constant n_list[NUM_HYPOTHESES] = {0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 5.0f, 6.0f, 5.0f, 6.0f, 6.0f, 7.0f, 7.0f, 8.0f, 8.0f, 7.0f, 8.0f, 9.0f, 9.0f}; +float constant m_list[NUM_HYPOTHESES] = {0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 8.0f, 8.0f, 9.0f, 9.0f, 10.0f, 10.0f, 11.0f, 11.0f, 12.0f, 12.0f, 13.0f, 13.0f, 14.0f}; + +void calcErr(const float k, const float n, const float m, const float t0, const float t1, const float t2, float* err1, float* err2, float* err3) +{ + //phase unwrapping equation residuals + *err1 = 3.0f * n - 15.0f * k - (t1 - t0); + *err2 = 3.0f * n - 2.0f * m - (t2 - t0); + *err3 = 15.0f * k - 2.0f * m - (t2 - t1); +} + +/******************************************************************************** + * Rank all 30 phase hypothses and returns the two most likley + ********************************************************************************/ +void phaseUnWrapper(float t0, float t1,float t2, float* phase_first, float* phase_second, float* err_w1, float* err_w2) +{ + float err; + float err1,err2,err3; + + //unwrapping weight for cost function + float w1 = 1.0f; + float w2 = 10.0f; + float w3 = 1.0218f; + + float err_min = 100000.0f; + float err_min_second = 200000.0f; + unsigned int ind_min, ind_second; + + float k, n, m; + + for(int i = 0; i < NUM_HYPOTHESES; i++) + { + m = m_list[i]; + n = n_list[i]; + k = k_list[i]; + calcErr(k, n, m, t0, t1, t2, &err1, &err2, &err3); + err = w1 * err1 * err1 + w2 * err2 * err2 + w3 * err3 * err3; + if(err < err_min) + { + err_min_second = err_min; + ind_second = ind_min; + err_min = err; + ind_min = i; + + } + else if(err < err_min_second) + { + err_min_second = err; + ind_second = i; + } + } + + //decode ind_min + float mvals = m_list[ind_min]; + float nvals = n_list[ind_min]; + float kvals = k_list[ind_min]; + + //Weighted phases for phase fusion weighted average + float phi2_out = (t2 / 2.0f + mvals); + float phi1_out = (t1 / 15.0f + kvals); + float phi0_out = (t0 / 3.0f + nvals); + + *err_w1 = err_min; + + //phase fusion + *phase_first = (phi2_out + phi1_out + phi0_out) / 3.0f; + + mvals = m_list[ind_second]; + nvals = n_list[ind_second]; + kvals = k_list[ind_second]; + + //Weighted phases for phase fusion weighted average + phi2_out = (t2 / 2.0f + mvals); + phi1_out = (t1 / 15.0f + kvals); + phi0_out = (t0 / 3.0f + nvals); + + *err_w2 = err_min_second; + + //phase fusion + *phase_second = (phi2_out + phi1_out + phi0_out) / 3.0f; + +} + +/******************************************************************************* + * Predict phase variance from amplitude direct quadratic model + ******************************************************************************/ +void calculatePhaseUnwrappingVarDirect(float3 ir, float3* var) +{ + //Model: sigma = 1/(gamma0*a+gamma1*a^2+gamma2). Possibly better than calculatePhaseUnwrappingVar + //The gammas are optimized using lsqnonlin in matlab. + //For more details see the paper "Efficient Phase Unwrapping using Kernel Density Estimation" + //section 3.3 and 4.4. + float sigma_max = 0.5f * M_PI_F; + + //Set sigma = pi/2 as a maximum standard deviation of the phase. Cut off function after root + float q0 = ir.x > 5.244404f ? 0.7919451669f * ir.x - 0.002363097609f * ir.x * ir.x - 3.088285897f : 1.0f / sigma_max; + float q1 = ir.y > 4.084835f ? 1.214266794f * ir.y - 0.00581082634f * ir.y * ir.y - 3.863119924f : 1.0f / sigma_max; + float q2 = ir.z > 6.379475f ? 0.6101457464f * ir.z - 0.00113679233f * ir.z * ir.z - 2.84614442f : 1.0f / sigma_max; + float3 q = (float3)(q0, q1, q2); + float3 roots = (float3)(5.244404f, 4.084835f, 6.379475f); + float3 sigma = (float3)(1.0f)/q; + sigma = select(sigma, (float3)(sigma_max), isless((float3)(sigma_max), sigma)); + *var = sigma; +} + + +/******************************************************************************* + * Predict phase variance from amplitude quadratic atan model + ******************************************************************************/ +//void calculatePhaseUnwrappingVar(float3 ir, float* var0, float* var1, float* var2) +void calculatePhaseUnwrappingVar(float3 ir, float3 *var) +{ + //Model: sigma = atan(sqrt(1/(gamma0*a+gamma1*a^2+gamma2)-1)). The gammas are optimized using lsqnonlin in matlab. + //For more details see the paper "Efficient Phase Unwrapping using Kernel Density Estimation", + //section 3.3 and 4.4. + float q0 = 0.8211288451f * ir.x - 0.002601348899f * ir.x * ir.x - 3.549793908f; + float q1 = 1.259642407f * ir.y - 0.005478390508f * ir.y * ir.y - 4.335841127f; + float q2 = 0.6447928035f * ir.z - 0.0009627273649f * ir.z * ir.z - 3.368205575f; + float3 q = (float3)(q0, q1, q2); + q *= q; + float3 roots = (float3)(5.64173671f, 4.31705182f, 6.84453530f); + float3 sigma = select(select((float3)(0.5f * M_PI_F), roots * 0.5f * M_PI_F / ir, isless(roots,ir)), atan(sqrt((float3)(1.0f) / (q - (float3)(1.0f)))), isless((float3)(1.0f), q)); + sigma = select(sigma, (float3)(0.001f), isless(sigma, (float3)(0.001f))); + *var = sigma*sigma; +} + +void kernel processPixelStage2_phase(global const float3 *a_in, global const float3 *b_in, global float4 *phase_conf_vec) +{ + const uint i = get_global_id(0); + + //read complex number real (a) and imaginary part (b) + float3 a = a_in[i]; + float3 b = b_in[i]; + + //calculate complex argument + float3 phase = atan2(b, a); + phase = select(phase, (float3)(0.0f), isnan(phase)); + phase = select(phase, phase + 2.0f * M_PI_F, isless(phase, (float3)(0.0f))); + + //calculate amplitude or the absolute value + float3 ir = sqrt(a * a + b * b) * AB_MULTIPLIER; + + float ir_sum = ir.x + ir.y + ir.z; + + float phase_first = 0.0f; + float phase_second = 0.0f; + + float J_1, J_2, unwrapping_likelihood1, unwrapping_likelihood2; + + //scale with least common multiples of modulation frequencies + float3 t = phase / (2.0f * M_PI_F) * (float3)(3.0f, 15.0f, 2.0f); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + //rank and extract two most likely phase hypothises + phaseUnWrapper(t0, t1, t2, &phase_first, &phase_second, &J_1, &J_2); + + float phase_likelihood; + + //check if near saturation + if(ir_sum < 0.4f * 65535.0f) + { + //calculate phase likelihood from amplitude + //float var0, var1, var2; + float3 var; + calculatePhaseUnwrappingVar(ir, &var); + phase_likelihood = exp(-(var.x + var.y + var.z) / (2.0f * PHASE_CONFIDENCE_SCALE)); + phase_likelihood = select(phase_likelihood, 0.0f, isnan(phase_likelihood)); + } + else + { + phase_likelihood = 0.0f; + } + + //merge phase likelihood with phase likelihood + unwrapping_likelihood1 = phase_likelihood*exp(-J_1 / (2 * UNWRAPPING_LIKELIHOOD_SCALE)); + unwrapping_likelihood2 = phase_likelihood*exp(-J_2 / (2 * UNWRAPPING_LIKELIHOOD_SCALE)); + + //suppress confidence if phase is beyond allowed range + unwrapping_likelihood1 = phase_first > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood1; + unwrapping_likelihood2 = phase_second > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood2; + + phase_conf_vec[i] = (float4)(phase_first,phase_second, unwrapping_likelihood1, unwrapping_likelihood2); + +} + +void kernel filter_kde(global const float4* phase_conf_vec, global const float* gauss_filt_array, global const float* z_table, global const float* x_table, global float* depth) +{ + const uint i = get_global_id(0); + float kde_val_1, kde_val_2; + + const int loadX = i % 512; + const int loadY = i / 512; + + int k, l; + float sum_1, sum_2; + + //initialize neighborhood boundaries + int from_x = (loadX > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadX + 1); + int from_y = (loadY > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadY + 1); + int to_x = (loadX < 511 - KDE_NEIGBORHOOD_SIZE - 1 ? KDE_NEIGBORHOOD_SIZE: 511 - loadX - 1); + int to_y = (loadY < 423 - KDE_NEIGBORHOOD_SIZE ? KDE_NEIGBORHOOD_SIZE: 423 - loadY); + + kde_val_1 = 0.0f; + kde_val_2 = 0.0f; + float2 phase_local = phase_conf_vec[i].xy; + + if(loadX >= 1 && loadX < 511 && loadY >= 0 && loadY<424) + { + sum_1=0.0f; + sum_2=0.0f; + float gauss; + float sum_gauss = 0.0f; + + float phase_1_local; + float phase_2_local; + float conf1_local; + float conf2_local; + float4 phase_conf_local; + uint ind; + + float diff11, diff21, diff12, diff22; + + //calculate KDE for all hypothesis within the neigborhood + for(k = from_y; k <= to_y; k++) + for(l = from_x; l <= to_x; l++) + { + ind = (loadY + k) * 512 + (loadX + l); + phase_conf_local = phase_conf_vec[ind]; + conf1_local = phase_conf_local.z; + conf2_local = phase_conf_local.w; + + phase_1_local = phase_conf_local.x; + phase_2_local = phase_conf_local.y; + + gauss = gauss_filt_array[k + KDE_NEIGBORHOOD_SIZE] * gauss_filt_array[l + KDE_NEIGBORHOOD_SIZE]; + sum_gauss += gauss * (conf1_local + conf2_local); + diff11 = phase_1_local - phase_local.x; + diff21 = phase_2_local - phase_local.x; + diff12 = phase_1_local - phase_local.y; + diff22 = phase_2_local - phase_local.y; + sum_1 += gauss * (conf1_local * exp(-diff11 * diff11 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff21 * diff21 / (2 * KDE_SIGMA_SQR))); + sum_2 += gauss * (conf1_local * exp(-diff12 * diff12 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff22 * diff22 / (2 * KDE_SIGMA_SQR))); + } + kde_val_1 = sum_gauss > 0.5f ? sum_1 / sum_gauss : sum_1 * 2.0f; + kde_val_2 = sum_gauss > 0.5f ? sum_2 / sum_gauss : sum_2 * 2.0f; + } + + //select hypothesis + int val_ind = kde_val_2 <= kde_val_1 ? 1: 0; + + float phase_final = val_ind ? phase_local.x: phase_local.y; + float max_val = val_ind ? kde_val_1: kde_val_2; + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0f; + + bool cond1 = true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0f) / (max_depth * max_depth * 8192.0f); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + + max_val = d < MIN_DEPTH || d > MAX_DEPTH ? 0.0f: max_val; + + //set to zero if confidence is low + depth[i] = max_val >= KDE_THRESHOLD ? d: 0.0f; +} + + +/***************************************************************** + * THREE HYPOTHESIS + *****************************************************************/ + +void phaseUnWrapper3(float t0, float t1,float t2, float* phase_first, float* phase_second, float* phase_third, float* err_w1, float* err_w2, float* err_w3) +{ + float err; + float err1, err2, err3; + + //unwrapping weight for cost function + float w1 = 1.0f; + float w2 = 10.0f; + float w3 = 1.0218f; + + float err_min = 100000.0f; + float err_min_second = 200000.0f; + float err_min_third = 300000.0f; + unsigned int ind_min, ind_second, ind_third; + + float k, n, m; + + for(int i = 0; i < NUM_HYPOTHESES; i++) + { + m = m_list[i]; + n = n_list[i]; + k = k_list[i]; + calcErr(k, n, m, t0, t1, t2, &err1, &err2, &err3); + err = w1 * err1 * err1 + w2 * err2 * err2 + w3 * err3 * err3; + if(err < err_min) + { + err_min_third = err_min_second; + ind_third = ind_second; + err_min_second = err_min; + ind_second = ind_min; + err_min = err; + ind_min = i; + + } + else if(err MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood1; + unwrapping_likelihood2 = phase_second > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood2; + unwrapping_likelihood3 = phase_third > MAX_DEPTH * 9.0f / 18750.0f ? 0.0f: unwrapping_likelihood3; + + conf1[i] = unwrapping_likelihood1; + conf2[i] = unwrapping_likelihood2; + conf3[i] = unwrapping_likelihood3; + +} + + + +void kernel filter_kde3(global const float *phase_1, global const float *phase_2, global const float *phase_3, global const float* conf1, global const float* conf2, global const float* conf3, global const float* gauss_filt_array, global const float* z_table, global const float* x_table, global float* depth) +{ + const uint i = get_global_id(0); + float kde_val_1, kde_val_2, kde_val_3; + + const int loadX = i % 512; + const int loadY = i / 512; + int k, l; + float sum_1, sum_2, sum_3; + + //initialize neighborhood boundaries + int from_x = (loadX > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadX + 1); + int from_y = (loadY > KDE_NEIGBORHOOD_SIZE ? -KDE_NEIGBORHOOD_SIZE : -loadY + 1); + int to_x = (loadX < 511 - KDE_NEIGBORHOOD_SIZE - 1 ? KDE_NEIGBORHOOD_SIZE: 511 - loadX - 1); + int to_y = (loadY < 423 - KDE_NEIGBORHOOD_SIZE ? KDE_NEIGBORHOOD_SIZE: 423 - loadY); + + kde_val_1 = 0.0f; + kde_val_2 = 0.0f; + kde_val_3 = 0.0f; + float phase_first = phase_1[i]; + float phase_second = phase_2[i]; + float phase_third = phase_3[i]; + if(loadX >= 1 && loadX < 511 && loadY >= 0 && loadY < 424) + { + //Filter kernel + sum_1 = 0.0f; + sum_2 = 0.0f; + sum_3 = 0.0f; + float gauss; + float sum_gauss = 0.0f; + + float phase_1_local; + float phase_2_local; + float phase_3_local; + float conf1_local; + float conf2_local; + float conf3_local; + float diff11, diff12, diff13, diff21, diff22, diff23, diff31, diff32, diff33; + uint ind; + + //calculate KDE for all hypothesis within the neigborhood + for(k = from_y; k <= to_y; k++) + for(l = from_x; l <= to_x; l++) + { + ind = (loadY + k) * 512 + (loadX + l); + conf1_local = conf1[ind]; + conf2_local = conf2[ind]; + conf3_local = conf3[ind]; + phase_1_local = phase_1[ind]; + phase_2_local = phase_2[ind]; + phase_3_local = phase_3[ind]; + diff11 = phase_1_local - phase_first; + diff12 = phase_1_local - phase_second; + diff13 = phase_1_local - phase_third; + diff21 = phase_2_local - phase_first; + diff22 = phase_2_local - phase_second; + diff23 = phase_2_local - phase_third; + diff31 = phase_3_local - phase_first; + diff32 = phase_3_local - phase_second; + diff33 = phase_3_local - phase_third; + gauss = gauss_filt_array[k + KDE_NEIGBORHOOD_SIZE] * gauss_filt_array[l + KDE_NEIGBORHOOD_SIZE]; + sum_gauss += gauss * (conf1_local + conf2_local + conf3_local); + sum_1 += gauss*(conf1_local * exp(-diff11 * diff11 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff21 * diff21 / (2 * KDE_SIGMA_SQR)) + conf3_local * exp(-diff31 * diff31 /(2 * KDE_SIGMA_SQR))); + sum_2 += gauss * (conf1_local * exp(-diff12 * diff12 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff22 * diff22/(2 * KDE_SIGMA_SQR))+conf3_local * exp(-diff32 * diff32 / (2 * KDE_SIGMA_SQR))); + sum_3 += gauss * (conf1_local * exp(-diff13 * diff13 / (2 * KDE_SIGMA_SQR)) + conf2_local * exp(-diff23 * diff23 / (2 * KDE_SIGMA_SQR)) + conf3_local * exp(-diff33 * diff33 / (2 * KDE_SIGMA_SQR))); + } + kde_val_1 = sum_gauss > 0.5f ? sum_1 / sum_gauss : sum_1 * 2.0f; + kde_val_2 = sum_gauss > 0.5f ? sum_2 / sum_gauss : sum_2 * 2.0f; + kde_val_3 = sum_gauss > 0.5f ? sum_3 / sum_gauss : sum_3 * 2.0f; + } + + //select hypothesis + float phase_final, max_val; + if(kde_val_2 > kde_val_1 || kde_val_3 > kde_val_1) + { + if(kde_val_3 > kde_val_2) + { + phase_final = phase_third; + max_val = kde_val_3; + } + else + { + phase_final = phase_second; + max_val = kde_val_2; + } + } + else + { + phase_final = phase_first; + max_val = kde_val_1; + } + + float zmultiplier = z_table[i]; + float xmultiplier = x_table[i]; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * UNAMBIGIOUS_DIST * 2.0; + + bool cond1 = true && 0.0f < depth_linear && 0.0f < max_depth; + + xmultiplier = (xmultiplier * 90.0f) / (max_depth * max_depth * 8192.0f); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0f ? 0.0f : depth_fit; + + float d = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + + max_val = depth_linear < MIN_DEPTH || depth_linear > MAX_DEPTH ? 0.0f: max_val; + + //set to zero if confidence is low + depth[i] = max_val >= KDE_THRESHOLD ? d: 0.0f; +} + + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cpp new file mode 100644 index 0000000..98dbdff --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opencl_kde_depth_packet_processor.cpp @@ -0,0 +1,885 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file opencl_depth_packet_processor.cl Implementation of the OpenCL depth packet processor. */ + +#include +#include +#include +#include + +#include + +#define _USE_MATH_DEFINES +#include + +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#define CL_USE_DEPRECATED_OPENCL_2_0_APIS + +#ifdef LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD +#define CL_USE_DEPRECATED_OPENCL_1_1_APIS +#include +#ifdef CL_VERSION_1_2 +#undef CL_VERSION_1_2 +#endif //CL_VERSION_1_2 +#endif //LIBFREENECT2_OPENCL_ICD_LOADER_IS_OLD + +#include + +#ifndef REG_OPENCL_FILE +#define REG_OPENCL_FILE "" +#endif + +#include + +#define CHECK_CL_PARAM(expr) do { cl_int err = CL_SUCCESS; (expr); if (err != CL_SUCCESS) { LOG_ERROR << #expr ": " << err; return false; } } while(0) +#define CHECK_CL_RETURN(expr) do { cl_int err = (expr); if (err != CL_SUCCESS) { LOG_ERROR << #expr ": " << err; return false; } } while(0) +#define CHECK_CL_ON_FAIL(expr, on_fail) do { cl_int err = (expr); if (err != CL_SUCCESS) { LOG_ERROR << #expr ": " << err; on_fail; return false; } } while(0) + +namespace libfreenect2 +{ + +std::string loadCLKdeSource(const std::string &filename) +{ + const unsigned char *data; + size_t length = 0; + + if(!loadResource(filename, &data, &length)) + { + LOG_ERROR << "failed to load cl source!"; + return ""; + } + + return std::string(reinterpret_cast(data), length); +} + +class OpenCLKdeDepthPacketProcessorImpl; + +class OpenCLKdeBuffer: public Buffer +{ +public: + cl::Buffer buffer; +}; + +class OpenCLKdeAllocator: public Allocator +{ +private: + cl::Context &context; + cl::CommandQueue &queue; + const bool isInputBuffer; + + bool allocate_opencl(OpenCLKdeBuffer *b, size_t size) + { + if(isInputBuffer) + { + CHECK_CL_PARAM(b->buffer = cl::Buffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, size, NULL, &err)); + CHECK_CL_PARAM(b->data = (unsigned char*)queue.enqueueMapBuffer(b->buffer, CL_TRUE, CL_MAP_WRITE, 0, size, NULL, NULL, &err)); + } + else + { + CHECK_CL_PARAM(b->buffer = cl::Buffer(context, CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, size, NULL, &err)); + CHECK_CL_PARAM(b->data = (unsigned char*)queue.enqueueMapBuffer(b->buffer, CL_TRUE, CL_MAP_READ, 0, size, NULL, NULL, &err)); + } + + b->length = 0; + b->capacity = size; + return true; + } + + bool release_opencl(OpenCLKdeBuffer *b) + { + cl::Event event; + CHECK_CL_RETURN(queue.enqueueUnmapMemObject(b->buffer, b->data, NULL, &event)); + CHECK_CL_RETURN(event.wait()); + return true; + } + +public: + OpenCLKdeAllocator(cl::Context &context, cl::CommandQueue &queue, bool isInputBuffer) : context(context), queue(queue), isInputBuffer(isInputBuffer) + { + } + + virtual Buffer *allocate(size_t size) + { + OpenCLKdeBuffer *b = new OpenCLKdeBuffer(); + if(!allocate_opencl(b, size)) + b->data = NULL; + return b; + } + + virtual void free(Buffer *b) + { + if(b == NULL) + return; + release_opencl(static_cast(b)); + delete b; + } +}; + +class OpenCLKdeFrame: public Frame +{ +private: + OpenCLKdeBuffer *buffer; + +public: + OpenCLKdeFrame(OpenCLKdeBuffer *buffer) + : Frame(512, 424, 4, (unsigned char*)-1) + , buffer(buffer) + { + data = buffer->data; + } + + virtual ~OpenCLKdeFrame() + { + buffer->allocator->free(buffer); + data = NULL; + } +}; + +class OpenCLKdeDepthPacketProcessorImpl: public WithPerfLogging +{ +public: + static const size_t IMAGE_SIZE = 512*424; + static const size_t LUT_SIZE = 2048; + + libfreenect2::DepthPacketProcessor::Config config; + DepthPacketProcessor::Parameters params; + + Frame *ir_frame, *depth_frame; + Allocator *input_buffer_allocator; + Allocator *ir_buffer_allocator; + Allocator *depth_buffer_allocator; + + cl::Context context; + cl::Device device; + + cl::Program program; + cl::CommandQueue queue; + + cl::Kernel kernel_processPixelStage1; + cl::Kernel kernel_filterPixelStage1; + cl::Kernel kernel_processPixelStage2_phase; + cl::Kernel kernel_filter_kde; + + // Read only buffers + size_t buf_lut11to16_size; + size_t buf_p0_table_size; + size_t buf_x_table_size; + size_t buf_z_table_size; + size_t buf_packet_size; + size_t buf_gauss_kernel_size; + + cl::Buffer buf_lut11to16; + cl::Buffer buf_p0_table; + cl::Buffer buf_x_table; + cl::Buffer buf_z_table; + cl::Buffer buf_packet; + + // Read-Write buffers + size_t buf_a_size; + size_t buf_b_size; + size_t buf_n_size; + size_t buf_ir_size; + size_t buf_a_filtered_size; + size_t buf_b_filtered_size; + size_t buf_edge_test_size; + size_t buf_depth_size; + size_t buf_ir_sum_size; + size_t buf_phase_conf_size; + + cl::Buffer buf_a; + cl::Buffer buf_b; + cl::Buffer buf_n; + cl::Buffer buf_ir; + cl::Buffer buf_a_filtered; + cl::Buffer buf_b_filtered; + cl::Buffer buf_edge_test; + cl::Buffer buf_depth; + cl::Buffer buf_ir_sum; + cl::Buffer buf_conf_1; + cl::Buffer buf_conf_2; + cl::Buffer buf_conf_3; + cl::Buffer buf_phase_1; + cl::Buffer buf_phase_2; + cl::Buffer buf_phase_3; + cl::Buffer buf_gaussian_kernel; + cl::Buffer buf_phase_conf; + + bool deviceInitialized; + bool programBuilt; + bool programInitialized; + bool runtimeOk; + std::string sourceCode; + +#ifdef LIBFREENECT2_WITH_PROFILING_CL + std::vector timings; + int count; +#endif + + OpenCLKdeDepthPacketProcessorImpl(const int deviceId = -1) + : deviceInitialized(false) + , programBuilt(false) + , programInitialized(false) + , runtimeOk(true) + { +#if _BSD_SOURCE || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 + setenv("OCL_IGNORE_SELF_TEST", "1", 0); + setenv("OCL_STRICT_CONFORMANCE", "0", 0); +#endif + + deviceInitialized = initDevice(deviceId); + + input_buffer_allocator = new PoolAllocator(new OpenCLKdeAllocator(context, queue, true)); + ir_buffer_allocator = new PoolAllocator(new OpenCLKdeAllocator(context, queue, false)); + depth_buffer_allocator = new PoolAllocator(new OpenCLKdeAllocator(context, queue, false)); + + newIrFrame(); + newDepthFrame(); + + const int CL_ICDL_VERSION = 2; + typedef cl_int (*icdloader_func)(int, size_t, void*, size_t*); +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + icdloader_func clGetICDLoaderInfoOCLICD = (icdloader_func)clGetExtensionFunctionAddress("clGetICDLoaderInfoOCLICD"); +#ifdef _MSC_VER +#pragma warning(pop) +#else +#pragma GCC diagnostic pop +#endif + if (clGetICDLoaderInfoOCLICD != NULL) + { + char buf[16]; + if (clGetICDLoaderInfoOCLICD(CL_ICDL_VERSION, sizeof(buf), buf, NULL) == CL_SUCCESS) + { + if (strcmp(buf, "2.2.4") < 0) + LOG_WARNING << "Your ocl-icd has deadlock bugs. Update to 2.2.4+ is recommended."; + } + } + } + + ~OpenCLKdeDepthPacketProcessorImpl() + { + delete ir_frame; + delete depth_frame; + delete input_buffer_allocator; + delete ir_buffer_allocator; + delete depth_buffer_allocator; + } + + void generateOptions(std::string &options) const + { + std::ostringstream oss; + oss.precision(16); + oss << std::scientific; + oss << " -D BFI_BITMASK=" << "0x180"; + + oss << " -D AB_MULTIPLIER=" << params.ab_multiplier << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ0=" << params.ab_multiplier_per_frq[0] << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ1=" << params.ab_multiplier_per_frq[1] << "f"; + oss << " -D AB_MULTIPLIER_PER_FRQ2=" << params.ab_multiplier_per_frq[2] << "f"; + oss << " -D AB_OUTPUT_MULTIPLIER=" << params.ab_output_multiplier << "f"; + + oss << " -D PHASE_IN_RAD0=" << params.phase_in_rad[0] << "f"; + oss << " -D PHASE_IN_RAD1=" << params.phase_in_rad[1] << "f"; + oss << " -D PHASE_IN_RAD2=" << params.phase_in_rad[2] << "f"; + + oss << " -D JOINT_BILATERAL_AB_THRESHOLD=" << params.joint_bilateral_ab_threshold << "f"; + oss << " -D JOINT_BILATERAL_MAX_EDGE=" << params.joint_bilateral_max_edge << "f"; + oss << " -D JOINT_BILATERAL_EXP=" << params.joint_bilateral_exp << "f"; + oss << " -D JOINT_BILATERAL_THRESHOLD=" << (params.joint_bilateral_ab_threshold * params.joint_bilateral_ab_threshold) / (params.ab_multiplier * params.ab_multiplier) << "f"; + oss << " -D GAUSSIAN_KERNEL_0=" << params.gaussian_kernel[0] << "f"; + oss << " -D GAUSSIAN_KERNEL_1=" << params.gaussian_kernel[1] << "f"; + oss << " -D GAUSSIAN_KERNEL_2=" << params.gaussian_kernel[2] << "f"; + oss << " -D GAUSSIAN_KERNEL_3=" << params.gaussian_kernel[3] << "f"; + oss << " -D GAUSSIAN_KERNEL_4=" << params.gaussian_kernel[4] << "f"; + oss << " -D GAUSSIAN_KERNEL_5=" << params.gaussian_kernel[5] << "f"; + oss << " -D GAUSSIAN_KERNEL_6=" << params.gaussian_kernel[6] << "f"; + oss << " -D GAUSSIAN_KERNEL_7=" << params.gaussian_kernel[7] << "f"; + oss << " -D GAUSSIAN_KERNEL_8=" << params.gaussian_kernel[8] << "f"; + + oss << " -D PHASE_OFFSET=" << params.phase_offset << "f"; + oss << " -D UNAMBIGIOUS_DIST=" << params.unambigious_dist << "f"; + oss << " -D INDIVIDUAL_AB_THRESHOLD=" << params.individual_ab_threshold << "f"; + oss << " -D AB_THRESHOLD=" << params.ab_threshold << "f"; + oss << " -D AB_CONFIDENCE_SLOPE=" << params.ab_confidence_slope << "f"; + oss << " -D AB_CONFIDENCE_OFFSET=" << params.ab_confidence_offset << "f"; + oss << " -D MIN_DEALIAS_CONFIDENCE=" << params.min_dealias_confidence << "f"; + oss << " -D MAX_DEALIAS_CONFIDENCE=" << params.max_dealias_confidence << "f"; + + oss << " -D EDGE_AB_AVG_MIN_VALUE=" << params.edge_ab_avg_min_value << "f"; + oss << " -D EDGE_AB_STD_DEV_THRESHOLD=" << params.edge_ab_std_dev_threshold << "f"; + oss << " -D EDGE_CLOSE_DELTA_THRESHOLD=" << params.edge_close_delta_threshold << "f"; + oss << " -D EDGE_FAR_DELTA_THRESHOLD=" << params.edge_far_delta_threshold << "f"; + oss << " -D EDGE_MAX_DELTA_THRESHOLD=" << params.edge_max_delta_threshold << "f"; + oss << " -D EDGE_AVG_DELTA_THRESHOLD=" << params.edge_avg_delta_threshold << "f"; + oss << " -D MAX_EDGE_COUNT=" << params.max_edge_count << "f"; + + oss << " -D MIN_DEPTH=" << config.MinDepth * 1000.0f << "f"; + oss << " -D MAX_DEPTH=" << config.MaxDepth * 1000.0f << "f"; + + oss << " -D KDE_SIGMA_SQR="< &platforms, std::vector &devices) + { + devices.clear(); + for(size_t i = 0; i < platforms.size(); ++i) + { + const cl::Platform &platform = platforms[i]; + + std::vector devs; + if(platform.getDevices(CL_DEVICE_TYPE_ALL, &devs) != CL_SUCCESS) + { + continue; + } + + devices.insert(devices.end(), devs.begin(), devs.end()); + } + } + + std::string deviceString(cl::Device &dev) + { + std::string devName, devVendor, devType; + cl_device_type devTypeID; + dev.getInfo(CL_DEVICE_NAME, &devName); + dev.getInfo(CL_DEVICE_VENDOR, &devVendor); + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + switch(devTypeID) + { + case CL_DEVICE_TYPE_CPU: + devType = "CPU"; + break; + case CL_DEVICE_TYPE_GPU: + devType = "GPU"; + break; + case CL_DEVICE_TYPE_ACCELERATOR: + devType = "ACCELERATOR"; + break; + default: + devType = "CUSTOM/UNKNOWN"; + } + + return devName + " (" + devType + ")[" + devVendor + ']'; + } + + void listDevice(std::vector &devices) + { + LOG_INFO << " devices:"; + for(size_t i = 0; i < devices.size(); ++i) + { + LOG_INFO << " " << i << ": " << deviceString(devices[i]); + } + } + + bool selectDevice(std::vector &devices, const int deviceId) + { + if(deviceId != -1 && devices.size() > (size_t)deviceId) + { + device = devices[deviceId]; + return true; + } + + bool selected = false; + size_t selectedType = 0; + + for(size_t i = 0; i < devices.size(); ++i) + { + cl::Device &dev = devices[i]; + cl_device_type devTypeID = 0; + dev.getInfo(CL_DEVICE_TYPE, &devTypeID); + + if(!selected || (selectedType != CL_DEVICE_TYPE_GPU && devTypeID == CL_DEVICE_TYPE_GPU)) + { + selectedType = devTypeID; + selected = true; + device = dev; + } + } + return selected; + } + + bool initDevice(const int deviceId) + { + if(!readProgram(sourceCode)) + { + return false; + } + + std::vector platforms; + CHECK_CL_RETURN(cl::Platform::get(&platforms)); + + if(platforms.empty()) + { + LOG_ERROR << "no opencl platforms found."; + return false; + } + + std::vector devices; + getDevices(platforms, devices); + listDevice(devices); + if(!selectDevice(devices, deviceId)) + { + LOG_ERROR << "could not find any suitable device"; + return false; + } + LOG_INFO << "selected device: " << deviceString(device); + + CHECK_CL_PARAM(context = cl::Context(device, NULL, NULL, NULL, &err)); + + if(!initBuffers()) + return false; + + return buildProgram(sourceCode); + } + + bool initBuffers() + { +#ifdef LIBFREENECT2_WITH_PROFILING_CL + count = 0; + CHECK_CL_PARAM(queue = cl::CommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &err)); +#else + CHECK_CL_PARAM(queue = cl::CommandQueue(context, device, 0, &err)); +#endif + + //Read only + buf_lut11to16_size = LUT_SIZE * sizeof(cl_short); + buf_p0_table_size = IMAGE_SIZE * sizeof(cl_float3); + buf_x_table_size = IMAGE_SIZE * sizeof(cl_float); + buf_z_table_size = IMAGE_SIZE * sizeof(cl_float); + buf_packet_size = ((IMAGE_SIZE * 11) / 16) * 10 * sizeof(cl_ushort); + buf_gauss_kernel_size = (2*params.kde_neigborhood_size+1)*sizeof(cl_float); + + CHECK_CL_PARAM(buf_lut11to16 = cl::Buffer(context, CL_MEM_READ_ONLY, buf_lut11to16_size, NULL, &err)); + CHECK_CL_PARAM(buf_p0_table = cl::Buffer(context, CL_MEM_READ_ONLY, buf_p0_table_size, NULL, &err)); + CHECK_CL_PARAM(buf_x_table = cl::Buffer(context, CL_MEM_READ_ONLY, buf_x_table_size, NULL, &err)); + CHECK_CL_PARAM(buf_z_table = cl::Buffer(context, CL_MEM_READ_ONLY, buf_z_table_size, NULL, &err)); + CHECK_CL_PARAM(buf_packet = cl::Buffer(context, CL_MEM_READ_ONLY, buf_packet_size, NULL, &err)); + CHECK_CL_PARAM(buf_gaussian_kernel = cl::Buffer(context, CL_MEM_READ_ONLY, buf_gauss_kernel_size, NULL, &err)); + + //Read-Write + buf_a_size = IMAGE_SIZE * sizeof(cl_float3); + buf_b_size = IMAGE_SIZE * sizeof(cl_float3); + buf_n_size = IMAGE_SIZE * sizeof(cl_float3); + buf_ir_size = IMAGE_SIZE * sizeof(cl_float); + buf_a_filtered_size = IMAGE_SIZE * sizeof(cl_float3); + buf_b_filtered_size = IMAGE_SIZE * sizeof(cl_float3); + buf_edge_test_size = IMAGE_SIZE * sizeof(cl_uchar); + buf_depth_size = IMAGE_SIZE * sizeof(cl_float); + buf_ir_sum_size = IMAGE_SIZE * sizeof(cl_float); + buf_phase_conf_size = IMAGE_SIZE * sizeof(cl_float4); + + CHECK_CL_PARAM(buf_a = cl::Buffer(context, CL_MEM_READ_WRITE, buf_a_size, NULL, &err)); + CHECK_CL_PARAM(buf_b = cl::Buffer(context, CL_MEM_READ_WRITE, buf_b_size, NULL, &err)); + CHECK_CL_PARAM(buf_n = cl::Buffer(context, CL_MEM_READ_WRITE, buf_n_size, NULL, &err)); + CHECK_CL_PARAM(buf_ir = cl::Buffer(context, CL_MEM_WRITE_ONLY, buf_ir_size, NULL, &err)); + CHECK_CL_PARAM(buf_a_filtered = cl::Buffer(context, CL_MEM_READ_WRITE, buf_a_filtered_size, NULL, &err)); + CHECK_CL_PARAM(buf_b_filtered = cl::Buffer(context, CL_MEM_READ_WRITE, buf_b_filtered_size, NULL, &err)); + CHECK_CL_PARAM(buf_edge_test = cl::Buffer(context, CL_MEM_READ_WRITE, buf_edge_test_size, NULL, &err)); + CHECK_CL_PARAM(buf_depth = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_ir_sum = cl::Buffer(context, CL_MEM_READ_WRITE, buf_ir_sum_size, NULL, &err)); + CHECK_CL_PARAM(buf_phase_1 = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_phase_2 = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_conf_1 = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_conf_2 = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_phase_conf = cl::Buffer(context, CL_MEM_READ_WRITE, buf_phase_conf_size, NULL, &err)); + if(params.num_hyps == 3) + { + CHECK_CL_PARAM(buf_phase_3 = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + CHECK_CL_PARAM(buf_conf_3 = cl::Buffer(context, CL_MEM_READ_WRITE, buf_depth_size, NULL, &err)); + } + + return true; + } + + bool initProgram() + { + if(!deviceInitialized) + { + return false; + } + + if (!programBuilt) + if (!buildProgram(sourceCode)) + return false; + + CHECK_CL_PARAM(kernel_processPixelStage1 = cl::Kernel(program, "processPixelStage1", &err)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(0, buf_lut11to16)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(1, buf_z_table)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(2, buf_p0_table)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(3, buf_packet)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(4, buf_a)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(5, buf_b)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(6, buf_n)); + CHECK_CL_RETURN(kernel_processPixelStage1.setArg(7, buf_ir)); + + CHECK_CL_PARAM(kernel_filterPixelStage1 = cl::Kernel(program, "filterPixelStage1", &err)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(0, buf_a)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(1, buf_b)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(2, buf_n)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(3, buf_a_filtered)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(4, buf_b_filtered)); + CHECK_CL_RETURN(kernel_filterPixelStage1.setArg(5, buf_edge_test)); + + if(params.num_hyps == 3) + { + CHECK_CL_PARAM(kernel_processPixelStage2_phase = cl::Kernel(program, "processPixelStage2_phase3", &err)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(0, config.EnableBilateralFilter ? buf_a_filtered : buf_a)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(1, config.EnableBilateralFilter ? buf_b_filtered : buf_b)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(2, buf_phase_1)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(3, buf_phase_2)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(4, buf_phase_3)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(5, buf_conf_1)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(6, buf_conf_2)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(7, buf_conf_3)); + + CHECK_CL_PARAM(kernel_filter_kde = cl::Kernel(program, "filter_kde3", &err)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(0, buf_phase_1)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(1, buf_phase_2)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(2, buf_phase_3)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(3, buf_conf_1)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(4, buf_conf_2)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(5, buf_conf_3)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(6, buf_gaussian_kernel)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(7, buf_z_table)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(8, buf_x_table)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(9, buf_depth)); + } + else + { + CHECK_CL_PARAM(kernel_processPixelStage2_phase = cl::Kernel(program, "processPixelStage2_phase", &err)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(0, config.EnableBilateralFilter ? buf_a_filtered : buf_a)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(1, config.EnableBilateralFilter ? buf_b_filtered : buf_b)); + CHECK_CL_RETURN(kernel_processPixelStage2_phase.setArg(2, buf_phase_conf)); + + CHECK_CL_PARAM(kernel_filter_kde = cl::Kernel(program, "filter_kde", &err)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(0, buf_phase_conf)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(1, buf_gaussian_kernel)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(2, buf_z_table)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(3, buf_x_table)); + CHECK_CL_RETURN(kernel_filter_kde.setArg(4, buf_depth)); + } + + programInitialized = true; + return true; + } + + bool run(const DepthPacket &packet) + { + std::vector eventWrite(1), eventPPS1(1), eventFPS1(1), eventPPS2(1), eventFPS2(1); + cl::Event eventReadIr, eventReadDepth; + + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_packet, CL_FALSE, 0, buf_packet_size, packet.buffer, NULL, &eventWrite[0])); + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_processPixelStage1, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventWrite, &eventPPS1[0])); + CHECK_CL_RETURN(queue.enqueueReadBuffer(buf_ir, CL_FALSE, 0, buf_ir_size, ir_frame->data, &eventPPS1, &eventReadIr)); + + if(config.EnableBilateralFilter) + { + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_filterPixelStage1, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventPPS1, &eventFPS1[0])); + } + else + { + eventFPS1[0] = eventPPS1[0]; + } + + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_processPixelStage2_phase, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventFPS1, &eventPPS2[0])); + + CHECK_CL_RETURN(queue.enqueueNDRangeKernel(kernel_filter_kde, cl::NullRange, cl::NDRange(IMAGE_SIZE), cl::NullRange, &eventPPS2, &eventFPS2[0])); + + CHECK_CL_RETURN(queue.enqueueReadBuffer(buf_depth, CL_FALSE, 0, buf_depth_size, depth_frame->data, &eventFPS2, &eventReadDepth)); + CHECK_CL_RETURN(eventReadIr.wait()); + CHECK_CL_RETURN(eventReadDepth.wait()); + +#ifdef LIBFREENECT2_WITH_PROFILING_CL + if(count == 0) + { + timings.clear(); + timings.resize(7, 0.0); + } + + timings[0] += eventWrite[0].getProfilingInfo() - eventWrite[0].getProfilingInfo(); + timings[1] += eventPPS1[0].getProfilingInfo() - eventPPS1[0].getProfilingInfo(); + timings[2] += eventFPS1[0].getProfilingInfo() - eventFPS1[0].getProfilingInfo(); + timings[3] += eventPPS2[0].getProfilingInfo() - eventPPS2[0].getProfilingInfo(); + timings[4] += eventFPS2[0].getProfilingInfo() - eventFPS2[0].getProfilingInfo(); + timings[5] += eventReadIr.getProfilingInfo() - eventReadIr.getProfilingInfo(); + timings[6] += eventReadDepth.getProfilingInfo() - eventReadDepth.getProfilingInfo(); + + if(++count == 100) + { + double sum = timings[0] + timings[1] + timings[2] + timings[3] + timings[4] + timings[5] + timings[6]; + LOG_INFO << "writing package: " << timings[0] / 100000000.0 << " ms."; + LOG_INFO << "stage 1: " << timings[1] / 100000000.0 << " ms."; + LOG_INFO << "filter 1: " << timings[2] / 100000000.0 << " ms."; + LOG_INFO << "stage 2: " << timings[3] / 100000000.0 << " ms."; + LOG_INFO << "filter 2: " << timings[4] / 100000000.0 << " ms."; + LOG_INFO << "reading ir: " << timings[5] / 100000000.0 << " ms."; + LOG_INFO << "reading depth: " << timings[6] / 100000000.0 << " ms."; + LOG_INFO << "overall: " << sum / 100000000.0 << " ms."; + count = 0; + } +#endif + + return true; + } + + bool readProgram(std::string &source) const + { + source = loadCLKdeSource("opencl_kde_depth_packet_processor.cl"); + return !source.empty(); + } + + bool buildProgram(const std::string &sources) + { + LOG_INFO << "building OpenCL program..."; + + std::string options; + generateOptions(options); + + cl::Program::Sources source(1, std::make_pair(sources.c_str(), sources.length())); + CHECK_CL_PARAM(program = cl::Program(context, source, &err)); + + CHECK_CL_ON_FAIL(program.build(options.c_str()), + LOG_ERROR << "failed to build program: " << err; + LOG_ERROR << "Build Status: " << program.getBuildInfo(device); + LOG_ERROR << "Build Options:\t" << program.getBuildInfo(device); + LOG_ERROR << "Build Log:\t " << program.getBuildInfo(device)); + + LOG_INFO << "OpenCL program built successfully"; + programBuilt = true; + return true; + } + + void newIrFrame() + { + ir_frame = new OpenCLKdeFrame(static_cast(ir_buffer_allocator->allocate(IMAGE_SIZE * sizeof(cl_float)))); + ir_frame->format = Frame::Float; + } + + void newDepthFrame() + { + depth_frame = new OpenCLKdeFrame(static_cast(depth_buffer_allocator->allocate(IMAGE_SIZE * sizeof(cl_float)))); + depth_frame->format = Frame::Float; + } + + bool fill_trig_table(const libfreenect2::protocol::P0TablesResponse *p0table) + { + if(!deviceInitialized) + { + LOG_ERROR << "OpenCLKdeDepthPacketProcessor is not initialized!"; + return false; + } + + cl_float3 *p0_table = new cl_float3[IMAGE_SIZE]; + + for(int r = 0; r < 424; ++r) + { + cl_float3 *it = &p0_table[r * 512]; + const uint16_t *it0 = &p0table->p0table0[r * 512]; + const uint16_t *it1 = &p0table->p0table1[r * 512]; + const uint16_t *it2 = &p0table->p0table2[r * 512]; + for(int c = 0; c < 512; ++c, ++it, ++it0, ++it1, ++it2) + { + it->s[0] = -((float)*it0) * 0.000031 * M_PI; + it->s[1] = -((float)*it1) * 0.000031 * M_PI; + it->s[2] = -((float)*it2) * 0.000031 * M_PI; + it->s[3] = 0.0f; + } + } + + cl::Event event; + CHECK_CL_ON_FAIL(queue.enqueueWriteBuffer(buf_p0_table, CL_FALSE, 0, buf_p0_table_size, p0_table, NULL, &event), delete[] p0_table); + CHECK_CL_ON_FAIL(event.wait(), delete[] p0_table); + delete[] p0_table; + return true; + } + + bool fill_xz_tables(const float *xtable, const float *ztable) + { + if(!deviceInitialized) + { + LOG_ERROR << "OpenCLKdeDepthPacketProcessor is not initialized!"; + return false; + } + + cl::Event event0, event1; + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_x_table, CL_FALSE, 0, buf_x_table_size, xtable, NULL, &event0)); + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_z_table, CL_FALSE, 0, buf_z_table_size, ztable, NULL, &event1)); + + float* gauss_kernel; + createGaussianKernel(&gauss_kernel, params.kde_neigborhood_size); + + cl::Event event2; + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_gaussian_kernel, CL_FALSE, 0, buf_gauss_kernel_size, gauss_kernel, NULL, &event2)); + + + CHECK_CL_RETURN(event0.wait()); + CHECK_CL_RETURN(event1.wait()); + CHECK_CL_RETURN(event2.wait()); + return true; + } + + bool fill_lut(const short *lut) + { + if(!deviceInitialized) + { + LOG_ERROR << "OpenCLKdeDepthPacketProcessor is not initialized!"; + return false; + } + + cl::Event event; + CHECK_CL_RETURN(queue.enqueueWriteBuffer(buf_lut11to16, CL_FALSE, 0, buf_lut11to16_size, lut, NULL, &event)); + CHECK_CL_RETURN(event.wait()); + return true; + } + + //initialize spatial weights + void createGaussianKernel(float** kernel, int size) + { + *kernel = new float[2*size+1]; + float sigma = 0.5f*(float)size; + + for(int i = -size; i <= size; i++) + { + (*kernel)[i+size] = exp(-0.5f*i*i/(sigma*sigma)); + } + } +}; + +OpenCLKdeDepthPacketProcessor::OpenCLKdeDepthPacketProcessor(const int deviceId) : + impl_(new OpenCLKdeDepthPacketProcessorImpl(deviceId)) +{ +} + +OpenCLKdeDepthPacketProcessor::~OpenCLKdeDepthPacketProcessor() +{ + delete impl_; +} + +void OpenCLKdeDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + + if ( impl_->config.MaxDepth != config.MaxDepth + || impl_->config.MinDepth != config.MinDepth) + { + // OpenCL program needs to be rebuilt, then reinitialized + impl_->programBuilt = false; + impl_->programInitialized = false; + } + else if (impl_->config.EnableBilateralFilter != config.EnableBilateralFilter + || impl_->config.EnableEdgeAwareFilter != config.EnableEdgeAwareFilter) + { + // OpenCL program only needs to be reinitialized + impl_->programInitialized = false; + } + + impl_->config = config; + if (!impl_->programBuilt) + impl_->buildProgram(impl_->sourceCode); +} + +void OpenCLKdeDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char *buffer, size_t buffer_length) +{ + libfreenect2::protocol::P0TablesResponse *p0table = (libfreenect2::protocol::P0TablesResponse *)buffer; + + if(buffer_length < sizeof(libfreenect2::protocol::P0TablesResponse)) + { + LOG_ERROR << "P0Table response too short!"; + return; + } + + impl_->fill_trig_table(p0table); +} + +void OpenCLKdeDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) +{ + impl_->fill_xz_tables(xtable, ztable); +} + +void OpenCLKdeDepthPacketProcessor::loadLookupTable(const short *lut) +{ + impl_->fill_lut(lut); +} + +bool OpenCLKdeDepthPacketProcessor::good() +{ + return impl_->deviceInitialized && impl_->runtimeOk; +} + +void OpenCLKdeDepthPacketProcessor::process(const DepthPacket &packet) +{ + if (!listener_) + return; + + if(!impl_->programInitialized && !impl_->initProgram()) + { + impl_->runtimeOk = false; + LOG_ERROR << "could not initialize OpenCLKdeDepthPacketProcessor"; + return; + } + + impl_->startTiming(); + + impl_->ir_frame->timestamp = packet.timestamp; + impl_->depth_frame->timestamp = packet.timestamp; + impl_->ir_frame->sequence = packet.sequence; + impl_->depth_frame->sequence = packet.sequence; + + impl_->runtimeOk = impl_->run(packet); + + impl_->stopTiming(LOG_INFO); + + if (!impl_->runtimeOk) + { + impl_->ir_frame->status = 1; + impl_->depth_frame->status = 1; + } + + if(listener_->onNewFrame(Frame::Ir, impl_->ir_frame)) + impl_->newIrFrame(); + if(listener_->onNewFrame(Frame::Depth, impl_->depth_frame)) + impl_->newDepthFrame(); +} + +Allocator *OpenCLKdeDepthPacketProcessor::getAllocator() +{ + return impl_->input_buffer_allocator; +} +} /* namespace libfreenect2 */ + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opengl_depth_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opengl_depth_packet_processor.cpp new file mode 100644 index 0000000..f9d0adc --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/opengl_depth_packet_processor.cpp @@ -0,0 +1,986 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file opengl_depth_packet_processor.cpp Depth packet processor implementation using OpenGL. */ + +#include +#include +#include +#include +#include "flextGL.h" +#include + +#include +#include +#include +#include + +#include + +#define CHECKGL() do { \ +for (GLenum glerror = glGetError(); glerror != GL_NO_ERROR; glerror = glGetError()) \ + LOG_ERROR << "line " << __LINE__ << ": GL error " << glerror; \ +} while(0) + +namespace libfreenect2 +{ + +struct ChangeCurrentOpenGLContext +{ + GLFWwindow *last_ctx; + + ChangeCurrentOpenGLContext(GLFWwindow *new_context); + ~ChangeCurrentOpenGLContext(); +}; + +ChangeCurrentOpenGLContext::ChangeCurrentOpenGLContext(GLFWwindow *new_context) +{ + last_ctx = glfwGetCurrentContext(); + glfwMakeContextCurrent(new_context); +} + +ChangeCurrentOpenGLContext::~ChangeCurrentOpenGLContext() +{ + //LOG_INFO << "restoring context!"; + if(last_ctx != 0) + { + glfwMakeContextCurrent(last_ctx); + } + else + { + glfwMakeContextCurrent(0); + } +} + +class WithOpenGLBindings +{ +private: + OpenGLBindings *bindings; +protected: + WithOpenGLBindings() : bindings(0) {} + virtual ~WithOpenGLBindings() {} + + virtual void onOpenGLBindingsChanged(OpenGLBindings *b) { } +public: + void gl(OpenGLBindings *bindings) + { + this->bindings = bindings; + onOpenGLBindingsChanged(this->bindings); + } + + OpenGLBindings *gl() + { + return bindings; + } +}; + +std::string loadShaderSource(const std::string& filename) +{ + const unsigned char* data; + size_t length = 0; + + if(!loadResource(filename, &data, &length)) + { + LOG_ERROR << "failed to load shader source!"; + return ""; + } + + return std::string(reinterpret_cast(data), length); +} + +struct ShaderProgram : public WithOpenGLBindings +{ + typedef std::map FragDataMap; + FragDataMap frag_data_map_; + GLuint program, vertex_shader, fragment_shader; + + char error_buffer[2048]; + + std::string defines; + bool is_mesa_checked; + + ShaderProgram() : + program(0), + vertex_shader(0), + fragment_shader(0), + is_mesa_checked(false) + { + } + + void checkMesaBug() + { + if (is_mesa_checked) + return; + is_mesa_checked = true; + std::string ren((const char*)glGetString(GL_RENDERER)); + std::string ver((const char*)glGetString(GL_VERSION)); + if (ren.find("Mesa DRI Intel") == 0) + { + size_t mesa_pos = ver.rfind("Mesa "); + if (mesa_pos != std::string::npos) + { + double mesa_ver = atof(ver.substr(mesa_pos + 5).c_str()); + if (mesa_ver < 10.3) + { + defines += "#define MESA_BUGGY_BOOL_CMP\n"; + LOG_WARNING << "Working around buggy boolean instructions in your Mesa driver. Mesa DRI 10.3+ is recommended."; + } + } + } + } + + void setVertexShader(const std::string& src) + { + checkMesaBug(); + const GLchar *sources[] = {"#version 140\n", defines.c_str(), src.c_str()}; + vertex_shader = gl()->glCreateShader(GL_VERTEX_SHADER); + gl()->glShaderSource(vertex_shader, 3, sources, NULL); + CHECKGL(); + } + + void setFragmentShader(const std::string& src) + { + checkMesaBug(); + const GLchar *sources[] = {"#version 140\n", defines.c_str(), src.c_str()}; + fragment_shader = gl()->glCreateShader(GL_FRAGMENT_SHADER); + gl()->glShaderSource(fragment_shader, 3, sources, NULL); + CHECKGL(); + } + + void bindFragDataLocation(const std::string &name, int output) + { + frag_data_map_[name] = output; + } + + void build() + { + GLint status; + + gl()->glCompileShader(vertex_shader); + gl()->glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status); + + if(status != GL_TRUE) + { + gl()->glGetShaderInfoLog(vertex_shader, sizeof(error_buffer), NULL, error_buffer); + + LOG_ERROR << "failed to compile vertex shader!" << std::endl << error_buffer; + } + + gl()->glCompileShader(fragment_shader); + + gl()->glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); + if(status != GL_TRUE) + { + gl()->glGetShaderInfoLog(fragment_shader, sizeof(error_buffer), NULL, error_buffer); + + LOG_ERROR << "failed to compile fragment shader!" << std::endl << error_buffer; + } + + program = gl()->glCreateProgram(); + gl()->glAttachShader(program, vertex_shader); + gl()->glAttachShader(program, fragment_shader); + + for(FragDataMap::iterator it = frag_data_map_.begin(); it != frag_data_map_.end(); ++it) + { + gl()->glBindFragDataLocation(program, it->second, it->first.c_str()); + } + + gl()->glLinkProgram(program); + + gl()->glGetProgramiv(program, GL_LINK_STATUS, &status); + + if(status != GL_TRUE) + { + gl()->glGetProgramInfoLog(program, sizeof(error_buffer), NULL, error_buffer); + LOG_ERROR << "failed to link shader program!" << std::endl << error_buffer; + } + CHECKGL(); + } + + GLint getAttributeLocation(const std::string& name) + { + return gl()->glGetAttribLocation(program, name.c_str()); + } + + void setUniform(const std::string& name, GLint value) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniform1i(idx, value); + CHECKGL(); + } + + void setUniform(const std::string& name, GLfloat value) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniform1f(idx, value); + CHECKGL(); + } + + void setUniformVector3(const std::string& name, GLfloat value[3]) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniform3fv(idx, 1, value); + CHECKGL(); + } + + void setUniformMatrix3(const std::string& name, GLfloat value[9]) + { + GLint idx = gl()->glGetUniformLocation(program, name.c_str()); + if(idx == -1) return; + + gl()->glUniformMatrix3fv(idx, 1, false, value); + CHECKGL(); + } + + void use() + { + gl()->glUseProgram(program); + CHECKGL(); + } +}; + +template +struct ImageFormat +{ + static const size_t BytesPerPixel = TBytesPerPixel; + static const GLenum InternalFormat = TInternalFormat; + static const GLenum Format = TFormat; + static const GLenum Type = TType; +}; + +typedef ImageFormat<1, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE> U8C1; +typedef ImageFormat<2, GL_R16I, GL_RED_INTEGER, GL_SHORT> S16C1; +typedef ImageFormat<2, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT> U16C1; +typedef ImageFormat<4, GL_R32F, GL_RED, GL_FLOAT> F32C1; +typedef ImageFormat<8, GL_RG32F, GL_RG, GL_FLOAT> F32C2; +typedef ImageFormat<12, GL_RGB32F, GL_RGB, GL_FLOAT> F32C3; +typedef ImageFormat<16, GL_RGBA32F, GL_RGBA, GL_FLOAT> F32C4; + +template +struct Texture : public WithOpenGLBindings +{ +protected: + size_t bytes_per_pixel, height, width; + +public: + GLuint texture; + unsigned char *data; + size_t size; + + Texture() : bytes_per_pixel(FormatT::BytesPerPixel), height(0), width(0), texture(0), data(0), size(0) + { + } + + ~Texture() + { + delete[] data; + } + + void bindToUnit(GLenum unit) + { + gl()->glActiveTexture(unit); + glBindTexture(GL_TEXTURE_RECTANGLE, texture); + CHECKGL(); + } + + void allocate(size_t new_width, size_t new_height) + { + if (size) + return; + + GLint max_size; + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &max_size); + if (new_width > (size_t)max_size || new_height > (size_t)max_size) + { + LOG_ERROR << "GL_MAX_RECTANGLE_TEXTURE_SIZE is too small: " << max_size; + exit(-1); + } + + width = new_width; + height = new_height; + size = height * width * bytes_per_pixel; + data = new unsigned char[size]; + + glGenTextures(1, &texture); + bindToUnit(GL_TEXTURE0); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, FormatT::InternalFormat, width, height, 0, FormatT::Format, FormatT::Type, 0); + CHECKGL(); + } + + void upload() + { + bindToUnit(GL_TEXTURE0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_RECTANGLE, /*level*/0, /*xoffset*/0, /*yoffset*/0, width, height, FormatT::Format, FormatT::Type, data); + CHECKGL(); + } + + void download() + { + downloadToBuffer(data); + } + + void downloadToBuffer(unsigned char *data) + { + glReadPixels(0, 0, width, height, FormatT::Format, FormatT::Type, data); + CHECKGL(); + } + + void flipY() + { + flipYBuffer(data); + } + + void flipYBuffer(unsigned char *data) + { + typedef unsigned char type; + + size_t linestep = width * bytes_per_pixel / sizeof(type); + + type *first_line = reinterpret_cast(data), *last_line = reinterpret_cast(data) + (height - 1) * linestep; + + for(size_t y = 0; y < height / 2; ++y) + { + for(size_t x = 0; x < linestep; ++x, ++first_line, ++last_line) + { + std::swap(*first_line, *last_line); + } + last_line -= 2 * linestep; + } + } + + Frame *downloadToNewFrame() + { + Frame *f = new Frame(width, height, bytes_per_pixel); + f->format = Frame::Float; + downloadToBuffer(f->data); + flipYBuffer(f->data); + + return f; + } +}; + +class OpenGLDepthPacketProcessorImpl : public WithOpenGLBindings, public WithPerfLogging +{ +public: + GLFWwindow *opengl_context_ptr; + libfreenect2::DepthPacketProcessor::Config config; + + GLuint square_vbo, square_vao, stage1_framebuffer, filter1_framebuffer, stage2_framebuffer, filter2_framebuffer; + Texture lut11to16; + Texture p0table[3]; + Texture x_table, z_table; + + Texture input_data; + + Texture stage1_debug; + Texture stage1_data[3]; + Texture stage1_infrared; + + Texture filter1_data[2]; + Texture filter1_max_edge_test; + Texture filter1_debug; + + Texture stage2_debug; + + Texture stage2_depth; + Texture stage2_depth_and_ir_sum; + + Texture filter2_debug; + Texture filter2_depth; + + ShaderProgram stage1, filter1, stage2, filter2, debug; + + DepthPacketProcessor::Parameters params; + bool params_need_update; + + bool do_debug; + + struct Vertex + { + float x, y; + float u, v; + }; + + OpenGLDepthPacketProcessorImpl(GLFWwindow *new_opengl_context_ptr, bool debug) : + opengl_context_ptr(new_opengl_context_ptr), + square_vbo(0), + square_vao(0), + stage1_framebuffer(0), + filter1_framebuffer(0), + stage2_framebuffer(0), + filter2_framebuffer(0), + params_need_update(true), + do_debug(debug) + { + } + + virtual ~OpenGLDepthPacketProcessorImpl() + { + if(gl() != 0) + { + delete gl(); + gl(0); + } + glfwDestroyWindow(opengl_context_ptr); + opengl_context_ptr = 0; + } + + virtual void onOpenGLBindingsChanged(OpenGLBindings *b) + { + lut11to16.gl(b); + p0table[0].gl(b); + p0table[1].gl(b); + p0table[2].gl(b); + x_table.gl(b); + z_table.gl(b); + + input_data.gl(b); + + stage1_debug.gl(b); + stage1_data[0].gl(b); + stage1_data[1].gl(b); + stage1_data[2].gl(b); + stage1_infrared.gl(b); + + filter1_data[0].gl(b); + filter1_data[1].gl(b); + filter1_max_edge_test.gl(b); + filter1_debug.gl(b); + + stage2_debug.gl(b); + + stage2_depth.gl(b); + stage2_depth_and_ir_sum.gl(b); + + filter2_debug.gl(b); + filter2_depth.gl(b); + + stage1.gl(b); + filter1.gl(b); + stage2.gl(b); + filter2.gl(b); + debug.gl(b); + } + + static void glfwErrorCallback(int error, const char* description) + { + LOG_ERROR << "GLFW error " << error << " " << description; + } + + void checkFBO(GLenum target) + { + GLenum status = gl()->glCheckFramebufferStatus(target); + if (status != GL_FRAMEBUFFER_COMPLETE) + { + LOG_ERROR << "incomplete FBO " << status; + exit(-1); + } + CHECKGL(); + } + + void initialize() + { + ChangeCurrentOpenGLContext ctx(opengl_context_ptr); + + int major = glfwGetWindowAttrib(opengl_context_ptr, GLFW_CONTEXT_VERSION_MAJOR); + int minor = glfwGetWindowAttrib(opengl_context_ptr, GLFW_CONTEXT_VERSION_MINOR); + + if (major * 10 + minor < 31) { + LOG_ERROR << "OpenGL version 3.1 not supported."; + LOG_ERROR << "Your version is " << major << "." << minor; + LOG_ERROR << "Try updating your graphics driver."; + exit(-1); + } + + OpenGLBindings *b = new OpenGLBindings(); + flextInit(b); + gl(b); + + input_data.allocate(352, 424 * 9); + + for(int i = 0; i < 3; ++i) + stage1_data[i].allocate(512, 424); + + if(do_debug) stage1_debug.allocate(512, 424); + stage1_infrared.allocate(512, 424); + + for(int i = 0; i < 2; ++i) + filter1_data[i].allocate(512, 424); + + filter1_max_edge_test.allocate(512, 424); + if(do_debug) filter1_debug.allocate(512, 424); + + if(do_debug) stage2_debug.allocate(512, 424); + stage2_depth.allocate(512, 424); + stage2_depth_and_ir_sum.allocate(512, 424); + + if(do_debug) filter2_debug.allocate(512, 424); + filter2_depth.allocate(512, 424); + + stage1.setVertexShader(loadShaderSource("default.vs")); + stage1.setFragmentShader(loadShaderSource("stage1.fs")); + stage1.bindFragDataLocation("Debug", 0); + stage1.bindFragDataLocation("A", 1); + stage1.bindFragDataLocation("B", 2); + stage1.bindFragDataLocation("Norm", 3); + stage1.bindFragDataLocation("Infrared", 4); + stage1.build(); + + filter1.setVertexShader(loadShaderSource("default.vs")); + filter1.setFragmentShader(loadShaderSource("filter1.fs")); + filter1.bindFragDataLocation("Debug", 0); + filter1.bindFragDataLocation("FilterA", 1); + filter1.bindFragDataLocation("FilterB", 2); + filter1.bindFragDataLocation("MaxEdgeTest", 3); + filter1.build(); + + stage2.setVertexShader(loadShaderSource("default.vs")); + stage2.setFragmentShader(loadShaderSource("stage2.fs")); + stage2.bindFragDataLocation("Debug", 0); + stage2.bindFragDataLocation("Depth", 1); + stage2.bindFragDataLocation("DepthAndIrSum", 2); + stage2.build(); + + filter2.setVertexShader(loadShaderSource("default.vs")); + filter2.setFragmentShader(loadShaderSource("filter2.fs")); + filter2.bindFragDataLocation("Debug", 0); + filter2.bindFragDataLocation("FilterDepth", 1); + filter2.build(); + + if(do_debug) + { + debug.setVertexShader(loadShaderSource("default.vs")); + debug.setFragmentShader(loadShaderSource("debug.fs")); + debug.bindFragDataLocation("Debug", 0); + debug.build(); + } + + GLenum debug_attachment = do_debug ? GL_COLOR_ATTACHMENT0 : GL_NONE; + + gl()->glGenFramebuffers(1, &stage1_framebuffer); + gl()->glBindFramebuffer(GL_FRAMEBUFFER, stage1_framebuffer); + + const GLenum stage1_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4 }; + gl()->glDrawBuffers(5, stage1_buffers); + glReadBuffer(GL_COLOR_ATTACHMENT4); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, stage1_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, stage1_data[0].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_RECTANGLE, stage1_data[1].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_RECTANGLE, stage1_data[2].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_RECTANGLE, stage1_infrared.texture, 0); + checkFBO(GL_FRAMEBUFFER); + + gl()->glGenFramebuffers(1, &filter1_framebuffer); + gl()->glBindFramebuffer(GL_FRAMEBUFFER, filter1_framebuffer); + + const GLenum filter1_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; + gl()->glDrawBuffers(4, filter1_buffers); + glReadBuffer(GL_NONE); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, filter1_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, filter1_data[0].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_RECTANGLE, filter1_data[1].texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_RECTANGLE, filter1_max_edge_test.texture, 0); + checkFBO(GL_FRAMEBUFFER); + + gl()->glGenFramebuffers(1, &stage2_framebuffer); + gl()->glBindFramebuffer(GL_FRAMEBUFFER, stage2_framebuffer); + + const GLenum stage2_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + gl()->glDrawBuffers(3, stage2_buffers); + glReadBuffer(GL_COLOR_ATTACHMENT1); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, stage2_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, stage2_depth.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_RECTANGLE, stage2_depth_and_ir_sum.texture, 0); + checkFBO(GL_FRAMEBUFFER); + + gl()->glGenFramebuffers(1, &filter2_framebuffer); + gl()->glBindFramebuffer(GL_FRAMEBUFFER, filter2_framebuffer); + + const GLenum filter2_buffers[] = { debug_attachment, GL_COLOR_ATTACHMENT1 }; + gl()->glDrawBuffers(2, filter2_buffers); + glReadBuffer(GL_COLOR_ATTACHMENT1); + + if(do_debug) gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, filter2_debug.texture, 0); + gl()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_RECTANGLE, filter2_depth.texture, 0); + checkFBO(GL_FRAMEBUFFER); + + Vertex bl = {-1.0f, -1.0f, 0.0f, 0.0f }, br = { 1.0f, -1.0f, 512.0f, 0.0f }, tl = {-1.0f, 1.0f, 0.0f, 424.0f }, tr = { 1.0f, 1.0f, 512.0f, 424.0f }; + Vertex vertices[] = { + bl, tl, tr, tr, br, bl + }; + gl()->glGenBuffers(1, &square_vbo); + gl()->glGenVertexArrays(1, &square_vao); + + gl()->glBindVertexArray(square_vao); + gl()->glBindBuffer(GL_ARRAY_BUFFER, square_vbo); + gl()->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + GLint position_attr = stage1.getAttributeLocation("InputPosition"); + gl()->glVertexAttribPointer(position_attr, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); + gl()->glEnableVertexAttribArray(position_attr); + + GLint texcoord_attr = stage1.getAttributeLocation("InputTexCoord"); + gl()->glVertexAttribPointer(texcoord_attr, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(2 * sizeof(float))); + gl()->glEnableVertexAttribArray(texcoord_attr); + CHECKGL(); + } + + void deinitialize() + { + } + + void updateShaderParametersForProgram(ShaderProgram &program) + { + if(!params_need_update) return; + + program.setUniform("Params.ab_multiplier", params.ab_multiplier); + program.setUniformVector3("Params.ab_multiplier_per_frq", params.ab_multiplier_per_frq); + program.setUniform("Params.ab_output_multiplier", params.ab_output_multiplier); + + program.setUniformVector3("Params.phase_in_rad", params.phase_in_rad); + + program.setUniform("Params.joint_bilateral_ab_threshold", params.joint_bilateral_ab_threshold); + program.setUniform("Params.joint_bilateral_max_edge", params.joint_bilateral_max_edge); + program.setUniform("Params.joint_bilateral_exp", params.joint_bilateral_exp); + program.setUniformMatrix3("Params.gaussian_kernel", params.gaussian_kernel); + + program.setUniform("Params.phase_offset", params.phase_offset); + program.setUniform("Params.unambigious_dist", params.unambigious_dist); + program.setUniform("Params.individual_ab_threshold", params.individual_ab_threshold); + program.setUniform("Params.ab_threshold", params.ab_threshold); + program.setUniform("Params.ab_confidence_slope", params.ab_confidence_slope); + program.setUniform("Params.ab_confidence_offset", params.ab_confidence_offset); + program.setUniform("Params.min_dealias_confidence", params.min_dealias_confidence); + program.setUniform("Params.max_dealias_confidence", params.max_dealias_confidence); + + program.setUniform("Params.edge_ab_avg_min_value", params.edge_ab_avg_min_value); + program.setUniform("Params.edge_ab_std_dev_threshold", params.edge_ab_std_dev_threshold); + program.setUniform("Params.edge_close_delta_threshold", params.edge_close_delta_threshold); + program.setUniform("Params.edge_far_delta_threshold", params.edge_far_delta_threshold); + program.setUniform("Params.edge_max_delta_threshold", params.edge_max_delta_threshold); + program.setUniform("Params.edge_avg_delta_threshold", params.edge_avg_delta_threshold); + program.setUniform("Params.max_edge_count", params.max_edge_count); + + program.setUniform("Params.min_depth", params.min_depth); + program.setUniform("Params.max_depth", params.max_depth); + } + + void run(Frame **ir, Frame **depth) + { + // data processing 1 + glViewport(0, 0, 512, 424); + stage1.use(); + updateShaderParametersForProgram(stage1); + + p0table[0].bindToUnit(GL_TEXTURE0); + stage1.setUniform("P0Table0", 0); + p0table[1].bindToUnit(GL_TEXTURE1); + stage1.setUniform("P0Table1", 1); + p0table[2].bindToUnit(GL_TEXTURE2); + stage1.setUniform("P0Table2", 2); + lut11to16.bindToUnit(GL_TEXTURE3); + stage1.setUniform("Lut11to16", 3); + input_data.bindToUnit(GL_TEXTURE4); + stage1.setUniform("Data", 4); + z_table.bindToUnit(GL_TEXTURE5); + stage1.setUniform("ZTable", 5); + + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, stage1_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + CHECKGL(); + + if(ir != 0) + { + gl()->glBindFramebuffer(GL_READ_FRAMEBUFFER, stage1_framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT4); + *ir = stage1_infrared.downloadToNewFrame(); + } + + if(config.EnableBilateralFilter) + { + // bilateral filter + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, filter1_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + filter1.use(); + updateShaderParametersForProgram(filter1); + + stage1_data[0].bindToUnit(GL_TEXTURE0); + filter1.setUniform("A", 0); + stage1_data[1].bindToUnit(GL_TEXTURE1); + filter1.setUniform("B", 1); + stage1_data[2].bindToUnit(GL_TEXTURE2); + filter1.setUniform("Norm", 2); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + } + // data processing 2 + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, stage2_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + stage2.use(); + updateShaderParametersForProgram(stage2); + CHECKGL(); + + if(config.EnableBilateralFilter) + { + filter1_data[0].bindToUnit(GL_TEXTURE0); + filter1_data[1].bindToUnit(GL_TEXTURE1); + } + else + { + stage1_data[0].bindToUnit(GL_TEXTURE0); + stage1_data[1].bindToUnit(GL_TEXTURE1); + } + stage2.setUniform("A", 0); + stage2.setUniform("B", 1); + x_table.bindToUnit(GL_TEXTURE2); + stage2.setUniform("XTable", 2); + z_table.bindToUnit(GL_TEXTURE3); + stage2.setUniform("ZTable", 3); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + CHECKGL(); + + if(config.EnableEdgeAwareFilter) + { + // edge aware filter + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, filter2_framebuffer); + glClear(GL_COLOR_BUFFER_BIT); + + filter2.use(); + updateShaderParametersForProgram(filter2); + + stage2_depth_and_ir_sum.bindToUnit(GL_TEXTURE0); + filter2.setUniform("DepthAndIrSum", 0); + filter1_max_edge_test.bindToUnit(GL_TEXTURE1); + filter2.setUniform("MaxEdgeTest", 1); + + gl()->glBindVertexArray(square_vao); + glDrawArrays(GL_TRIANGLES, 0, 6); + if(depth != 0) + { + gl()->glBindFramebuffer(GL_READ_FRAMEBUFFER, filter2_framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT1); + *depth = filter2_depth.downloadToNewFrame(); + } + } + else + { + if(depth != 0) + { + gl()->glBindFramebuffer(GL_READ_FRAMEBUFFER, stage2_framebuffer); + glReadBuffer(GL_COLOR_ATTACHMENT1); + *depth = stage2_depth.downloadToNewFrame(); + } + } + CHECKGL(); + + if(do_debug) + { + // debug drawing + gl()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT); + + gl()->glBindVertexArray(square_vao); + + debug.use(); + stage2_debug.bindToUnit(GL_TEXTURE0); + debug.setUniform("Debug", 0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glViewport(512, 0, 512, 424); + filter2_debug.bindToUnit(GL_TEXTURE0); + debug.setUniform("Debug", 0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glViewport(0, 424, 512, 424); + stage1_debug.bindToUnit(GL_TEXTURE0); + debug.setUniform("Debug", 0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + } + CHECKGL(); + + params_need_update = false; + } +}; + +OpenGLDepthPacketProcessor::OpenGLDepthPacketProcessor(void *parent_opengl_context_ptr, bool debug) +{ + GLFWwindow* parent_window = (GLFWwindow *)parent_opengl_context_ptr; + + GLFWerrorfun prev_func = glfwSetErrorCallback(&OpenGLDepthPacketProcessorImpl::glfwErrorCallback); + if (prev_func) + glfwSetErrorCallback(prev_func); + + // init glfw - if already initialized nothing happens + if (glfwInit() == GL_FALSE) + { + LOG_ERROR << "Failed to initialize GLFW."; + exit(-1); + } + + // setup context + glfwDefaultWindowHints(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +#ifdef __APPLE__ + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#else + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); +#endif + glfwWindowHint(GLFW_VISIBLE, debug ? GL_TRUE : GL_FALSE); + + GLFWwindow* window = glfwCreateWindow(1024, 848, "OpenGLDepthPacketProcessor", 0, parent_window); + + if (window == NULL) + { + LOG_ERROR << "Failed to create opengl window."; + exit(-1); + } + + impl_ = new OpenGLDepthPacketProcessorImpl(window, debug); + impl_->initialize(); +} + +OpenGLDepthPacketProcessor::~OpenGLDepthPacketProcessor() +{ + delete impl_; +} + + +void OpenGLDepthPacketProcessor::setConfiguration(const libfreenect2::DepthPacketProcessor::Config &config) +{ + DepthPacketProcessor::setConfiguration(config); + impl_->config = config; + + impl_->params.min_depth = impl_->config.MinDepth * 1000.0f; + impl_->params.max_depth = impl_->config.MaxDepth * 1000.0f; + + impl_->params_need_update = true; +} + +void OpenGLDepthPacketProcessor::loadP0TablesFromCommandResponse(unsigned char* buffer, size_t buffer_length) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + size_t n = 512 * 424; + libfreenect2::protocol::P0TablesResponse* p0table = (libfreenect2::protocol::P0TablesResponse*)buffer; + + impl_->p0table[0].allocate(512, 424); + std::copy(reinterpret_cast(p0table->p0table0), reinterpret_cast(p0table->p0table0 + n), impl_->p0table[0].data); + impl_->p0table[0].flipY(); + impl_->p0table[0].upload(); + + impl_->p0table[1].allocate(512, 424); + std::copy(reinterpret_cast(p0table->p0table1), reinterpret_cast(p0table->p0table1 + n), impl_->p0table[1].data); + impl_->p0table[1].flipY(); + impl_->p0table[1].upload(); + + impl_->p0table[2].allocate(512, 424); + std::copy(reinterpret_cast(p0table->p0table2), reinterpret_cast(p0table->p0table2 + n), impl_->p0table[2].data); + impl_->p0table[2].flipY(); + impl_->p0table[2].upload(); + +} + +void OpenGLDepthPacketProcessor::loadXZTables(const float *xtable, const float *ztable) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + impl_->x_table.allocate(512, 424); + std::copy(xtable, xtable + TABLE_SIZE, (float *)impl_->x_table.data); + impl_->x_table.upload(); + + impl_->z_table.allocate(512, 424); + std::copy(ztable, ztable + TABLE_SIZE, (float *)impl_->z_table.data); + impl_->z_table.upload(); +} + +void OpenGLDepthPacketProcessor::loadLookupTable(const short *lut) +{ + ChangeCurrentOpenGLContext ctx(impl_->opengl_context_ptr); + + impl_->lut11to16.allocate(2048, 1); + std::copy(lut, lut + LUT_SIZE, (short *)impl_->lut11to16.data); + impl_->lut11to16.upload(); +} + +void OpenGLDepthPacketProcessor::process(const DepthPacket &packet) +{ + if (!listener_) + return; + Frame *ir = 0, *depth = 0; + + impl_->startTiming(); + + glfwMakeContextCurrent(impl_->opengl_context_ptr); + + std::copy(packet.buffer, packet.buffer + packet.buffer_length/10*9, impl_->input_data.data); + impl_->input_data.upload(); + impl_->run(&ir, &depth); + + if(impl_->do_debug) glfwSwapBuffers(impl_->opengl_context_ptr); + + impl_->stopTiming(LOG_INFO); + + ir->timestamp = packet.timestamp; + depth->timestamp = packet.timestamp; + ir->sequence = packet.sequence; + depth->sequence = packet.sequence; + + if(!listener_->onNewFrame(Frame::Ir, ir)) + delete ir; + + if(!listener_->onNewFrame(Frame::Depth, depth)) + delete depth; +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.cpp new file mode 100644 index 0000000..cd2712f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.cpp @@ -0,0 +1,212 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#define _USE_MATH_DEFINES +#include // for M_PI +#include "ColorStream.hpp" + +using namespace Freenect2Driver; + +// from NUI library & converted to radians +const float ColorStream::DIAGONAL_FOV = 73.9 * (M_PI / 180); +const float ColorStream::HORIZONTAL_FOV = 62 * (M_PI / 180); +const float ColorStream::VERTICAL_FOV = 48.6 * (M_PI / 180); + +ColorStream::ColorStream(Device* driver_dev, libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg) : VideoStream(driver_dev, pDevice, reg) +{ + video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 1920, 1080, 30); + setVideoMode(video_mode); +} + +// Add video modes here as you implement them +ColorStream::FreenectVideoModeMap ColorStream::getSupportedVideoModes() const +{ + FreenectVideoModeMap modes; + // pixelFormat, resolutionX, resolutionY, fps freenect_video_format, freenect_resolution + modes[makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 512, 424, 30)] = 0; + modes[makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 1920, 1080, 30)] = 1; + + return modes; + + /* working format possiblities + FREENECT_VIDEO_RGB + FREENECT_VIDEO_YUV_RGB + FREENECT_VIDEO_YUV_RAW + */ +} + +void ColorStream::populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const +{ + dstFrame->sensorType = getSensorType(); + dstFrame->stride = dstFrame->width * 3; + + // copy stream buffer from freenect + switch (video_mode.pixelFormat) + { + default: + LogError("Pixel format " + to_string(video_mode.pixelFormat) + " not supported by populateFrame()"); + return; + + case ONI_PIXEL_FORMAT_RGB888: + if (reg->isEnabled()) { + libfreenect2::Frame registered(512, 424, 4); + + reg->colorFrameRGB888(srcFrame, ®istered); + + copyFrame(static_cast(registered.data), srcX, srcY, registered.width * registered.bytes_per_pixel, + static_cast(dstFrame->data), dstX, dstY, dstFrame->stride, + width, height, mirroring); + } else { + copyFrame(static_cast(srcFrame->data), srcX, srcY, srcFrame->width * srcFrame->bytes_per_pixel, + static_cast(dstFrame->data), dstX, dstY, dstFrame->stride, + width, height, mirroring); + } + return; + } +} + +void ColorStream::copyFrame(uint8_t* srcPix, int srcX, int srcY, int srcStride, uint8_t* dstPix, int dstX, int dstY, int dstStride, int width, int height, bool mirroring) +{ + srcPix += srcX + srcY * srcStride; + dstPix += dstX + dstY * dstStride; + + for (int y = 0; y < height; y++) { + uint8_t* dst = dstPix + y * dstStride; + uint8_t* src = srcPix + y * srcStride; + if (mirroring) { + dst += dstStride - 1; + for (int x = 0; x < srcStride; ++x) + { + if (x % 4 != 3) + { + *dst-- = *src++; + } + else + { + ++src; + } + } + } else { + for (int x = 0; x < dstStride-2; x += 3) + { + *dst++ = src[2]; + *dst++ = src[1]; + *dst++ = src[0]; + src += 4; + } + } + } +} + +OniSensorType ColorStream::getSensorType() const { return ONI_SENSOR_COLOR; } + +OniStatus ColorStream::setImageRegistrationMode(OniImageRegistrationMode mode) +{ + if (mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR) { + // XXX, switch color resolution to 512x424 for registrarion here + OniVideoMode video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_RGB888, 512, 424, 30); + setProperty(ONI_STREAM_PROPERTY_VIDEO_MODE, &video_mode, sizeof(video_mode)); + } + return ONI_STATUS_OK; +} + +// from StreamBase +OniBool ColorStream::isPropertySupported(int propertyId) +{ + switch(propertyId) + { + default: + return VideoStream::isPropertySupported(propertyId); + + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: + case ONI_STREAM_PROPERTY_VERTICAL_FOV: + case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: + case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: + return true; + } +} + +OniStatus ColorStream::getProperty(int propertyId, void* data, int* pDataSize) +{ + switch (propertyId) + { + default: + return VideoStream::getProperty(propertyId, data, pDataSize); + + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float (radians) + { + if (*pDataSize != sizeof(float)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_HORIZONTAL_FOV"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = HORIZONTAL_FOV; + return ONI_STATUS_OK; + } + case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float (radians) + { + if (*pDataSize != sizeof(float)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_VERTICAL_FOV"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = VERTICAL_FOV; + return ONI_STATUS_OK; + } + + // camera + case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool + { + if (*pDataSize != sizeof(OniBool)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = auto_white_balance; + return ONI_STATUS_OK; + } + case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool + { + if (*pDataSize != sizeof(OniBool)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_AUTO_EXPOSURE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = auto_exposure; + return ONI_STATUS_OK; + } + } +} + +OniStatus ColorStream::setProperty(int propertyId, const void* data, int dataSize) +{ + switch (propertyId) + { + case 0: + default: + return VideoStream::setProperty(propertyId, data, dataSize); + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.hpp new file mode 100644 index 0000000..964e196 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/ColorStream.hpp @@ -0,0 +1,67 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#pragma once + +#include +#include +#include +#include "VideoStream.hpp" + + +namespace Freenect2Driver +{ + class ColorStream : public VideoStream + { + public: + // from NUI library & converted to radians + static const float DIAGONAL_FOV; + static const float HORIZONTAL_FOV; + static const float VERTICAL_FOV; + + private: + typedef std::map< OniVideoMode, int > FreenectVideoModeMap; + OniSensorType getSensorType() const; + VideoModeMap getSupportedVideoModes() const; + void populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const; + + static void copyFrame(uint8_t* srcPix, int srcX, int srcY, int srcStride, uint8_t* dstPix, int dstX, int dstY, int dstStride, int width, int height, bool mirroring); + + bool auto_white_balance; + bool auto_exposure; + + public: + ColorStream(Device* driver_dev, libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg); + //~ColorStream() { } + + OniStatus setImageRegistrationMode(OniImageRegistrationMode mode); + + // from StreamBase + OniBool isPropertySupported(int propertyId); + OniStatus getProperty(int propertyId, void* data, int* pDataSize); + OniStatus setProperty(int propertyId, const void* data, int dataSize); + }; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.cpp new file mode 100644 index 0000000..cc18015 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.cpp @@ -0,0 +1,251 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#define _USE_MATH_DEFINES +#include // for M_PI +#include "DepthStream.hpp" + +using namespace Freenect2Driver; + +// from NUI library and converted to radians +const float DepthStream::DIAGONAL_FOV = 70 * (M_PI / 180); +const float DepthStream::HORIZONTAL_FOV = 58.5 * (M_PI / 180); +const float DepthStream::VERTICAL_FOV = 45.6 * (M_PI / 180); +// from DepthKinectStream.cpp +const int DepthStream::MAX_VALUE; +const unsigned long long DepthStream::GAIN_VAL; +const unsigned long long DepthStream::CONST_SHIFT_VAL; +const unsigned long long DepthStream::MAX_SHIFT_VAL; +const unsigned long long DepthStream::PARAM_COEFF_VAL; +const unsigned long long DepthStream::SHIFT_SCALE_VAL; +const unsigned long long DepthStream::ZERO_PLANE_DISTANCE_VAL; +const double DepthStream::ZERO_PLANE_PIXEL_SIZE_VAL = 0.10520000010728836; +const double DepthStream::EMITTER_DCMOS_DISTANCE_VAL = 7.5; + +DepthStream::DepthStream(Device* driver_dev, libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg) : VideoStream(driver_dev, pDevice, reg) +{ + //video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, 512, 424, 30); + video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, 640, 480, 30); + setVideoMode(video_mode); + setImageRegistrationMode(ONI_IMAGE_REGISTRATION_OFF); +} + +// Add video modes here as you implement them +// Note: if image_registration_mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR, +// setVideoFormat() will try FREENECT_DEPTH_REGISTERED first then fall back on what is set here. +DepthStream::VideoModeMap DepthStream::getSupportedVideoModes() const +{ + VideoModeMap modes; + // pixelFormat, resolutionX, resolutionY, fps + modes[makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, 640, 480, 30)] = 0; + modes[makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, 512, 424, 30)] = 1; + + return modes; +} + +void DepthStream::populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const +{ + dstFrame->sensorType = getSensorType(); + dstFrame->stride = dstFrame->width * sizeof(uint16_t); + + // XXX, save depth map for registration + if (reg->isEnabled()) + reg->depthFrame(srcFrame); + + if (srcFrame->width < (size_t)dstFrame->width || srcFrame->height < (size_t)dstFrame->height) + memset(dstFrame->data, 0x00, dstFrame->width * dstFrame->height * 2); + + // copy stream buffer from freenect + copyFrame(static_cast((void*)srcFrame->data), srcX, srcY, srcFrame->width, + static_cast(dstFrame->data), dstX, dstY, dstFrame->width, + width, height, mirroring); +} + +OniSensorType DepthStream::getSensorType() const { return ONI_SENSOR_DEPTH; } + +OniImageRegistrationMode DepthStream::getImageRegistrationMode() const { return image_registration_mode; } + +OniStatus DepthStream::setImageRegistrationMode(OniImageRegistrationMode mode) +{ + if (!isImageRegistrationModeSupported(mode)) + return ONI_STATUS_NOT_SUPPORTED; + image_registration_mode = mode; + reg->setEnable(image_registration_mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR); + return setVideoMode(video_mode); +} + +// from StreamBase +OniBool DepthStream::isImageRegistrationModeSupported(OniImageRegistrationMode mode) { return (mode == ONI_IMAGE_REGISTRATION_OFF || mode == ONI_IMAGE_REGISTRATION_DEPTH_TO_COLOR); } + +OniBool DepthStream::isPropertySupported(int propertyId) +{ + switch(propertyId) + { + default: + return VideoStream::isPropertySupported(propertyId); + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: + case ONI_STREAM_PROPERTY_VERTICAL_FOV: + case ONI_STREAM_PROPERTY_MAX_VALUE: + case XN_STREAM_PROPERTY_GAIN: + case XN_STREAM_PROPERTY_CONST_SHIFT: + case XN_STREAM_PROPERTY_MAX_SHIFT: + case XN_STREAM_PROPERTY_PARAM_COEFF: + case XN_STREAM_PROPERTY_SHIFT_SCALE: + case XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE: + case XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE: + case XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE: + case XN_STREAM_PROPERTY_S2D_TABLE: + case XN_STREAM_PROPERTY_D2S_TABLE: + return true; + } +} + +OniStatus DepthStream::getProperty(int propertyId, void* data, int* pDataSize) +{ + switch (propertyId) + { + default: + return VideoStream::getProperty(propertyId, data, pDataSize); + + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float (radians) + if (*pDataSize != sizeof(float)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_HORIZONTAL_FOV"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = HORIZONTAL_FOV; + return ONI_STATUS_OK; + case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float (radians) + if (*pDataSize != sizeof(float)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_VERTICAL_FOV"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = VERTICAL_FOV; + return ONI_STATUS_OK; + case ONI_STREAM_PROPERTY_MAX_VALUE: // int + if (*pDataSize != sizeof(int)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_MAX_VALUE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = MAX_VALUE; + return ONI_STATUS_OK; + + case XN_STREAM_PROPERTY_PIXEL_REGISTRATION: // XnPixelRegistration (get only) + case XN_STREAM_PROPERTY_WHITE_BALANCE_ENABLED: // unsigned long long + case XN_STREAM_PROPERTY_HOLE_FILTER: // unsigned long long + case XN_STREAM_PROPERTY_REGISTRATION_TYPE: // XnProcessingType + case XN_STREAM_PROPERTY_AGC_BIN: // XnDepthAGCBin* + case XN_STREAM_PROPERTY_PIXEL_SIZE_FACTOR: // unsigned long long + case XN_STREAM_PROPERTY_DCMOS_RCMOS_DISTANCE: // double + case XN_STREAM_PROPERTY_CLOSE_RANGE: // unsigned long long + return ONI_STATUS_NOT_SUPPORTED; + + case XN_STREAM_PROPERTY_GAIN: // unsigned long long + if (*pDataSize != sizeof(unsigned long long)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_GAIN"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = GAIN_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_CONST_SHIFT: // unsigned long long + if (*pDataSize != sizeof(unsigned long long)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_CONST_SHIFT"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = CONST_SHIFT_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_MAX_SHIFT: // unsigned long long + if (*pDataSize != sizeof(unsigned long long)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_MAX_SHIFT"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = MAX_SHIFT_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_PARAM_COEFF: // unsigned long long + if (*pDataSize != sizeof(unsigned long long)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_PARAM_COEFF"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = PARAM_COEFF_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_SHIFT_SCALE: // unsigned long long + if (*pDataSize != sizeof(unsigned long long)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_SHIFT_SCALE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = SHIFT_SCALE_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE: // unsigned long long + if (*pDataSize != sizeof(unsigned long long)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_ZERO_PLANE_DISTANCE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = ZERO_PLANE_DISTANCE_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE: // double + if (*pDataSize != sizeof(double)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_ZERO_PLANE_PIXEL_SIZE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = ZERO_PLANE_PIXEL_SIZE_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE: // double + if (*pDataSize != sizeof(double)) + { + LogError("Unexpected size for XN_STREAM_PROPERTY_EMITTER_DCMOS_DISTANCE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = EMITTER_DCMOS_DISTANCE_VAL; + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_S2D_TABLE: // OniDepthPixel[] + { + uint16_t *s2d = (uint16_t *)data; + *pDataSize = sizeof(*s2d) * 2048; + memset(data, 0, *pDataSize); + for (int i = 1; i <= 1052; i++) + s2d[i] = 342205.0/(1086.671 - i); + } + return ONI_STATUS_OK; + case XN_STREAM_PROPERTY_D2S_TABLE: // unsigned short[] + { + uint16_t *d2s = (uint16_t *)data; + *pDataSize = sizeof(*d2s) * 10001; + memset(data, 0, *pDataSize); + for (int i = 315; i <= 10000; i++) + d2s[i] = 1086.671 - 342205.0/(i + 1); + } + return ONI_STATUS_OK; + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.hpp new file mode 100644 index 0000000..7b0156a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DepthStream.hpp @@ -0,0 +1,72 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#pragma once + +#include +#include +#include "VideoStream.hpp" + + +namespace Freenect2Driver +{ + class DepthStream : public VideoStream + { + public: + // from NUI library and converted to radians + static const float DIAGONAL_FOV; + static const float HORIZONTAL_FOV; + static const float VERTICAL_FOV; + // from DepthKinectStream.cpp + static const int MAX_VALUE = 10000; + static const unsigned long long GAIN_VAL = 42; + static const unsigned long long CONST_SHIFT_VAL = 200; + static const unsigned long long MAX_SHIFT_VAL = 2047; + static const unsigned long long PARAM_COEFF_VAL = 4; + static const unsigned long long SHIFT_SCALE_VAL = 10; + static const unsigned long long ZERO_PLANE_DISTANCE_VAL = 120; + static const double ZERO_PLANE_PIXEL_SIZE_VAL; + static const double EMITTER_DCMOS_DISTANCE_VAL; + + private: + OniSensorType getSensorType() const; + OniImageRegistrationMode image_registration_mode; + VideoModeMap getSupportedVideoModes() const; + void populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const; + + public: + DepthStream(Device* driver_dev, libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg); + //~DepthStream() { } + + OniImageRegistrationMode getImageRegistrationMode() const; + OniStatus setImageRegistrationMode(OniImageRegistrationMode mode); + + // from StreamBase + OniBool isImageRegistrationModeSupported(OniImageRegistrationMode mode); + OniBool isPropertySupported(int propertyId); + OniStatus getProperty(int propertyId, void* data, int* pDataSize); + }; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DeviceDriver.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DeviceDriver.cpp new file mode 100644 index 0000000..c84a9e5 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/DeviceDriver.cpp @@ -0,0 +1,576 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ +/** +* FreenectDriver +* Copyright 2013 Benn Snyder +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DepthStream.hpp" +#include "ColorStream.hpp" +#include "IrStream.hpp" + + +namespace Freenect2Driver +{ + typedef std::map ConfigStrings; + + class DeviceImpl : public Device + { + private: + libfreenect2::Freenect2Device *dev; + ColorStream* color; + DepthStream* depth; + IrStream* ir; + Registration *reg; + ConfigStrings config; + bool device_stop; + bool device_used; + libfreenect2::SyncMultiFrameListener listener; + libfreenect2::thread* thread; + + static void static_run(void* cookie) + { + static_cast(cookie)->run(); + } + + VideoStream* getStream(libfreenect2::Frame::Type type) + { + if (type == libfreenect2::Frame::Depth) + return depth; + if (type == libfreenect2::Frame::Ir) + return ir; + if (type == libfreenect2::Frame::Color) + return color; + return NULL; + } + + void run() + { + libfreenect2::FrameMap frames; + uint32_t seqNum = 0; + libfreenect2::Frame::Type seqType; + + struct streams { + const char* name; + libfreenect2::Frame::Type type; + } streams[] = { + { "Ir", libfreenect2::Frame::Ir }, + { "Depth", libfreenect2::Frame::Depth }, + { "Color", libfreenect2::Frame::Color } + }; + while(!device_stop) + { + listener.waitForNewFrame(frames); + + for (unsigned i = 0; i < sizeof(streams)/sizeof(*streams); i++) { + struct streams& s = streams[i]; + VideoStream* stream = getStream(s.type); + libfreenect2::Frame *frame = frames[s.type]; + if (stream) { + if (seqNum == 0) + seqType = s.type; + if (s.type == seqType) + seqNum++; + frame->timestamp = seqNum * 33369; + stream->buildFrame(frame); + } + } + + listener.release(frames); + } + } + + OniStatus setStreamProperties(VideoStream* stream, std::string pfx) + { + pfx += '-'; + OniStatus res = ONI_STATUS_OK, tmp_res; + if (config.find(pfx + "size") != config.end()) { + WriteMessage("setStreamProperty: " + pfx + "size: " + config[pfx + "size"]); + std::string size(config[pfx + "size"]); + int i = size.find("x"); + OniVideoMode video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_DEPTH_1_MM, atoi(size.substr(0, i).c_str()), atoi(size.substr(i + 1).c_str()), 30); + tmp_res = stream->setProperty(ONI_STREAM_PROPERTY_VIDEO_MODE, (void*)&video_mode, sizeof(video_mode)); + if (tmp_res != ONI_STATUS_OK) + res = tmp_res; + } + + return res; + } + + void allocStream() { + if (! color) { + color = new ColorStream(this, dev, reg); + setStreamProperties(color, "color"); + } + if (! depth) { + depth = new DepthStream(this, dev, reg); + setStreamProperties(depth, "depth"); + } + if (! ir) { + ir = new IrStream(this, dev, reg); + setStreamProperties(ir, "ir"); + } + } + + void deallocStream() { + if (color != NULL) + { + delete color; + color = NULL; + } + if (depth != NULL) + { + delete depth; + depth = NULL; + } + if (ir != NULL) + { + delete ir; + ir = NULL; + } + } + + public: + DeviceImpl(int index) : //libfreenect2::Freenect2Device(fn_ctx, index), + dev(NULL), + color(NULL), + depth(NULL), + ir(NULL), + reg(NULL), + device_stop(true), + device_used(false), + listener(libfreenect2::Frame::Depth | libfreenect2::Frame::Ir | libfreenect2::Frame::Color), + thread(NULL) + { + } + ~DeviceImpl() + { + destroyStream(color); + destroyStream(ir); + destroyStream(depth); + deallocStream(); + close(); + if (reg) { + delete reg; + reg = NULL; + } + } + + // for Freenect2Device + void setFreenect2Device(libfreenect2::Freenect2Device *dev) { + this->dev = dev; + dev->setColorFrameListener(&listener); + dev->setIrAndDepthFrameListener(&listener); + reg = new Registration(dev); + allocStream(); + } + void setConfigStrings(ConfigStrings& config) { + this->config = config; + } + void start() { + WriteMessage("Freenect2Driver::Device: start()"); + if (device_stop) { + device_used = true; + device_stop = false; + thread = new libfreenect2::thread(&DeviceImpl::static_run, this); + dev->start(); + } + } + void stop() { + WriteMessage("Freenect2Driver::Device: stop()"); + if (!device_stop) { + device_stop = true; + thread->join(); + dev->stop(); + } + } + void close() { + WriteMessage("Freenect2Driver::Device: close()"); + if (this->dev && device_used) { + stop(); + dev->close(); + } + this->dev = NULL; + } + + // for DeviceBase + + OniBool isImageRegistrationModeSupported(OniImageRegistrationMode mode) { return depth->isImageRegistrationModeSupported(mode); } + + OniStatus getSensorInfoList(OniSensorInfo** pSensors, int* numSensors) + { + *numSensors = 3; + OniSensorInfo * sensors = new OniSensorInfo[*numSensors]; + sensors[0] = depth->getSensorInfo(); + sensors[1] = color->getSensorInfo(); + sensors[2] = ir->getSensorInfo(); + *pSensors = sensors; + return ONI_STATUS_OK; + } + + oni::driver::StreamBase* createStream(OniSensorType sensorType) + { + switch (sensorType) + { + default: + LogError("Cannot create a stream of type " + to_string(sensorType)); + return NULL; + case ONI_SENSOR_COLOR: + WriteMessage("Device: createStream(color)"); + return color; + case ONI_SENSOR_DEPTH: + WriteMessage("Device: createStream(depth)"); + return depth; + case ONI_SENSOR_IR: + WriteMessage("Device: createStream(ir)"); + return ir; + } + } + + void destroyStream(oni::driver::StreamBase* pStream) + { + if (pStream == color) + WriteMessage("Device: destroyStream(color)"); + if (pStream == depth) + WriteMessage("Device: destroyStream(depth)"); + if (pStream == ir) + WriteMessage("Device: destroyStream(ir)"); + } + + // todo: fill out properties + OniBool isPropertySupported(int propertyId) + { + if (propertyId == ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION) + return true; + return false; + } + + OniStatus getProperty(int propertyId, void* data, int* pDataSize) + { + switch (propertyId) + { + default: + case ONI_DEVICE_PROPERTY_FIRMWARE_VERSION: // string + case ONI_DEVICE_PROPERTY_DRIVER_VERSION: // OniVersion + case ONI_DEVICE_PROPERTY_HARDWARE_VERSION: // int + case ONI_DEVICE_PROPERTY_SERIAL_NUMBER: // string + case ONI_DEVICE_PROPERTY_ERROR_STATE: // ? + // files + case ONI_DEVICE_PROPERTY_PLAYBACK_SPEED: // float + case ONI_DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED: // OniBool + // xn + case XN_MODULE_PROPERTY_USB_INTERFACE: // XnSensorUsbInterface + case XN_MODULE_PROPERTY_MIRROR: // bool + case XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP: // unsigned long long + case XN_MODULE_PROPERTY_LEAN_INIT: // unsigned long long + case XN_MODULE_PROPERTY_SERIAL_NUMBER: // unsigned long long + case XN_MODULE_PROPERTY_VERSION: // XnVersions + return ONI_STATUS_NOT_SUPPORTED; + + case ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION: // OniImageRegistrationMode + if (*pDataSize != sizeof(OniImageRegistrationMode)) + { + LogError("Unexpected size for ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = depth->getImageRegistrationMode(); + return ONI_STATUS_OK; + } + } + + OniStatus setProperty(int propertyId, const void* data, int dataSize) + { + switch (propertyId) + { + default: + case ONI_DEVICE_PROPERTY_FIRMWARE_VERSION: // By implementation + case ONI_DEVICE_PROPERTY_DRIVER_VERSION: // OniVersion + case ONI_DEVICE_PROPERTY_HARDWARE_VERSION: // int + case ONI_DEVICE_PROPERTY_SERIAL_NUMBER: // string + case ONI_DEVICE_PROPERTY_ERROR_STATE: // ? + // files + case ONI_DEVICE_PROPERTY_PLAYBACK_SPEED: // float + case ONI_DEVICE_PROPERTY_PLAYBACK_REPEAT_ENABLED: // OniBool + // xn + case XN_MODULE_PROPERTY_USB_INTERFACE: // XnSensorUsbInterface + case XN_MODULE_PROPERTY_MIRROR: // bool + case XN_MODULE_PROPERTY_RESET_SENSOR_ON_STARTUP: // unsigned long long + case XN_MODULE_PROPERTY_LEAN_INIT: // unsigned long long + case XN_MODULE_PROPERTY_SERIAL_NUMBER: // unsigned long long + case XN_MODULE_PROPERTY_VERSION: // XnVersions + // xn commands + case XN_MODULE_PROPERTY_FIRMWARE_PARAM: // XnInnerParam + case XN_MODULE_PROPERTY_RESET: // unsigned long long + case XN_MODULE_PROPERTY_IMAGE_CONTROL: // XnControlProcessingData + case XN_MODULE_PROPERTY_DEPTH_CONTROL: // XnControlProcessingData + case XN_MODULE_PROPERTY_AHB: // XnAHBData + case XN_MODULE_PROPERTY_LED_STATE: // XnLedState + return ONI_STATUS_NOT_SUPPORTED; + + case ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION: // OniImageRegistrationMode + if (dataSize != sizeof(OniImageRegistrationMode)) + { + LogError("Unexpected size for ONI_DEVICE_PROPERTY_IMAGE_REGISTRATION"); + return ONI_STATUS_ERROR; + } + OniImageRegistrationMode mode = *(static_cast(data)); + color->setImageRegistrationMode(mode); + return depth->setImageRegistrationMode(mode); + } + } + + OniBool isCommandSupported(int commandId) + { + switch (commandId) + { + default: + case ONI_DEVICE_COMMAND_SEEK: + return false; + } + } + + OniStatus invoke(int commandId, void* data, int dataSize) + { + switch (commandId) + { + default: + case ONI_DEVICE_COMMAND_SEEK: // OniSeek + return ONI_STATUS_NOT_SUPPORTED; + } + } + + + /* todo: for DeviceBase + virtual OniStatus tryManualTrigger() {return ONI_STATUS_OK;} + */ + }; + + + class Driver : public oni::driver::DriverBase + { + private: + typedef std::map OniDeviceMap; + OniDeviceMap devices; + std::string uriScheme; + ConfigStrings config; + libfreenect2::Freenect2 freenect2; + + std::string devid_to_uri(int id) { + return uriScheme + "://" + to_string(id); + } + + int uri_to_devid(const std::string uri) { + int id; + std::istringstream is(uri); + is.seekg((uriScheme + "://").length()); + is >> id; + return id; + } + + void register_uri(std::string uri) { + OniDeviceInfo info; + strncpy(info.uri, uri.c_str(), ONI_MAX_STR); + strncpy(info.vendor, "Microsoft", ONI_MAX_STR); + //strncpy(info.name, "Kinect 2", ONI_MAX_STR); // XXX, NiTE does not accept new name + strncpy(info.name, "Kinect", ONI_MAX_STR); + if (devices.find(info) == devices.end()) { + WriteMessage("Driver: register new uri: " + uri); + devices[info] = NULL; + deviceConnected(&info); + deviceStateChanged(&info, 0); + } + } + + public: + Driver(OniDriverServices* pDriverServices) : DriverBase(pDriverServices), + uriScheme("freenect2") + { + //WriteMessage("Using libfreenect v" + to_string(PROJECT_VER)); + WriteMessage("Using libfreenect2"); + + DriverServices = &getServices(); + } + ~Driver() { shutdown(); } + + // for DriverBase + + OniStatus initialize(oni::driver::DeviceConnectedCallback connectedCallback, oni::driver::DeviceDisconnectedCallback disconnectedCallback, oni::driver::DeviceStateChangedCallback deviceStateChangedCallback, void* pCookie) + { + DriverBase::initialize(connectedCallback, disconnectedCallback, deviceStateChangedCallback, pCookie); + int devices_found = freenect2.enumerateDevices(); + for (int i = 0; i < devices_found; i++) + { + std::string serial = freenect2.getDeviceSerialNumber(i); + + std::string uri = devid_to_uri(i) + "?serial=" + serial; + const char* modes_c[] = { + "", + "&depth-size=640x480", + "&depth-size=512x424", + }; + + std::vector modes(modes_c, modes_c + 3); + + WriteMessage("Found device " + uri); + + for (int j = 0; j < 3; j++) { + register_uri(uri + modes[j]); + } + +#if 0 + freenect_device* dev; + if (freenect_open_device(m_ctx, &dev, i) == 0) + { + info.usbVendorId = dev->usb_cam.VID; + info.usbProductId = dev->usb_cam.PID; + freenect_close_device(dev); + } + else + { + WriteMessage("Unable to open device to query VID/PID"); + } +#endif // 0 + } + return ONI_STATUS_OK; + } + + oni::driver::DeviceBase* deviceOpen(const char* c_uri, const char* c_mode = NULL) + { + std::string uri(c_uri); + std::string mode(c_mode ? c_mode : ""); + if (uri.find("?") != std::string::npos) { + mode += "&"; + mode += uri.substr(uri.find("?") + 1); + uri = uri.substr(0, uri.find("?")); + } + std::stringstream ss(mode); + std::string buf; + while(std::getline(ss, buf, '&')) { + if (buf.find("=") != std::string::npos) { + config[buf.substr(0, buf.find("="))] = buf.substr(buf.find("=")+1); + } else { + if (0 < buf.length()) + config[buf] = ""; + } + } + WriteMessage("deiveOpen: " + uri); + for (std::map::iterator it = config.begin(); it != config.end(); it++) { + WriteMessage(" " + it->first + " = " + it->second); + } + + for (OniDeviceMap::iterator iter = devices.begin(); iter != devices.end(); iter++) + { + std::string iter_uri(iter->first.uri); + if (iter_uri.substr(0, iter_uri.find("?")) == uri) // found + { + if (iter->second) // already open + { + return iter->second; + } + else + { + WriteMessage("Opening device " + std::string(uri)); + int id = uri_to_devid(iter->first.uri); + DeviceImpl* device = new DeviceImpl(id); + // The LIBFREENECT2_PIPELINE variable allows to select + // the non-default pipeline + device->setFreenect2Device(freenect2.openDevice(id)); + device->setConfigStrings(config); + iter->second = device; + return device; + } + } + } + + LogError("Could not find device " + std::string(uri)); + return NULL; + } + + void deviceClose(oni::driver::DeviceBase* pDevice) + { + for (OniDeviceMap::iterator iter = devices.begin(); iter != devices.end(); iter++) + { + if (iter->second == pDevice) + { + WriteMessage("Closing device " + std::string(iter->first.uri)); + //int id = uri_to_devid(iter->first.uri); + + DeviceImpl* device = (DeviceImpl*)iter->second; + device->stop(); + device->close(); + + devices.erase(iter); + return; + } + } + + LogError("Could not close unrecognized device"); + } + + OniStatus tryDevice(const char* uri) + { + oni::driver::DeviceBase* device = deviceOpen(uri); + if (! device) + return ONI_STATUS_ERROR; + deviceClose(device); + register_uri(std::string(uri)); // XXX, register new uri here. + return ONI_STATUS_OK; + } + + void shutdown() + { + for (OniDeviceMap::iterator iter = devices.begin(); iter != devices.end(); iter++) + { + if (iter->second) { + deviceClose(iter->second); + } + } + } + + + /* todo: for DriverBase + virtual void* enableFrameSync(oni::driver::StreamBase** pStreams, int streamCount); + virtual void disableFrameSync(void* frameSyncGroup); + */ + }; +} + + +// macros defined in XnLib (not included) - workaround +#define XN_NEW(type, arg) new type(arg) +#define XN_DELETE(p) delete(p) +ONI_EXPORT_DRIVER(Freenect2Driver::Driver); +#undef XN_NEW +#undef XN_DELETE diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.cpp new file mode 100644 index 0000000..4e718ce --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.cpp @@ -0,0 +1,103 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2015 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#define _USE_MATH_DEFINES +#include // for M_PI +#include "IrStream.hpp" + +using namespace Freenect2Driver; + +// from NUI library and converted to radians +const float IrStream::HORIZONTAL_FOV = 58.5 * (M_PI / 180); +const float IrStream::VERTICAL_FOV = 45.6 * (M_PI / 180); + +IrStream::IrStream(Device* driver_dev, libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg) : VideoStream(driver_dev, pDevice, reg) +{ + video_mode = makeOniVideoMode(ONI_PIXEL_FORMAT_GRAY16, 512, 424, 30); + setVideoMode(video_mode); +} + +// Add video modes here as you implement them +IrStream::VideoModeMap IrStream::getSupportedVideoModes() const +{ + VideoModeMap modes; + // pixelFormat, resolutionX, resolutionY, fps + modes[makeOniVideoMode(ONI_PIXEL_FORMAT_GRAY16, 512, 424, 30)] = 0; + + return modes; +} + +void IrStream::populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const +{ + dstFrame->sensorType = getSensorType(); + dstFrame->stride = dstFrame->width * sizeof(uint16_t); + + // copy stream buffer from freenect + copyFrame(static_cast((void*)srcFrame->data), srcX, srcY, srcFrame->width, + static_cast(dstFrame->data), dstX, dstY, dstFrame->width, + width, height, mirroring); +} + +OniSensorType IrStream::getSensorType() const { return ONI_SENSOR_IR; } + +// from StreamBase +OniBool IrStream::isPropertySupported(int propertyId) +{ + switch(propertyId) + { + default: + return VideoStream::isPropertySupported(propertyId); + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: + case ONI_STREAM_PROPERTY_VERTICAL_FOV: + return true; + } +} + +OniStatus IrStream::getProperty(int propertyId, void* data, int* pDataSize) +{ + switch (propertyId) + { + default: + return VideoStream::getProperty(propertyId, data, pDataSize); + + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float (radians) + if (*pDataSize != sizeof(float)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_HORIZONTAL_FOV"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = HORIZONTAL_FOV; + return ONI_STATUS_OK; + case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float (radians) + if (*pDataSize != sizeof(float)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_VERTICAL_FOV"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = VERTICAL_FOV; + return ONI_STATUS_OK; + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.hpp new file mode 100644 index 0000000..0fec1ac --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/IrStream.hpp @@ -0,0 +1,55 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2015 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#pragma once + +#include +#include +#include "VideoStream.hpp" + +namespace Freenect2Driver +{ + class IrStream : public VideoStream + { + public: + // from NUI library and converted to radians + static const float HORIZONTAL_FOV; + static const float VERTICAL_FOV; + + private: + OniSensorType getSensorType() const; + VideoModeMap getSupportedVideoModes() const; + void populateFrame(libfreenect2::Frame* srcFrame, int srcX, int srcY, OniFrame* dstFrame, int dstX, int dstY, int width, int height) const; + + public: + IrStream(Device* driver_dev, libfreenect2::Freenect2Device* pDevice, Freenect2Driver::Registration *reg); + //~IrStream() { } + + // from StreamBase + OniBool isPropertySupported(int propertyId); + OniStatus getProperty(int propertyId, void* data, int* pDataSize); + }; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.cpp new file mode 100644 index 0000000..16e1be4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.cpp @@ -0,0 +1,90 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2015 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include "Registration.hpp" + +using namespace Freenect2Driver; + +Registration::Registration(libfreenect2::Freenect2Device* dev) : + dev(dev), + reg(NULL), + enabled(false) +{ +} + +Registration::~Registration() { + delete reg; +} + +void Registration::depthFrame(libfreenect2::Frame* frame) { + lastDepthFrame = frame; +} + +static libfreenect2::Registration* make_registration(libfreenect2::Freenect2Device* dev) +{ + libfreenect2::Freenect2Device::ColorCameraParams colCamParams = dev->getColorCameraParams(); + libfreenect2::Freenect2Device::IrCameraParams irCamParams = dev->getIrCameraParams(); + { + libfreenect2::Freenect2Device::ColorCameraParams cp = colCamParams; + std::cout << "fx=" << cp.fx << ",fy=" << cp.fy + << ",cx=" << cp.cx << ",cy=" << cp.cy << std::endl; + libfreenect2::Freenect2Device::IrCameraParams ip = irCamParams; + std::cout << "fx=" << ip.fx << ",fy=" << ip.fy + << ",ix=" << ip.cx << ",iy=" << ip.cy + << ",k1=" << ip.k1 << ",k2=" << ip.k2 << ",k3=" << ip.k3 + << ",p1=" << ip.p1 << ",p2=" << ip.p2 << std::endl; + } + + return new libfreenect2::Registration(irCamParams, colCamParams); +} + +void Registration::colorFrameRGB888(libfreenect2::Frame* colorFrame, libfreenect2::Frame* registeredFrame) +{ + if (!reg) + { + reg = make_registration(dev); + } + + libfreenect2::Frame undistorted(lastDepthFrame->width, lastDepthFrame->height, lastDepthFrame->bytes_per_pixel); + + reg->apply(colorFrame, lastDepthFrame, &undistorted, registeredFrame); +} + +void Registration::setEnable(bool enable) { enabled = enable; } + +bool Registration::isEnabled() { return enabled; } + +void Registration::depthToColor(int dx, int dy, float dz, float& cx, float& cy) +{ + if (!reg) + { + reg = make_registration(dev); + } + + reg->apply(dx, dy, dz, cx, cy); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.hpp new file mode 100644 index 0000000..102b4c0 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Registration.hpp @@ -0,0 +1,49 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2015 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#pragma once + +#include + +namespace Freenect2Driver { + class Registration { + private: + libfreenect2::Freenect2Device* dev; + libfreenect2::Registration* reg; + libfreenect2::Frame* lastDepthFrame; + bool enabled; + + public: + Registration(libfreenect2::Freenect2Device* dev); + ~Registration(); + + void depthFrame(libfreenect2::Frame* frame); + void colorFrameRGB888(libfreenect2::Frame* srcFrame, libfreenect2::Frame* dstFrame); + void setEnable(bool enable = true); + bool isEnabled(); + void depthToColor(int dx, int dy, float dz, float& cx, float& cy); + }; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.cpp new file mode 100644 index 0000000..5ab7e30 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.cpp @@ -0,0 +1,58 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +// This file contains symbols that may be used by any class or don't really go anywhere else. +#include +#include "Driver/OniDriverAPI.h" + + +// Oni helpers + +OniVideoMode makeOniVideoMode(OniPixelFormat pixel_format, int resolution_x, int resolution_y, int frames_per_second) +{ + OniVideoMode mode; + mode.pixelFormat = pixel_format; + mode.resolutionX = resolution_x; + mode.resolutionY = resolution_y; + mode.fps = frames_per_second; + return mode; +} + +bool operator==(const OniVideoMode& left, const OniVideoMode& right) +{ + return (left.pixelFormat == right.pixelFormat && left.resolutionX == right.resolutionX + && left.resolutionY == right.resolutionY && left.fps == right.fps); +} + +bool operator<(const OniVideoMode& left, const OniVideoMode& right) +{ + return (left.resolutionX * left.resolutionY < right.resolutionX * right.resolutionY); +} + +bool operator<(const OniDeviceInfo& left, const OniDeviceInfo& right) +{ + return (strcmp(left.uri, right.uri) < 0); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.hpp new file mode 100644 index 0000000..7225967 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/Utility.hpp @@ -0,0 +1,74 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +// This file contains symbols that may be used by any class or don't really go anywhere else. +#pragma once + +#include +#include + +// Oni helpers + +OniVideoMode makeOniVideoMode(OniPixelFormat pixel_format, int resolution_x, int resolution_y, int frames_per_second); + +bool operator==(const OniVideoMode& left, const OniVideoMode& right); + +bool operator<(const OniVideoMode& left, const OniVideoMode& right); + +bool operator<(const OniDeviceInfo& left, const OniDeviceInfo& right); + +// holding out on C++11 +template +static std::string to_string(const T& n) +{ + std::ostringstream oss; + oss << n; + return oss.str(); +} + + +// global logging +namespace Freenect2Driver +{ + // DriverServices is set in DeviceDriver.cpp so all files can call errorLoggerAppend() + static oni::driver::DriverServices* DriverServices; + + // from XnLog.h + typedef enum XnLogSeverity { + XN_LOG_VERBOSE = 0, + XN_LOG_INFO = 1, + XN_LOG_WARNING = 2, + XN_LOG_ERROR = 3, + XN_LOG_SEVERITY_NONE = 10, + } XnLogSeverity; +} +#define FN2DRV_LOG_MASK "Freenect2Driver" +#define WriteVerbose(str) do { if (DriverServices != NULL) DriverServices->log(XN_LOG_VERBOSE, __FILE__, __LINE__, FN2DRV_LOG_MASK, std::string(str).c_str()); } while(0) +#define WriteInfo(str) do { if (DriverServices != NULL) DriverServices->log(XN_LOG_INFO, __FILE__, __LINE__, FN2DRV_LOG_MASK, std::string(str).c_str()); } while(0) +#define WriteWarning(str) do { if (DriverServices != NULL) DriverServices->log(XN_LOG_WARNING, __FILE__, __LINE__, FN2DRV_LOG_MASK, std::string(str).c_str()); } while(0) +#define WriteError(str) do { if (DriverServices != NULL) DriverServices->log(XN_LOG_ERROR, __FILE__, __LINE__, FN2DRV_LOG_MASK, std::string(str).c_str()); } while(0) +#define WriteMessage(str) WriteInfo(str) +#define LogError(str) WriteError(str) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.cpp new file mode 100644 index 0000000..919c84a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.cpp @@ -0,0 +1,292 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include +#include "PS1080.h" +#include "VideoStream.hpp" +#include "Utility.hpp" +#include "Registration.hpp" + +struct ExtractKey +{ + template typename T::first_type + operator()(T pair) const + { + return pair.first; + } +}; + +namespace Freenect2Driver +{ +OniStatus VideoStream::setVideoMode(OniVideoMode requested_mode) +{ + VideoModeMap supported_video_modes = getSupportedVideoModes(); + VideoModeMap::const_iterator matched_mode_iter = supported_video_modes.find(requested_mode); + if (matched_mode_iter == supported_video_modes.end()) + return ONI_STATUS_NOT_SUPPORTED; + + video_mode = requested_mode; + return ONI_STATUS_OK; +} + +void VideoStream::copyFrame(float* srcPix, int srcX, int srcY, int srcStride, uint16_t* dstPix, int dstX, int dstY, int dstStride, int width, int height, bool mirroring) +{ + srcPix += srcX + srcY * srcStride; + dstPix += dstX + dstY * dstStride; + + for (int y = 0; y < height; y++) { + uint16_t* dst = dstPix + y * dstStride; + float* src = srcPix + y * srcStride; + if (mirroring) { + dst += width; + for (int x = 0; x < width; x++) + *dst-- = *src++; + } else { + for (int x = 0; x < width; x++) + *dst++ = *src++; + } + } +} +void VideoStream::raisePropertyChanged(int propertyId, const void* data, int dataSize) { + if (callPropertyChangedCallback) + StreamBase::raisePropertyChanged(propertyId, data, dataSize); +} + +VideoStream::VideoStream(Device* drvdev, libfreenect2::Freenect2Device* device, Freenect2Driver::Registration *reg) : + frame_id(1), + device(device), + driver_dev(drvdev), + running(false), + mirroring(false), + reg(reg), + callPropertyChangedCallback(false) + { + // joy of structs + memset(&cropping, 0, sizeof(cropping)); + memset(&video_mode, 0, sizeof(video_mode)); + } +//~VideoStream() { stop(); } + + +OniSensorInfo VideoStream::getSensorInfo() +{ + VideoModeMap supported_modes = getSupportedVideoModes(); + OniVideoMode* modes = new OniVideoMode[supported_modes.size()]; + std::transform(supported_modes.begin(), supported_modes.end(), modes, ExtractKey()); + OniSensorInfo sensors = { getSensorType(), static_cast(supported_modes.size()), modes }; + return sensors; +} + +void VideoStream::setPropertyChangedCallback(oni::driver::PropertyChangedCallback handler, void* pCookie) { + callPropertyChangedCallback = true; + StreamBase::setPropertyChangedCallback(handler, pCookie); +} + +bool VideoStream::buildFrame(libfreenect2::Frame* lf2Frame) +{ + if (!running) + return false; + + OniFrame* oniFrame = getServices().acquireFrame(); + oniFrame->frameIndex = frame_id++; + oniFrame->timestamp = lf2Frame->timestamp; + oniFrame->videoMode = video_mode; + oniFrame->width = video_mode.resolutionX; + oniFrame->height = video_mode.resolutionY; + + if (cropping.enabled) + { + oniFrame->height = cropping.height; + oniFrame->width = cropping.width; + oniFrame->cropOriginX = cropping.originX; + oniFrame->cropOriginY = cropping.originY; + oniFrame->croppingEnabled = true; + } + else + { + oniFrame->cropOriginX = 0; + oniFrame->cropOriginY = 0; + oniFrame->croppingEnabled = false; + } + //min is a macro with MSVC + #undef min + int width = std::min(oniFrame->width, (int)lf2Frame->width); + int height = std::min(oniFrame->height, (int)lf2Frame->height); + + populateFrame(lf2Frame, oniFrame->cropOriginX, oniFrame->cropOriginY, oniFrame, 0, 0, width, height); + raiseNewFrame(oniFrame); + getServices().releaseFrame(oniFrame); + + return false; +} + +// from StreamBase + +OniStatus VideoStream::start() +{ + driver_dev->start(); + running = true; + return ONI_STATUS_OK; +} +void VideoStream::stop() +{ + driver_dev->stop(); + running = false; +} + +// only add to property handlers if the property is generic to all children +// otherwise, implement in child and call these in default case +OniBool VideoStream::isPropertySupported(int propertyId) +{ + switch(propertyId) + { + case ONI_STREAM_PROPERTY_VIDEO_MODE: + case ONI_STREAM_PROPERTY_CROPPING: + case ONI_STREAM_PROPERTY_MIRRORING: + return true; + default: + return false; + } +} + +OniStatus VideoStream::getProperty(int propertyId, void* data, int* pDataSize) +{ + switch (propertyId) + { + default: + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float: radians + case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float: radians + case ONI_STREAM_PROPERTY_MAX_VALUE: // int + case ONI_STREAM_PROPERTY_MIN_VALUE: // int + case ONI_STREAM_PROPERTY_STRIDE: // int + case ONI_STREAM_PROPERTY_NUMBER_OF_FRAMES: // int + // camera + case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool + case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool + // xn + case XN_STREAM_PROPERTY_INPUT_FORMAT: // unsigned long long + case XN_STREAM_PROPERTY_CROPPING_MODE: // XnCroppingMode + return ONI_STATUS_NOT_SUPPORTED; + + case ONI_STREAM_PROPERTY_VIDEO_MODE: // OniVideoMode* + if (*pDataSize != sizeof(OniVideoMode)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_VIDEO_MODE"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = video_mode; + return ONI_STATUS_OK; + + case ONI_STREAM_PROPERTY_CROPPING: // OniCropping* + if (*pDataSize != sizeof(OniCropping)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_CROPPING"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = cropping; + return ONI_STATUS_OK; + + case ONI_STREAM_PROPERTY_MIRRORING: // OniBool + if (*pDataSize != sizeof(OniBool)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_MIRRORING"); + return ONI_STATUS_ERROR; + } + *(static_cast(data)) = mirroring; + return ONI_STATUS_OK; + } +} +OniStatus VideoStream::setProperty(int propertyId, const void* data, int dataSize) +{ + switch (propertyId) + { + default: + case ONI_STREAM_PROPERTY_HORIZONTAL_FOV: // float: radians + case ONI_STREAM_PROPERTY_VERTICAL_FOV: // float: radians + case ONI_STREAM_PROPERTY_MAX_VALUE: // int + case ONI_STREAM_PROPERTY_MIN_VALUE: // int + case ONI_STREAM_PROPERTY_STRIDE: // int + case ONI_STREAM_PROPERTY_NUMBER_OF_FRAMES: // int + // camera + case ONI_STREAM_PROPERTY_AUTO_WHITE_BALANCE: // OniBool + case ONI_STREAM_PROPERTY_AUTO_EXPOSURE: // OniBool + // xn + case XN_STREAM_PROPERTY_INPUT_FORMAT: // unsigned long long + case XN_STREAM_PROPERTY_CROPPING_MODE: // XnCroppingMode + return ONI_STATUS_NOT_SUPPORTED; + + case ONI_STREAM_PROPERTY_VIDEO_MODE: // OniVideoMode* + if (dataSize != sizeof(OniVideoMode)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_VIDEO_MODE"); + return ONI_STATUS_ERROR; + } + if (ONI_STATUS_OK != setVideoMode(*(static_cast(data)))) + return ONI_STATUS_NOT_SUPPORTED; + raisePropertyChanged(propertyId, data, dataSize); + return ONI_STATUS_OK; + + case ONI_STREAM_PROPERTY_CROPPING: // OniCropping* + if (dataSize != sizeof(OniCropping)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_CROPPING"); + return ONI_STATUS_ERROR; + } + cropping = *(static_cast(data)); + raisePropertyChanged(propertyId, data, dataSize); + return ONI_STATUS_OK; + + case ONI_STREAM_PROPERTY_MIRRORING: // OniBool + if (dataSize != sizeof(OniBool)) + { + LogError("Unexpected size for ONI_STREAM_PROPERTY_MIRRORING"); + return ONI_STATUS_ERROR; + } + mirroring = !!*(static_cast(data)); + raisePropertyChanged(propertyId, data, dataSize); + return ONI_STATUS_OK; + } +} + +OniStatus VideoStream::convertDepthToColorCoordinates(StreamBase* colorStream, int depthX, int depthY, OniDepthPixel depthZ, int* pColorX, int* pColorY) +{ + if (!reg) + { + return ONI_STATUS_NOT_SUPPORTED; + } + + float cx, cy; + const float dz = depthZ; + reg->depthToColor(depthX, depthY, dz, cx, cy); + + *pColorX = cx; + *pColorY = cy; + + return ONI_STATUS_OK; +} + +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.hpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.hpp new file mode 100644 index 0000000..1555785 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/openni2/VideoStream.hpp @@ -0,0 +1,90 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 Benn Snyder, 2015 individual OpenKinect contributors. + * See the CONTRIB file for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#pragma once + +#include +#include +#include +#include "Utility.hpp" +#include "Registration.hpp" + +namespace Freenect2Driver +{ + class Device : public oni::driver::DeviceBase + { + public: + virtual void start() = 0; + virtual void stop() = 0; + }; + + class VideoStream : public oni::driver::StreamBase + { + private: + unsigned int frame_id; // number each frame + virtual void populateFrame(libfreenect2::Frame* lf2Frame, int srcX, int srcY, OniFrame* oniFrame, int tgtX, int tgtY, int width, int height) const = 0; + + protected: + virtual OniSensorType getSensorType() const = 0; + libfreenect2::Freenect2Device* device; + Device* driver_dev; + bool running; // buildFrame() does something iff true + OniVideoMode video_mode; + OniCropping cropping; + bool mirroring; + Freenect2Driver::Registration *reg; + bool callPropertyChangedCallback; + typedef std::map< OniVideoMode, int > VideoModeMap; + virtual VideoModeMap getSupportedVideoModes() const = 0; + + OniStatus setVideoMode(OniVideoMode requested_mode); + + static void copyFrame(float* srcPix, int srcX, int srcY, int srcStride, uint16_t* dstPix, int dstX, int dstY, int dstStride, int width, int height, bool mirroring); + void raisePropertyChanged(int propertyId, const void* data, int dataSize); + + public: + VideoStream(Device* driver_dev, libfreenect2::Freenect2Device* device, Freenect2Driver::Registration *reg); + + OniSensorInfo getSensorInfo(); + + void setPropertyChangedCallback(oni::driver::PropertyChangedCallback handler, void* pCookie); + + bool buildFrame(libfreenect2::Frame* lf2Frame); + + OniStatus start(); + void stop(); + + // only add to property handlers if the property is generic to all children + // otherwise, implement in child and call these in default case + OniBool isPropertySupported(int propertyId); + + virtual OniStatus getProperty(int propertyId, void* data, int* pDataSize); + virtual OniStatus setProperty(int propertyId, const void* data, int dataSize); + + virtual OniStatus convertDepthToColorCoordinates(StreamBase* colorStream, int depthX, int depthY, OniDepthPixel depthZ, int* pColorX, int* pColorY); + + }; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/packet_pipeline.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/packet_pipeline.cpp new file mode 100644 index 0000000..e5d7ca3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/packet_pipeline.cpp @@ -0,0 +1,210 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file packet_pipeline.cpp Packet pipeline implementation. */ + +#include +#include +#include +#include +#include +#include + +namespace libfreenect2 +{ + +static RgbPacketProcessor *getDefaultRgbPacketProcessor() +{ +#if defined(LIBFREENECT2_WITH_VT_SUPPORT) + return new VTRgbPacketProcessor(); +#elif defined(LIBFREENECT2_WITH_VAAPI_SUPPORT) + RgbPacketProcessor *vaapi = new VaapiRgbPacketProcessor(); + if (vaapi->good()) + return vaapi; + else + delete vaapi; + return new TurboJpegRgbPacketProcessor(); +#elif defined(LIBFREENECT2_WITH_TEGRAJPEG_SUPPORT) + RgbPacketProcessor *tegra = new TegraJpegRgbPacketProcessor(); + if (tegra->good()) + return tegra; + else + delete tegra; + return new TurboJpegRgbPacketProcessor(); +#elif defined(LIBFREENECT2_WITH_TURBOJPEG_SUPPORT) + return new TurboJpegRgbPacketProcessor(); +#else + #error No jpeg decoder is enabled +#endif +} + +class PacketPipelineComponents +{ +public: + RgbPacketStreamParser *rgb_parser_; + DepthPacketStreamParser *depth_parser_; + + RgbPacketProcessor *rgb_processor_; + BaseRgbPacketProcessor *async_rgb_processor_; + DepthPacketProcessor *depth_processor_; + BaseDepthPacketProcessor *async_depth_processor_; + + ~PacketPipelineComponents(); + void initialize(RgbPacketProcessor *rgb, DepthPacketProcessor *depth); +}; + +void PacketPipelineComponents::initialize(RgbPacketProcessor *rgb, DepthPacketProcessor *depth) +{ + rgb_parser_ = new RgbPacketStreamParser(); + depth_parser_ = new DepthPacketStreamParser(); + + rgb_processor_ = rgb; + depth_processor_ = depth; + + async_rgb_processor_ = new AsyncPacketProcessor(rgb_processor_); + async_depth_processor_ = new AsyncPacketProcessor(depth_processor_); + + rgb_parser_->setPacketProcessor(async_rgb_processor_); + depth_parser_->setPacketProcessor(async_depth_processor_); +} + +PacketPipelineComponents::~PacketPipelineComponents() +{ + delete async_rgb_processor_; + delete async_depth_processor_; + delete rgb_processor_; + delete depth_processor_; + delete rgb_parser_; + delete depth_parser_; +} + +PacketPipeline::PacketPipeline(): comp_(new PacketPipelineComponents()) {} + +PacketPipeline::~PacketPipeline() +{ + delete comp_; +} + +PacketPipeline::PacketParser *PacketPipeline::getRgbPacketParser() const +{ + return comp_->rgb_parser_; +} + +PacketPipeline::PacketParser *PacketPipeline::getIrPacketParser() const +{ + return comp_->depth_parser_; +} + +RgbPacketProcessor *PacketPipeline::getRgbPacketProcessor() const +{ + return comp_->rgb_processor_; +} + +DepthPacketProcessor *PacketPipeline::getDepthPacketProcessor() const +{ + return comp_->depth_processor_; +} + +CpuPacketPipeline::CpuPacketPipeline() +{ + comp_->initialize(getDefaultRgbPacketProcessor(), new CpuDepthPacketProcessor()); +} + +CpuPacketPipeline::~CpuPacketPipeline() { } + +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT +OpenGLPacketPipeline::OpenGLPacketPipeline(void *parent_opengl_context, bool debug) : parent_opengl_context_(parent_opengl_context), debug_(debug) +{ + comp_->initialize(getDefaultRgbPacketProcessor(), new OpenGLDepthPacketProcessor(parent_opengl_context_, debug_)); +} + +OpenGLPacketPipeline::~OpenGLPacketPipeline() { } +#endif // LIBFREENECT2_WITH_OPENGL_SUPPORT + + +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT +OpenCLPacketPipeline::OpenCLPacketPipeline(const int deviceId) : deviceId(deviceId) +{ + comp_->initialize(getDefaultRgbPacketProcessor(), new OpenCLDepthPacketProcessor(deviceId)); +} + +OpenCLPacketPipeline::~OpenCLPacketPipeline() { } + + +OpenCLKdePacketPipeline::OpenCLKdePacketPipeline(const int deviceId) : deviceId(deviceId) +{ + comp_->initialize(getDefaultRgbPacketProcessor(), new OpenCLKdeDepthPacketProcessor(deviceId)); +} + +OpenCLKdePacketPipeline::~OpenCLKdePacketPipeline() { } +#endif // LIBFREENECT2_WITH_OPENCL_SUPPORT + +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT +CudaPacketPipeline::CudaPacketPipeline(const int deviceId) : deviceId(deviceId) +{ + comp_->initialize(getDefaultRgbPacketProcessor(), new CudaDepthPacketProcessor(deviceId)); +} + +CudaKdePacketPipeline::~CudaKdePacketPipeline() { } + +CudaKdePacketPipeline::CudaKdePacketPipeline(const int deviceId) : deviceId(deviceId) +{ + comp_->initialize(getDefaultRgbPacketProcessor(), new CudaKdeDepthPacketProcessor(deviceId)); +} + +CudaPacketPipeline::~CudaPacketPipeline() { } +#endif // LIBFREENECT2_WITH_CUDA_SUPPORT + +DumpPacketPipeline::DumpPacketPipeline() +{ + RgbPacketProcessor *rgb = new DumpRgbPacketProcessor(); + DepthPacketProcessor *depth = new DumpDepthPacketProcessor(); + comp_->initialize(rgb, depth); +} + +DumpPacketPipeline::~DumpPacketPipeline() {} + +const unsigned char* DumpPacketPipeline::getDepthP0Tables(size_t* length) { + *length = sizeof(libfreenect2::protocol::P0TablesResponse); + return static_cast(getDepthPacketProcessor())->getP0Tables(); +} + +const float* DumpPacketPipeline::getDepthXTable(size_t* length) { + *length = DepthPacketProcessor::TABLE_SIZE; + return static_cast(getDepthPacketProcessor())->getXTable(); +} + +const float* DumpPacketPipeline::getDepthZTable(size_t* length) { + *length = DepthPacketProcessor::TABLE_SIZE; + return static_cast(getDepthPacketProcessor())->getZTable(); +} + +const short* DumpPacketPipeline::getDepthLookupTable(size_t* length) { + *length = DepthPacketProcessor::LUT_SIZE; + return static_cast(getDepthPacketProcessor())->getLookupTable(); +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/registration.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/registration.cpp new file mode 100644 index 0000000..49a3b03 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/registration.cpp @@ -0,0 +1,405 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file Implementation of merging depth and color images. */ + +#define _USE_MATH_DEFINES +#include +#include +#include + +namespace libfreenect2 +{ + +/* + * most information, including the table layout in command_response.h, was + * provided by @sh0 in https://github.com/OpenKinect/libfreenect2/issues/41 + */ + +// these seem to be hardcoded in the original SDK +static const float depth_q = 0.01; +static const float color_q = 0.002199; + +class RegistrationImpl +{ +public: + RegistrationImpl(Freenect2Device::IrCameraParams depth_p, Freenect2Device::ColorCameraParams rgb_p); + + void apply(int dx, int dy, float dz, float& cx, float &cy) const; + void apply(const Frame* rgb, const Frame* depth, Frame* undistorted, Frame* registered, const bool enable_filter, Frame* bigdepth, int* color_depth_map) const; + void undistortDepth(const Frame *depth, Frame *undistorted) const; + void getPointXYZRGB (const Frame* undistorted, const Frame* registered, int r, int c, float& x, float& y, float& z, float& rgb) const; + void getPointXYZ (const Frame* undistorted, int r, int c, float& x, float& y, float& z) const; + void distort(int mx, int my, float& dx, float& dy) const; + void depth_to_color(float mx, float my, float& rx, float& ry) const; + +private: + Freenect2Device::IrCameraParams depth; ///< Depth camera parameters. + Freenect2Device::ColorCameraParams color; ///< Color camera parameters. + + int distort_map[512 * 424]; + float depth_to_color_map_x[512 * 424]; + float depth_to_color_map_y[512 * 424]; + int depth_to_color_map_yi[512 * 424]; + + const int filter_width_half; + const int filter_height_half; + const float filter_tolerance; +}; + +void RegistrationImpl::distort(int mx, int my, float& x, float& y) const +{ + // see http://en.wikipedia.org/wiki/Distortion_(optics) for description + float dx = ((float)mx - depth.cx) / depth.fx; + float dy = ((float)my - depth.cy) / depth.fy; + float dx2 = dx * dx; + float dy2 = dy * dy; + float r2 = dx2 + dy2; + float dxdy2 = 2 * dx * dy; + float kr = 1 + ((depth.k3 * r2 + depth.k2) * r2 + depth.k1) * r2; + x = depth.fx * (dx * kr + depth.p2 * (r2 + 2 * dx2) + depth.p1 * dxdy2) + depth.cx; + y = depth.fy * (dy * kr + depth.p1 * (r2 + 2 * dy2) + depth.p2 * dxdy2) + depth.cy; +} + +void RegistrationImpl::depth_to_color(float mx, float my, float& rx, float& ry) const +{ + mx = (mx - depth.cx) * depth_q; + my = (my - depth.cy) * depth_q; + + float wx = + (mx * mx * mx * color.mx_x3y0) + (my * my * my * color.mx_x0y3) + + (mx * mx * my * color.mx_x2y1) + (my * my * mx * color.mx_x1y2) + + (mx * mx * color.mx_x2y0) + (my * my * color.mx_x0y2) + (mx * my * color.mx_x1y1) + + (mx * color.mx_x1y0) + (my * color.mx_x0y1) + (color.mx_x0y0); + + float wy = + (mx * mx * mx * color.my_x3y0) + (my * my * my * color.my_x0y3) + + (mx * mx * my * color.my_x2y1) + (my * my * mx * color.my_x1y2) + + (mx * mx * color.my_x2y0) + (my * my * color.my_x0y2) + (mx * my * color.my_x1y1) + + (mx * color.my_x1y0) + (my * color.my_x0y1) + (color.my_x0y0); + + rx = (wx / (color.fx * color_q)) - (color.shift_m / color.shift_d); + ry = (wy / color_q) + color.cy; +} + +void Registration::apply( int dx, int dy, float dz, float& cx, float &cy) const +{ + impl_->apply(dx, dy, dz, cx, cy); +} + +void RegistrationImpl::apply( int dx, int dy, float dz, float& cx, float &cy) const +{ + const int index = dx + dy * 512; + float rx = depth_to_color_map_x[index]; + cy = depth_to_color_map_y[index]; + + rx += (color.shift_m / dz); + cx = rx * color.fx + color.cx; +} + +void Registration::apply(const Frame *rgb, const Frame *depth, Frame *undistorted, Frame *registered, const bool enable_filter, Frame *bigdepth, int *color_depth_map) const +{ + impl_->apply(rgb, depth, undistorted, registered, enable_filter, bigdepth, color_depth_map); +} + +void RegistrationImpl::apply(const Frame *rgb, const Frame *depth, Frame *undistorted, Frame *registered, const bool enable_filter, Frame *bigdepth, int *color_depth_map) const +{ + // Check if all frames are valid and have the correct size + if (!rgb || !depth || !undistorted || !registered || + rgb->width != 1920 || rgb->height != 1080 || rgb->bytes_per_pixel != 4 || + depth->width != 512 || depth->height != 424 || depth->bytes_per_pixel != 4 || + undistorted->width != 512 || undistorted->height != 424 || undistorted->bytes_per_pixel != 4 || + registered->width != 512 || registered->height != 424 || registered->bytes_per_pixel != 4) + return; + + const float *depth_data = (float*)depth->data; + const unsigned int *rgb_data = (unsigned int*)rgb->data; + float *undistorted_data = (float*)undistorted->data; + unsigned int *registered_data = (unsigned int*)registered->data; + const int *map_dist = distort_map; + const float *map_x = depth_to_color_map_x; + const int *map_yi = depth_to_color_map_yi; + + const int size_depth = 512 * 424; + const int size_color = 1920 * 1080; + const float color_cx = color.cx + 0.5f; // 0.5f added for later rounding + + // size of filter map with a border of filter_height_half on top and bottom so that no check for borders is needed. + // since the color image is wide angle no border to the sides is needed. + const int size_filter_map = size_color + 1920 * filter_height_half * 2; + // offset to the important data + const int offset_filter_map = 1920 * filter_height_half; + + // map for storing the min z values used for each color pixel + float *filter_map = NULL; + // pointer to the beginning of the important data + float *p_filter_map = NULL; + + // map for storing the color offset for each depth pixel + int *depth_to_c_off = color_depth_map ? color_depth_map : new int[size_depth]; + int *map_c_off = depth_to_c_off; + + // initializing the depth_map with values outside of the Kinect2 range + if(enable_filter){ + filter_map = bigdepth ? (float*)bigdepth->data : new float[size_filter_map]; + p_filter_map = filter_map + offset_filter_map; + + for(float *it = filter_map, *end = filter_map + size_filter_map; it != end; ++it){ + *it = std::numeric_limits::infinity(); + } + } + + /* Fix depth distortion, and compute pixel to use from 'rgb' based on depth measurement, + * stored as x/y offset in the rgb data. + */ + + // iterating over all pixels from undistorted depth and registered color image + // the four maps have the same structure as the images, so their pointers are increased each iteration as well + for(int i = 0; i < size_depth; ++i, ++undistorted_data, ++map_dist, ++map_x, ++map_yi, ++map_c_off){ + // getting index of distorted depth pixel + const int index = *map_dist; + + // check if distorted depth pixel is outside of the depth image + if(index < 0){ + *map_c_off = -1; + *undistorted_data = 0; + continue; + } + + // getting depth value for current pixel + const float z = depth_data[index]; + *undistorted_data = z; + + // checking for invalid depth value + if(z <= 0.0f){ + *map_c_off = -1; + continue; + } + + // calculating x offset for rgb image based on depth value + const float rx = (*map_x + (color.shift_m / z)) * color.fx + color_cx; + const int cx = rx; // same as round for positive numbers (0.5f was already added to color_cx) + // getting y offset for depth image + const int cy = *map_yi; + // combining offsets + const int c_off = cx + cy * 1920; + + // check if c_off is outside of rgb image + // checking rx/cx is not needed because the color image is much wider then the depth image + if(c_off < 0 || c_off >= size_color){ + *map_c_off = -1; + continue; + } + + // saving the offset for later + *map_c_off = c_off; + + if(enable_filter){ + // setting a window around the filter map pixel corresponding to the color pixel with the current z value + int yi = (cy - filter_height_half) * 1920 + cx - filter_width_half; // index of first pixel to set + for(int r = -filter_height_half; r <= filter_height_half; ++r, yi += 1920) // index increased by a full row each iteration + { + float *it = p_filter_map + yi; + for(int c = -filter_width_half; c <= filter_width_half; ++c, ++it) + { + // only set if the current z is smaller + if(z < *it) + *it = z; + } + } + } + } + + /* Construct 'registered' image. */ + + // reseting the pointers to the beginning + map_c_off = depth_to_c_off; + undistorted_data = (float*)undistorted->data; + + /* Filter drops duplicate pixels due to aspect of two cameras. */ + if(enable_filter){ + // run through all registered color pixels and set them based on filter results + for(int i = 0; i < size_depth; ++i, ++map_c_off, ++undistorted_data, ++registered_data){ + const int c_off = *map_c_off; + + // check if offset is out of image + if(c_off < 0){ + *registered_data = 0; + continue; + } + + const float min_z = p_filter_map[c_off]; + const float z = *undistorted_data; + + // check for allowed depth noise + *registered_data = (z - min_z) / z > filter_tolerance ? 0 : *(rgb_data + c_off); + } + + if (!bigdepth) delete[] filter_map; + } + else + { + // run through all registered color pixels and set them based on c_off + for(int i = 0; i < size_depth; ++i, ++map_c_off, ++registered_data){ + const int c_off = *map_c_off; + + // check if offset is out of image + *registered_data = c_off < 0 ? 0 : *(rgb_data + c_off); + } + } + if (!color_depth_map) delete[] depth_to_c_off; +} + +void Registration::undistortDepth(const Frame *depth, Frame *undistorted) const +{ + impl_->undistortDepth(depth, undistorted); +} + +void RegistrationImpl::undistortDepth(const Frame *depth, Frame *undistorted) const +{ + // Check if all frames are valid and have the correct size + if (!depth || !undistorted || + depth->width != 512 || depth->height != 424 || depth->bytes_per_pixel != 4 || + undistorted->width != 512 || undistorted->height != 424 || undistorted->bytes_per_pixel != 4) + return; + + const float *depth_data = (float*)depth->data; + float *undistorted_data = (float*)undistorted->data; + const int *map_dist = distort_map; + + const int size_depth = 512 * 424; + + /* Fix depth distortion, and compute pixel to use from 'rgb' based on depth measurement, + * stored as x/y offset in the rgb data. + */ + + // iterating over all pixels from undistorted depth and registered color image + // the four maps have the same structure as the images, so their pointers are increased each iteration as well + for(int i = 0; i < size_depth; ++i, ++undistorted_data, ++map_dist){ + // getting index of distorted depth pixel + const int index = *map_dist; + + // check if distorted depth pixel is outside of the depth image + if(index < 0){ + *undistorted_data = 0; + continue; + } + + // getting depth value for current pixel + const float z = depth_data[index]; + *undistorted_data = z; + } +} + +void Registration::getPointXYZRGB (const Frame* undistorted, const Frame* registered, int r, int c, float& x, float& y, float& z, float& rgb) const +{ + impl_->getPointXYZRGB(undistorted, registered, r, c, x, y, z, rgb); +} + +void RegistrationImpl::getPointXYZRGB (const Frame* undistorted, const Frame* registered, int r, int c, float& x, float& y, float& z, float& rgb) const +{ + getPointXYZ(undistorted, r, c, x, y, z); + + if(isnan(z)) + { + rgb = 0; + } + else + { + float* registered_data = (float *)registered->data; + rgb = registered_data[512*r+c]; + } +} + +void Registration::getPointXYZ(const Frame *undistorted, int r, int c, float &x, float &y, float &z) const +{ + impl_->getPointXYZ(undistorted,r,c,x,y,z); +} + +void RegistrationImpl::getPointXYZ (const Frame *undistorted, int r, int c, float &x, float &y, float &z) const +{ + const float bad_point = std::numeric_limits::quiet_NaN(); + const float cx(depth.cx), cy(depth.cy); + const float fx(1/depth.fx), fy(1/depth.fy); + float* undistorted_data = (float *)undistorted->data; + const float depth_val = undistorted_data[512*r+c]/1000.0f; //scaling factor, so that value of 1 is one meter. + if (isnan(depth_val) || depth_val <= 0.001) + { + //depth value is not valid + x = y = z = bad_point; + } + else + { + x = (c + 0.5 - cx) * fx * depth_val; + y = (r + 0.5 - cy) * fy * depth_val; + z = depth_val; + } +} + +Registration::Registration(Freenect2Device::IrCameraParams depth_p, Freenect2Device::ColorCameraParams rgb_p): + impl_(new RegistrationImpl(depth_p, rgb_p)) {} + +Registration::~Registration() +{ + delete impl_; +} + +RegistrationImpl::RegistrationImpl(Freenect2Device::IrCameraParams depth_p, Freenect2Device::ColorCameraParams rgb_p): + depth(depth_p), color(rgb_p), filter_width_half(2), filter_height_half(1), filter_tolerance(0.01f) +{ + float mx, my; + int ix, iy, index; + float rx, ry; + int *map_dist = distort_map; + float *map_x = depth_to_color_map_x; + float *map_y = depth_to_color_map_y; + int *map_yi = depth_to_color_map_yi; + + for (int y = 0; y < 424; y++) { + for (int x = 0; x < 512; x++) { + // compute the dirstored coordinate for current pixel + distort(x,y,mx,my); + // rounding the values and check if the pixel is inside the image + ix = (int)(mx + 0.5f); + iy = (int)(my + 0.5f); + if(ix < 0 || ix >= 512 || iy < 0 || iy >= 424) + index = -1; + else + // computing the index from the coordianted for faster access to the data + index = iy * 512 + ix; + *map_dist++ = index; + + // compute the depth to color mapping entries for the current pixel + depth_to_color(x,y,rx,ry); + *map_x++ = rx; + *map_y++ = ry; + // compute the y offset to minimize later computations + *map_yi++ = (int)(ry + 0.5f); + } + } +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/resource.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/resource.cpp new file mode 100644 index 0000000..3f01dcd --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/resource.cpp @@ -0,0 +1,104 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file resource.cpp Implementation of resource loading (from file or in-program). */ + +#include +#include +#include +#include + +namespace libfreenect2 +{ + +/** Meta information of an in-program resource. */ +struct ResourceDescriptor +{ + const char *filename; + const unsigned char *data; + size_t length; +}; + +#ifdef RESOURCES_INC +#include "resources.inc.h" +#else +static ResourceDescriptor resource_descriptors[] = {{NULL, NULL, 0}}; +static int resource_descriptors_length = 0; +#endif + +/** + * Find data of a requested resource. + * @param name Name of the resource to retrieve. + * @param [out] data Address of the resource data, if found. + * @param [out] Length of the resource data, if found. + * @return Whether the resource could be retrieved. + */ +bool loadResource(const std::string &name, unsigned char const**data, size_t *length) +{ + bool result = false; + + for(int i = 0; i < resource_descriptors_length; ++i) + { + if(name.compare(resource_descriptors[i].filename) == 0) + { + *data = resource_descriptors[i].data; + *length = resource_descriptors[i].length; + result = true; + break; + } + } + return result; +} + +/** + * Get resource data into a supplied buffer. + * @param filename Name of the file to get. + * @param buffer Buffer to use as target storage. + * @param n Size of the supplied buffer. + * @return Whether the requested resource could be loaded (copied) into the supplied buffer. + */ +bool loadBufferFromResources(const std::string &filename, unsigned char *buffer, const size_t n) +{ + size_t length = 0; + const unsigned char *data = NULL; + + if(!loadResource(filename, &data, &length)) + { + LOG_ERROR << "failed to load resource: " << filename; + return false; + } + + if(length != n) + { + LOG_ERROR << "wrong size of resource: " << filename; + return false; + } + + memcpy(buffer, data, length); + return true; +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_processor.cpp new file mode 100644 index 0000000..554e27e --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_processor.cpp @@ -0,0 +1,75 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file rgb_packet_processor.cpp Implementation of generic color packet processors. */ + +#include +#include + +#include +#include +#include + +namespace libfreenect2 +{ + +RgbPacketProcessor::RgbPacketProcessor() : + listener_(0) +{ +} + +RgbPacketProcessor::~RgbPacketProcessor() +{ +} + +void RgbPacketProcessor::setFrameListener(libfreenect2::FrameListener *listener) +{ + listener_ = listener; +} + +DumpRgbPacketProcessor::DumpRgbPacketProcessor() {} +DumpRgbPacketProcessor::~DumpRgbPacketProcessor() {} + +void DumpRgbPacketProcessor::process(const RgbPacket &packet) +{ + Frame *frame = new Frame(1, 1, 1920*1080*4); + frame->sequence = packet.sequence; + frame->timestamp = packet.timestamp; + frame->exposure = packet.exposure; + frame->gain = packet.gain; + frame->gamma = packet.gamma; + frame->format = Frame::Raw; + frame->bytes_per_pixel = packet.jpeg_buffer_length; + + std::memcpy(frame->data, packet.jpeg_buffer, packet.jpeg_buffer_length); + + if (!listener_->onNewFrame(Frame::Color, frame)) { + delete frame; + } + frame = NULL; +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_stream_parser.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_stream_parser.cpp new file mode 100644 index 0000000..bc3fb6c --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/rgb_packet_stream_parser.cpp @@ -0,0 +1,178 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file rgb_packet_stream_parser.cpp Parser implementation for retrieving JPEG data from a stream. */ + +#include +#include +#include +#include + +namespace libfreenect2 +{ + + +LIBFREENECT2_PACK(struct RawRgbPacket +{ + uint32_t sequence; + uint32_t magic_header; // is 'BBBB' equal 0x42424242 + + unsigned char jpeg_buffer[0]; +}); + +// starting from JPEG EOI: 0xff 0xd9 +// char pad_0xa5[]; //0-3 bytes alignment of 0xa5 +// char filler[filler_length] = "ZZZZ..."; +LIBFREENECT2_PACK(struct RgbPacketFooter { + uint32_t magic_header; // is '9999' equal 0x39393939 + uint32_t sequence; + uint32_t filler_length; + uint32_t unknown1; // seems 0 always + uint32_t unknown2; // seems 0 always + uint32_t timestamp; + float exposure; // ? ranges from 0.5 to about 60.0 with powerfull light at camera or totally covered + float gain; // ? ranges from 1.0 when camera is clear to 1.5 when camera is covered. + uint32_t magic_footer; // is 'BBBB' equal 0x42424242 + uint32_t packet_size; + float gamma; // ranges from 1.0f to about 6.4 when camera is fully covered + uint32_t unknown4[3]; // seems to be 0 all the time. +}); + +RgbPacketStreamParser::RgbPacketStreamParser() : + buffer_size_(2*1024*1024), + processor_(noopProcessor()) +{ + processor_->allocateBuffer(packet_, buffer_size_); +} + +RgbPacketStreamParser::~RgbPacketStreamParser() +{ +} + +void RgbPacketStreamParser::setPacketProcessor(BaseRgbPacketProcessor *processor) +{ + processor_->releaseBuffer(packet_); + processor_ = (processor != 0) ? processor : noopProcessor(); + processor_->allocateBuffer(packet_, buffer_size_); +} + +void RgbPacketStreamParser::onDataReceived(unsigned char* buffer, size_t length) +{ + if (packet_.memory == NULL || packet_.memory->data == NULL) + { + LOG_ERROR << "Packet buffer is NULL"; + return; + } + Buffer &fb = *packet_.memory; + + // package containing data + if(length > 0) + { + if(fb.length + length <= fb.capacity) + { + memcpy(fb.data + fb.length, buffer, length); + fb.length += length; + } + else + { + LOG_INFO << "buffer overflow!"; + fb.length = 0; + return; + } + + // not enough data to do anything + if (fb.length <= sizeof(RawRgbPacket) + sizeof(RgbPacketFooter)) + return; + + RgbPacketFooter* footer = reinterpret_cast(&fb.data[fb.length - sizeof(RgbPacketFooter)]); + + if (footer->magic_header == 0x39393939 && footer->magic_footer == 0x42424242) + { + RawRgbPacket *raw_packet = reinterpret_cast(fb.data); + + if (fb.length != footer->packet_size || raw_packet->sequence != footer->sequence) + { + LOG_INFO << "packetsize or sequence doesn't match!"; + fb.length = 0; + return; + } + + if (fb.length - sizeof(RawRgbPacket) - sizeof(RgbPacketFooter) < footer->filler_length) + { + LOG_INFO << "not enough space for packet filler!"; + fb.length = 0; + return; + } + + size_t jpeg_length = 0; + //check for JPEG EOI 0xff 0xd9 within 0 to 3 alignment bytes + size_t length_no_filler = fb.length - sizeof(RawRgbPacket) - sizeof(RgbPacketFooter) - footer->filler_length; + for (size_t i = 0; i < 4; i++) + { + if (length_no_filler < i + 2) + break; + size_t eoi = length_no_filler - i; + + if (raw_packet->jpeg_buffer[eoi - 2] == 0xff && raw_packet->jpeg_buffer[eoi - 1] == 0xd9) + jpeg_length = eoi; + } + + if (jpeg_length == 0) + { + LOG_INFO << "no JPEG detected!"; + fb.length = 0; + return; + } + + // can the processor handle the next image? + if(processor_->ready()) + { + RgbPacket &rgb_packet = packet_; + rgb_packet.sequence = raw_packet->sequence; + rgb_packet.timestamp = footer->timestamp; + rgb_packet.exposure = footer->exposure; + rgb_packet.gain = footer->gain; + rgb_packet.gamma = footer->gamma; + rgb_packet.jpeg_buffer = raw_packet->jpeg_buffer; + rgb_packet.jpeg_buffer_length = jpeg_length; + + // call the processor + processor_->process(rgb_packet); + //allocatePacket() should never return NULL when processor is ready() + processor_->allocateBuffer(packet_, buffer_size_); + } + else + { + LOG_DEBUG << "skipping rgb packet!"; + } + + // reset front buffer + packet_.memory->length = 0; + } + } +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/debug.fs b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/debug.fs new file mode 100644 index 0000000..226e9d2 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/debug.fs @@ -0,0 +1,12 @@ +uniform sampler2DRect Data; + +in vec2 TexCoord; + +out vec4 Color; + +void main(void) +{ + ivec2 uv = ivec2(TexCoord.x, TexCoord.y); + + Color = texelFetch(Data, uv); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/default.vs b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/default.vs new file mode 100644 index 0000000..f8c0209 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/default.vs @@ -0,0 +1,10 @@ +in vec2 InputPosition; +in vec2 InputTexCoord; + +out vec2 TexCoord; + +void main(void) +{ + gl_Position = vec4(InputPosition, 0.0, 1.0); + TexCoord = InputTexCoord; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter1.fs b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter1.fs new file mode 100644 index 0000000..50e1d5d --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter1.fs @@ -0,0 +1,122 @@ +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform sampler2DRect A; +uniform sampler2DRect B; +uniform sampler2DRect Norm; + +uniform Parameters Params; + +in vec2 TexCoord; + +/*layout(location = 0)*/ out vec4 Debug; +/*layout(location = 1)*/ out vec3 FilterA; +/*layout(location = 2)*/ out vec3 FilterB; +/*layout(location = 3)*/ out uint MaxEdgeTest; + +void applyBilateralFilter(ivec2 uv) +{ + vec3 threshold = vec3((Params.joint_bilateral_ab_threshold * Params.joint_bilateral_ab_threshold) / (Params.ab_multiplier * Params.ab_multiplier)); + vec3 joint_bilateral_exp = vec3(Params.joint_bilateral_exp); + + vec3 self_a = texelFetch(A, uv).xyz; + vec3 self_b = texelFetch(B, uv).xyz; + vec3 self_norm = texelFetch(Norm, uv).xyz; + vec3 self_normalized_a = self_a / self_norm; + vec3 self_normalized_b = self_b / self_norm; + + vec4 weight_acc = vec4(0.0); + vec4 weighted_a_acc = vec4(0.0); + vec4 weighted_b_acc = vec4(0.0); + + bvec3 c0 = lessThan(self_norm * self_norm, threshold); + + threshold = mix(threshold, vec3(0.0), c0); + joint_bilateral_exp = mix(joint_bilateral_exp, vec3(0.0), c0); + + for(int y = 0; y < 3; ++y) + { + for(int x = 0; x < 3; ++x) + { + ivec2 ouv = uv + ivec2(x - 1, y - 1); + + vec3 other_a = texelFetch(A, ouv).xyz; + vec3 other_b = texelFetch(B, ouv).xyz; + vec3 other_norm = texelFetch(Norm, ouv).xyz; + + vec3 other_normalized_a = other_a / other_norm; + vec3 other_normalized_b = other_b / other_norm; + + bvec3 c1 = lessThan(other_norm * other_norm, threshold); + + vec3 dist = 0.5f * (1.0f - (self_normalized_a * other_normalized_a + self_normalized_b * other_normalized_b)); + vec3 weight = mix(Params.gaussian_kernel[x][y] * exp(-1.442695 * joint_bilateral_exp * dist), vec3(0.0), c1); + + weighted_a_acc.xyz += weight * other_a; + weighted_b_acc.xyz += weight * other_b; + weight_acc.xyz += weight; + + // TODO: this sucks, but otherwise opengl reports error: temporary registers exceeded :( + weighted_a_acc.w += mix(dist.x, 0, c1.x); + weighted_b_acc.w += mix(dist.y, 0, c1.y); + weight_acc.w += mix(dist.z, 0, c1.z); + } + } + + bvec3 c2 = lessThan(vec3(0.0), weight_acc.xyz); + FilterA = mix(vec3(0.0), weighted_a_acc.xyz / weight_acc.xyz, c2); + FilterB = mix(vec3(0.0), weighted_b_acc.xyz / weight_acc.xyz, c2); + + if(uv.x < 1 || uv.y < 1 || uv.x > 510 || uv.y > 422) + { + FilterA = self_a; + FilterB = self_b; + } + + vec3 dist_acc = vec3(weighted_a_acc.w, weighted_b_acc.w, weight_acc.w); + MaxEdgeTest = uint(all(lessThan(dist_acc, vec3(Params.joint_bilateral_max_edge)))); + //Debug = vec4(vec3(MaxEdgeTest), 1); +} + +void main(void) +{ + ivec2 uv = ivec2(TexCoord.x, TexCoord.y); + + applyBilateralFilter(uv); + + vec3 norm = sqrt(FilterA * FilterA + FilterB * FilterB); + float i = min(dot(norm, vec3(0.333333333 * Params.ab_multiplier * Params.ab_output_multiplier)), 65535.0); + + Debug = vec4(vec3(i, i, i) / 65535.0, 1); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter2.fs b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter2.fs new file mode 100644 index 0000000..d1618a0 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/filter2.fs @@ -0,0 +1,130 @@ +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform sampler2DRect DepthAndIrSum; +uniform usampler2DRect MaxEdgeTest; + +uniform Parameters Params; + +in vec2 TexCoord; + +/*layout(location = 0)*/ out vec4 Debug; +/*layout(location = 1)*/ out float FilterDepth; + +void applyEdgeAwareFilter(ivec2 uv) +{ + vec2 v = texelFetch(DepthAndIrSum, uv).xy; + + if(v.x >= Params.min_depth && v.x <= Params.max_depth) + { + if(uv.x < 1 || uv.y < 1 || uv.x > 510 || uv.y > 422) + { + FilterDepth = v.x; + } + else + { + bool max_edge_test_ok = texelFetch(MaxEdgeTest, uv).x > 0u; + + float ir_sum_acc = v.y, squared_ir_sum_acc = v.y * v.y, min_depth = v.x, max_depth = v.x; + + for(int yi = -1; yi < 2; ++yi) + { + for(int xi = -1; xi < 2; ++xi) + { + if(yi == 0 && xi == 0) continue; + + vec2 other = texelFetch(DepthAndIrSum, uv + ivec2(xi, yi)).xy; + + ir_sum_acc += other.y; + squared_ir_sum_acc += other.y * other.y; + + if(0.0f < other.x) + { + min_depth = min(min_depth, other.x); + max_depth = max(max_depth, other.x); + } + } + } + + float tmp0 = sqrt(squared_ir_sum_acc * 9.0f - ir_sum_acc * ir_sum_acc) / 9.0f; + float edge_avg = max(ir_sum_acc / 9.0f, Params.edge_ab_avg_min_value); + tmp0 /= edge_avg; + + float abs_min_diff = abs(v.x - min_depth); + float abs_max_diff = abs(v.x - max_depth); + + float avg_diff = (abs_min_diff + abs_max_diff) * 0.5f; + float max_abs_diff = max(abs_min_diff, abs_max_diff); + + bool cond0 = + 0.0f < v.x && + tmp0 >= Params.edge_ab_std_dev_threshold && + Params.edge_close_delta_threshold < abs_min_diff && + Params.edge_far_delta_threshold < abs_max_diff && + Params.edge_max_delta_threshold < max_abs_diff && + Params.edge_avg_delta_threshold < avg_diff; + + FilterDepth = cond0 ? 0.0f : v.x; + + if(!cond0) + { + if(max_edge_test_ok) + { + float tmp1 = 1500.0f > v.x ? 30.0f : 0.02f * v.x; + float edge_count = 0.0f; + + FilterDepth = edge_count > Params.max_edge_count ? 0.0f : v.x; + } + else + { + FilterDepth = !max_edge_test_ok ? 0.0f : v.x; + //FilterDepth = true ? FilterDepth : v.x; + } + } + } + } + else + { + FilterDepth = 0.0f; + } +} + +void main(void) +{ + ivec2 uv = ivec2(TexCoord.x, TexCoord.y); + + applyEdgeAwareFilter(uv); + + Debug = vec4(vec3(FilterDepth / Params.max_depth), 1); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage1.fs b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage1.fs new file mode 100644 index 0000000..cb64734 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage1.fs @@ -0,0 +1,120 @@ +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform usampler2DRect P0Table0; +uniform usampler2DRect P0Table1; +uniform usampler2DRect P0Table2; +uniform isampler2DRect Lut11to16; +uniform usampler2DRect Data; +uniform sampler2DRect ZTable; + +uniform Parameters Params; + +in vec2 TexCoord; + +/*layout(location = 0)*/ out vec4 Debug; +/* */ +/*layout(location = 1)*/ out vec3 A; +/*layout(location = 2)*/ out vec3 B; +/*layout(location = 3)*/ out vec3 Norm; +/*layout(location = 4)*/ out float Infrared; + +#define M_PI 3.1415926535897932384626433832795 + +int data(ivec2 uv) +{ + return int(texelFetch(Data, uv).x); +} + +float decode_data(ivec2 uv, int sub) +{ + int row_idx = 424 * sub + (uv.y < 212 ? uv.y + 212 : 423 - uv.y); + + int m = int(0xffffffff); + int bitmask = (((1 << 2) - 1) << 7) & m; + int idx = (((uv.x >> 2) + ((uv.x << 7) & bitmask)) * 11) & m; + + int col_idx = idx >> 4; + int upper_bytes = idx & 15; + int lower_bytes = 16 - upper_bytes; + + ivec2 data_idx0 = ivec2(col_idx, row_idx); + ivec2 data_idx1 = ivec2(col_idx + 1, row_idx); + + int lut_idx = (uv.x < 1 || 510 < uv.x || col_idx > 352) ? 0 : ((data(data_idx0) >> upper_bytes) | (data(data_idx1) << lower_bytes)) & 2047; + + return float(texelFetch(Lut11to16, ivec2(int(lut_idx), 0)).x); +} + +vec2 processMeasurementTriple(in ivec2 uv, in usampler2DRect p0table, in int offset, in float ab_multiplier_per_frq, inout bool saturated) +{ + float p0 = -float(texelFetch(p0table, uv).x) * 0.000031 * M_PI; + + vec3 v = vec3(decode_data(uv, offset + 0), decode_data(uv, offset + 1), decode_data(uv, offset + 2)); + + saturated = saturated && any(equal(v, vec3(32767.0))); + + float a = dot(v, cos( p0 + Params.phase_in_rad)) * ab_multiplier_per_frq; + float b = dot(v, sin(-p0 - Params.phase_in_rad)) * ab_multiplier_per_frq; + + return vec2(a, b); +} + +void main(void) +{ + ivec2 uv = ivec2(TexCoord.x, TexCoord.y); + + bool valid_pixel = 0.0 < texelFetch(ZTable, uv).x; + bvec3 saturated = bvec3(valid_pixel); + + vec2 ab0 = processMeasurementTriple(uv, P0Table0, 0, Params.ab_multiplier_per_frq.x, saturated.x); + vec2 ab1 = processMeasurementTriple(uv, P0Table1, 3, Params.ab_multiplier_per_frq.y, saturated.y); + vec2 ab2 = processMeasurementTriple(uv, P0Table2, 6, Params.ab_multiplier_per_frq.z, saturated.z); + +#ifdef MESA_BUGGY_BOOL_CMP + valid_pixel = valid_pixel ? true : false; +#endif + bvec3 invalid_pixel = bvec3(!valid_pixel); + + A = mix(vec3(ab0.x, ab1.x, ab2.x), vec3(0.0), invalid_pixel); + B = mix(vec3(ab0.y, ab1.y, ab2.y), vec3(0.0), invalid_pixel); + Norm = sqrt(A * A + B * B); + + A = mix(A, vec3(0.0), saturated); + B = mix(B, vec3(0.0), saturated); + + Infrared = min(dot(mix(Norm, vec3(65535.0), saturated), vec3(0.333333333 * Params.ab_multiplier * Params.ab_output_multiplier)), 65535.0); + + Debug = vec4(sqrt(vec3(Infrared / 65535.0)), 1.0); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage2.fs b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage2.fs new file mode 100644 index 0000000..c31472c --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/shader/stage2.fs @@ -0,0 +1,155 @@ +struct Parameters +{ + float ab_multiplier; + vec3 ab_multiplier_per_frq; + float ab_output_multiplier; + + vec3 phase_in_rad; + + float joint_bilateral_ab_threshold; + float joint_bilateral_max_edge; + float joint_bilateral_exp; + mat3 gaussian_kernel; + + float phase_offset; + float unambigious_dist; + float individual_ab_threshold; + float ab_threshold; + float ab_confidence_slope; + float ab_confidence_offset; + float min_dealias_confidence; + float max_dealias_confidence; + + float edge_ab_avg_min_value; + float edge_ab_std_dev_threshold; + float edge_close_delta_threshold; + float edge_far_delta_threshold; + float edge_max_delta_threshold; + float edge_avg_delta_threshold; + float max_edge_count; + + float min_depth; + float max_depth; +}; + +uniform sampler2DRect A; +uniform sampler2DRect B; +uniform sampler2DRect XTable; +uniform sampler2DRect ZTable; + +uniform Parameters Params; + +in vec2 TexCoord; + +/*layout(location = 0)*/ out vec4 Debug; +/*layout(location = 1)*/ out float Depth; +/*layout(location = 2)*/ out vec2 DepthAndIrSum; + +#define M_PI 3.1415926535897932384626433832795 + +void main(void) +{ + ivec2 uv = ivec2(TexCoord.x, TexCoord.y); + + vec3 a = texelFetch(A, uv).xyz; + vec3 b = texelFetch(B, uv).xyz; + + vec3 phase = atan(b, a); + phase = mix(phase, phase + 2.0 * M_PI, lessThan(phase, vec3(0.0))); + phase = mix(phase, vec3(0.0), isnan(phase)); + vec3 ir = sqrt(a * a + b * b) * Params.ab_multiplier; + + float ir_sum = ir.x + ir.y + ir.z; + float ir_min = min(ir.x, min(ir.y, ir.z)); + float ir_max = max(ir.x, max(ir.y, ir.z)); + + float phase_final = 0; + + if(ir_min >= Params.individual_ab_threshold && ir_sum >= Params.ab_threshold) + { + vec3 t = phase / (2.0 * M_PI) * vec3(3.0, 15.0, 2.0); + + float t0 = t.x; + float t1 = t.y; + float t2 = t.z; + + float t5 = (floor((t1 - t0) * 0.333333f + 0.5f) * 3.0f + t0); + float t3 = (-t2 + t5); + float t4 = t3 * 2.0f; + + bool c1 = t4 >= -t4; // true if t4 positive + + float f1 = c1 ? 2.0f : -2.0f; + float f2 = c1 ? 0.5f : -0.5f; + t3 *= f2; + t3 = (t3 - floor(t3)) * f1; + + bool c2 = 0.5f < abs(t3) && abs(t3) < 1.5f; + + float t6 = c2 ? t5 + 15.0f : t5; + float t7 = c2 ? t1 + 15.0f : t1; + + float t8 = (floor((-t2 + t6) * 0.5f + 0.5f) * 2.0f + t2) * 0.5f; + + t6 *= 0.333333f; // = / 3 + t7 *= 0.066667f; // = / 15 + + float t9 = (t8 + t6 + t7); // transformed phase measurements (they are transformed and divided by the values the original values were multiplied with) + float t10 = t9 * 0.333333f; // some avg + + t6 *= 2.0f * M_PI; + t7 *= 2.0f * M_PI; + t8 *= 2.0f * M_PI; + + // some cross product + float t8_new = t7 * 0.826977f - t8 * 0.110264f; + float t6_new = t8 * 0.551318f - t6 * 0.826977f; + float t7_new = t6 * 0.110264f - t7 * 0.551318f; + + t8 = t8_new; + t6 = t6_new; + t7 = t7_new; + + float norm = t8 * t8 + t6 * t6 + t7 * t7; + float mask = t9 >= 0.0f ? 1.0f : 0.0f; + t10 *= mask; + + bool slope_positive = 0 < Params.ab_confidence_slope; + + float ir_x = slope_positive ? ir_min : ir_max; + + ir_x = log(ir_x); + ir_x = (ir_x * Params.ab_confidence_slope * 0.301030f + Params.ab_confidence_offset) * 3.321928f; + ir_x = exp(ir_x); + ir_x = min(Params.max_dealias_confidence, max(Params.min_dealias_confidence, ir_x)); + ir_x *= ir_x; + + float mask2 = ir_x >= norm ? 1.0f : 0.0f; + + float t11 = t10 * mask2; + + float mask3 = Params.max_dealias_confidence * Params.max_dealias_confidence >= norm ? 1.0f : 0.0f; + t10 *= mask3; + phase_final = true/*(modeMask & 2) != 0*/ ? t11 : t10; + } + + float zmultiplier = texelFetch(ZTable, uv).x; + float xmultiplier = texelFetch(XTable, uv).x; + + phase_final = 0.0 < phase_final ? phase_final + Params.phase_offset : phase_final; + + float depth_linear = zmultiplier * phase_final; + float max_depth = phase_final * Params.unambigious_dist * 2.0; + + bool cond1 = /*(modeMask & 32) != 0*/ true && 0.0 < depth_linear && 0.0 < max_depth; + + xmultiplier = (xmultiplier * 90.0) / (max_depth * max_depth * 8192.0); + + float depth_fit = depth_linear / (-depth_linear * xmultiplier + 1); + depth_fit = depth_fit < 0.0 ? 0.0 : depth_fit; + + Depth = cond1 ? depth_fit : depth_linear; // r1.y -> later r2.z + DepthAndIrSum = vec2(Depth, ir_sum); + + Debug = vec4(vec3(Depth / Params.max_depth), 1.0); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tegra_jpeg_rgb_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tegra_jpeg_rgb_packet_processor.cpp new file mode 100644 index 0000000..9c38205 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tegra_jpeg_rgb_packet_processor.cpp @@ -0,0 +1,304 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include +#include "libfreenect2/logging.h" + +namespace nv_headers { +#define DONT_USE_EXTERN_C +#include "nv_headers/jpeglib.h" +} + +#include + +#ifdef LIBFREENECT2_WITH_CXX11_SUPPORT +#define TYPEOF(expr) decltype(expr) +#else +#define TYPEOF(expr) __typeof__(expr) +#endif + +#define FOR_ALL(MACRO) \ + MACRO(jpeg_std_error) \ + MACRO(jpeg_CreateDecompress) \ + MACRO(jpeg_mem_src) \ + MACRO(jpeg_read_header) \ + MACRO(jpeg_start_decompress) \ + MACRO(jpeg_read_scanlines) \ + MACRO(jpeg_finish_decompress) \ + MACRO(jpeg_abort_decompress) \ + MACRO(jpeg_destroy_decompress) + +class libjpeg_handle +{ +private: + void *handle; +public: + #define DECLARE(func) TYPEOF(&nv_headers::func) func; + FOR_ALL(DECLARE) + bool good; + + #define INIT(func) func(0), + libjpeg_handle(): FOR_ALL(INIT) good(false) + { + handle = dlopen(LIBFREENECT2_TEGRAJPEG_LIBRARY, RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND); + const char *err; + err = dlerror(); + if (handle == NULL) { + LOG_ERROR << "dlopen: " << err; + return; + } + #define IMPORT(func) func = reinterpret_cast(dlsym(handle, #func)); if ((err = dlerror())) { LOG_ERROR << "dlsym: " << err; dlclose(handle); handle = NULL; return; } + FOR_ALL(IMPORT) + good = true; + } + + ~libjpeg_handle() + { + if (handle) + dlclose(handle); + } +}; + +using namespace nv_headers; + +namespace libfreenect2 +{ + +class TegraImage: public Buffer +{ +public: + struct jpeg_decompress_struct dinfo; +}; + +class TegraImageAllocator: public Allocator +{ +public: + void *owner; + struct jpeg_error_mgr *jerr; + libjpeg_handle &libjpeg; + + TegraImageAllocator(void *owner, struct jpeg_error_mgr *jerr, libjpeg_handle &libjpeg): + owner(owner), jerr(jerr), libjpeg(libjpeg) {} + + virtual Buffer *allocate(size_t size) + { + TegraImage *ti = new TegraImage(); + ti->allocator = this; + ti->dinfo.client_data = owner; + ti->dinfo.err = jerr; + libjpeg.jpeg_create_decompress(&ti->dinfo); + return ti; + } + + virtual void free(Buffer *b) + { + if (b == NULL) + return; + TegraImage *ti = static_cast(b); + libjpeg.jpeg_destroy_decompress(&ti->dinfo); + delete ti; + } +}; + +class TegraFrame: public Frame +{ +public: + TegraFrame(size_t width, size_t height, size_t bpp, TegraImage *ti): + Frame(width, height, bpp, (unsigned char*)-1) + { + data = NULL; + rawdata = reinterpret_cast(ti); + } + + TegraImage *image() + { + return reinterpret_cast(rawdata); + } + + virtual ~TegraFrame() + { + image()->allocator->free(image()); + rawdata = NULL; + } + + void fill() + { + data = image()->dinfo.jpegTegraMgr->buff[0]; + } +}; + +class TegraJpegRgbPacketProcessorImpl: public WithPerfLogging +{ +public: + libjpeg_handle libjpeg; + struct jpeg_error_mgr jerr; + size_t real_bib; + + static const size_t WIDTH = 1920; + static const size_t HEIGHT = 1080; + static const size_t BPP = 4; + + bool good; + + TegraFrame *frame; + + Allocator *image_allocator; + + TegraJpegRgbPacketProcessorImpl(): + libjpeg(), + good(true), + frame(NULL), + image_allocator(NULL) + { + if (!libjpeg.good) { + good = false; + return; + } + libjpeg.jpeg_std_error(&jerr); + jerr.error_exit = TegraJpegRgbPacketProcessorImpl::my_error_exit; + + image_allocator = new PoolAllocator(new TegraImageAllocator(reinterpret_cast(this), &jerr, libjpeg)); + + newFrame(); + } + + ~TegraJpegRgbPacketProcessorImpl() + { + delete frame; + delete image_allocator; + } + + void newFrame() + { + frame = new TegraFrame(WIDTH, HEIGHT, BPP, static_cast(image_allocator->allocate(0))); + frame->format = Frame::RGBX; + } + + static inline TegraJpegRgbPacketProcessorImpl *owner(j_decompress_ptr dinfo) + { + return static_cast(dinfo->client_data); + } + + static int fill_input_buffer(j_decompress_ptr dinfo) + { + dinfo->src->bytes_in_buffer = owner(dinfo)->real_bib; + return 1; + } + + static void abort_jpeg_error(j_decompress_ptr dinfo, const char *msg) + { + owner(dinfo)->libjpeg.jpeg_abort_decompress(dinfo); + LOG_ERROR << msg; + owner(dinfo)->good = false; + } + + static void my_error_exit(j_common_ptr info) + { + char buffer[JMSG_LENGTH_MAX]; + info->err->format_message(info, buffer); + abort_jpeg_error((j_decompress_ptr)info, buffer); + } + + void decompress(unsigned char *buf, size_t len) + { + j_decompress_ptr dinfo = &frame->image()->dinfo; + libjpeg.jpeg_mem_src(dinfo, buf, len); + + // This hack prevents an extra memcpy in jpeg_read_header + real_bib = len; + dinfo->src->bytes_in_buffer = 0; + dinfo->src->fill_input_buffer = TegraJpegRgbPacketProcessorImpl::fill_input_buffer; + libjpeg.jpeg_read_header(dinfo, true); + + if (dinfo->progressive_mode) + abort_jpeg_error(dinfo, "Tegra HW doesn't support progressive JPEG; use TurboJPEG"); + + if (!dinfo->tegra_acceleration) + abort_jpeg_error(dinfo, "Tegra HW acceleration is disabled unexpectedly"); + + if (dinfo->image_width != WIDTH || dinfo->image_height != HEIGHT) + abort_jpeg_error(dinfo, "image dimensions does not match preset"); + + dinfo->out_color_space = JCS_RGBA_8888; + + libjpeg.jpeg_start_decompress(dinfo); + + // Hardware acceleration returns the entire surface in one go. + // The normal way with software decoding uses jpeg_read_scanlines with loop. + if (libjpeg.jpeg_read_scanlines(dinfo, NULL, 0) != dinfo->output_height || dinfo->output_height != HEIGHT) + abort_jpeg_error(dinfo, "Incomplete decoding result"); + + /* Empirically: 1 surface for RGBA; 3 surfaces for YUV */ + //size_t pitch = dinfo->jpegTegraMgr->pitch[0]; + //unsigned char *surface = dinfo->jpegTegraMgr->buff[0]; + //if (pitch == 0 || surface == NULL) + // abort_jpeg_error(dinfo, "Empty result buffer"); + + frame->fill(); + + libjpeg.jpeg_finish_decompress(dinfo); + } +}; + +TegraJpegRgbPacketProcessor::TegraJpegRgbPacketProcessor() : + impl_(new TegraJpegRgbPacketProcessorImpl()) +{ +} + +TegraJpegRgbPacketProcessor::~TegraJpegRgbPacketProcessor() +{ + delete impl_; +} + +bool TegraJpegRgbPacketProcessor::good() +{ + return impl_->good; +} + +void TegraJpegRgbPacketProcessor::process(const RgbPacket &packet) +{ + if (listener_ == NULL) + return; + + impl_->startTiming(); + + impl_->frame->timestamp = packet.timestamp; + impl_->frame->sequence = packet.sequence; + impl_->frame->exposure = packet.exposure; + impl_->frame->gain = packet.gain; + impl_->frame->gamma = packet.gamma; + + impl_->decompress(packet.jpeg_buffer, packet.jpeg_buffer_length); + + impl_->stopTiming(LOG_INFO); + + if (!impl_->good) + impl_->frame->status = 1; + + if (listener_->onNewFrame(Frame::Color, impl_->frame)) + impl_->newFrame(); +} +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.cpp new file mode 100644 index 0000000..60308fa --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.cpp @@ -0,0 +1,294 @@ +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- +Copyright (c) 2010-2012 Marcus Geelnard + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#include +#include "tinythread.h" + +#if defined(_TTHREAD_POSIX_) + #include + #include +#elif defined(_TTHREAD_WIN32_) + #include +#endif + + +namespace tthread { + +//------------------------------------------------------------------------------ +// condition_variable +//------------------------------------------------------------------------------ +// NOTE 1: The Win32 implementation of the condition_variable class is based on +// the corresponding implementation in GLFW, which in turn is based on a +// description by Douglas C. Schmidt and Irfan Pyarali: +// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html +// +// NOTE 2: Windows Vista actually has native support for condition variables +// (InitializeConditionVariable, WakeConditionVariable, etc), but we want to +// be portable with pre-Vista Windows versions, so TinyThread++ does not use +// Vista condition variables. +//------------------------------------------------------------------------------ + +#if defined(_TTHREAD_WIN32_) + #define _CONDITION_EVENT_ONE 0 + #define _CONDITION_EVENT_ALL 1 +#endif + +#if defined(_TTHREAD_WIN32_) +condition_variable::condition_variable() : mWaitersCount(0) +{ + mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL); + mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL); + InitializeCriticalSection(&mWaitersCountLock); +} +#endif + +#if defined(_TTHREAD_WIN32_) +condition_variable::~condition_variable() +{ + CloseHandle(mEvents[_CONDITION_EVENT_ONE]); + CloseHandle(mEvents[_CONDITION_EVENT_ALL]); + DeleteCriticalSection(&mWaitersCountLock); +} +#endif + +#if defined(_TTHREAD_WIN32_) +void condition_variable::_wait() +{ + // Wait for either event to become signaled due to notify_one() or + // notify_all() being called + int result = WaitForMultipleObjects(2, mEvents, FALSE, INFINITE); + + // Check if we are the last waiter + EnterCriticalSection(&mWaitersCountLock); + -- mWaitersCount; + bool lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) && + (mWaitersCount == 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we are the last waiter to be notified to stop waiting, reset the event + if(lastWaiter) + ResetEvent(mEvents[_CONDITION_EVENT_ALL]); +} +#endif + +#if defined(_TTHREAD_WIN32_) +void condition_variable::notify_one() +{ + // Are there any waiters? + EnterCriticalSection(&mWaitersCountLock); + bool haveWaiters = (mWaitersCount > 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we have any waiting threads, send them a signal + if(haveWaiters) + SetEvent(mEvents[_CONDITION_EVENT_ONE]); +} +#endif + +#if defined(_TTHREAD_WIN32_) +void condition_variable::notify_all() +{ + // Are there any waiters? + EnterCriticalSection(&mWaitersCountLock); + bool haveWaiters = (mWaitersCount > 0); + LeaveCriticalSection(&mWaitersCountLock); + + // If we have any waiting threads, send them a signal + if(haveWaiters) + SetEvent(mEvents[_CONDITION_EVENT_ALL]); +} +#endif + + +//------------------------------------------------------------------------------ +// POSIX pthread_t to unique thread::id mapping logic. +// Note: Here we use a global thread safe std::map to convert instances of +// pthread_t to small thread identifier numbers (unique within one process). +// This method should be portable across different POSIX implementations. +//------------------------------------------------------------------------------ + +#if defined(_TTHREAD_POSIX_) +static thread::id _pthread_t_to_ID(const pthread_t &aHandle) +{ + static mutex idMapLock; + static std::map idMap; + static unsigned long int idCount(1); + + lock_guard guard(idMapLock); + if(idMap.find(aHandle) == idMap.end()) + idMap[aHandle] = idCount ++; + return thread::id(idMap[aHandle]); +} +#endif // _TTHREAD_POSIX_ + + +//------------------------------------------------------------------------------ +// thread +//------------------------------------------------------------------------------ + +/// Information to pass to the new thread (what to run). +struct _thread_start_info { + void (*mFunction)(void *); ///< Pointer to the function to be executed. + void * mArg; ///< Function argument for the thread function. + thread * mThread; ///< Pointer to the thread object. +}; + +// Thread wrapper function. +#if defined(_TTHREAD_WIN32_) +unsigned WINAPI thread::wrapper_function(void * aArg) +#elif defined(_TTHREAD_POSIX_) +void * thread::wrapper_function(void * aArg) +#endif +{ + // Get thread startup information + _thread_start_info * ti = (_thread_start_info *) aArg; + + // Call the actual client thread function + ti->mFunction(ti->mArg); + + // The thread is no longer executing + lock_guard guard(ti->mThread->mDataMutex); + ti->mThread->mNotAThread = true; + + // The thread is responsible for freeing the startup information + delete ti; + + return 0; +} + +thread::thread(void (*aFunction)(void *), void * aArg) +{ + // Serialize access to this thread structure + lock_guard guard(mDataMutex); + + // Fill out the thread startup information (passed to the thread wrapper, + // which will eventually free it) + _thread_start_info * ti = new _thread_start_info; + ti->mFunction = aFunction; + ti->mArg = aArg; + ti->mThread = this; + + // The thread is now alive + mNotAThread = false; + + // Create the thread +#if defined(_TTHREAD_WIN32_) + mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID); +#elif defined(_TTHREAD_POSIX_) + if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0) + mHandle = 0; +#endif + + // Did we fail to create the thread? + if(!mHandle) + { + mNotAThread = true; + delete ti; + } +} + +thread::~thread() +{ + if(joinable()) + std::terminate(); +} + +void thread::join() +{ + if(joinable()) + { +#if defined(_TTHREAD_WIN32_) + WaitForSingleObject(mHandle, INFINITE); + CloseHandle(mHandle); +#elif defined(_TTHREAD_POSIX_) + pthread_join(mHandle, NULL); +#endif + } +} + +bool thread::joinable() const +{ + mDataMutex.lock(); + bool result = !mNotAThread; + mDataMutex.unlock(); + return result; +} + +void thread::detach() +{ + mDataMutex.lock(); + if(!mNotAThread) + { +#if defined(_TTHREAD_WIN32_) + CloseHandle(mHandle); +#elif defined(_TTHREAD_POSIX_) + pthread_detach(mHandle); +#endif + mNotAThread = true; + } + mDataMutex.unlock(); +} + +thread::id thread::get_id() const +{ + if(!joinable()) + return id(); +#if defined(_TTHREAD_WIN32_) + return id((unsigned long int) mWin32ThreadID); +#elif defined(_TTHREAD_POSIX_) + return _pthread_t_to_ID(mHandle); +#endif +} + +unsigned thread::hardware_concurrency() +{ +#if defined(_TTHREAD_WIN32_) + SYSTEM_INFO si; + GetSystemInfo(&si); + return (int) si.dwNumberOfProcessors; +#elif defined(_SC_NPROCESSORS_ONLN) + return (int) sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(_SC_NPROC_ONLN) + return (int) sysconf(_SC_NPROC_ONLN); +#else + // The standard requires this function to return zero if the number of + // hardware cores could not be determined. + return 0; +#endif +} + + +//------------------------------------------------------------------------------ +// this_thread +//------------------------------------------------------------------------------ + +thread::id this_thread::get_id() +{ +#if defined(_TTHREAD_WIN32_) + return thread::id((unsigned long int) GetCurrentThreadId()); +#elif defined(_TTHREAD_POSIX_) + return _pthread_t_to_ID(pthread_self()); +#endif +} + +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.h new file mode 100644 index 0000000..39bf41d --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/tinythread/tinythread.h @@ -0,0 +1,716 @@ +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- +Copyright (c) 2010-2012 Marcus Geelnard + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef _TINYTHREAD_H_ +#define _TINYTHREAD_H_ + +#include + +/// @file +/// @mainpage TinyThread++ API Reference +/// +/// @section intro_sec Introduction +/// TinyThread++ is a minimal, portable implementation of basic threading +/// classes for C++. +/// +/// They closely mimic the functionality and naming of the C++11 standard, and +/// should be easily replaceable with the corresponding std:: variants. +/// +/// @section port_sec Portability +/// The Win32 variant uses the native Win32 API for implementing the thread +/// classes, while for other systems, the POSIX threads API (pthread) is used. +/// +/// @section class_sec Classes +/// In order to mimic the threading API of the C++11 standard, subsets of +/// several classes are provided. The fundamental classes are: +/// @li tthread::thread +/// @li tthread::mutex +/// @li tthread::recursive_mutex +/// @li tthread::condition_variable +/// @li tthread::lock_guard +/// @li tthread::fast_mutex +/// +/// @section misc_sec Miscellaneous +/// The following special keywords are available: #thread_local. +/// +/// For more detailed information (including additional classes), browse the +/// different sections of this documentation. A good place to start is: +/// tinythread.h. + +// Which platform are we on? +#if !defined(_TTHREAD_PLATFORM_DEFINED_) + #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + #define _TTHREAD_WIN32_ + #else + #define _TTHREAD_POSIX_ + #endif + #define _TTHREAD_PLATFORM_DEFINED_ +#endif + +// Platform specific includes +#if defined(_TTHREAD_WIN32_) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #define __UNDEF_LEAN_AND_MEAN + #endif + #include + #ifdef __UNDEF_LEAN_AND_MEAN + #undef WIN32_LEAN_AND_MEAN + #undef __UNDEF_LEAN_AND_MEAN + #endif +#else + #include + #include + #include + #include +#endif + +// Generic includes +#include + +/// TinyThread++ version (major number). +#define TINYTHREAD_VERSION_MAJOR 1 +/// TinyThread++ version (minor number). +#define TINYTHREAD_VERSION_MINOR 1 +/// TinyThread++ version (full version). +#define TINYTHREAD_VERSION (TINYTHREAD_VERSION_MAJOR * 100 + TINYTHREAD_VERSION_MINOR) + +// Do we have a fully featured C++11 compiler? +#if (__cplusplus > 199711L) || (defined(__STDCXX_VERSION__) && (__STDCXX_VERSION__ >= 201001L)) + #define _TTHREAD_CPP11_ +#endif + +// ...at least partial C++11? +#if defined(_TTHREAD_CPP11_) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) + #define _TTHREAD_CPP11_PARTIAL_ +#endif + +// Macro for disabling assignments of objects. +#ifdef _TTHREAD_CPP11_PARTIAL_ + #define _TTHREAD_DISABLE_ASSIGNMENT(name) \ + name(const name&) = delete; \ + name& operator=(const name&) = delete; +#else + #define _TTHREAD_DISABLE_ASSIGNMENT(name) \ + name(const name&); \ + name& operator=(const name&); +#endif + +/// @def thread_local +/// Thread local storage keyword. +/// A variable that is declared with the @c thread_local keyword makes the +/// value of the variable local to each thread (known as thread-local storage, +/// or TLS). Example usage: +/// @code +/// // This variable is local to each thread. +/// thread_local int variable; +/// @endcode +/// @note The @c thread_local keyword is a macro that maps to the corresponding +/// compiler directive (e.g. @c __declspec(thread)). While the C++11 standard +/// allows for non-trivial types (e.g. classes with constructors and +/// destructors) to be declared with the @c thread_local keyword, most pre-C++11 +/// compilers only allow for trivial types (e.g. @c int). So, to guarantee +/// portable code, only use trivial types for thread local storage. +/// @note This directive is currently not supported on Mac OS X (it will give +/// a compiler error), since compile-time TLS is not supported in the Mac OS X +/// executable format. Also, some older versions of MinGW (before GCC 4.x) do +/// not support this directive. +/// @hideinitializer + +#if !defined(_TTHREAD_CPP11_) && !defined(thread_local) + #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__) + #define thread_local __thread + #else + #define thread_local __declspec(thread) + #endif +#endif + + +/// Main name space for TinyThread++. +/// This namespace is more or less equivalent to the @c std namespace for the +/// C++11 thread classes. For instance, the tthread::mutex class corresponds to +/// the std::mutex class. +namespace tthread { + +/// Mutex class. +/// This is a mutual exclusion object for synchronizing access to shared +/// memory areas for several threads. The mutex is non-recursive (i.e. a +/// program may deadlock if the thread that owns a mutex object calls lock() +/// on that object). +/// @see recursive_mutex +class mutex { + public: + /// Constructor. + mutex() +#if defined(_TTHREAD_WIN32_) + : mAlreadyLocked(false) +#endif + { +#if defined(_TTHREAD_WIN32_) + InitializeCriticalSection(&mHandle); +#else + pthread_mutex_init(&mHandle, NULL); +#endif + } + + /// Destructor. + ~mutex() + { +#if defined(_TTHREAD_WIN32_) + DeleteCriticalSection(&mHandle); +#else + pthread_mutex_destroy(&mHandle); +#endif + } + + /// Lock the mutex. + /// The method will block the calling thread until a lock on the mutex can + /// be obtained. The mutex remains locked until @c unlock() is called. + /// @see lock_guard + inline void lock() + { +#if defined(_TTHREAD_WIN32_) + EnterCriticalSection(&mHandle); + while(mAlreadyLocked) Sleep(1000); // Simulate deadlock... + mAlreadyLocked = true; +#else + pthread_mutex_lock(&mHandle); +#endif + } + + /// Try to lock the mutex. + /// The method will try to lock the mutex. If it fails, the function will + /// return immediately (non-blocking). + /// @return @c true if the lock was acquired, or @c false if the lock could + /// not be acquired. + inline bool try_lock() + { +#if defined(_TTHREAD_WIN32_) + bool ret = (TryEnterCriticalSection(&mHandle) ? true : false); + if(ret && mAlreadyLocked) + { + LeaveCriticalSection(&mHandle); + ret = false; + } + return ret; +#else + return (pthread_mutex_trylock(&mHandle) == 0) ? true : false; +#endif + } + + /// Unlock the mutex. + /// If any threads are waiting for the lock on this mutex, one of them will + /// be unblocked. + inline void unlock() + { +#if defined(_TTHREAD_WIN32_) + mAlreadyLocked = false; + LeaveCriticalSection(&mHandle); +#else + pthread_mutex_unlock(&mHandle); +#endif + } + + _TTHREAD_DISABLE_ASSIGNMENT(mutex) + + private: +#if defined(_TTHREAD_WIN32_) + CRITICAL_SECTION mHandle; + bool mAlreadyLocked; +#else + pthread_mutex_t mHandle; +#endif + + friend class condition_variable; +}; + +/// Recursive mutex class. +/// This is a mutual exclusion object for synchronizing access to shared +/// memory areas for several threads. The mutex is recursive (i.e. a thread +/// may lock the mutex several times, as long as it unlocks the mutex the same +/// number of times). +/// @see mutex +class recursive_mutex { + public: + /// Constructor. + recursive_mutex() + { +#if defined(_TTHREAD_WIN32_) + InitializeCriticalSection(&mHandle); +#else + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mHandle, &attr); +#endif + } + + /// Destructor. + ~recursive_mutex() + { +#if defined(_TTHREAD_WIN32_) + DeleteCriticalSection(&mHandle); +#else + pthread_mutex_destroy(&mHandle); +#endif + } + + /// Lock the mutex. + /// The method will block the calling thread until a lock on the mutex can + /// be obtained. The mutex remains locked until @c unlock() is called. + /// @see lock_guard + inline void lock() + { +#if defined(_TTHREAD_WIN32_) + EnterCriticalSection(&mHandle); +#else + pthread_mutex_lock(&mHandle); +#endif + } + + /// Try to lock the mutex. + /// The method will try to lock the mutex. If it fails, the function will + /// return immediately (non-blocking). + /// @return @c true if the lock was acquired, or @c false if the lock could + /// not be acquired. + inline bool try_lock() + { +#if defined(_TTHREAD_WIN32_) + return TryEnterCriticalSection(&mHandle) ? true : false; +#else + return (pthread_mutex_trylock(&mHandle) == 0) ? true : false; +#endif + } + + /// Unlock the mutex. + /// If any threads are waiting for the lock on this mutex, one of them will + /// be unblocked. + inline void unlock() + { +#if defined(_TTHREAD_WIN32_) + LeaveCriticalSection(&mHandle); +#else + pthread_mutex_unlock(&mHandle); +#endif + } + + _TTHREAD_DISABLE_ASSIGNMENT(recursive_mutex) + + private: +#if defined(_TTHREAD_WIN32_) + CRITICAL_SECTION mHandle; +#else + pthread_mutex_t mHandle; +#endif + + friend class condition_variable; +}; + +/// Lock guard class. +/// The constructor locks the mutex, and the destructor unlocks the mutex, so +/// the mutex will automatically be unlocked when the lock guard goes out of +/// scope. Example usage: +/// @code +/// mutex m; +/// int counter; +/// +/// void increment() +/// { +/// lock_guard guard(m); +/// ++ counter; +/// } +/// @endcode + +template +class lock_guard { + public: + typedef T mutex_type; + + lock_guard() : mMutex(0) {} + + /// The constructor locks the mutex. + explicit lock_guard(mutex_type &aMutex) + { + mMutex = &aMutex; + mMutex->lock(); + } + + /// The destructor unlocks the mutex. + ~lock_guard() + { + if(mMutex) + mMutex->unlock(); + } + + private: + mutex_type * mMutex; +}; + +/// Condition variable class. +/// This is a signalling object for synchronizing the execution flow for +/// several threads. Example usage: +/// @code +/// // Shared data and associated mutex and condition variable objects +/// int count; +/// mutex m; +/// condition_variable cond; +/// +/// // Wait for the counter to reach a certain number +/// void wait_counter(int targetCount) +/// { +/// lock_guard guard(m); +/// while(count < targetCount) +/// cond.wait(m); +/// } +/// +/// // Increment the counter, and notify waiting threads +/// void increment() +/// { +/// lock_guard guard(m); +/// ++ count; +/// cond.notify_all(); +/// } +/// @endcode +class condition_variable { + public: + /// Constructor. +#if defined(_TTHREAD_WIN32_) + condition_variable(); +#else + condition_variable() + { + pthread_cond_init(&mHandle, NULL); + } +#endif + + /// Destructor. +#if defined(_TTHREAD_WIN32_) + ~condition_variable(); +#else + ~condition_variable() + { + pthread_cond_destroy(&mHandle); + } +#endif + + /// Wait for the condition. + /// The function will block the calling thread until the condition variable + /// is woken by @c notify_one(), @c notify_all() or a spurious wake up. + /// @param[in] aMutex A mutex that will be unlocked when the wait operation + /// starts, an locked again as soon as the wait operation is finished. + template + inline void wait(_mutexT &aMutex) + { +#if defined(_TTHREAD_WIN32_) + // Increment number of waiters + EnterCriticalSection(&mWaitersCountLock); + ++ mWaitersCount; + LeaveCriticalSection(&mWaitersCountLock); + + // Release the mutex while waiting for the condition (will decrease + // the number of waiters when done)... + aMutex.unlock(); + _wait(); + aMutex.lock(); +#else + pthread_cond_wait(&mHandle, &aMutex.mHandle); +#endif + } + + /// Notify one thread that is waiting for the condition. + /// If at least one thread is blocked waiting for this condition variable, + /// one will be woken up. + /// @note Only threads that started waiting prior to this call will be + /// woken up. +#if defined(_TTHREAD_WIN32_) + void notify_one(); +#else + inline void notify_one() + { + pthread_cond_signal(&mHandle); + } +#endif + + /// Notify all threads that are waiting for the condition. + /// All threads that are blocked waiting for this condition variable will + /// be woken up. + /// @note Only threads that started waiting prior to this call will be + /// woken up. +#if defined(_TTHREAD_WIN32_) + void notify_all(); +#else + inline void notify_all() + { + pthread_cond_broadcast(&mHandle); + } +#endif + + _TTHREAD_DISABLE_ASSIGNMENT(condition_variable) + + private: +#if defined(_TTHREAD_WIN32_) + void _wait(); + HANDLE mEvents[2]; ///< Signal and broadcast event HANDLEs. + unsigned int mWaitersCount; ///< Count of the number of waiters. + CRITICAL_SECTION mWaitersCountLock; ///< Serialize access to mWaitersCount. +#else + pthread_cond_t mHandle; +#endif +}; + + +/// Thread class. +class thread { + public: +#if defined(_TTHREAD_WIN32_) + typedef HANDLE native_handle_type; +#else + typedef pthread_t native_handle_type; +#endif + + class id; + + /// Default constructor. + /// Construct a @c thread object without an associated thread of execution + /// (i.e. non-joinable). + thread() : mHandle(0), mNotAThread(true) +#if defined(_TTHREAD_WIN32_) + , mWin32ThreadID(0) +#endif + {} + + /// Thread starting constructor. + /// Construct a @c thread object with a new thread of execution. + /// @param[in] aFunction A function pointer to a function of type: + /// void fun(void * arg) + /// @param[in] aArg Argument to the thread function. + /// @note This constructor is not fully compatible with the standard C++ + /// thread class. It is more similar to the pthread_create() (POSIX) and + /// CreateThread() (Windows) functions. + thread(void (*aFunction)(void *), void * aArg); + + /// Destructor. + /// @note If the thread is joinable upon destruction, @c std::terminate() + /// will be called, which terminates the process. It is always wise to do + /// @c join() before deleting a thread object. + ~thread(); + + /// Wait for the thread to finish (join execution flows). + /// After calling @c join(), the thread object is no longer associated with + /// a thread of execution (i.e. it is not joinable, and you may not join + /// with it nor detach from it). + void join(); + + /// Check if the thread is joinable. + /// A thread object is joinable if it has an associated thread of execution. + bool joinable() const; + + /// Detach from the thread. + /// After calling @c detach(), the thread object is no longer assicated with + /// a thread of execution (i.e. it is not joinable). The thread continues + /// execution without the calling thread blocking, and when the thread + /// ends execution, any owned resources are released. + void detach(); + + /// Return the thread ID of a thread object. + id get_id() const; + + /// Get the native handle for this thread. + /// @note Under Windows, this is a @c HANDLE, and under POSIX systems, this + /// is a @c pthread_t. + inline native_handle_type native_handle() + { + return mHandle; + } + + /// Determine the number of threads which can possibly execute concurrently. + /// This function is useful for determining the optimal number of threads to + /// use for a task. + /// @return The number of hardware thread contexts in the system. + /// @note If this value is not defined, the function returns zero (0). + static unsigned hardware_concurrency(); + + _TTHREAD_DISABLE_ASSIGNMENT(thread) + + private: + native_handle_type mHandle; ///< Thread handle. + mutable mutex mDataMutex; ///< Serializer for access to the thread private data. + bool mNotAThread; ///< True if this object is not a thread of execution. +#if defined(_TTHREAD_WIN32_) + unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex). +#endif + + // This is the internal thread wrapper function. +#if defined(_TTHREAD_WIN32_) + static unsigned WINAPI wrapper_function(void * aArg); +#else + static void * wrapper_function(void * aArg); +#endif +}; + +/// Thread ID. +/// The thread ID is a unique identifier for each thread. +/// @see thread::get_id() +class thread::id { + public: + /// Default constructor. + /// The default constructed ID is that of thread without a thread of + /// execution. + id() : mId(0) {}; + + id(unsigned long int aId) : mId(aId) {}; + + id(const id& aId) : mId(aId.mId) {}; + + inline id & operator=(const id &aId) + { + mId = aId.mId; + return *this; + } + + inline friend bool operator==(const id &aId1, const id &aId2) + { + return (aId1.mId == aId2.mId); + } + + inline friend bool operator!=(const id &aId1, const id &aId2) + { + return (aId1.mId != aId2.mId); + } + + inline friend bool operator<=(const id &aId1, const id &aId2) + { + return (aId1.mId <= aId2.mId); + } + + inline friend bool operator<(const id &aId1, const id &aId2) + { + return (aId1.mId < aId2.mId); + } + + inline friend bool operator>=(const id &aId1, const id &aId2) + { + return (aId1.mId >= aId2.mId); + } + + inline friend bool operator>(const id &aId1, const id &aId2) + { + return (aId1.mId > aId2.mId); + } + + inline friend std::ostream& operator <<(std::ostream &os, const id &obj) + { + os << obj.mId; + return os; + } + + private: + unsigned long int mId; +}; + + +// Related to - minimal to be able to support chrono. +typedef long long __intmax_t; + +/// Minimal implementation of the @c ratio class. This class provides enough +/// functionality to implement some basic @c chrono classes. +template <__intmax_t N, __intmax_t D = 1> class ratio { + public: + static double _as_double() { return double(N) / double(D); } +}; + +/// Minimal implementation of the @c chrono namespace. +/// The @c chrono namespace provides types for specifying time intervals. +namespace chrono { + /// Duration template class. This class provides enough functionality to + /// implement @c this_thread::sleep_for(). + template > class duration { + private: + _Rep rep_; + public: + typedef _Rep rep; + typedef _Period period; + + /// Construct a duration object with the given duration. + template + explicit duration(const _Rep2& r) : rep_(r) {}; + + /// Return the value of the duration object. + rep count() const + { + return rep_; + } + }; + + // Standard duration types. + typedef duration<__intmax_t, ratio<1, 1000000000> > nanoseconds; ///< Duration with the unit nanoseconds. + typedef duration<__intmax_t, ratio<1, 1000000> > microseconds; ///< Duration with the unit microseconds. + typedef duration<__intmax_t, ratio<1, 1000> > milliseconds; ///< Duration with the unit milliseconds. + typedef duration<__intmax_t> seconds; ///< Duration with the unit seconds. + typedef duration<__intmax_t, ratio<60> > minutes; ///< Duration with the unit minutes. + typedef duration<__intmax_t, ratio<3600> > hours; ///< Duration with the unit hours. +} + +/// The namespace @c this_thread provides methods for dealing with the +/// calling thread. +namespace this_thread { + /// Return the thread ID of the calling thread. + thread::id get_id(); + + /// Yield execution to another thread. + /// Offers the operating system the opportunity to schedule another thread + /// that is ready to run on the current processor. + inline void yield() + { +#if defined(_TTHREAD_WIN32_) + Sleep(0); +#else + sched_yield(); +#endif + } + + /// Blocks the calling thread for a period of time. + /// @param[in] aTime Minimum time to put the thread to sleep. + /// Example usage: + /// @code + /// // Sleep for 100 milliseconds + /// this_thread::sleep_for(chrono::milliseconds(100)); + /// @endcode + /// @note Supported duration types are: nanoseconds, microseconds, + /// milliseconds, seconds, minutes and hours. + template void sleep_for(const chrono::duration<_Rep, _Period>& aTime) + { +#if defined(_TTHREAD_WIN32_) + Sleep(int(double(aTime.count()) * (1000.0 * _Period::_as_double()) + 0.5)); +#else + usleep(int(double(aTime.count()) * (1000000.0 * _Period::_as_double()) + 0.5)); +#endif + } +} + +} + +// Define/macro cleanup +#undef _TTHREAD_DISABLE_ASSIGNMENT + +#endif // _TINYTHREAD_H_ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/transfer_pool.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/transfer_pool.cpp new file mode 100644 index 0000000..6c644b3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/transfer_pool.cpp @@ -0,0 +1,289 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file transfer_pool.cpp Data transfer implementation. */ + +#include +#include + +#define WRITE_LIBUSB_ERROR(__RESULT) libusb_error_name(__RESULT) << " " << libusb_strerror((libusb_error)__RESULT) + +namespace libfreenect2 +{ +namespace usb +{ + +TransferPool::TransferPool(libusb_device_handle* device_handle, unsigned char device_endpoint) : + callback_(0), + device_handle_(device_handle), + device_endpoint_(device_endpoint), + buffer_(0), + buffer_size_(0), + enable_submit_(false) +{ +} + +TransferPool::~TransferPool() +{ + deallocate(); +} + +void TransferPool::enableSubmission() +{ + enable_submit_ = true; +} + +void TransferPool::disableSubmission() +{ + enable_submit_ = false; +} + +bool TransferPool::enabled() +{ + return enable_submit_; +} + +void TransferPool::deallocate() +{ + for(TransferQueue::iterator it = transfers_.begin(); it != transfers_.end(); ++it) + { + libusb_free_transfer(it->transfer); + } + transfers_.clear(); + + if(buffer_ != 0) + { + delete[] buffer_; + buffer_ = 0; + buffer_size_ = 0; + } +} + +bool TransferPool::submit() +{ + if(!enable_submit_) + { + LOG_WARNING << "transfer submission disabled!"; + return false; + } + + size_t failcount = 0; + for(size_t i = 0; i < transfers_.size(); ++i) + { + libusb_transfer *transfer = transfers_[i].transfer; + transfers_[i].setStopped(false); + + int r = libusb_submit_transfer(transfer); + + if(r != LIBUSB_SUCCESS) + { + LOG_ERROR << "failed to submit transfer: " << WRITE_LIBUSB_ERROR(r); + transfers_[i].setStopped(true); + failcount++; + } + } + + if (failcount == transfers_.size()) + { + LOG_ERROR << "all submissions failed. Try debugging with environment variable: LIBUSB_DEBUG=3."; + return false; + } + + return true; +} + +void TransferPool::cancel() +{ + for(TransferQueue::iterator it = transfers_.begin(); it != transfers_.end(); ++it) + { + int r = libusb_cancel_transfer(it->transfer); + + if(r != LIBUSB_SUCCESS && r != LIBUSB_ERROR_NOT_FOUND) + { + LOG_ERROR << "failed to cancel transfer: " << WRITE_LIBUSB_ERROR(r); + } + } + + for(;;) + { + libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(100)); + size_t stopped_transfers = 0; + for(TransferQueue::iterator it = transfers_.begin(); it != transfers_.end(); ++it) + stopped_transfers += it->getStopped(); + if (stopped_transfers == transfers_.size()) + break; + LOG_INFO << "waiting for transfer cancellation"; + libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(1000)); + } +} + +void TransferPool::setCallback(DataCallback *callback) +{ + callback_ = callback; +} + +void TransferPool::allocateTransfers(size_t num_transfers, size_t transfer_size) +{ + buffer_size_ = num_transfers * transfer_size; + buffer_ = new unsigned char[buffer_size_]; + transfers_.reserve(num_transfers); + + unsigned char *ptr = buffer_; + + for(size_t i = 0; i < num_transfers; ++i) + { + libusb_transfer *transfer = allocateTransfer(); + fillTransfer(transfer); + + transfers_.push_back(TransferPool::Transfer(transfer, this)); + + transfer->dev_handle = device_handle_; + transfer->endpoint = device_endpoint_; + transfer->buffer = ptr; + transfer->length = transfer_size; + transfer->timeout = 1000; + transfer->callback = (libusb_transfer_cb_fn) &TransferPool::onTransferCompleteStatic; + transfer->user_data = &transfers_.back(); + + ptr += transfer_size; + } +} + +void TransferPool::onTransferCompleteStatic(libusb_transfer* transfer) +{ + TransferPool::Transfer *t = reinterpret_cast(transfer->user_data); + t->pool->onTransferComplete(t); +} + +void TransferPool::onTransferComplete(TransferPool::Transfer* t) +{ + if(t->transfer->status == LIBUSB_TRANSFER_CANCELLED) + { + t->setStopped(true); + return; + } + + // process data + processTransfer(t->transfer); + + if(!enable_submit_) + { + t->setStopped(true); + return; + } + + // resubmit self + int r = libusb_submit_transfer(t->transfer); + + if(r != LIBUSB_SUCCESS) + { + LOG_ERROR << "failed to submit transfer: " << WRITE_LIBUSB_ERROR(r); + t->setStopped(true); + } +} + +BulkTransferPool::BulkTransferPool(libusb_device_handle* device_handle, unsigned char device_endpoint) : + TransferPool(device_handle, device_endpoint) +{ +} + +BulkTransferPool::~BulkTransferPool() +{ +} + +void BulkTransferPool::allocate(size_t num_transfers, size_t transfer_size) +{ + allocateTransfers(num_transfers, transfer_size); +} + +libusb_transfer* BulkTransferPool::allocateTransfer() +{ + return libusb_alloc_transfer(0); +} + +void BulkTransferPool::fillTransfer(libusb_transfer* transfer) +{ + transfer->type = LIBUSB_TRANSFER_TYPE_BULK; +} + +void BulkTransferPool::processTransfer(libusb_transfer* transfer) +{ + if(transfer->status != LIBUSB_TRANSFER_COMPLETED) return; + + if(callback_) + callback_->onDataReceived(transfer->buffer, transfer->actual_length); +} + +IsoTransferPool::IsoTransferPool(libusb_device_handle* device_handle, unsigned char device_endpoint) : + TransferPool(device_handle, device_endpoint), + num_packets_(0), + packet_size_(0) +{ +} + +IsoTransferPool::~IsoTransferPool() +{ +} + +void IsoTransferPool::allocate(size_t num_transfers, size_t num_packets, size_t packet_size) +{ + num_packets_ = num_packets; + packet_size_ = packet_size; + + allocateTransfers(num_transfers, num_packets_ * packet_size_); +} + +libusb_transfer* IsoTransferPool::allocateTransfer() +{ + return libusb_alloc_transfer(num_packets_); +} + +void IsoTransferPool::fillTransfer(libusb_transfer* transfer) +{ + transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; + transfer->num_iso_packets = num_packets_; + + libusb_set_iso_packet_lengths(transfer, packet_size_); +} + +void IsoTransferPool::processTransfer(libusb_transfer* transfer) +{ + unsigned char *ptr = transfer->buffer; + + for(size_t i = 0; i < num_packets_; ++i) + { + if(transfer->iso_packet_desc[i].status != LIBUSB_TRANSFER_COMPLETED) continue; + + if(callback_) + callback_->onDataReceived(ptr, transfer->iso_packet_desc[i].actual_length); + + ptr += transfer->iso_packet_desc[i].length; + } +} + +} /* namespace usb */ +} /* namespace libfreenect2 */ + diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/turbo_jpeg_rgb_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/turbo_jpeg_rgb_packet_processor.cpp new file mode 100644 index 0000000..5fdb615 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/turbo_jpeg_rgb_packet_processor.cpp @@ -0,0 +1,117 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file turbo_jpeg_rgb_packet_processor.cpp JPEG decoder with Turbo Jpeg. */ + +#include +#include +#include + +namespace libfreenect2 +{ + +/** Implementation of the Turbo-Jpeg decoder processor. */ +class TurboJpegRgbPacketProcessorImpl: public WithPerfLogging +{ +public: + + tjhandle decompressor; + + Frame *frame; + + TurboJpegRgbPacketProcessorImpl() + { + decompressor = tjInitDecompress(); + if(decompressor == 0) + { + LOG_ERROR << "Failed to initialize TurboJPEG decompressor! TurboJPEG error: '" << tjGetErrorStr() << "'"; + } + + newFrame(); + } + + ~TurboJpegRgbPacketProcessorImpl() + { + delete frame; + + if(decompressor != 0) + { + if(tjDestroy(decompressor) == -1) + { + LOG_ERROR << "Failed to destroy TurboJPEG decompressor! TurboJPEG error: '" << tjGetErrorStr() << "'"; + } + } + } + + void newFrame() + { + frame = new Frame(1920, 1080, tjPixelSize[TJPF_BGRX]); + frame->format = Frame::BGRX; + } +}; + +TurboJpegRgbPacketProcessor::TurboJpegRgbPacketProcessor() : + impl_(new TurboJpegRgbPacketProcessorImpl()) +{ +} + +TurboJpegRgbPacketProcessor::~TurboJpegRgbPacketProcessor() +{ + delete impl_; +} + +void TurboJpegRgbPacketProcessor::process(const RgbPacket &packet) +{ + if(impl_->decompressor != 0 && listener_ != 0) + { + impl_->startTiming(); + + impl_->frame->timestamp = packet.timestamp; + impl_->frame->sequence = packet.sequence; + impl_->frame->exposure = packet.exposure; + impl_->frame->gain = packet.gain; + impl_->frame->gamma = packet.gamma; + + int r = tjDecompress2(impl_->decompressor, packet.jpeg_buffer, packet.jpeg_buffer_length, impl_->frame->data, 1920, 1920 * tjPixelSize[TJPF_BGRX], 1080, TJPF_BGRX, 0); + + impl_->stopTiming(LOG_INFO); + + if(r == 0) + { + if(listener_->onNewFrame(Frame::Color, impl_->frame)) + { + impl_->newFrame(); + } + } + else + { + LOG_ERROR << "Failed to decompress rgb image! TurboJPEG error: '" << tjGetErrorStr() << "'"; + } + + } +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/usb_control.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/usb_control.cpp new file mode 100644 index 0000000..bbda5bf --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/usb_control.cpp @@ -0,0 +1,325 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2011 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file usb_control.cpp USB control using libusb. */ + +#include +#include + +#include + +namespace libfreenect2 +{ +namespace protocol +{ + +namespace libusb_ext +{ + enum DeviceFeatureSelector + { + U1_ENABLE = 48, + U2_ENABLE = 49 + }; + + enum InterfaceFeatureSelector + { + FUNCTION_SUSPEND = 0, + }; + + template + struct FeatureSelectorRecipient + { + static uint8_t get(); + }; + + template<> + struct FeatureSelectorRecipient + { + static uint8_t get() { return LIBUSB_RECIPIENT_DEVICE; }; + }; + + template<> + struct FeatureSelectorRecipient + { + static uint8_t get() { return LIBUSB_RECIPIENT_INTERFACE; }; + }; + + int set_isochronous_delay(libusb_device_handle *handle, int timeout) + { + // for details see USB 3.1 r1 spec section 9.4.11 + + uint8_t bmRequestType = LIBUSB_RECIPIENT_DEVICE; + uint8_t bRequest = LIBUSB_SET_ISOCH_DELAY; + // if no super speed hubs in between, then it is equal to tTPTransmissionDelay(=40ns) + uint16_t wValue = 40; // 40 nanoseconds + uint16_t wIndex = 0; + uint16_t wLength = 0; + uint8_t *data = 0; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + int set_sel(libusb_device_handle *handle, int timeout, uint8_t u1sel, uint8_t u1pel, uint8_t u2sel, uint8_t u2pel) + { + // for details see USB 3.1 r1 spec section 9.4.12 + + uint8_t bmRequestType = LIBUSB_RECIPIENT_DEVICE; + uint8_t bRequest = LIBUSB_REQUEST_SET_SEL; + uint16_t wValue = 0; + uint16_t wIndex = 0; + uint16_t wLength = 6; + unsigned char data[6] = { 0x55, 0, 0x55, 0, 0, 0 }; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + template + int set_feature(libusb_device_handle *handle, int timeout, TFeatureSelector feature_selector) + { + // for details see USB 3.1 r1 spec section 9.4.9 + + uint8_t bmRequestType = FeatureSelectorRecipient::get(); + uint8_t bRequest = LIBUSB_REQUEST_SET_FEATURE; + uint16_t wValue = static_cast(feature_selector); + uint16_t wIndex = 0; + uint16_t wLength = 0; + uint8_t *data = 0; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + int set_feature_function_suspend(libusb_device_handle *handle, int timeout, bool low_power_suspend, bool function_remote_wake) + { + uint8_t suspend_options = 0; + suspend_options |= low_power_suspend ? 1 : 0; + suspend_options |= function_remote_wake ? 2 : 0; + + // for details see USB 3.1 r1 spec section 9.4.9 + + InterfaceFeatureSelector feature_selector = FUNCTION_SUSPEND; + uint8_t bmRequestType = FeatureSelectorRecipient::get(); + uint8_t bRequest = LIBUSB_REQUEST_SET_FEATURE; + uint16_t wValue = static_cast(feature_selector); + uint16_t wIndex = suspend_options << 8 | 0; + uint16_t wLength = 0; + uint8_t *data = 0; + + return libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + } + + int get_max_iso_packet_size(libusb_device *device, int configuration, int alternate_setting, int endpoint) + { + libusb_config_descriptor *config_desc; + int r = LIBUSB_ERROR_NOT_FOUND; + + r = libusb_get_config_descriptor_by_value(device, configuration, &config_desc); + + if(r == LIBUSB_SUCCESS) + { + for(int interface_idx = 0; interface_idx < config_desc->bNumInterfaces; ++interface_idx) + { + const libusb_interface &interface = config_desc->interface[interface_idx]; + + if(interface.num_altsetting > alternate_setting) + { + const libusb_interface_descriptor &interface_desc = interface.altsetting[alternate_setting]; + const libusb_endpoint_descriptor *endpoint_desc = 0; + + for(int endpoint_idx = 0; endpoint_idx < interface_desc.bNumEndpoints; ++endpoint_idx) + { + if(interface_desc.endpoint[endpoint_idx].bEndpointAddress == endpoint && (interface_desc.endpoint[endpoint_idx].bmAttributes & 0x3) == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) + { + endpoint_desc = interface_desc.endpoint + endpoint_idx; + break; + } + } + + if(endpoint_desc != 0) + { + libusb_ss_endpoint_companion_descriptor *companion_desc; + // ctx is only used for error reporting, libusb should better ask for a libusb_device anyway... + r = libusb_get_ss_endpoint_companion_descriptor(NULL /* ctx */, endpoint_desc, &companion_desc); + + if(r != LIBUSB_SUCCESS) continue; + + r = companion_desc->wBytesPerInterval; + + libusb_free_ss_endpoint_companion_descriptor(companion_desc); + break; + } + } + } + } + libusb_free_config_descriptor(config_desc); + + return r; + } +} + +UsbControl::UsbControl(libusb_device_handle *handle) : + handle_(handle), + timeout_(1000) +{ +} + +UsbControl::~UsbControl() +{ +} + +#define CHECK_LIBUSB_RESULT(__CODE, __RESULT) if((__CODE = (__RESULT == LIBUSB_SUCCESS ? Success : Error)) == Error) LOG_ERROR +#define WRITE_LIBUSB_ERROR(__RESULT) libusb_error_name(__RESULT) << " " << libusb_strerror((libusb_error)__RESULT) << ". Try debugging with environment variable: export LIBUSB_DEBUG=3 ." + +UsbControl::ResultCode UsbControl::setConfiguration() +{ + UsbControl::ResultCode code = Success; + int desired_config_id = 1; + int current_config_id = -1; + int r; + + r = libusb_get_configuration(handle_, ¤t_config_id); + CHECK_LIBUSB_RESULT(code, r) << "failed to get configuration! " << WRITE_LIBUSB_ERROR(r); + + if(code == Success) + { + if(current_config_id != desired_config_id) + { + r = libusb_set_configuration(handle_, desired_config_id); + CHECK_LIBUSB_RESULT(code, r) << "failed to set configuration! " << WRITE_LIBUSB_ERROR(r); + } + } + + return code; +} + +UsbControl::ResultCode UsbControl::claimInterfaces() +{ + UsbControl::ResultCode code = Success; + int r; + + r = libusb_claim_interface(handle_, ControlAndRgbInterfaceId); + CHECK_LIBUSB_RESULT(code, r) << "failed to claim interface with ControlAndRgbInterfaceId(="<< ControlAndRgbInterfaceId << ")! " << WRITE_LIBUSB_ERROR(r); + + if(code == Success) + { + r = libusb_claim_interface(handle_, IrInterfaceId); + CHECK_LIBUSB_RESULT(code, r) << "failed to claim interface with IrInterfaceId(="<< IrInterfaceId << ")! " << WRITE_LIBUSB_ERROR(r); + } + + return code; +} + +UsbControl::ResultCode UsbControl::releaseInterfaces() +{ + UsbControl::ResultCode code = Success; + int r; + + r = libusb_release_interface(handle_, ControlAndRgbInterfaceId); + CHECK_LIBUSB_RESULT(code, r) << "failed to release interface with ControlAndRgbInterfaceId(="<< ControlAndRgbInterfaceId << ")! " << WRITE_LIBUSB_ERROR(r); + + if(code == Success) + { + r = libusb_release_interface(handle_, IrInterfaceId); + CHECK_LIBUSB_RESULT(code, r) << "failed to release interface with IrInterfaceId(="<< IrInterfaceId << ")! " << WRITE_LIBUSB_ERROR(r); + } + + return code; +} + +UsbControl::ResultCode UsbControl::setIsochronousDelay() +{ + int r = libusb_ext::set_isochronous_delay(handle_, timeout_); + + UsbControl::ResultCode code; + CHECK_LIBUSB_RESULT(code, r) << "failed to set isochronous delay! " << WRITE_LIBUSB_ERROR(r); + return code; +} + +UsbControl::ResultCode UsbControl::setPowerStateLatencies() +{ + int r = libusb_ext::set_sel(handle_, timeout_, 0x55, 0, 0x55, 0); + + UsbControl::ResultCode code; + CHECK_LIBUSB_RESULT(code, r) << "failed to set power state latencies! " << WRITE_LIBUSB_ERROR(r); + return code; +} + +UsbControl::ResultCode UsbControl::enablePowerStates() +{ + UsbControl::ResultCode code; + int r; + + r = libusb_ext::set_feature(handle_, timeout_, libusb_ext::U1_ENABLE); + CHECK_LIBUSB_RESULT(code, r) << "failed to enable power states U1! " << WRITE_LIBUSB_ERROR(r); + + if(code == Success) + { + r = libusb_ext::set_feature(handle_, timeout_, libusb_ext::U2_ENABLE); + CHECK_LIBUSB_RESULT(code, r) << "failed to enable power states U2! " << WRITE_LIBUSB_ERROR(r); + } + + return code; +} + +UsbControl::ResultCode UsbControl::setVideoTransferFunctionState(UsbControl::State state) +{ + bool suspend = state == Enabled ? false : true; + int r = libusb_ext::set_feature_function_suspend(handle_, timeout_, suspend, suspend); + + UsbControl::ResultCode code; + CHECK_LIBUSB_RESULT(code, r) << "failed to set video transfer function state! " << WRITE_LIBUSB_ERROR(r); + return code; +} + +UsbControl::ResultCode UsbControl::setIrInterfaceState(UsbControl::State state) +{ + int alternate_setting = state == Enabled ? 1 : 0; + int r = libusb_set_interface_alt_setting(handle_, IrInterfaceId, alternate_setting); + + UsbControl::ResultCode code; + CHECK_LIBUSB_RESULT(code, r) << "failed to set ir interface state! " << WRITE_LIBUSB_ERROR(r); + return code; +} + + +UsbControl::ResultCode UsbControl::getIrMaxIsoPacketSize(int &size) +{ + size = 0; + libusb_device *dev = libusb_get_device(handle_); + int r = libusb_ext::get_max_iso_packet_size(dev, 1, 1, 0x84); + + if(r > LIBUSB_SUCCESS) + { + size = r; + r = LIBUSB_SUCCESS; + } + + UsbControl::ResultCode code; + CHECK_LIBUSB_RESULT(code, r) << "failed to get max iso packet size! " << WRITE_LIBUSB_ERROR(r); + return code; +} + +} /* namespace protocol */ +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vaapi_rgb_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vaapi_rgb_packet_processor.cpp new file mode 100644 index 0000000..255cbb8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vaapi_rgb_packet_processor.cpp @@ -0,0 +1,493 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include + +#include +#include //jpeglib.h does not include stdio.h +#include +#include +#include +#include +#include +#include "libfreenect2/logging.h" +#include "libfreenect2/allocator.h" + +#define CHECK_COND(cond) do { if (!(cond)) { LOG_ERROR << #cond " failed"; return false; } } while(0) +#define CHECK_VA(expr) do { VAStatus err = (expr); if (err != VA_STATUS_SUCCESS) { LOG_ERROR << #expr ": " << vaErrorStr(err); return false; } } while(0) +#define CALL_VA(expr) do { VAStatus err = (expr); if (err != VA_STATUS_SUCCESS) { LOG_ERROR << #expr ": " << vaErrorStr(err); } } while(0) + +namespace libfreenect2 +{ + +class VaapiImage: public Buffer +{ +public: + VAImage image; +}; + +class VaapiImageAllocator: public Allocator +{ +public: + VADisplay display; + unsigned short width; + unsigned short height; + VAImageFormat format; + Allocator *pool; + + VaapiImageAllocator(VADisplay display, unsigned short width, unsigned short height, const VAImageFormat &format): + display(display), width(width), height(height), format(format) + { + } + + virtual Buffer *allocate(size_t size) + { + VaapiImage *vi = new VaapiImage(); + vi->allocator = this; + CALL_VA(vaCreateImage(display, &format, width, height, &vi->image)); + return vi; + } + + virtual void free(Buffer *b) + { + if (b == NULL) + return; + VaapiImage *vi = static_cast(b); + if (vi->data) { + CALL_VA(vaUnmapBuffer(display, vi->image.buf)); + vi->data = NULL; + } + CALL_VA(vaDestroyImage(display, vi->image.image_id)); + delete vi; + } +}; + +class VaapiFrame: public Frame +{ +public: + VaapiFrame(VaapiImage *vi): + Frame(vi->image.width, vi->image.height, vi->image.format.bits_per_pixel/8, (unsigned char*)-1) + { + data = NULL; + rawdata = reinterpret_cast(vi); + } + + virtual ~VaapiFrame() + { + VaapiImage *vi = reinterpret_cast(rawdata); + vi->allocator->free(vi); + rawdata = NULL; + } + + bool draw(VADisplay display, VASurfaceID surface) + { + VaapiImage *vi = reinterpret_cast(rawdata); + VAImage &image = vi->image; + data = NULL; + if (vi->data != NULL) { + vi->data = NULL; + CHECK_VA(vaUnmapBuffer(display, image.buf)); + } + CHECK_VA(vaGetImage(display, surface, 0, 0, image.width, image.height, image.image_id)); + CHECK_VA(vaMapBuffer(display, image.buf, (void**)&vi->data)); + data = vi->data; + return true; + } +}; + +class VaapiBuffer: public Buffer +{ +public: + VABufferID id; + + VaapiBuffer(): Buffer(), id(VA_INVALID_ID) {} +}; + +class VaapiAllocator: public Allocator +{ +private: + VADisplay display; + VAContextID context; + + bool allocate_va(VaapiBuffer *b, size_t size) + { + CHECK_VA(vaCreateBuffer(display, context, VASliceDataBufferType, size, 1, NULL, &b->id)); + CHECK_VA(vaMapBuffer(display, b->id, (void**)&b->data)); + b->capacity = size; + return true; + } + +public: + VaapiAllocator(VADisplay display, VAContextID context): + display(display), context(context) {} + + virtual Buffer *allocate(size_t size) + { + VaapiBuffer *vb = new VaapiBuffer(); + if (!allocate_va(vb, size)) + vb->data = NULL; + return vb; + } + + virtual void free(Buffer *b) + { + if (b == NULL) + return; + VaapiBuffer *vb = static_cast(b); + if (vb->data) { + CALL_VA(vaUnmapBuffer(display, vb->id)); + CALL_VA(vaDestroyBuffer(display, vb->id)); + } + delete vb; + } +}; + +class VaapiRgbPacketProcessorImpl: public WithPerfLogging +{ +public: + int drm_fd; + VADisplay display; + VAConfigID config; + VASurfaceID surface; + VAContextID context; + + VABufferID pic_param_buf; + VABufferID iq_buf; + VABufferID huff_buf; + VABufferID slice_param_buf; + + bool jpeg_first_packet; + size_t jpeg_header_size; + + struct jpeg_decompress_struct dinfo; + struct jpeg_error_mgr jerr; + + bool good; + + static const int WIDTH = 1920; + static const int HEIGHT = 1080; + + VaapiFrame *frame; + + Allocator *buffer_allocator; + Allocator *image_allocator; + + VaapiRgbPacketProcessorImpl(): + frame(NULL), + buffer_allocator(NULL), + image_allocator(NULL) + { + dinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&dinfo); + + good = initializeVaapi(); + if (!good) + return; + + buffer_allocator = new PoolAllocator(new VaapiAllocator(display, context)); + + VAImageFormat format = {0}; + format.fourcc = VA_FOURCC_BGRX; + format.byte_order = VA_LSB_FIRST; + format.bits_per_pixel = 4*8; + format.depth = 8; + + image_allocator = new PoolAllocator(new VaapiImageAllocator(display, WIDTH, HEIGHT, format)); + + newFrame(); + + jpeg_first_packet = true; + } + + ~VaapiRgbPacketProcessorImpl() + { + delete frame; + delete buffer_allocator; + delete image_allocator; + if (good && !jpeg_first_packet) { + CALL_VA(vaDestroyBuffer(display, pic_param_buf)); + CALL_VA(vaDestroyBuffer(display, iq_buf)); + CALL_VA(vaDestroyBuffer(display, huff_buf)); + CALL_VA(vaDestroyBuffer(display, slice_param_buf)); + } + if (good) { + CALL_VA(vaDestroyContext(display, context)); + CALL_VA(vaDestroySurfaces(display, &surface, 1)); + CALL_VA(vaDestroyConfig(display, config)); + CALL_VA(vaTerminate(display)); + } + if (drm_fd >= 0) + close(drm_fd); + jpeg_destroy_decompress(&dinfo); + } + + void newFrame() + { + frame = new VaapiFrame(static_cast(image_allocator->allocate(0))); + frame->format = Frame::BGRX; + } + + bool initializeVaapi() + { + /* Open display */ + static const char *drm_devices[] = { + "/dev/dri/renderD128", + "/dev/dri/card0", + NULL, + }; + for (int i = 0; drm_devices[i]; i++) { + drm_fd = open(drm_devices[i], O_RDWR); + if (drm_fd < 0) + continue; + display = vaGetDisplayDRM(drm_fd); + if (vaDisplayIsValid(display)) + break; + close(drm_fd); + drm_fd = -1; + display = NULL; + } + CHECK_COND(vaDisplayIsValid(display)); + + /* Initialize and create config */ + int major_ver, minor_ver; + CHECK_VA(vaInitialize(display, &major_ver, &minor_ver)); + + LOG_INFO << "driver: " << vaQueryVendorString(display); + + int max_entrypoints = vaMaxNumEntrypoints(display); + CHECK_COND(max_entrypoints >= 1); + + VAEntrypoint entrypoints[max_entrypoints]; + int num_entrypoints; + CHECK_VA(vaQueryConfigEntrypoints(display, VAProfileJPEGBaseline, entrypoints, &num_entrypoints)); + CHECK_COND(num_entrypoints >= 1 && num_entrypoints <= max_entrypoints); + + int vld_entrypoint; + for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) { + if (entrypoints[vld_entrypoint] == VAEntrypointVLD) + break; + } + CHECK_COND(vld_entrypoint < num_entrypoints); + + VAConfigAttrib attr; + attr.type = VAConfigAttribRTFormat; + CHECK_VA(vaGetConfigAttributes(display, VAProfileJPEGBaseline, VAEntrypointVLD, &attr, 1)); + unsigned int rtformat = VA_RT_FORMAT_YUV444; + if ((attr.value & rtformat) == 0) { + LOG_WARNING << "YUV444 not supported by libva, chroma will be halved"; + rtformat = VA_RT_FORMAT_YUV420; + } + CHECK_COND((attr.value & rtformat) != 0); + + CHECK_VA(vaCreateConfig(display, VAProfileJPEGBaseline, VAEntrypointVLD, &attr, 1, &config)); + + /* Create surface and context */ + CHECK_VA(vaCreateSurfaces(display, rtformat, WIDTH, HEIGHT, &surface, 1, NULL, 0)); + + CHECK_VA(vaCreateContext(display, config, WIDTH, HEIGHT, 0, &surface, 1, &context)); + + return true; + } + + VABufferID createBuffer(VABufferType type, unsigned int size, void *data) + { + VABufferID buffer = VA_INVALID_ID; + CALL_VA(vaCreateBuffer(display, context, type, size, 1, data, &buffer)); + if (buffer == VA_INVALID_ID) + LOG_ERROR << "failed to create valid buffer"; + return buffer; + } + + bool createParameters(struct jpeg_decompress_struct &dinfo, const unsigned char *vb_start) + { + /* Picture Parameter */ + VAPictureParameterBufferJPEGBaseline pic = {0}; + pic.picture_width = dinfo.image_width; + pic.picture_height = dinfo.image_height; + for (int i = 0; i< dinfo.num_components; i++) { + pic.components[i].component_id = dinfo.comp_info[i].component_id; + pic.components[i].h_sampling_factor = dinfo.comp_info[i].h_samp_factor; + pic.components[i].v_sampling_factor = dinfo.comp_info[i].v_samp_factor; + pic.components[i].quantiser_table_selector = dinfo.comp_info[i].quant_tbl_no; + } + pic.num_components = dinfo.num_components; + pic_param_buf = createBuffer(VAPictureParameterBufferType, sizeof(pic), &pic); + + /* IQ Matrix */ + VAIQMatrixBufferJPEGBaseline iq = {0}; + for (int i = 0; i < NUM_QUANT_TBLS; i++) { + if (!dinfo.quant_tbl_ptrs[i]) + continue; + iq.load_quantiser_table[i] = 1; + /* Assuming dinfo.data_precision == 8 */ + const int natural_order[DCTSIZE2] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + }; + + for (int j = 0; j < DCTSIZE2; j++) + iq.quantiser_table[i][j] = dinfo.quant_tbl_ptrs[i]->quantval[natural_order[j]]; + } + iq_buf = createBuffer(VAIQMatrixBufferType, sizeof(iq), &iq); + + /* Huffman Table */ + VAHuffmanTableBufferJPEGBaseline huff = {0}; + const int num_huffman_tables = 2; + for (int i = 0; i < num_huffman_tables; i++) { + if (!dinfo.dc_huff_tbl_ptrs[i] || !dinfo.ac_huff_tbl_ptrs[i]) + continue; + huff.load_huffman_table[i] = 1; + memcpy(huff.huffman_table[i].num_dc_codes, &dinfo.dc_huff_tbl_ptrs[i]->bits[1], + sizeof(huff.huffman_table[i].num_dc_codes)); + memcpy(huff.huffman_table[i].dc_values, dinfo.dc_huff_tbl_ptrs[i]->huffval, + sizeof(huff.huffman_table[i].dc_values)); + memcpy(huff.huffman_table[i].num_ac_codes, &dinfo.ac_huff_tbl_ptrs[i]->bits[1], + sizeof(huff.huffman_table[i].num_ac_codes)); + memcpy(huff.huffman_table[i].ac_values, dinfo.ac_huff_tbl_ptrs[i]->huffval, + sizeof(huff.huffman_table[i].ac_values)); + } + huff_buf = createBuffer(VAHuffmanTableBufferType, sizeof(huff), &huff); + + /* Slice Parameter */ + VASliceParameterBufferJPEGBaseline *pslice; + slice_param_buf = createBuffer(VASliceParameterBufferType, sizeof(*pslice), NULL); + CHECK_VA(vaMapBuffer(display, slice_param_buf, (void**)&pslice)); + VASliceParameterBufferJPEGBaseline &slice = *pslice; + + slice.slice_data_offset = dinfo.src->next_input_byte - vb_start; + slice.slice_data_flag = VA_SLICE_DATA_FLAG_ALL; + for (int i = 0; i < dinfo.comps_in_scan; i++) { + slice.components[i].component_selector = dinfo.cur_comp_info[i]->component_id; + slice.components[i].dc_table_selector = dinfo.cur_comp_info[i]->dc_tbl_no; + slice.components[i].ac_table_selector = dinfo.cur_comp_info[i]->ac_tbl_no; + } + slice.num_components = dinfo.comps_in_scan; + slice.restart_interval = dinfo.restart_interval; + unsigned int mcu_h_size = dinfo.max_h_samp_factor * DCTSIZE; + unsigned int mcu_v_size = dinfo.max_v_samp_factor * DCTSIZE; + unsigned int mcus_per_row = (WIDTH + mcu_h_size - 1) / mcu_h_size; + unsigned int mcu_rows_in_scan = (HEIGHT + mcu_v_size - 1) / mcu_v_size; + slice.num_mcus = mcus_per_row * mcu_rows_in_scan; + + CHECK_VA(vaUnmapBuffer(display, slice_param_buf)); + return true; + } + + bool decompress(unsigned char *buf, size_t len, VaapiBuffer *vb) + { + if (jpeg_first_packet) { + jpeg_mem_src(&dinfo, buf, len); + int header_status = jpeg_read_header(&dinfo, true); + CHECK_COND(header_status == JPEG_HEADER_OK); + CHECK_COND(dinfo.image_width == WIDTH && dinfo.image_height == HEIGHT); + + jpeg_first_packet = false; + if (!createParameters(dinfo, vb->data)) + return false; + + jpeg_header_size = len - dinfo.src->bytes_in_buffer; + jpeg_abort_decompress(&dinfo); + } + /* Grab the packet buffer for VAAPI backend */ + CHECK_VA(vaUnmapBuffer(display, vb->id)); + + /* The only parameter that changes after the first packet */ + VASliceParameterBufferJPEGBaseline *slice; + CHECK_VA(vaMapBuffer(display, slice_param_buf, (void**)&slice)); + slice->slice_data_size = len - jpeg_header_size; + CHECK_VA(vaUnmapBuffer(display, slice_param_buf)); + + /* Commit buffers */ + CHECK_VA(vaBeginPicture(display, context, surface)); + VABufferID va_bufs[5] = {pic_param_buf, iq_buf, huff_buf, slice_param_buf, vb->id}; + CHECK_VA(vaRenderPicture(display, context, va_bufs, 5)); + CHECK_VA(vaEndPicture(display, context)); + + /* Sync surface */ + CHECK_VA(vaSyncSurface(display, surface)); + + if (!frame->draw(display, surface)) + return false; + + CHECK_VA(vaMapBuffer(display, vb->id, (void**)&vb->data)); + + return true; + } +}; + +VaapiRgbPacketProcessor::VaapiRgbPacketProcessor() : + impl_(new VaapiRgbPacketProcessorImpl()) +{ +} + +VaapiRgbPacketProcessor::~VaapiRgbPacketProcessor() +{ + delete impl_; +} + +bool VaapiRgbPacketProcessor::good() +{ + return impl_->good; +} + +void VaapiRgbPacketProcessor::process(const RgbPacket &packet) +{ + if (listener_ == 0) + return; + + impl_->startTiming(); + + impl_->frame->timestamp = packet.timestamp; + impl_->frame->sequence = packet.sequence; + impl_->frame->exposure = packet.exposure; + impl_->frame->gain = packet.gain; + impl_->frame->gamma = packet.gamma; + + unsigned char *buf = packet.jpeg_buffer; + size_t len = packet.jpeg_buffer_length; + VaapiBuffer *vb = static_cast(packet.memory); + impl_->good = impl_->decompress(buf, len, vb); + + impl_->stopTiming(LOG_INFO); + + if (!impl_->good) + impl_->frame->status = 1; + + if (listener_->onNewFrame(Frame::Color, impl_->frame)) + impl_->newFrame(); +} + +Allocator *VaapiRgbPacketProcessor::getAllocator() +{ + return impl_->buffer_allocator; +} +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vt_rgb_packet_processor.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vt_rgb_packet_processor.cpp new file mode 100644 index 0000000..c6838a3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/src/vt_rgb_packet_processor.cpp @@ -0,0 +1,179 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + + +#include +#include + +#include + +namespace libfreenect2 { + +class VTFrame: public Frame +{ + public: + VTFrame(size_t width, size_t height, size_t bytes_per_pixel, CVPixelBufferRef pixelBuffer) : + Frame(width, + height, + bytes_per_pixel, + reinterpret_cast(CVPixelBufferGetBaseAddress(lockPixelBuffer(pixelBuffer)))), + pixelBuffer(pixelBuffer) { + } + + ~VTFrame() { + CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); + CVPixelBufferRelease(pixelBuffer); + } + + protected: + CVPixelBufferRef lockPixelBuffer(CVPixelBufferRef _pixelBuffer) { + CVPixelBufferLockBaseAddress(_pixelBuffer, 0); + + return _pixelBuffer; + } + + CVPixelBufferRef pixelBuffer; +}; + +class VTRgbPacketProcessorImpl: public WithPerfLogging +{ + public: + CMFormatDescriptionRef format; + VTDecompressionSessionRef decoder; + + VTRgbPacketProcessorImpl() { + int32_t width = 1920, height = 1080; + + CMVideoFormatDescriptionCreate(NULL, kCMVideoCodecType_JPEG, width, height, NULL, &format); + + int32_t pixelFormat = kCVPixelFormatType_32BGRA; + const void *outputKeys[] = {kCVPixelBufferPixelFormatTypeKey, kCVPixelBufferWidthKey, kCVPixelBufferHeightKey}; + const void *outputValues[] = + {CFNumberCreate(NULL, kCFNumberSInt32Type, &pixelFormat), CFNumberCreate(NULL, kCFNumberSInt32Type, &width), + CFNumberCreate(NULL, kCFNumberSInt32Type, &height)}; + + CFDictionaryRef outputConfiguration = CFDictionaryCreate(NULL, + outputKeys, + outputValues, + 3, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + VTDecompressionOutputCallbackRecord callback = {&VTRgbPacketProcessorImpl::decodeFrame, NULL}; + + VTDecompressionSessionCreate(NULL, format, NULL, outputConfiguration, &callback, &decoder); + + CFRelease(outputConfiguration); + } + + ~VTRgbPacketProcessorImpl() { + VTDecompressionSessionInvalidate(decoder); + CFRelease(decoder); + CFRelease(format); + } + + static void decodeFrame(void *decompressionOutputRefCon, + void *sourceFrameRefCon, + OSStatus status, + VTDecodeInfoFlags infoFlags, + CVImageBufferRef pixelBuffer, + CMTime presentationTimeStamp, + CMTime presentationDuration) { + CVPixelBufferRef *outputPixelBuffer = (CVPixelBufferRef *) sourceFrameRefCon; + *outputPixelBuffer = CVPixelBufferRetain(pixelBuffer); + } +}; + +VTRgbPacketProcessor::VTRgbPacketProcessor() + : RgbPacketProcessor () + , impl_(new VTRgbPacketProcessorImpl()) +{ +} + +VTRgbPacketProcessor::~VTRgbPacketProcessor() +{ + delete impl_; +} + +void VTRgbPacketProcessor::process(const RgbPacket &packet) +{ + if (listener_ != 0) { + impl_->startTiming(); + + CMBlockBufferRef blockBuffer; + CMBlockBufferCreateWithMemoryBlock( + NULL, + packet.jpeg_buffer, + packet.jpeg_buffer_length, + kCFAllocatorNull, + NULL, + 0, + packet.jpeg_buffer_length, + 0, + &blockBuffer + ); + + CMSampleBufferRef sampleBuffer; + CMSampleBufferCreate( + NULL, + blockBuffer, + true, + NULL, + NULL, + impl_->format, + 1, + 0, + NULL, + 0, + NULL, + &sampleBuffer + ); + + CVPixelBufferRef pixelBuffer = NULL; + VTDecompressionSessionDecodeFrame(impl_->decoder, sampleBuffer, 0, &pixelBuffer, NULL); + + Frame *frame = new VTFrame(1920, 1080, 4, pixelBuffer); + frame->format = Frame::BGRX; + + frame->timestamp = packet.timestamp; + frame->sequence = packet.sequence; + frame->exposure = packet.exposure; + frame->gain = packet.gain; + frame->gamma = packet.gamma; + + if (!listener_->onNewFrame(Frame::Color, frame)) { + // The listener didn't take ownership of the frame, so we delete it + delete frame; + } + + CFRelease(sampleBuffer); + CFRelease(blockBuffer); + + impl_->stopTiming(LOG_INFO); + } +} + +} /* namespace libfreenect2 */ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/generate_resources.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/generate_resources.cpp new file mode 100644 index 0000000..30bd305 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/generate_resources.cpp @@ -0,0 +1,98 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2014 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file generate_resources.cpp Generator of the resource file, to load tables from in-program data. */ + +#include +#include +#include +#include + +/** + * Add the content of the given filename to the resources. + * @param filename File to add to the resources. + */ +void dumpFile(const std::string& filename) +{ + using namespace std; + + ifstream f(filename.c_str(), ios::binary); + + unsigned char buffer[1024]; + + while(!f.eof()) + { + f.read(reinterpret_cast(buffer), sizeof(buffer)); + size_t n = f.gcount(); + + if(n == 0) break; + + cout << hex << setw(2) << setfill('0') << " "; + for(size_t i = 0; i < n; ++i) + { + cout << "0x" << int(buffer[i]) << ", "; + } + cout << endl; + } + cout << dec; +} + +/** + * Main application entry point. + * Arguments: List of files to add as resource. + */ +int main(int argc, char **argv) +{ + if(argc < 2) return -1; + + using namespace std; + + string basefolder(argv[1]); + + for(int i = 2; i < argc; ++i) + { + cout << "static unsigned char resource" << (i - 2) << "[] = {" << endl; + dumpFile(basefolder + "/" + argv[i]); + cout << "};" << endl; + } + + cout << "static ResourceDescriptor resource_descriptors[] = {" << endl; + + for(int i = 2; i < argc; ++i) + { + string path(argv[i]); + size_t last_slash = path.find_last_of("\\/"); + if (last_slash != std::string::npos) + path.erase(0, last_slash + 1); + cout << " { \"" << path << "\", resource" << (i - 2) << ", " << "sizeof(resource" << (i - 2) << ") }," << endl; + } + + cout << " {NULL, NULL, 0}," << endl; + cout << "};" << endl; + cout << "static int resource_descriptors_length = " << (argc - 2) << ";" << endl; + + return 0; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/mkcontrib.py b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/mkcontrib.py new file mode 100644 index 0000000..430404a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/mkcontrib.py @@ -0,0 +1,26 @@ +# 1. Visual inspection: python mkcontrib.py +# 2. If OK, python mkcontrib.py | grep -v ^# > CONTRIB + +from subprocess import Popen, PIPE +from collections import defaultdict, Counter + +p = Popen(["git","log","--no-merges","--format=%aN <%aE>"], stdout=PIPE).stdout +common_email = defaultdict(Counter) +common_name = defaultdict(Counter) +for line in p: + author, email = line.rstrip().split('<') + common_email[author].update([email]) + common_name[email].update([author]) + +for email in common_name: + names = common_name[email] + names = sorted(names, key=lambda x: (names[x], len(x)), reverse=True) + for name in names[1:]: + common_email[names[0]] += common_email[name] + del common_email[name] + print '# Less common or shorter name', name, 'is replaced by', names[0] + +for name in sorted(common_email): + for k in common_email[name].most_common()[1:]: + print '# Less common email <' + k[0] + ' is removed.' + print name + '<' + common_email[name].most_common(1)[0][0] diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/CMakeLists.txt new file mode 100644 index 0000000..77f203f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/CMakeLists.txt @@ -0,0 +1,120 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.1) + +if(WIN32 AND NOT MINGW) + if(NOT DEFINED CMAKE_DEBUG_POSTFIX) + set(CMAKE_DEBUG_POSTFIX "d") + endif() +endif() + +IF(NOT DEFINED CMAKE_BUILD_TYPE) + # No effect for multi-configuration generators (e.g. for Visual Studio) + SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose: RelWithDebInfo Release Debug MinSizeRel None") +ENDIF() + +PROJECT(libfreenect2_tools_SR) + +SET(MY_DIR ${libfreenect2_tools_SR_SOURCE_DIR}) +SET(DEPENDS_DIR "${MY_DIR}/../../../depends" CACHE STRING "Dependency directory") + +OPTION(ENABLE_OPENGL "Enable OpenGL support" ON) + +# The build system could be standalone if these files are copied instead of being referenced here. +SET(freenect2_ROOT_DIR ${MY_DIR}/../..) +SET(flextGL_SOURCES ${freenect2_ROOT_DIR}/src/flextGL.cpp) +SET(flextGL_INCLUDE_DIRS ${freenect2_ROOT_DIR}/src) # for flextGL.h +SET(example_INCLUDE_DIRS ${freenect2_ROOT_DIR}/examples) # for protonect viewer + +FIND_PACKAGE(PkgConfig) # try find PKGConfig as it will be used if found +LIST(APPEND CMAKE_MODULE_PATH ${freenect2_ROOT_DIR}/cmake_modules) # FindGLFW3.cmake + +IF(TARGET freenect2) + MESSAGE(STATUS "Using in-tree freenect2 target") + SET(freenect2_LIBRARIES freenect2) + SET(freenect2_DLLS ${LIBFREENECT2_DLLS}) +ELSE() + FIND_PACKAGE(freenect2 REQUIRED) + # Out-of-tree build will have to have DLLs manually copied. +ENDIF() + +INCLUDE_DIRECTORIES( + ${freenect2_INCLUDE_DIR} + ${example_INCLUDE_DIRS} + ${MY_DIR}/include +) + +SET(ProtonectSR_src + ProtonectSR.cpp + PracticalSocket.cpp + streamer.cpp + recorder.cpp +) + +SET(ProtonectSR_LIBRARIES + ${freenect2_LIBRARIES} +) + +SET(ProtonectSR_DLLS + ${freenect2_DLLS} +) + +# Add OpenCV package dependency for udp-image-streaming +FIND_PACKAGE(OpenCV REQUIRED) +INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS}) +LIST(APPEND ProtonectSR_LIBRARIES + ${OpenCV_LIBS} +) +# OpenCV requires exception. +IF(UNIX AND NOT APPLE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") +ENDIF() + +IF(ENABLE_OPENGL) + FIND_PACKAGE(GLFW3) + FIND_PACKAGE(OpenGL) + IF(GLFW3_FOUND AND OPENGL_FOUND) + INCLUDE_DIRECTORIES( + ${GLFW3_INCLUDE_DIRS} + ${flextGL_INCLUDE_DIRS} + ) + + LIST(APPEND ProtonectSR_DLLS ${GLFW3_DLL}) + LIST(APPEND ProtonectSR_src + ${example_INCLUDE_DIRS}/viewer.cpp + ${flextGL_SOURCES} + ) + LIST(APPEND ProtonectSR_LIBRARIES + ${GLFW3_LIBRARIES} + ${OPENGL_gl_LIBRARY} + ) + ADD_DEFINITIONS(-DEXAMPLES_WITH_OPENGL_SUPPORT=1) + ENDIF() +ENDIF(ENABLE_OPENGL) + +ADD_EXECUTABLE(ProtonectSR + ${ProtonectSR_src} +) + +TARGET_LINK_LIBRARIES(ProtonectSR + ${ProtonectSR_LIBRARIES} +) + +if(EXISTS ProtonectSR) + configure_file(build/ProtonectSR freenect2-record COPYONLY) + configure_file(build/ProtonectSR freenect2-replay COPYONLY) + configure_file(build/ProtonectSR freenect2-stream COPYONLY) +endif() + +file(MAKE_DIRECTORY build/recordings) +file(MAKE_DIRECTORY build/recordings/depth) +file(MAKE_DIRECTORY build/recordings/regist) + +IF(WIN32) + INSTALL(TARGETS ProtonectSR DESTINATION bin) + LIST(REMOVE_DUPLICATES ProtonectSR_DLLS) + FOREACH(FILEI ${ProtonectSR_DLLS}) + ADD_CUSTOM_COMMAND(TARGET ProtonectSR POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILEI} $ + ) + ENDFOREACH(FILEI) + INSTALL(FILES ${ProtonectSR_DLLS} DESTINATION bin) +ENDIF() diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/PracticalSocket.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/PracticalSocket.cpp new file mode 100644 index 0000000..4c78989 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/PracticalSocket.cpp @@ -0,0 +1,383 @@ +/* + * C++ sockets on Unix and Windows + * Copyright (C) 2002 Michael J. Donahoo and Kenneth L. Calvert + * http://cs.ecs.baylor.edu/%7Edonahoo/practical/CSockets/practical/ + * Modified code forked from https://github.com/chenxiaoqino/udp-image-streaming + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "PracticalSocket.h" + +#ifdef WIN32 + #include // For socket(), connect(), send(), and recv() + typedef int socklen_t; + typedef char raw_type; // Type used for raw data on this platform +#else + #include // For data types + #include // For socket(), connect(), send(), and recv() + #include // For gethostbyname() + #include // For inet_addr() + #include // For close() + #include // For sockaddr_in + #include // For strerror(), memset() + typedef void raw_type; // Type used for raw data on this platform +#endif + +#include // For errno + +using namespace std; + +#ifdef WIN32 +static bool initialized = false; +#endif + +// SocketException Code + +SocketException::SocketException(const string &message, bool inclSysMsg) + throw() : userMessage(message) { + if (inclSysMsg) { + userMessage.append(": "); + userMessage.append(strerror(errno)); + } +} + +SocketException::~SocketException() throw() { +} + +const char *SocketException::what() const throw() { + return userMessage.c_str(); +} + +// Function to fill in address structure given an address and port +static void fillAddr(const string &address, unsigned short port, + sockaddr_in &addr) { + memset(&addr, 0, sizeof(addr)); // Zero out address structure + addr.sin_family = AF_INET; // Internet address + + hostent *host; // Resolve name + if ((host = gethostbyname(address.c_str())) == NULL) { + // strerror() will not work for gethostbyname() and hstrerror() + // is supposedly obsolete + throw SocketException("Failed to resolve name (gethostbyname())"); + } + addr.sin_addr.s_addr = *((unsigned long *) host->h_addr_list[0]); + + addr.sin_port = htons(port); // Assign port in network byte order +} + +// Socket Code + +Socket::Socket(int type, int protocol) throw(SocketException) { + #ifdef WIN32 + if (!initialized) { + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); // Request WinSock v2.0 + if (WSAStartup(wVersionRequested, &wsaData) != 0) { // Load WinSock DLL + throw SocketException("Unable to load WinSock DLL"); + } + initialized = true; + } + #endif + + // Make a new socket + if ((sockDesc = socket(PF_INET, type, protocol)) < 0) { + throw SocketException("Socket creation failed (socket())", true); + } +} + +Socket::Socket(int sockDesc) { + this->sockDesc = sockDesc; +} + +Socket::~Socket() { + #ifdef WIN32 + ::closesocket(sockDesc); + #else + ::close(sockDesc); + #endif + sockDesc = -1; +} + +string Socket::getLocalAddress() throw(SocketException) { + sockaddr_in addr; + unsigned int addr_len = sizeof(addr); + + if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { + throw SocketException("Fetch of local address failed (getsockname())", true); + } + return inet_ntoa(addr.sin_addr); +} + +unsigned short Socket::getLocalPort() throw(SocketException) { + sockaddr_in addr; + unsigned int addr_len = sizeof(addr); + + if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { + throw SocketException("Fetch of local port failed (getsockname())", true); + } + return ntohs(addr.sin_port); +} + +void Socket::setLocalPort(unsigned short localPort) throw(SocketException) { + // Bind the socket to its port + sockaddr_in localAddr; + memset(&localAddr, 0, sizeof(localAddr)); + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + localAddr.sin_port = htons(localPort); + + if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) { + throw SocketException("Set of local port failed (bind())", true); + } +} + +void Socket::setLocalAddressAndPort(const string &localAddress, + unsigned short localPort) throw(SocketException) { + // Get the address of the requested host + sockaddr_in localAddr; + fillAddr(localAddress, localPort, localAddr); + + if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) { + throw SocketException("Set of local address and port failed (bind())", true); + } +} + +void Socket::cleanUp() throw(SocketException) { + #ifdef WIN32 + if (WSACleanup() != 0) { + throw SocketException("WSACleanup() failed"); + } + #endif +} + +unsigned short Socket::resolveService(const string &service, + const string &protocol) { + struct servent *serv; /* Structure containing service information */ + + if ((serv = getservbyname(service.c_str(), protocol.c_str())) == NULL) + return atoi(service.c_str()); /* Service is port number */ + else + return ntohs(serv->s_port); /* Found port (network byte order) by name */ +} + +// CommunicatingSocket Code + +CommunicatingSocket::CommunicatingSocket(int type, int protocol) + throw(SocketException) : Socket(type, protocol) { +} + +CommunicatingSocket::CommunicatingSocket(int newConnSD) : Socket(newConnSD) { +} + +void CommunicatingSocket::connect(const string &foreignAddress, + unsigned short foreignPort) throw(SocketException) { + // Get the address of the requested host + sockaddr_in destAddr; + fillAddr(foreignAddress, foreignPort, destAddr); + + // Try to connect to the given port + if (::connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr)) < 0) { + throw SocketException("Connect failed (connect())", true); + } +} + +void CommunicatingSocket::send(const void *buffer, int bufferLen) + throw(SocketException) { + if (::send(sockDesc, (raw_type *) buffer, bufferLen, 0) < 0) { + throw SocketException("Send failed (send())", true); + } +} + +int CommunicatingSocket::recv(void *buffer, int bufferLen) + throw(SocketException) { + int rtn; + if ((rtn = ::recv(sockDesc, (raw_type *) buffer, bufferLen, 0)) < 0) { + throw SocketException("Received failed (recv())", true); + } + + return rtn; +} + +string CommunicatingSocket::getForeignAddress() + throw(SocketException) { + sockaddr_in addr; + unsigned int addr_len = sizeof(addr); + + if (getpeername(sockDesc, (sockaddr *) &addr,(socklen_t *) &addr_len) < 0) { + throw SocketException("Fetch of foreign address failed (getpeername())", true); + } + return inet_ntoa(addr.sin_addr); +} + +unsigned short CommunicatingSocket::getForeignPort() throw(SocketException) { + sockaddr_in addr; + unsigned int addr_len = sizeof(addr); + + if (getpeername(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) { + throw SocketException("Fetch of foreign port failed (getpeername())", true); + } + return ntohs(addr.sin_port); +} + +// TCPSocket Code + +TCPSocket::TCPSocket() + throw(SocketException) : CommunicatingSocket(SOCK_STREAM, + IPPROTO_TCP) { +} + +TCPSocket::TCPSocket(const string &foreignAddress, unsigned short foreignPort) + throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) { + connect(foreignAddress, foreignPort); +} + +TCPSocket::TCPSocket(int newConnSD) : CommunicatingSocket(newConnSD) { +} + +// TCPServerSocket Code + +TCPServerSocket::TCPServerSocket(unsigned short localPort, int queueLen) + throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) { + setLocalPort(localPort); + setListen(queueLen); +} + +TCPServerSocket::TCPServerSocket(const string &localAddress, + unsigned short localPort, int queueLen) + throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) { + setLocalAddressAndPort(localAddress, localPort); + setListen(queueLen); +} + +TCPSocket *TCPServerSocket::accept() throw(SocketException) { + int newConnSD; + if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0) { + throw SocketException("Accept failed (accept())", true); + } + + return new TCPSocket(newConnSD); +} + +void TCPServerSocket::setListen(int queueLen) throw(SocketException) { + if (listen(sockDesc, queueLen) < 0) { + throw SocketException("Set listening socket failed (listen())", true); + } +} + +// UDPSocket Code + +UDPSocket::UDPSocket() throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, + IPPROTO_UDP) { + setBroadcast(); +} + +UDPSocket::UDPSocket(unsigned short localPort) throw(SocketException) : + CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { + setLocalPort(localPort); + setBroadcast(); +} + +UDPSocket::UDPSocket(const string &localAddress, unsigned short localPort) + throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) { + setLocalAddressAndPort(localAddress, localPort); + setBroadcast(); +} + +void UDPSocket::setBroadcast() { + // If this fails, we'll hear about it when we try to send. This will allow + // system that cannot broadcast to continue if they don't plan to broadcast + int broadcastPermission = 1; + setsockopt(sockDesc, SOL_SOCKET, SO_BROADCAST, + (raw_type *) &broadcastPermission, sizeof(broadcastPermission)); +} + +void UDPSocket::disconnect() throw(SocketException) { + sockaddr_in nullAddr; + memset(&nullAddr, 0, sizeof(nullAddr)); + nullAddr.sin_family = AF_UNSPEC; + + // Try to disconnect + if (::connect(sockDesc, (sockaddr *) &nullAddr, sizeof(nullAddr)) < 0) { + #ifdef WIN32 + if (errno != WSAEAFNOSUPPORT) { + #else + if (errno != EAFNOSUPPORT) { + #endif + throw SocketException("Disconnect failed (connect())", true); + } + } +} + +void UDPSocket::sendTo(const void *buffer, int bufferLen, + const string &foreignAddress, unsigned short foreignPort) + throw(SocketException) { + sockaddr_in destAddr; + fillAddr(foreignAddress, foreignPort, destAddr); + + // Write out the whole buffer as a single message. + if (sendto(sockDesc, (raw_type *) buffer, bufferLen, 0, + (sockaddr *) &destAddr, sizeof(destAddr)) != bufferLen) { + throw SocketException("Send failed (sendto())", true); + } +} + +int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress, + unsigned short &sourcePort) throw(SocketException) { + sockaddr_in clntAddr; + socklen_t addrLen = sizeof(clntAddr); + int rtn; + if ((rtn = recvfrom(sockDesc, (raw_type *) buffer, bufferLen, 0, + (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) { + throw SocketException("Receive failed (recvfrom())", true); + } + sourceAddress = inet_ntoa(clntAddr.sin_addr); + sourcePort = ntohs(clntAddr.sin_port); + + return rtn; +} + +void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) { + if (setsockopt(sockDesc, IPPROTO_IP, IP_MULTICAST_TTL, + (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) { + throw SocketException("Multicast TTL set failed (setsockopt())", true); + } +} + +void UDPSocket::joinGroup(const string &multicastGroup) throw(SocketException) { + struct ip_mreq multicastRequest; + + multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str()); + multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); + if (setsockopt(sockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (raw_type *) &multicastRequest, + sizeof(multicastRequest)) < 0) { + throw SocketException("Multicast group join failed (setsockopt())", true); + } +} + +void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException) { + struct ip_mreq multicastRequest; + + multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str()); + multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); + if (setsockopt(sockDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP, + (raw_type *) &multicastRequest, + sizeof(multicastRequest)) < 0) { + throw SocketException("Multicast group leave failed (setsockopt())", true); + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/ProtonectSR.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/ProtonectSR.cpp new file mode 100644 index 0000000..9dd7eb4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/ProtonectSR.cpp @@ -0,0 +1,534 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2017 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +/** @file ProtonectSR.cpp Main tool application file. */ + +#include +#include +#include + +// For replay devices +#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + #include +#else + #include +#endif + +/// [headers] +#include +#include +#include +#include +#include +#include "include/streamer.h" +#include "include/recorder.h" +/// [headers] +#ifdef EXAMPLES_WITH_OPENGL_SUPPORT +#include "viewer.h" +#endif + +bool protonect_shutdown = false; ///< Whether the running application should shut down. + +void sigint_handler(int s) +{ + protonect_shutdown = true; +} + +bool protonect_paused = false; +libfreenect2::Freenect2Device *devtopause; + +//Doing non-trivial things in signal handler is bad. If you want to pause, +//do it in another thread. +//Though libusb operations are generally thread safe, I cannot guarantee +//everything above is thread safe when calling start()/stop() while +//waitForNewFrame(). +void sigusr1_handler(int s) +{ + if (devtopause == 0) + return; +/// [pause] + if (protonect_paused) + devtopause->start(); + else + devtopause->stop(); + protonect_paused = !protonect_paused; +/// [pause] +} + +//The following demostrates how to create a custom logger +/// [logger] +#include +#include +class MyFileLogger: public libfreenect2::Logger +{ +private: + std::ofstream logfile_; +public: + MyFileLogger(const char *filename) + { + if (filename) + logfile_.open(filename); + level_ = Debug; + } + bool good() + { + return logfile_.is_open() && logfile_.good(); + } + virtual void log(Level level, const std::string &message) + { + logfile_ << "[" << libfreenect2::Logger::level2str(level) << "] " << message << std::endl; + } +}; +/// [logger] + +bool hasSuffix(const std::string& str, const std::string& suffix) +{ + if (str.length() < suffix.length()) + { + return false; + } + return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; +} + +/// [main] +/** + * Main application entry point. + * + * Accepted argumemnts: + * - cpu Perform depth processing with the CPU. + * - gl Perform depth processing with OpenGL. + * - cl Perform depth processing with OpenCL. + * - Serial number of the device to open. + * - -noviewer Disable viewer window. + * - -streamer Enable UDP Streaming of captured images. + * - -recorder Enable recording of captured images. + * - -replay Enable replay of captured images. + */ +int main(int argc, char *argv[]) +/// [main] +{ + std::string program_path(argv[0]); + std::cerr << "Version: " << LIBFREENECT2_VERSION << std::endl; + std::cerr << "Environment variables: LOGFILE=" << std::endl; + std::cerr << "Usage: " << program_path << " [-gpu=] [gl | cl | clkde | cuda | cudakde | cpu] []" << std::endl; + std::cerr << " [-noviewer] [-norgb | -nodepth] [-help] [-version]" << std::endl; + std::cerr << " [-recorder] [-streamer] [-replay]" << std::endl; + std::cerr << " [-frames ]" << std::endl; + std::cerr << "To pause and unpause: pkill -USR1 ProtonectSR" << std::endl; + size_t executable_name_idx = program_path.rfind("ProtonectSR"); + + const std::string prog(argv[0]); + + std::string binpath = "/"; + + if(executable_name_idx != std::string::npos) + { + binpath = program_path.substr(0, executable_name_idx); + } + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + // avoid flooing the very slow Windows console with debug messages + libfreenect2::setGlobalLogger(libfreenect2::createConsoleLogger(libfreenect2::Logger::Info)); +#else + // create a console logger with debug level (default is console logger with info level) +/// [logging] + libfreenect2::setGlobalLogger(libfreenect2::createConsoleLogger(libfreenect2::Logger::Debug)); +/// [logging] +#endif +/// [file logging] + MyFileLogger *filelogger = new MyFileLogger(getenv("LOGFILE")); + if (filelogger->good()) + libfreenect2::setGlobalLogger(filelogger); + else + delete filelogger; +/// [file logging] + +/// [context] + libfreenect2::Freenect2 freenect2; + // TODO: enable on merge + //libfreenect2::Freenect2Replay freenect2replay; + libfreenect2::Freenect2Device *dev = 0; + libfreenect2::PacketPipeline *pipeline = 0; +/// [context] + + std::string serial = ""; + + bool viewer_enabled = true; + bool streamer_enabled = false; + bool recorder_enabled = false; + bool replay_enabled = false; + bool enable_rgb = true; + bool enable_depth = true; + int deviceId = -1; + size_t framemax = -1; + + for(int argI = 1; argI < argc; ++argI) + { + const std::string arg(argv[argI]); + + if(arg == "-help" || arg == "--help" || arg == "-h" || arg == "-v" || arg == "--version" || arg == "-version") + { + // Just let the initial lines display at the beginning of main + return 0; + } + else if(arg.find("-gpu=") == 0) + { + if (pipeline) + { + std::cerr << "-gpu must be specified before pipeline argument" << std::endl; + return -1; + } + deviceId = atoi(argv[argI] + 5); + } + else if(arg == "cpu") + { + if(!pipeline) +/// [pipeline] + pipeline = new libfreenect2::CpuPacketPipeline(); +/// [pipeline] + } + else if(arg == "gl") + { +#ifdef LIBFREENECT2_WITH_OPENGL_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::OpenGLPacketPipeline(); +#else + std::cout << "OpenGL pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "cl") + { +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::OpenCLPacketPipeline(deviceId); +#else + std::cout << "OpenCL pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "clkde") + { +#ifdef LIBFREENECT2_WITH_OPENCL_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::OpenCLKdePacketPipeline(deviceId); +#else + std::cout << "OpenCL pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "cuda") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::CudaPacketPipeline(deviceId); +#else + std::cout << "CUDA pipeline is not supported!" << std::endl; +#endif + } + else if(arg == "cudakde") + { +#ifdef LIBFREENECT2_WITH_CUDA_SUPPORT + if(!pipeline) + pipeline = new libfreenect2::CudaKdePacketPipeline(deviceId); +#else + std::cout << "CUDA pipeline is not supported!" << std::endl; +#endif + } + else if(arg.find_first_not_of("0123456789") == std::string::npos) //check if parameter could be a serial number + { + serial = arg; + } + else if(arg == "-noviewer" || arg == "--noviewer") + { + viewer_enabled = false; + } + else if(arg == "-norgb" || arg == "--norgb") + { + enable_rgb = false; + } + else if(arg == "-nodepth" || arg == "--nodepth") + { + enable_depth = false; + } + else if(arg == "-frames") + { + ++argI; + framemax = strtol(argv[argI], NULL, 0); + if (framemax == 0) { + std::cerr << "invalid frame count '" << argv[argI] << "'" << std::endl; + return -1; + } + } + else if(arg == "-streamer" || arg == "--streamer" || prog == "freenect2-stream") + { + streamer_enabled = true; + } + else if(arg == "-recorder" || arg == "--recorder" || prog == "freenect2-record") + { + recorder_enabled = true; + } + else if(arg == "-replay" || arg == "--replay" || prog == "freenect2-replay") + { + replay_enabled = true; + } + else + { + std::cout << "Unknown argument: " << arg << std::endl; + } + } + + if (!enable_rgb && !enable_depth) + { + std::cerr << "Disabling both streams is not allowed!" << std::endl; + return -1; + } + +/// [discovery] + if(replay_enabled == false) + { + if(freenect2.enumerateDevices() == 0) + { + std::cout << "no device connected!" << std::endl; + return -1; + } + + if(serial == "") + { + serial = freenect2.getDefaultDeviceSerialNumber(); + } + } +/// [discovery] + + if(replay_enabled == false) + { + if(pipeline) + { +/// [open] + dev = freenect2.openDevice(serial, pipeline); +/// [open] + } + else + { + dev = freenect2.openDevice(serial); + } + } + else + { + DIR *d; + struct dirent *dir; + + std::vector frame_filenames; + + d = opendir("recordings/depth"); + + if(!d) + { + std::cerr << "Could not open directory " << dir << " for replay." << std::endl; + exit(1); + } + + while((dir = readdir(d)) != NULL) + { + std::string name = dir->d_name; + + if(hasSuffix(name, ".depth")) + { + frame_filenames.push_back(name); + } + else + { + std::cerr << "Skipping currently unsupported frame filename: " << name << std::endl; + } + } + // TODO: enable on merge +/* + if(pipeline) + { +/// [open] + dev = freenect2replay.openDevice(frame_filenames, pipeline); +/// [open] + } + else + { + dev = freenect2replay.openDevice(frame_filenames); + } +*/ + } + + if(dev == 0) + { + std::cout << "failure opening device!" << std::endl; + return -1; + } + + devtopause = dev; + + signal(SIGINT,sigint_handler); +#ifdef SIGUSR1 + signal(SIGUSR1, sigusr1_handler); +#endif + protonect_shutdown = false; + +/// [listeners] + int types = 0; + if (enable_rgb) + types |= libfreenect2::Frame::Color; + if (enable_depth) + types |= libfreenect2::Frame::Ir | libfreenect2::Frame::Depth; + libfreenect2::SyncMultiFrameListener listener(types); + libfreenect2::FrameMap frames; + + dev->setColorFrameListener(&listener); + dev->setIrAndDepthFrameListener(&listener); +/// [listeners] + +/// [start] + if (enable_rgb && enable_depth) + { + if (!dev->start()) + return -1; + } + else + { + if (!dev->startStreams(enable_rgb, enable_depth)) + return -1; + } + + std::cout << "device serial: " << dev->getSerialNumber() << std::endl; + std::cout << "device firmware: " << dev->getFirmwareVersion() << std::endl; +/// [start] + +/// [registration setup] + libfreenect2::Registration* registration = new libfreenect2::Registration(dev->getIrCameraParams(), dev->getColorCameraParams()); + libfreenect2::Frame undistorted(512, 424, 4), registered(512, 424, 4); +/// [registration setup] + + size_t framecount = 0; +#ifdef EXAMPLES_WITH_OPENGL_SUPPORT + Viewer viewer; + if (viewer_enabled) + viewer.initialize(); +#else + viewer_enabled = false; +#endif + + Streamer streamer; // have to declare it outside statements to be accessible everywhere + Recorder recorder; + + if(streamer_enabled) + { + streamer.initialize(); + } + + if(recorder_enabled) + { + recorder.initialize(); + } + +/// [loop start] + while(!protonect_shutdown && (framemax == (size_t)-1 || framecount < framemax)) + { + if (!listener.waitForNewFrame(frames, 10*1000)) // 10 sconds + { + std::cout << "timeout!" << std::endl; + return -1; + } + libfreenect2::Frame *rgb = frames[libfreenect2::Frame::Color]; + libfreenect2::Frame *ir = frames[libfreenect2::Frame::Ir]; + libfreenect2::Frame *depth = frames[libfreenect2::Frame::Depth]; +/// [loop start] + + if (enable_rgb && enable_depth) + { +/// [registration] + registration->apply(rgb, depth, &undistorted, ®istered); +/// [registration] + } + + framecount++; + + if (streamer_enabled) + { + streamer.stream(depth); + } + + if (recorder_enabled) + { + // TODO: add recording timestamp if max frame number reached + // + avoid recording new ones + recorder.record(depth, "depth"); + recorder.record(®istered, "registered"); + // recorder.record(rgb,"rgb"); + + recorder.registTimeStamp(); + } + + if (!viewer_enabled) + { + if (framecount % 100 == 0) + std::cout << "The viewer is turned off. Received " << framecount << " frames. Ctrl-C to stop." << std::endl; + listener.release(frames); + continue; + } + +#ifdef EXAMPLES_WITH_OPENGL_SUPPORT + if (enable_rgb) + { + viewer.addFrame("RGB", rgb); + } + if (enable_depth) + { + viewer.addFrame("ir", ir); + viewer.addFrame("depth", depth); + } + if (enable_rgb && enable_depth) + { + viewer.addFrame("registered", ®istered); + } + + protonect_shutdown = protonect_shutdown || viewer.render(); +#endif + +/// [loop end] + listener.release(frames); + /** libfreenect2::this_thread::sleep_for(libfreenect2::chrono::milliseconds(100)); */ + } +/// [loop end] + + if (recorder_enabled) + { + recorder.saveTimeStamp(); + } + + // TODO: restarting ir stream doesn't work! + // TODO: bad things will happen, if frame listeners are freed before dev->stop() :( +/// [stop] + dev->stop(); + dev->close(); +/// [stop] + + delete registration; + + return 0; +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/README.md b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/README.md new file mode 100644 index 0000000..682dcc8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/README.md @@ -0,0 +1,82 @@ +# libfreenect2 Streamer/Recorder toolbox + +## Table of Contents + +* [Description](README.md#description) +* [Maintainers](README.md#maintainers) +* [Installation](README.md#installation) + * [Windows / Visual Studio](README.md#windows--visual-studio) + * [MacOS X](README.md#mac-osx) + * [Linux](README.md#linux) + + +## Description + +Additional toolbox based off `Protonect` featuring: +- UDP streaming of Kinect captured images (``-streamer`` option) +- Recording of Kinect captured images to disk (``-recorder`` option) +- Replay of Kinect captured images from disk (``-replay`` option) + +## Maintainers + +* David Poirier-Quinot +* Serguei A. Mokhov + +## Installation + +### Windows / Visual Studio + +TODO + +### Mac OS X + +* Install OpenCV + +``` +brew install opencv3 +``` + +* Install Numpy for Blender viewer +``` +pip3 install numpy +``` + +and link numpy and cv2 to blender python3 site-package (rename / remove old numpy if needed) + +(tested with 1.10.4, previous versions happened to raise ``ImportError: numpy.core.multiarray failed to import`` when typing ``import cv2`` in python) + +* Build (start from the libfreenect2 root directory) +``` +mkdir build && cd build +cmake .. -DBUILD_STREAMER_RECORDER=ON +make +make install +``` +* Run the test program (accepts all the same options as Protonect with 3 extra): + - `./bin/ProtonectSR -record` -- to start recording frames + - `./bin/ProtonectSR -stream` -- to start streaming frames to a receiver application + - `./bin/ProtonectSR -replay` -- to start replaying recorded frames + - `./bin/ProtonectSR -replay -stream` -- to relay and stream recorded frames + - `./bin/ProtonectSR -record -stream` -- to record and stream frames + +### Linux + +* Install build tools +``` +sudo apt-get install opencv3 +``` + +* Build (start from the libfreenect2 root directory) +``` +mkdir build && cd build +cmake .. -DBUILD_STREAMER_RECORDER=ON +make +make install +``` + +* Run the test program (accepts all the same options as Protonect with 3 extra): + - `./bin/ProtonectSR -record` -- to start recording enable frames (`freenect2-record` presupposes this option) + - `./bin/ProtonectSR -stream` -- to start streaming frames to a receiver application (`freenect2-stream` presupposes this option) + - `./bin/ProtonectSR -replay` -- to start replaying recorded frames (`freenect2-replay` presupposes this option) + - `./bin/ProtonectSR -replay -stream` -- to relay and stream recorded frames + - `./bin/ProtonectSR -record -stream` -- to record and stream frames diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/blender_viewer/blender_viewer.blend b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/blender_viewer/blender_viewer.blend new file mode 100644 index 0000000000000000000000000000000000000000..5b0c2c0d392f22f25a46f71021fce0063ccecd65 GIT binary patch literal 516012 zcmeEv31C&#ng0z$h}KqYRd#sb7TI?~LiPj#vPnSERze655)DaA0)iV66yv_PxKwd# z)3KfDw06q404~$XzqPGxwbD-8I9r=(Ypb13hq251f8Ralckg#k?s>e0YQT5l<=pSw z^E=D$ch0%zoV%4Rsa#f3xpMN>8FOc^q}?jVaU$P8P!rohJG5o#-+Sa%*F~G6?3v=W zs#*DGzI3H)7b(R%7ZQ3*|cHX>sRvf2mDadEK~$7v?pPFXA4Z{oy>J?EWw zUg&T7^yyaIj2SaRF&r0{+m;^tbJ=Zavi>$K*GC(U{cSk*pFDZ86&o+jS+izYaYssX z%9JTqEY~?(erL~~ZN+h#$?DH_#`Y^JDzer?=FEm;jcx6%tgOt6w&B=6qks7M%*JO%f8GAajOrOa zadgk9(SCm*+ke?&Y9ke8Ufq-J|Gcw@_e92y^y;i^{|o4RRaH>n;bi+CLupMoXL!$O zk)~|_Zkm<;IaIdA5$BHX89AQvtNSn6{!1$>d-4}8qWo5P=_1^yQKNf?kLGi)-!^6Y zFPpcxr@XY%!^t$y88N=+%n|;WNVfk9I@d3zex!ohAlfI|KbMco$>l{pWcx2$oYzw> z$|>9b$g@WEj5yoZMYjJkDqr4W%C9JAs_lQ|xY0dl%pTJ-a;(p(r$6alvV3|^*@9xP zY*PQ3lZN)3edY+SY*PP4r2SGlXH`(Y&%8+exz5a*bVkqEF@D|g^sgxIlcv;S=rqzX z*Uziezi{Ego|(&*^)Nrs0=$nL9qBn^%&Z=E;V1PknZCTItZ1Q!lW9&KmfJI7*f~9; zsSYt#>d*CjIgN=>PEHs4kEOOXYw{UA<3t;g`j;%9)>F2y&`VS5KYYUIo?(;2^)Ftq zpl90hAQO;ELcexnj^U1cSKi6r|_Bk!7zpU4cllpUekeo>UIqVqX#!Z{{+4b}f zNmFVuigBVnN&Pv0QhT;#8ly)0ZJ+(6{^ezUonf3zlXZvojFb9vSXoZCp+AQ;%PI9Y zxt036WfbLMdOM~(~TSEgZ>Q?~z+qs9mNfoUo z8{%V3>`5XzXS#E z{+ON-XZiC3sej3eDLrM2^F1A<{ygvHIUeQ+Qh(;;0vbnD(wG4HK>yLCVg9t!d(Iy3 z&nu<=JRdDRpXSX}-}oo>=e2>;=h7Ho%x4g;gyu?0|PHMvOkk(?;rF zI&*1H>6|5$o|+>_{m-JcfqAD->lr)JpIboxN?IG>a>_a&_0OMvde6CM4foQN`j;-5 z(^I;P&b4~}CG{V9CY6(P85!|)NmYO5rzBqcr}Y8US9YcTuA_bY z;74AL!}+rPsGi2SJYhf9--g?~d2=X+<6-@6IQD1#!_s5F+S*zxmi4#c*gsyH%a$#( zVp)G1cH6dXRvf3fYu7F-mi4#g_u`8$w&GZS8;<=+Qat|e>PvsvZ=LwjuD>zgw%-+3 zToJqS$}2;EmtK0Q703Cv;kItwYQ=Frnwpxd*mdjHS+N&hc%c=?d9js|{V%`#ax0eW zoDI8j*suddPL#)@E+F;RY*?^TKV)hGqS2`Q4O>-JWyNuPw0>sA zHa0d|v0OK7Y0?^x6~}32(Z+&{EpGb{rc)3|SL(mJvonxxK>z&UIiipLox44(seitK zmHKz?_HkS`slSQqqrXU#v4L_LX-fUgat8I!55&_)|J^~3r2hHyf>^1)Sx!^`e5#|! ze;@sga)#*7Rbid@g|`1W^A^S?6mE^pomb+e1^sWh`R3TgPd*vD=FU4k9i{#go9D-7 zuJp?%^}pf1)>y|Qb+ManzR|@>{VPi5#@g3Uh?N%4_0sh8C+(l0^T=ISUFD@I^>4Uj za%|1A=^jq%f8*U(#ya-WdHZJn{0si(md%SzXrCXOTkdlz_2+VKyZdf0O{xFXg7vX! z1(#Bqs;pA~8?U}Iw&Ri~VmIx&#lu4X;=ICG`-Jte1#?Qh{7U_wq;lRv=S8lk{FC~B zYQ^+e-Rdc^f&!IassHXfu8r+@^5WR;Td()9A^IoW{$~~}@$$!fL4VHERd?OxrNOq; zfA(VHL$oQW|L$9M#csU)Iu9%L=QPf*oE=Eh)1T6i+H;yx|EluYvBLR&y^;EJUAytl ztGzTC3;o%h#rYL&O6qTxQ|dn_zalm_-)|pMe@^3u?Lm&9zgx~(m4P&+{&yMYJgI*f zwT<$UIUZK(@1}Wo@O&Afe?skF@_~J+Kc^*sQh$VpEA^KcH@}(lzpJIx-{eT@4^H8l z`kUAg{S$8gNCR$0|C`)7C-^X3v;CV|$o6ky-$(u9wtwzZ`_qs6+f05^*Cg5YZ`N69 zXV!n_#g2pZpSbN`>TT|4^gk~2k9+=y=DT;?7Q24^BeC6L{sR5;=FN{yE~t;qndgsT z<@#^*;fG^aiaC>9|DClwKQ^_dAeJ{@&0pmD@9tYWV%O8$aQ7`cy|E>)weh)<=lAs& zPmV1t^T)n?Za{t?XlRJt+urWkJch?Pc5%h*SlxwFVub~Ho*!_WmYb%SGx6L3*va(; zvDu6K`GIWzO`rKp?27yE_tNCK3UG7gEr?B?UmwexSLFG5>%Y5hj$L0z+;-gNVR?)U zY{TSBV&{wb0k5ATzxPqOK11v2SR;_@zZEnuxQyn(#f5%3sj-{uKZ&*f8*h&7+`K1t zlUT!m{yg8EUa%&Xmp|Xjv(&%k)1Qv*y!BQu&r<(6mHDw5D@cDmKa~34)OllU*Qc9f zyU9g)J^iT;@ch1TzF#(}|9zzWZ98^&IH`YW(cIXoB{QfF`B=p7rK#5=*k9^DeGTQc zFkJsD@3}{~wd;9iK{pVBtzGV5dSb->Ki2ez+f8e;Z^iQn) zhvYG%|M7qRZ)Z`elH#Khb{uK&-S|8wR$jphL0ymN^JF#@aw;PJ?)Y8>tkFGPzO*>zSi7y>BLxBvA?b$_3xlGZ@9~^ zJ5v8?YYSr2F81fLQvYl2xFfdqvBzS&Zs~jdckaC6*u?qGF}{9?d`SIwT>5y-ZC`o} zF7;nCeOYYn)aqD4o~k=i|J&*QoX2UbaLZ1A{Uk*HgxWvnt7xv@hS`Sx%%NNtVq5Aj z*E|>}_2+g0?M?kT?A#(>d$v9OIZe8D4E@-Z`t!O#zL@vQ_RsA?YR_1X8^0paZ?K=# z-%L~L&udtD`Z_%0r2d?S)Shj>{Sz+VZ&!?!`kUNJ{aN?H8D84Qx&Cq6e;8Nr%dGz#7wbQ9+ds4pbB`DOFI$}- z=+n)z9_Q=73Ag{-IywS8N&U;_76!XTQMuKh3>v;veOcf9CqXsS7psl&=5XL34>G*Q^Q5 zC7^#{-h8@$wKi5Y+kYNN>fdqcW3e0B?(^~}^`DWyT3r{_*AAur*WGrTdtWiH5ukjY z{-oiAE%Rfu&iCgBQvd58S?^vu1WxL|jOO=EmrjZm>1&5l|68e!KS67+w~M+i^>448 z5L>!nmZyi*f9FH>v7HZG?yX5k{rQ^lgto$1Ua_BF=)aTZgnVD|b+_N{l~d|JVg8ob z%zS_TEcM^nxF>e~ribX-p}MzR>c5cY>|5x*VmW6I(Ldq#e>*)}1U}h?{#+-^=lJ)% zvMu#j*R}n7-=+S1?|{5#R_f1b?4UXz)AaPGGH^Ki~7bTeL-~KVJ`(^Lwd3 zr**ryZp^mSU*2oWX-fUM&)I#8zosDd=dg1sg87C1ZaIbaY)k#+x&X%`_2;>voF7X4 zIc&vj|DJNTL-ha9pZ`t$nSc3{`ZI^}C-s*Y-Z%A^INq1~n^>v8iIe)9I8%QU8=`;0 z?cYpGwtq7n+5SzOZ2uW?Z-OuHO#OdU!%0) zKKaQ{hGICLmX;PPj^pEJF~ibhKc4^F(p*Dh7aMNh?H5~d9AABXy%ifTO@8LomL~gO zaKQ!EbfeLz70cJwZRM=4uD0Sh&1BoZ*;b@|ysZDcyk|q8PnTuneeOHV{scDnIc9j+ znf1Tmxe~naxeff8?q6g5kLUNFyJlgGbq@Re>ticpd=9Yv_T6!D?5Vr9gy#7;&_C|^ zADZ!fwp;5a#7e}x8SS61rSLO~cV2Ui$B|tBZJAgTTRC&F*G{DVH?-at>!ACJaeY(j zKX+b5Y{L9@dgjz0!}6Gl>kMBv;yIIi9#5|SPHvbV<9juce;&i3uHA6YR(k$(ZR{p} z{YbWdp5JewXHMlfU$%cP=iNFF9G}#G{pzW)OIJ?wt{uzv&(9m~c;b@4z06qu&nr>S zoX)1}$H=c-|L1aUrF%<}f4TlYz2H-^DFtwEq0#%u0~?O5|DAv;M!lYNnSz z&L{Ned`V8&mijN5wIFccfYg8Y&Rb%fPn1pS&uPpmSQd$L5H{9hvH!St%H2L~JbYNHNZ}ODU1eM9 zFSTc!)PHV%dEmOSdHrYCR=?gbHbnn~+P~xj`%-^dF5Z{=BRpKGzlk&T2L`Ux-^5D& z5gu+pf6AZ4n)(9+SL!cuyf5`fc(|tiCRXYX3|y(diIe&xJX}+M6C0v`-0?r+4RbU4 z9~b(^ZU1Z6u8rA#T=&=0eKcV|Zi_Y?9}C04&xT`vgb8!wrOE3wVHo!N^6m?)dF3=y zEoZzmIo){WjF%=Kvtf^vX0q+y>_4QPS^o*H|4MFnKePT9JkNrk%=(`i=l7HK-?-<0 zXvWu5c0RO;u5bF+H_-n1-7~eTrqVSP|JtZr|9#-H%VPYT8sd`rFPU8#yLkHY7~fya zV+^_e%X5RB^$!NFZ}{uK^xSAcZD8!n{UXxfXEEjcfX8qc!^~MYFE;H`|C!Uk`Y&C> z-T7dB;NC*H{$ERTyvkDl-cY&z&(C7syTxB8knO*m-etrb$!AVI{fSe)b|~M|!((LR zcWPZhY|cXe+L2uU-$L`k*8A>r=fhlfx&F`Bji=JwP~Ll;?D`-0sE;mH~gxbH$ zg}9%BZRpSC$*1e_C>Oi3{eutiDfQ=fm*s2i87JGn8(ut9z_zbHr{{CRSgF6uhkg#1 zaZ-N{i|37bpMS`k>l)>h`kUpH`g1vDS*8A*hI|f}ZBKv7pL~vi^C0z?@6KYJZ2ue< z+Vj5DpTo-MjoA*-KkoS7<%9DV@{{^=-0~;&H?dNGiQ)Y|`Wxv6^$(^g^*7Tr^*7Ts z!%JK0Z{no>62tqZ{w6k{zfsPB{sy2Sx{o}U(?ev_C?Z><j9&z#z@tiKJ*&tlqe?9cDIwPE>sr47s1 zPi;7UF4Tr&{}BD-wtut!Nc(tM|Kau{%Vq9!-yz$W+~+!HhKHS5{|old;D!4($)Vi; zAl835edI07JmD)qmao==kRX)*O*G~0hBj^p5S zD(VZrQx*H{%JqMK-wxkfh;;c}g|Ii$xKPdw*dO88mGAdqTk3C?Q?`GejJnC<^g z@vd4k3l;X`d>HO{t@M==J-vr2bda{FkpC z%loH8^iR0`&n*egx1c}QEBTHtwx#|&_m%Icmil+zcw^vMOsPL}QEWVO>gmsE()tjm zg`d=)=e~08BlYL`lKCtqcxQL6xJR39slQoHsXsq+D(Cl7f6k-So^9ywmQ$>qur2jB z)0FzV&z#Qpb&>jW8uGncY=`I{cl^(JvHhg}9Jl;Q{Y|{oUt)OQ)ZfHP{Y|XY-^5A% zO&r^1cxg-hO{~;kVtC)w-^5D&O{~=4#7X^4oT-{EPl|C(bax&F)F&5-9LJ{NoWqj##x_Yv_q+z*>i zW5eM4Har}S1E2Sr!)~hW{~CHejpq__JPG~t3ibV~G)F{QQvZ&}E{)xApZ_jissCzv z4=caN7vpBB|84ZVA&Hk_>d)^g-qrkRuRciq`CUts3Y+K} zkY9hGKhKr8oE_r1L#aQ18)lZcS5xZG*T-$ofAajEpB9db_B6(>=j-yi-bwxWn(+jlvx|9Ki2ez;e{;z%=Rzm_ncqo&uN(Dl=?3e>jI3E`n%7Z-s->KN$SsGXN&s=*bdP@?)YEwV(v@* zId1ur`kOeZzr^sqslSPp`kPp(zloFjn>e=3@Y0t0n^>v8#PGhUzloLln^>v8iIe)9 zI8%QU8=`;0?cYo*qyKR+{)^lG`P!%L$InIbTrTX#?ZSrRXG6m<>~|U6D`vy7Kd*h* zusr{>VfmV=4afdA9Q*TJ)`pFjCbv@?j{SL#XG@o#@w8$2-eDV#-&JhGv467d-|Ro6 zomu}mF4lkIwtuO&xu4PhxX?fD`5&6k&aaA{H~-4OvzXAI-`}~0=1lTEzH zgYL0JTs*eHSYp@xSJ3xAY2L2yx0LJu3+S0sp8LrAin0FB_u29Lh~&2s<@*0+lRp{b z?`9xP9>XEc8|j(29rRA3-MmIX<23#u+}wHP^vvm2`j(A<-I>RZ2*>4=&*Sl!6WA$q zpDusP2KVd9_5T~`ov}Nfpl@-CZ`ok|pRfP%v$b-ZFW3LMobp>Xa{Zs5H|2NT7U=s* z<@*1PcU&F2?x~9c_Z6qJ{y(GO0SKY!y#-j6QzS84j|E^LSBpHTak{9s?|&vDD2 z)F0vDO8q5<_f7qQfh+Ylu~L78hb!B^iDMh#!d$7piIw`BSW|x!EA=* z{w6j=|IGRS!>xbZ_RsgB+J3yo!*jr}AJ6}6IDU3948wk0w{1A~=ed{-%kAHW{nV#E zWyNuPHXQr&z09ek$#YH{j{SLlXiJype>N=7|7b9*&Oj z`#(7hZ*bSqe&~|F4%T^qxN%uNfu@fdtuwo}onqkAH&?B z{!0DN967FM>d^Cg#)Rol^}J-}(w=g1ftC6X9X*}OIo_)`QvbZgi+i{Zlvk)W63~C# z=$@f7#*qGgos;^PEDM%X>OX_ZIey#-FHNccqWt`x#d&!>6}q36`g7ZuG4TxQQ~f$; zYv(q9aNxS4?X&Ic&+${)bX#Iqw*NBbLvzA7slThcsGouM&t(#ApRv%N(-M!%j`%-_IPu@56H?cOIZT=je?Z;X~B9YMFj2Sbm zxY@I3hhjLc@#Du^ahwmlM&tbxTbLY;r;yAuA4E)YJ?>sA(^+!0<i4(2Z$&)8raa`x(rD@aI=5N*?X>>5J`)3* z^_S_$eXchM7v{>a=058fhGD;WX>$9p;n<)1Ix{WU+(+85+_xf}>2jZJ!?C|jXPdtn zzqB*@f4KBNbA&(d;d&6zzsR58aXpjmf8?k$1NBw5e;yl_RQh9Wv;B`e(;qK$nzH?u zEeQ5MvMr9M`H~#_$o9|Ur3G}JknKd)Yn~rSJJ9}(a>_JEj$+(c4{Nr6IS1mjW&1bF zDcgV9!eBXN`{y~HoCBNff1%Mw+uFI!A3U5z+83NYy(co#FQ2D>X+=-*q?J8oh5j5* z>VNu}yq@8s&+~YZ`tzJ=`ts#H?i_(Qk@}AuKf34i{4qTvY3_u4c>2@4pm^n^p0X)OD#puYathwW7+B z5)W(B+2#)p*p=F|?deatmDBowY)?{uwJzjqDD`LEB_~pUPJ_9TdGPe-G%NjbaoSRg zv13LC=7&;$ZvRqy#>zCza!UQpa>_K_wm;fGr%U}g4cX7J4gJH)DfKtYDfQ>My`0}m z{W%S(J=->&ZT^xMb3dRz#m({KC-paRQh$VpYwB-e1Nw{f7$4LkI8T%MBQ5Eg=}0@E ze-de$`pfiqU+OQ@)i36zpY+m{KK!8Wq8T( zlBolkI*_RYnL3cE1DQIIsRNlhkf{TiI*_RYnL3cE1DQIIsRNlhkf{TiI*_RYnL3cE z1DQIIsRNlhkf{TiI*_RYnL6-6)`5jfmY0=eJ5J>L2WnzF9OpgC3_mDJ_mWR@oR4Ll zK>NJyY5(;Z?4Ogr`b2h}AH;hxe{#vu@7%X|ram=UsQ3y1Fge+BUVct-ZCh zrKK@Cbwz9QWzo9!wyBkM_03Zo8`f`ZjYgZuXGYM7ZmZo);oGLJZ;Uo=h_=>jZHQhO zZ8gj(?olL`aWf2L80c3FT(p!PET@hlH|tk!zwr~=cl(VaBn`|raT-+kiSZobWgww-jwNIt&rOAifaH$uMw`bSR6+rH1ep2P7C z>ryW4`p*abdw+C~o3801;fm5#rCb1%^QW}W@tWJ-v)^#jL%)vWZFSr&!%EG4_=JlF za++Dr3C?c@@);z{%R}yI&%5c`VulX&7k}5~-*ex6XadJsuic!scirQ?S15N|YtZeS z_S#1|eD2x@T%4I+*QSnB`8e~HLoV#6X`lVERWEa#cgWZ`P}QGzX`hepIYZe9XS&rZ zXI4Zmq*GU9!Is8G^JrqW%m)zr?o;{hyhFKr9#-y}CzQJ{Tjgup$HVjIoxc&GGsxSE zx5GR|C;-y`9qn`eIzRG@&~`$H+zmK{1Fq{YKX-A658)kW9F0blE)jAO4!HWfUwter z-Pnmi9Kr#&=dS;9afpx8;4OBda*@kH$ zyujP?kMO|fJ+APG7rcT8v-}7TJlX-`MfnkriAQ+gaUAh_`Pc0Y$C(=NL&IH%vE398+>T<$;UAwr2M)}3PIgXm zt{*(Y{VCj${(`TtaO#YcMR9ZKcpIUde)<=>KnLj3nWJ=pUT*d~zEbXV)W6~vrK1FP zHhG?|4?Lz%rgv!jRPEv%i{siG4r@|!5(Ua~20I^joa{jqTQ2e9da z-ze*w$WY&7{|2yEs$or`3r&yOxs_d}8LAg@7z0Exb z%S^uh-N_}==Kb3TbsTUU{y81|JL&sN_On~@+wT?4{QGb3-}lG`ZafRFY$(2S@q(f= zC;cNIcOGAL@$;V>7cHJp_#Z`VV;lGV<`)TG%y`CpnZoh0SrpeDgl7!f|48w2ToX0E zsHUQH=C&^#YgWXYkb|JYA?aP!3Rj(xhZl=4uz^PK}l_3f*ROTNB<($9Y8%&Ug(e{0Y^g|lDi zqWsR9xw>V`OUqt6RQkvxC%p9NA0It<*__t0um9nV7ytN^fo0zvxYx}C=Y!+q?cyI? zeW3ZAyrOldpHskg>Gw`4`tG{2;wS%Ryc=f8=|3<0&4@_xQ(vq+z{mf1`K~%>xS>wcaPiWUWyar`hTV%MiPBNIt)D*+NbQY zPAXue^xLm4DZ;rd>tuDl3XRmO&xz$dJdVVCxs3ed^KcgZ%^7wd?VVi4`TzE-uNFGa zRTbo6*@n=ZVK5K!-?wdmPK>xLeDHzcMXqj?I_7k5AA0jYy45g%}Bec4|JM>ybev(>sg;sY+0tyT?@9>M|FdxF9tKH%Qq6EM|i z;1CYD`X?1Hh|kCQ>)8?VL^$9&pHeu)=i|Oh)z424;ehMLwvx!F_3Y7J`oPMJwsJHKzzV`Gb@-L!U5Nc)5Dqx>1Bef}HwNZYjq!OwIN%Tt@xhK|GfwHp z*Duh&VEuic&L_g79h&Wmb#$+P=a24}6!#BVP0?Hax-ue@NpIFY;}+U!;%lz~_um{2^Yn zUt9VJ4}6}+BVOd+Y|ls^;eoH$c*KkJZFqzSevif@Uhr@B3rHW~f$!FM#EX8x#vj51 ze^}!YFYq@05FYs4k-9(9@gU!b$E^Pd5BwU9N4&tB{S?ZN@W6L!JmN*VHax-uzfa>4 zFWQgU-ywa32fkP15ifYR;SnDAVWV{W*YP0VHax-uU#0Pg7yO|gH~B|+;J0Z!;zjyq z|BLb?Jn&r_k9d);4Uh1^AJTZli}sUi^vg&e;epS=_z*nk@rDhL@WAJ3JmN+FgY%2Y zAHoA)uknZ%?cRn*c;NSFJmN*ZZFqzSzFXrFFX}IJF!PV_z~eaLMZF8tZ!ZNttkc7~ z!?5wH{vsZvkMp1He8%BpG*=Vr4kv`IJ9LlJ{flE;bdNSpfbBZ1w6uE$ycAC921R?)a;gaUAs@He&YdM zpaXP42BDX0hps!UD|MWf(y(<0_TvrL)B4xCgQ^`WhyCv_>rz75Lc2R!>kb_6UWym} z1^SPwTU9$ozk+cG&I9OAF)pJh-0g=nsz-bK4z=&>>cP zXNgdFgRieq8qAluaZKEQ;E=M-Q2ob7{{bDK3vvj(T)X48a;N0)U%{~fWdCW$m{zxQ?+MHW$T>GWABekb z^{Q3NmsQuSSXEQk+|(Z3){Y~Ix#{A|Q%Tgw+D~G!7}uw>4F50_Jb@SRl$)z~0)HlU zW#zJp%9Tu0bo2V?h7HjTW{CK9y7)?+YGg%Y?e=JE{KPCrn~0}>p<@>s$8~2J@C8rc z1w2)qr+5N?0T3B}IXBgAj@Gm!o7;5p)$O%S8)_Syo1&>Rb?aXgPv0^MS7F#}f+z3- zp6Vwkp1_|8HOkr69&L>_n}Ook>Ef%CO)w-c%Qa7CyVDm90|@X0Ucgi5M8y;M3xLQl z%UNH$p`mG$8Om;_i?2>L!H}$c=g+D>H5kVh7&e>W3A})(u1Sg~@Ml8Ja&D&@wb=|5 z$4(btoos?3c^RpBddN7o(6HGAPv8YSbx&42fj<*!lygHv8+TD=D7&35z9QKKL$Xr+ zCsm)mY#ggHY&O9YcmYqnQxs3&&xHErj5gIZC)egUu5|I0DWw`LMSYB%xM03nShB$rcmYqHvlLI@&xE3!>uE$>v#GUtOG}#>B(9w7x2_QNAU#y5EoqVw5h(itsS08xar~-rkJkG;$P@|$MvaN zdeVN#&9z>;125pIcdp_I{25Vs{Zqr`ZOx5a>Gc*3?X_)nW+=N2o>IjxYNAA`N}b=( z6y@8;>XK{rZpMDDc|tBxpGx2%T+}D<0-kc_DW1TefVjIT=jLX<#jU2Lw!J>7oTiIk z>ZTi6k!-rM9N)3jXPrCReN!DMaE8W$4oXPLJklP$-=zZ`6UcggVk>UybnNXCo zt);o$JeG)^F20)5jnHCUOA2#vEe0aw>kN4F_5RP z>GK`mD|?zaGEeMdm-Fjhztg;cr<^jy6Zk`TxG1N-cvrJI+E$NaiMZ+F6G`JpVQlBS zi6KDn1YW>XZn@$K^~!{zoK4NGn`;}BAHAfDUzTFJvK$-r`OaK#nj{11eeeWcz*AL) z;tBkjP?VFe1aE1L*0iE37)_UcCTyd_$5 zd31Y{O)p)%J0yslpLDvi92J_U<=#HC-7%NQO+$}Yjo2yL&Ue! z#jn0Fva~kIwLvpS@9J@Zxz0;3811uxC-4HEx~mjV;Lil2oVwlBH8(c5CR3%-#p`xg zo@~0Z9FJId3VXN@Jb@SR)VoOW1pZ|FypM9Kaps2F_F6MUd^=tI!f5m6XnX7SNJY{~ zdl}np8E4M$Liju23A})(obwe=;Lk^>yShB$rcmYqj zOB7Gw&xDpOUskEFztO9HYa5!{lWBGIuyVS1zK%dQi=~vfF3j7yAOEdUxCw^MCU^ob z;Hhe<;tBkj(B)-|E6Z2OE0xXb`F+S{IGdd=-WG2%{n2<=o6L@jW)K`G;gfg5N)q*Nbnt+>Ef5TsYaSNMkHCT#kEZ2j_27|d4cmglrsdKsF z3H+H*zns+Sn%XwfG{OuL*G?C|Dy39|S^AZ3cjg7PNHCadfhX_+p1M{jp1_|8^~<>- z+Sp!OlPp{5;ww1SNP2AjK=XvMVcs$h9>N7r-~~K&U!Zsbe*)s}`sMT(s%dPlyFAg} zJYBrUP-ICGsRm2&oQ0?H!CRqXL0)HmdFK27C(S7|wq712+(#5Y#Db-*p zN;OaGgWk@WhRr5;0x#exXO-d!{FzX{oGIK~K#`@3PxICSw>T$gp3X7~XWD!iJb@SR zl)GB-1pbVuL^)Ht)f9{!E--PI+a@3}v^|#UG7%@aqteG^JLyPP)`W4@%XvMU%^Rx_G+MLdiy|lT0>H zj4hfc^E$$aKqzH^C-4HE>enfrz@G{A%IRJ~sM%cGRJ$pL;tBkjP+86m4I4LZ zX-lFq89b+guSg+HvkaRwPv&zPCz}Du22bDxJXO^zp1_|8l{~ezMC-OR)+Y6`g>>=N zDWqwZ;ZL-#!sokcopXO> z^6ImJC-4HE>RT00;Lik#a;7qEani*fjd{x~8jmwi&l-gjmlnJu;0e5dr_MIT6ZrE0 zdPkHq>3e-SigfX5-RP^!FiP{JO|RVzgokj!6Lr@-9F{qT-(x;I8A+dP7<$pqDK;vNz^FB zAq!7~jBsp%C-4HEa<(a+z@G^fJSAB|6;rzS^cYfk_!Er_xIVpN6i&a+Ip7PPzzcZ7 z`%b}M07Ql;XG7D*#w|47ORA4b7r!W#M2$k+LF<{!(}kk#agZD%9Glu9*F-x`Vt?}7hc+UGW(YrGGBOM{-V z*QEAFm=>K`q=)#C9^OBXeE8|%3b2kKLB~uF@gqG%gM9eutx|6QK!5~YnV$O|4b9)T z2+w@tI~2C)Fh;Q*@2~!Y9RA1Orcj%C&s~gOdazd?lMdH|4k9LJm+I&Lj}9_Vdu~v+ z4C^@SDwK`yYozgA;CIGWy5HA;+voclseKptZ5qT43KLO(7nsZDZpX-XfuRF*$=$7V zfnKUGHRaC1`LF1bkwbRLIM?nW>m7aI22>6|pu6|8_{WRsu!h-dyO+>!pqi(kbu$QiFANj%mgrTW)74qc!Fbg8;o z=>ok}>ZelQ!&_CEa!p(L+WwxRC$R2&8r~T~aaEK#a6|jCAt%mo_;=)u+bVzG{5fg` zVeLi5lI`}<99v?s9y#5=RtV?<9iR)+gI>y}_EFLx`Z3a_Hf6pp5*#B;Lwi3@xRyY2J6k~e9!r_6c>NbS-YYA zTk_v?ju2POm$@CQ-*biz&;{j!UdsM7aXIH@9CIAj@98Yp4G;?i_^vkkH@3Nd zLpVPk-c#!|4-Qo8G>&s}_8|H~^opzrSseF~Hd&9yQXJ;SF-bqumdE^5^^ zpbK<>E_n|IbynFqg{~_sc*W1!Ddn*p%D$64_tKBgM-z3Yc?a$DhVvEM^0<4@|3l+* zr-YyR*Vp0bI{aQ|(!e{N5eam{tPB4}(J$<}b(Zrhsug^FlmZ+B8+3sV(53q!r3>^@ zMHy1=INx~*#rnlY-%(wN zU5LeJocjho;p|MHy>Oq;Kh`C@y|7r>^e;p-d`7i1B7!S1gv&M!7yP8v`b zP}j8kOSyU*Qne7VQHVws6O|#|CO(X>!4sA%^%4U3=SpijLY2|AN~B3j3GX4)}M_{sH#m zP=w$A7s5VVGS9_^<^TLWw|=GN3a4P(-{Ae*sj7Kmwfewi9fwFpVOYc z_|X#fms{1a`@i;7Rdy--{v6w0{>6VgIgf2l|Id{ELppu44Eu|6X8ld%%>z5GY@Nm7 zyCQEEv){p@95?^G-$BPHj9WhDBftIOga4)Zc=ZoIo>6e#iv4pJZTm9g@A%mli%Q?v zHRH`)A93@~#~VNU%NY%ef5LjW<(XAC^uRD(9`^e%ZdVWeI_is8{6zfDUUK6>*6{b) zv-x)b;H`f*#M3`E|Ka(p6VkFS=FFLW%HFqKMM}T@>XITFe7Rc|y&N5hx%&p*BoBa23b zIXQRH-pOU0f3-IJUO9PKwjs_*&R~YUZ`%O9!cSZlKKQ`!BAoAXpH%%U&UgEsQg$$7 z#{H%pU#(Ebu^t!FiOYfz zJ~<{XzZ-Oc4$$RLm(m4#sS?orbIxE_ z2j70iwWThW`$;qRnF7Rm^tVd4wuN4BiKnLi8^q`lrZ=!kboL6wn zVO=`ry7oiF`4{QO^Vr|&K>&2Xx)9s)xEGJRqsB2gw2$-4Ad2yw0bk7i83q+WK)`}7 z?1}Vc0FEi1Esynweb%L(GJ^5h>$ESsbByC~o`HV)6z=5Yrgp!ndg@NxZ>r7}3a9_6V=GhdmwG7MxGI5rqicc0hP zN1Iw3rnr5A<1}o--my`JOfEAF9IFhN_nYSE`%US_J8$Fh&0ezV_4RCA-|l@z%?EJZ zyX$l6`gXUzzI_6bi>)Th8J7B;!vwo*XO!9uLHD6Wn!yWb|Wq1F* za%FsB`xq|+hw*aP--h51-c+ID!1~L7(tMLQ*vhi~4g?*&zY@i5GN%4$vj<%SspMrLuc5>+q7Fb+*^M%yu{Z zendZ>r*zSew?oSDuGhhSQ~L)UHIKQ4mOgnNL&xYk>W?T6{w20?xF_ky_1N50EEKao zka(9@xctCj8mPak|cz&p-G6>=oq;>5#iMV23Y8JMSjkR=BOk z)5VO*wEblJ#~!yAK5gOr^li!(nMd5vPaiR0KMPQ=&-Z<^MI{>K`!X*rWFkD@mCC%x z`vv{bM{m#Mp7XJnqQ^MpFzs`guIJQw2ICowS2~~muaEI@+@FW>3we1P*WYXD$MRqvVZJ`C zXbP10SRJ=O2j~J_p_eM;Tv~rURur6zc1d3NMf(K~?Kd31(Kz2dMdMqiB++^LB3%K8awa;SBrM;DuHC-#bh@Wxan>;R$AI{o z0=8iblWC_`>QxZ>R8%^ZQr+etzMdJBt5fY|RU7`x~EEJBsfl{B*+n4~64nKcu)u z5q>^l*j`WZa$Nte@uTZbC|O-J>c!u*eT4Hn1 zz4#ILeOYQ;#d+oJf7YM=!p~p);eqmw=iIce-|+q7)5df@zhTW+U4CA?=PUaMz59*A z&wb+iZuvGw{_%yTQ*S(Y_u5e|A3gh?dSUy3zdbm0=W{Pm952k<*ih1Q-=|(Exa6z* zDUSX7hA%kq`t-+&zJ2=l4^SKjzPEPi{@0$k=*8lXjVh%$s7xQu?aiO}t;dP@;r`8{ zA5JMAb;`U0Ti?6&g>`>=oa(At`(QSIP`JRm7g(|TPHC1gK8wX7bcpMMzp48pJBssO zSz0{g^rs5{7^8wc6P}Z;A@zI_$!pAe!E6bZVw=}mk@CWFeO;e^#n@*_Ywy^p!Oh50Q z_s=TbdhM?Hma;pw+xuR4zWR}LdTK*?`WU%cled?bm)+~0f%tF<^Gex zAwGnsyRv9hsoG0~T!aH|jm9B94$E8Y#2^mgfa}ya#HUb+8ux}_{5Fc=rIh);GFH z|JyA5BRue38jpC9?=A}-;ekJ-@rW1c+VBVue9ku&e~1_OLzeUr9{4op$n;{23jv}@EKga>|)#v@+f@+^3S2fkb55ii=04Uh1^AJ%xpi~487BRufAdi;QR z!5hk9wqJw?9^(+i3;u2CBRuekAMt{J)B_x6{`ZoB@ebCty1uLG55l4TqaV%H{R!F? z!m-O^fgC!k^GIUwV29qAu0~+7m_Hdf5K&Ue=^I~eaTm!K>Gdj9&^XY`{$tpbV0eG zmutVXxsv9B2XV}K>us%*Q_?(`j?j-cReR`qjka+er^z_3LgTN}MbDQ8l1sXD3?4wS zcw8cA9Ctj`VKpKS22$&d?3YYz!8qPei`z>HC5ZO+P1*;q@$#W5wgy4}f&K#hNB!%n z9iv}CzlDBum_84oUq%88Xk3W7L?d~ga>}z=o86pd1>eu|0~P-^?XG!E*}dOOuKxfI z^)wuRwb6h4l-9O+Lw}+y+h07dHk<==@R~ZWi)**g09}v;=tY+$4$Ai>&X~FQ#RtE)OY4I7^8=+^=z#u%?T^!;mF{8g zFOKxS#AmargHc*7=)xLuJvKKpCet>(%Po)1i<%7<6is|prf*7|zd;A+0_CBXvR|k7 zPhIf}j>UGoULHG8xdiP&etTMf9ujVj;m1KUtVK3o|k?$YsbJZ(9a8F z-I4V;?0X{|lLVW#JSO+^4ypQ`_pgc7bBRr7pWFEm;tT2jo+4xV*8C`bKFU_FTD5#x zb!$THu`4T=RaCBI znxdQ6M>lMUZZJc{x6{Q}>Qo~u8f&*lTjM8YIohOoy3jbTn_0jYJb@SRwC7(GPv9>A zBEv7|rrOQXnwDg9n=Zb(y|!sXZDVs&GOV%1(*dO`#XPD^-0_t?}o|_2@9UU3wS#GGsP45GodC=+o?vWD?Vn(a64Um zb+QSDWMib}=^^77o`sj*;0e5dr(tg?p1_~P@V-&b4GnGFMVX=OcDneAWD^X@O7)*q zefqL-EbIy{cmglr3F8y+XGA40)r>a>+pTqK%funpbFB&QOA6BaT&2q1Jb8h6k zyYsgyez>{+q0{@NayfjwjrHxIu@7*V-|hR)5PYBaKJTtjaVNH}I8#@O;SB0nL|9%| z)Nbg!dsg-chkr-jBwud)21Lc;uPY`Ns}afjXhIk009~qnp>%;>Dog$Mz0a%*|L&oT zay>S;Eay8k%s%$s`wShR%b{MS3-nUu^xyN$c7J;BGj!p$b+^iF;P0{e-e>3lUFvl| z2)$Gx&!q22H@@N*m~3a?%WOYEzh~&j>+IL-iSpyL&l}dM*p|oLgZ>|Por&XiW-)d_qx$Q4^ zQX2lf34Zz=)99IX@!sc-r{sH|3ID=Fg#B4t%R$D6<-faj^;hM4pRcC!;JwecUVFv- z>>vDnaY@^~&ocfW=C3XB)5hMHpLyc6$?*SzeD5=-|DZ_UEJOD1$ISZMKfZThXUpxg zIJRNuK2rSB%I=xpSlRtmw(q}Yz^oJV>Stx0_#N&yocBJttFXT5OGR8Jj_ac%=FWWj z;duvky>XX2{fkZhhoUFWK5gcmzxRFjz0W^b@tOJcWlqrw zT^&3b@`r{FgiT zQ@tzs&a5#ns@8)Lj>GSL{#4Q2;=E_y+W+>q?%O}`*T3A)?MuD8nCrRYB=X*8jO+iI z!ZZFzo7;vn?|nWJO-Jo`*n6M%QtX)bVIGM4@-aWeeQmf;4cB2YACwv7@jxy0)qFj1 z$dJmM&*_>V=YduKr}}lcy?Wlc?|+rQj4x~-^9|r|p5FG~A@~w{Zra`Syl+J|-514M zV)H=EYlkyr-8U#Mng_zAwx{|~zEf%7z-;<1+DT4j&ItF%fFp0<>#D#RS>ZS)Zb?|% zSN4(P{GdWW7w7<8a{fo@0=+({{3V<2)w&*=ICX#8u{RHd4$uYd4SK0^^8BLwWxvd9 zpX}OCkSEVKc)L|Ojyo`*eL3Hd$8|6`d@eDri$CMsMl+e)5F(CyH!Y5Gd$H-lF{$~6 zibUCQBGiZW{6W=ExJO1Doe}*sVrMwQOQ?(*VoovzM-|b#TL%ypDw;E z#dKwU3h8<;*QclHcbYs9vX6cR^%eCOK~b+A_dOX7_0jxXuTyc$?h&t4l;2)4e@j*Q zntytzobP$%I>hr~)ZZOs^M?A%wtpP``+Ey$w7cNf7wjuM>CI2L-xZ^;u`-O#a(55D zjqZKDime2;yC{BJ{pFbCX4>*tf7oYT?xOmO^Z36|rg%(uq;1HN0{j(^vwo>YZ$6iJ zGDS4x^jdd(?8n(r{M1J~Dt`aE{|z<&Sa1(dUpBWcYu*rD)f!Fm8ciZxbBe6fUUD(6 z!#IzR@rLoA`5Xh*{c#;Yg;sx0p_bX=7 zA8$ju2M+B%_s=2Yyp9Rf?s>zwZl__Zqqe^&&u|WKu#B)Y&Vw5|&Kp8&{rpR83&d|g zR4o2DFY#E7h~6g?x2k2O4=)-Rz0bU}NAUM>UuSQjW1UzcNV z{0$wT3(5(-lrA$=zg04-V&*?J?EhTeXNxbqcFO*zzk9!No&h@O4x#$YTX2O}`5leF z@!HD}V_n&_k4E}OGY;;@)|^Mr)9Lfn4=Hj>Hxx+Ly_aQ3iG%Mb%Yz$)!Pn*e_-vz| zcS;%Z-~$i1Yk-XBeHo94GP9duAj3e0feZr~1~Lp}7|1Y?VIadmhJg$N83r;8WEjXW zkYOOhz=wJfPsotf79CA;)dL97ZuaX$vuU=UZ-B`P&vE4k7 zgdLWnLjzR0RVOHSn|8Z$lzm9MhtF5GnVk7N2t5g51_`zKzS9UDLHfU=ea>Ib!0>eF zkh=kgaKPnh9O6TGyj>qSgafW#;}9Qk=69+P4!AuUhxmM)+CzE>2VA$tAwJ;vJ5^kM z;1CYD!y1S9faC8}NgTofmz%BlM0~*g)P3g5|Naxg0k=lu5TB3Z^n4t`0oSQ#1h%`2^biiXVY;3pKHz>jm~npj5DqxB z6T}A`y^ki4PlN*w;Se9}FXi~ST=GQw!*^D?bUqP2$5QXOoQy|!;13z?8hEoF0gv#& z=L}Ny2l3|V^v(JNJi-H?r}2mv>DurJ4}87GBVM#`vtA;7ga>|)#v|T(oqro1;eqeg zc*KkR=jwU~U64M)1AkcK5iiPZ!y`QKxr254)$t(TW;;Rp2oL-kjYqsl*M>)U;5#)Q z@go17mhvM!@cT3#@q&LF9^rxS)p*2QKitj}ReHld5=_^N)YxI&Iw+&S;klwv{L%bQ zQ^yx7)cX*%+voX6{vJ@~J5A65xnW-u5<8LWPh6WA1+%<;}m?C$*(nT zDDTgu?pVh5r6l$II%Da(w)#6w&4ULzYw4HxmgskyIOhJmaeFDD45Gaq?e8?9zrgd= zxn-&yd;N;;H_Uz<=LK;0Gtv~_X}W+Y&CVV_V5R#V6Yf6{islQYDt@?KA60hVDarL8 zz@eUoAWdh?f1vO=+~hGbU|LBmus^Q9sl(*jtwAtptI~1w#QR}XX--Vr}-bO zZM^RSy37sXjiPX$uii=Z(SN>r{D8cH{6mU%7rJnWu=vebOxqT7_YhUTyXJ@2^X@|3 z4obq0+u}WvKkLHpYeD*WUrX<)@zY87J0$7ikJfig##0?S>qsQgaqt9Qz*EjA6i?vK zjLLuCcx$w2L-HRINgJP1s=-p+MDMlv5_uH{y`52p%_evPFW@QnG{qD6GogMtH#BUH zHnlZ0H?^5z;@RoqD^f}|n4>4@`y9*@zXL*Uqotwu!4r4^PgSQYp1_|8^~+h?)ZS3r z*ihS+;`cdH!V1pW{nuFuov=60$~ zHR~I{t)5R~1w%2Z` zZLd9ILU988*uvA9AsFxkUcgh%D8&=_GogMto42&LY-u--AIVM^zdWT>gSlFzdE#$) z$}Mc%37)_Uc*-5EcmjVi9^UuMdF*}{=S=!84$tqfq1~MW58;9*@B*Hy#web^pMbc# zK2ICz-E?j3+Z&VV#U;JoZcmglrse8QQ3H+H*lc!_{<>}&&#(12+zsNk9-(PgsNsR)d-GLYI z)O)7l3H%u_alUigU0brBLo|6x7Jsz9zsNk9-(TdFU2_9Z-~~M8oUM2QeJ zMdsAbn!>)`-{vIHjE3-hKF#$6L=s<{@zZ4>y$_zi3wWx} zRXl+|6S}-?ab@``@tN)Oq5HalIsE#74O_tCm9*C+FQcVb8+;0e5dr_S>f zPvFml`sHklZjCm!)iiIc*+6sChDI}FxScM3iJNMqd1Is^iByAmxyHg1e}l~2z!P`@ zPhArfPvFnQ`Q>bHt!--K6(}=ETsvL-s+3XE%$6L50-kcFD4xKd3H8g_8f~oQD+!4*q+&`J zzcQs%gQY0dJgpCUJ0CM_Ho+5k0Z+M86;I&Lg!<*&)Y`nIB{`BPvUKqaQ%W^hiW4+X z=K1cFU@+GLPv8YSRZUYofj<-Kmow?1xEocv_@nVX^cyVmyRf%GgD3C;p6aJ7p1@xm zp0>0!Hq^OI&kPjD7CfbduSf|M%uto)$*fPfPeq0XPv8YSbvB|qIf&ZNr2 z_dm%E?N9oFC-4HE>hl#(;7?+B-z(?k(d~4DSWR0rxooG4Ki^F@Qk`V7fnsdYJQW0d z9p?nYW)nPt7x2_spm+j*Ce$luU2|h|YYpAjQ@bfjHy|cjx6;LzbFz`8$tD{p#-*Ak zc%mMKJ-G{>zzcZ7eaGMral!SV>1>LhSu2AIgLBp*$!z?A437WQ`4U z?_!E)PQ=9DjZ{xI!S#0(cwUO{;Yfs2oFk52PTrrG_=zVjAAg4|Y>Q2HoV_6j zm?!qf^J{pXt#^TH$9T@oe4ZH3)#5o}8TC)}iDMmko^lGmX+Y&kKF@ZzQpc~|L;Cr- z`ik)WQO3{vobL{b7C1aN6^ie;ze3^l^J{zm7_`mE4IAZg@6%X!4`KPc@Y)T1p6#cD zM>zaTYzxG1KvXRL_d*ko)rjbQGNB7}fG$WLdeNuB4?50u<;uURY|W21y_9?J?VgSB z(gjagCuEz~!WOuJ`1#kWGUu9ms@VPZtFO|uG*U_iZv(Pv8lOX&EL3(ve>r~Ea9v1f zGbYmxfqbA|tjk-J1GKx>Xg|EC2xc>EjXxNoe_A_q`Ov?4{h9X1dw$UG;W=HrHvrH1 zcN*_Mz;lk(GSWbk?2eT!8;26xXwW#=wRu73j#?I;}od);ny|CY}4 zy3SmRi~2XuRnL{P$^)ph*-mQD>%Oh|;&|kCtUj*`9iR)!1ih5~Y2tG6%Q)tgWYf80 zglnHl>l|2Pd_V^nq8HB4zrn_FFCKSC>GB{=`dJr;bQwf3KIoiEzaww59{-xq=EgC} z&9vpQ{;<#Od>VCVXm77lrV{DjLW;g zBEF#%DaZSU{^fjS;3T#=+zPs(0QMQ=$zgcoF(}@b#@AqYWD5H?TO7Y~cK9S?) z%?&^GHyovV@0rApq1glbBm7u5ytFyAwAF~%4?oa2o^9AC81^8;9&Fe-hJB)8pJdn{ zG3=8K`=f^aF~dH^u!k7-sfPV=!~TR}pJv#sh~)1K!yanb!wh@4VUIBEk%m3WutyvA z7{eZG*b&1XXV~Kn`%J?=%dpQj>~jqJT*J;a?DGtJf?-cI>`8__*|4V=_Ef{37O*qz zBhx;D?YDom57f^+XZ*_T-(ll@ps?}YP}q2HDD3V#-wxmpzZkT;e-pHG^!Wtm3#8Az z3G?OK>U`nb>U`nb>U`nb>U`nb>U`nb>U`nb>U`nb>U`nbeExGB@PYjKw#uJxtNi)4 z%Aaqm{Q0)ZpKq)D`L@cRZ>#+Iw#py$LH>MO<#+I zw#uJxtNi)4=1;e80eUhrYE(**a{G*BCk9PQ+ zUml(OVEqc~Ral=#ezC5F_hjO|l~~8ZIz7U(%j=r!$>sH{tgN37ek$aBbM=?0b*kPr z<#sJmZdEk7^()}8PLj7Q1mAH5t&8y1f7j=kudCfW2LBwZ>+{e7x^%A&>a0pRw%j>* z`YR}LmNT|I>)<5UzJoj;)d$|=0Sj%9D96G273{C*buE1uPBHD21m8FJsPokU{6moV zF2}!$(&l<>ZYq`&=;G<}`>n>Clq>uY5dRK(B z7m@CTiz+XgS;5cKwKq4@V`AP@D86XP8wj_wL@sJ*jYd|c@+!ms&)&DdS5aL5Zyvw}6%YXfzAg_jJ|IYV zM3Cg>0R#m>!Xx4%1h|ltkfce#p#JJ@t2J${TAxANpQ*3LR$G6T{+jwC3f0)6ec0C2 zT5J33BkjK`wYE*Qb^qtg%=hl@+})eI_XY`?xu3nWXXczUGv6~aJ3F&G%Q!tq&x3P) zdQ8hZ@UjO3C*T5{zyth1!`JIWeO+Ui-jUXuI@n|UROM;kt8j2Nca1Ts6AECQZlL;f z1^MgUIwVaC-;RsHs;S5`T9R);Uo-7Ma>^YP|e%JP(|t!PP|j->Gw*QYcM7`F}pH~|;n z)N+}`3Ha$5i7Dr%9Sx01T{jfYKIL;ug2nz))Js5Lz@YsN8K(_eRE9<~37minaB8oR zH~~LhGzO>I%IygcLP=Sw@=Ke-+x0y8rPnK*rfP!m#_PZZICX81H~~LRRctwZzK$P* zlTZ2ncn`lw;e@gQ9~z>@IMgTL0-Sm(B~HLk7mO*V&uyYpmG6)J==Q%S+uatea6>hk zN#F!rfKy)6xG<>U^(Q#%)T|+g!n3&imG^xr*$C<$uK2k;QrGJ$TCk{b<^4dR)@AGkA zg!?3D#QhWKf$H;GLA?8<{9(@dc}Z&nrvXs7?k%#v<96Oc0~FBDQr|53>e4_4~1zG=y zJW3*TFUyD1Ehb*mygC~GzIpXt4r4BofAX3y&6)jp-8V^pq`)oz%fIo*N9)IAL|-?4 zk;>El*ey9M|NZZOb-|j~uFtO<0-uSeR2 z>TygS!OZQmjZ|VC`#Fl>6tJERKHX=Y+}vCjy?R{;7QS#`Sw8ON(r6Ppp8s@rkcIEg z)gPgpe?EAuOWy%B0$DfF+0jL86N%jwB^2P{MjImx`f8ZljhBZ+s=?{>ybe3Ua^ao3 zC*-r;B2<8^8rjd{de^>P($4fYsIuU_mv1>~CvyySm%1UCz%d(Gmf!1BzG(Z>Uh=&c z{?6r>hD;Pkj4Iav)<2oBT;PHyYhnwrt=LIgo)5%-*adcgUGnOrU0^Sn_X>J$;N1OI zIfyoXwU6mv({WHmd>4gRG`!d1$8*~ZeTuNP)*B8QkEQ*Z4rqw)zeUki#5>8wF06@L z526kV3&z)XIAdWK*a3Fws+V?wy<{Hi$qrw8#>y|#d-gGHx64)!92qxu9`VvH)CJn@ zQk8a4U@ax%|HsoWwOH#wiEE9Y=Anv(U0?^;rMyAf1@;o@N8eAT_gC5JvNjO`McC+NEf^M~l*_mAI_moNi%z`7ID_IRWreZICt3i#d_*O#HB@nHHx znXf5*PJSl^yKpGdw{x(jc(grkAe^&Zswg8EpZ%21?cET@ak$RFe(Dl#1g>8leg4y5 zd3YBJ)8zC^$r#Y{l1hICtck@!!Nt`+zlzg$PIA^X(iSf{g^f)Oh4u7hyd2u$ zkM~1w%voDky(wHm4|r^9s@_@Mv@2)h)^Nop`Z^(P$5gqKK2g<>vr*s_JTJXSNFEZK>Q8u4t&k zE%~SMhBHxDc7eR_#d~Ofr5GOHG|!dqDdPRLsDL^tTeXB1s_A0@TdOx2GiJ^dV|<;d z586JC0&D9Ic^?vJR`(;y@4Zse*;h%w+mQK#9DKY_4?2yW(Q}U2cwGZ`(S}j~!}CRX zd7Kp_PNe^~lIl|VA=1@B4t$X7RdUd039l82Lk@h9%ibx=2YrycYlu@0e2^+ z>sE5mXUQ?1mK^vXhjs#ekZVqJ<`aC710VE(Zcel8mra3rs{Q?q&e=d!iUvRGsb23G zSC$7qxbT?e5T<@b^YKjib2JoF;p$cJt}@I$^z$wM#f-tAHUzz_LWB@eww z*GnG!knd9R&|9wRe?YZIJ^$c`e6Ny+Uf|{>4}Qo)KlCEsZt`u!jPVNIk8Np@^&fhW zfAoW1{TcJ~eCI+MJ@80i*f3t1;U1aycS|?A*IXZ9s`qNCKTD<4t;S1LpKzwj`q*Xv zX_eTYsp^}*6Z=+hy^D|{$YCDRRX%cmiPX{$>s-b`(#89`!I$%ptl!$-&Hp+V@RIqo z{#g^h!H&sDeVwa$oy4Dc{c7Z(XCFq0O z7ttJUC*q8QClgIBbY;m~{4kID&>i+yt5eIvm>+&qJ@A8gAshXZc46FTK{kVYT7NV~ zypi$NaNbKVQMXRjW1Zhxc~q7m&32qR)=InRa)*m%yM!olw7c)qIp-Jck4{~k*NQxt zVeit2Y`3s?_b1)jv9{i91f{+4-a3?e_@=V=1dhi#Gkn)|8e;^l67!LeWBp$HEJ`hw z)f3m6P}2R*1iQcvuuIjarCneznXt=xb7<0jjuoMCS4Qk>zdc5 z|Ju0LL!YMJzr=v~E46Lr=plumkMUdyTXU>?L!;>&wA?R;~uun=LH* z_Y8J{9blK1&q%w#ULw_)_2pw#Kc?27`^efT)sKm}sD##=M-QK6@X@#9bxrQa9;fS; zTYHgOto7!^wDz6uq2hpDUA_x-K8D_NtQP&2q{%L!j|tjsy%~1Ec!KFMB={I% z7wg>Cn@10SJY)3m2VMD{8ekU=b<@w9>=HU{j~fW*Y?ms^2*wZkdNaluxX!?SbQusX z(2?AFGtU*XAilcw`> zP4|Uzz9{>k(y#oy&q})MbJCaEtpBX@|0w1|yMFT<$Gj-yFkW_-zqeRwQuCrlM5C>A z+|B^v1dfb6OtLgD3O{B(hQE7Zq|saqAALIDHH)xfykZ<_;hj9AQJU5)HP767ubdZ! zAEU=-K;St!9`=&-)r4i`KE(aUyt?>(vsKXI8E;kSvz5PC z`M8gPT@VjF$}b>a+c(fiBb@m#df&cf0;}VBKezXoVHeirs-Ltt<_v{a=9aEwm8|D^ z*Ip#&^ZzO5nai)2^}Dsly`FdcNyWb@{i?U5-=+L+WtZ%2{_Vo=(IWkKD4SgV<}Wz& z(Ol-7&n;TBdi9D6%6Q|zO?9{PT8+D#|bgJ?tNu}z{(S5Y94dcY$3beaYJE6{j6L0}e-8V^`fS)dE zm6M+2uCA=9u53(T7X(X7s`7=D>hwb2$yynpvsDVG`E)+k7PHiLj#J z5B%`0a;gm@HrDKDKx6`bs`6!(+v#ci%|W$)M3KMLWd`RfoS0&qXb2_TdCIqYzzMhj zr>t8fPQcGD!{=5xeQrRa6s0QPAN!C@w&BFt0#4_vJlZ|r1YCeq-mMZR;AfZNbE}-R zv)-1v2Ku1&rm)TwhfY;~Wm2g+Gc>{jr)5qyK>;V=0-VZklQ;oCUDQ_2I@*V@zM*bY zxY0)!m8v}L*Vz=LcVPUb>MX_EwC@)8<8Y`?%MoDnffH~6PR+MVoPeKAM4VdXY;2;g zLXYl~PE~$+xT$h8y#&-}LU9;g@xX~5RgQ7M3Ag~K);lClz)u&n%2~IgseVV39^V(8 zs{D$iQg!BPwZh3>r-3Ag~Kj#h~i@Y6-Da?;Lxb(?*S30POE@{5v6)me%K zwC~oNwji{-m9{XP0w>@CoVs^QoPZzr;alb0Sh>wl2d)&PDqoaTs>r?cr+DCWp_5He zzzMhjr`|gyPQXtWwaU4rAslXO+U4`j#Z=`NCzYzR6i3_or?C`;`n1Z)CMe(pT!2&7 zmn2TWPZzby8Q#7zym@nYv(6EpPE~%9N;SB$rgB%<&j{DbS1sM&al2b<1&Omljb;)! z0TF<~CLNvZl(~&6PEEwc+HE`aF%F7$^Pyu1GJe4JY6N zoXY=O;spG3QLUVfP2q-coz4`8PF23lZ-Op)S)p*6s>RWyUW`M10xrO*`EH35@Y4nL za#mIPyXK`T-yioaFH--+^{HAbT!}_A37minaB6LnH~~LhR4?Z)s!@J65=~XU%x{8v z0f;_9;dGZ4rye?TgaRkv0-QR&B5?wK4k046a{AnLGn37minaLT%0;spG3QIykn zgHwu9malH)v51~6U-Tk{lirW>{HE@J6L0}ec@IdOfS;Qj*Qbp%f~nx`UF&^Kk4Nic zvhqbdauQEx`AgScj!&w7{2_ZFokur@w1opF-~yb=zbbJ8el`(tiu%CciK(bjkHG0n zap+X##rIPu%?D1v1voXgOPqk8O+=icoLj4C!c31$fKF9@ zNs{T>v-ZBa-j&${>0Do@;%MLmT!2&SgAym;r>Tmzo9bMNV7 zeC0G%d9}{6(r>!RKl?9w;KUCM=ngmm7vR+Wb%_)3bCVO}pB?mFwC&=n6pelcQNU?a zlJdnuj%Ube9iyo_seQWt*8``JURa`m6L0}ey$?y8fS)c}wBmwAYMe-0TUA!qHuroaLW3I#0mI;AHJ=e{1Ap1A0RFf zKUMie(&&rFYdk*7MG!av7vPllO^Flm(?wCvhA@4k%J0Jkq%2kWRY|66FUPxTocVw~ zkj`^8nn~aUT!2&gBN8Xzr;DPT$&SZUmG6)H;F}dr`nthvy|6Z%fD3SH{vU}G@Y6-3 zJ3lvTWL%TZ@0X82v0T5 z@Uw}CQMHBpNsY7vR+Vn8XSA>7pp7YImFJYU&#N zRH;$ZoR8g>Os zl7Cq2Y>)ZOnR;P~22Q{QICVTBaRPq2sI#1EUd6{CDpmRZ7-vrKz)9?rpcNQ60Tn0DK28b3Ag~Kyr(5jz)u&o%DFjQ(^OgE z7p+v~OE}eFYG}RWaUUGi3rjR`0xrO*{27T8@Y6-Daz+uVsHxkuEzz+-s`62UXv^fp zQ+1Z&aSxm(IoSjSoPY~(YThSt0)D!vRnFvQG*gxDkNM0(h0{i@aFaEfN#F!rfK%&! zi4*YCMXhosv1m@pQk73}$y^j?h{9>AR=6n|%_MLFF2JeddlDz$r;A$UOm5~kRr&sy z_q|4qpY-Q2blmJX0T0NYz=2nI7YDx3`3W6L0}e zSU*ZJ(bWy9E$*m-$D&HUX zcZLT}y#KoHfD>>5PUSz4H~~L5IljBwPVWG1sisFqbcQ}?PB#_#S%&(>Cj(++Ka z%oFWQ>Kr%$7vR)j-KKgNn=R8frF!C9a>Ud|c%T zMta=`k9Uy=PQV2?wZ0&60)AOX$HOUce2@hvPD#ioY!Rdw>sP7!VEy^t<6~K){S$Bj zP8}~woPb};$apwyulD;;of9Yj^2>dv7+ZKeU%>AHjkQH*+0Jo_`UG5nQ}+)gPQb5s zbUd8ut9CW|d!)^YlYjY@zEebrEx%j!Pa|kQ5WAaTC)7D`0xrO*_eT;Z;8%5A0ytIF zZKSt_H`OHY)RrqwKIB)Zl!A@b+jq!EW?V`aKM3mx`Z#lkW-^`57x%6lsI5pkL7$3LOT(7swR4mbf9;8gxoi4*WEKfT;hpR93WR?DVm4o~k@Oa>z?!w1_8d(->^33l{H6sLca}yWW-Wm2E+Q^2cd3lfVhM0H@}k zNt}RR%S`Y3RNoNZSslLIMZ0&9y*?!)zcPt5_1rwA=2cp>h@&)`N#F!rfK%(wB~HMv zYK}KfG$P-!qtQoYqIB&zB_m&wM4Ec>w6OxT;FN?s zJ%{1%MO&A$->PuZpU)iW!V8>$3vlZFg~SQ?^^|(!ByREO3&%~gD@LOC!*-mKkzc}J zT`cpLre6GM3Mc)&{82h1(ZC6~0H>^9N}PaS`T5>B`5#R?>r*oF{V^WDTfL9K@5zs~ zVKdrxj#Ju}m zWNteQ8%{~d_s4z9Y&9N#EQ*sn(Wc8CH~|;n)caeB6Y$H9c;e*y*-TE@hEr1VDLt4e z;V@2AI4Lsv-bMxjY(DA}Z~;zPzmqrtzq~Jc;#9r8a;v|aJ4)Y%Q&RFvlS$N8Za!V7 z#+eUm;kfSEgMkxp0Zw_pmpB2x_FLlPRME&Aq$a*iosN@Vd4W?RA7#TSDfy+zBpO9Rp8QJ9XRg%-0s)PWN#F!rfD>4OU-`E@aY|;G zXz$09lJAdk=Jym%C@cD>;Rvw#j8hlU_^!Y|=$zqg`Lk?yHdb-EW@*KmWwfCR?dhBB z7BW$lJj~;~xm|~&OevnAd?*jfSN{KG`A}{ovwTrmDVK1kd`z$c;eP#G65#UjTJt== z!an#>K9mRL%l?ZjAIc4tC?DOEtM|8(E}|%(+ngrS>JJ~~LwQiXUR6Gn8)>0@J9bic z-dM4d2Az!+k^oD>KHE?0Y7&-Blo91ac~HKtH>CYgZs>C@pC~0b68AsI@}WE^U#t3l z3Ci7bro7*e-ltO=q;<*0n!2XOWNYZ5EMIHQ?c#gjupi2U^1%uycWJY{&fq#q#iN_^ zl!_9{zW{T z@0P#0$*(SE9R|L`zTuV<2Q3NDf0Rc&|MU8OlBMr}!FT-**j9z^<^D%+T{>ml^x4%rU)N z(7a~9TSeeIT)$K_)-%4y1t*7iNk#t)=uG<#*v<5{EaZgx3+tBU%Y^-HC%{XN! z4Z7CsW?9dBH%J`eXZ>B)Pxx^&;1XF?EcIp2_iq>O50S2Z--M((j@{sxcV4z)${a!*Yoz=R zUjib6h3!&GXSiOxO6Li{U;yjbbWF!I46cJ&>bi&PV7BpwXb-qPHeW8=Z@cna)b+4b z(MV?}+4e57_j1bQ0y-Z)d|LWjw(nuK-tnC1x10YX^}+8_>G!;k*OUP2=BXt5DG ze!nF>DoWo-fo&?{5)1+?MsapS{CII496@!E`w{Aos2^!FE=|9Y4o#5@$#&smtE$I3 ziyUq8b&>JC`o~qjyKp?k zOs3-;3S2-3=;w*=MKCHogWg9O0eh>maKQKh;{}W#y4Cmr9<0&#JQJ_@w7->9>zi#rKKP zA3_fOVcyX$@*&w@$@}OCO@F_y`oSL+LVrB}J=KoH_#qUL;|KVzBe{gV`I>WS8VX)eKd__?c;|FN%Mu^h~u+e`1my) zJPy`fnsF(`42g~(+KlI;{W9}*%#-z8m+Lx4;*fo;^h*^k@OA$FqS-EdAC2^JAKf$3 zrM=h^UAuJAx?J%>YEvCAU5ID;d~7Y7s=Rm}&_{ZNCd1oz|U2memzZuM?8 z_d=RJKP1~DLW*%c!u6?qoNV8?Zb_Y^X`B!g*CVF?xMg(l`a8R0u1}Y%4B&c%>(kvT z9Px^TC$CR5n`6H|HPbzAGdSY-xIXcH)N3w4r3o!Vjmb&}YqhgA=eb{>^2RD0lpiMx z{ThXKg7o!v;+2@yAJkORGax+ITS*;?7kf;2s`4w4U|my{L0>bbK}BuH%YdT|R369lQ7KyO$XDsPy=G8+P|dFFN-K z8u2O`p3C@Z4~>HErK4}h_XvD=%>!V5CR5c~)@-l89l7rHw`aVpzuA+e-*-;>hXeH& z>7)Jzvf}5%s()J>!j<%GsCs%5F44^#DeI}qFA=E*SNcoUiP>p%J-mg2`1?lO@59;c zg)ra*T!2&d1c?*y13!GLocu~}?qGWt!di2aX0ZzaL zIF(M6H~~LPLY~ExbJLE7#-#c~g|koj+>&6izZCTn(0Ug=f66#*(4wfjh;hIPxB#cB z6C_T+PZx~A$>;WRsmk}qzH&thCzK82P`c%fali?<0H>A{B~HLk7mO(DX08UYwhL=A8(kX zDqj>$H7H&wXpH78@snFUa0<3x2`uceIubf!48g;R3!OZ|P`+chWa)%9+w7K?gi z4+c)a1vr5R_<@FRl{4J5sj7lD#P;`%BF%>K*PMaX*Q8+-HIws6N(FyzVFeo%XXd`}mP*ds%wbx|BVvKhArK<@!mv^83=+ zJyrI1Y?l_wFz9DVkTX2(n5X$R%i*-J2t`Kf#$-IsJ{>lPXSHlW;*`U6=L`$JJDSo> zNuD0#jTC5k6^Xiqsr*MX^;*-d9W4LY6Q>tO1J#LJm}&lNpPi5LFVfe`@UhSCi7C5V z*uq`;4nE-V>#2d5&(*qxefp? zxs62lkalVlai63BxcA-*8ux8GzhKA6ti7*{zw^l-PkE8*2Rqbp;pfV**ne)HZE5r# zf?CIZj#!8^u$~<&Aw!raH#gT&mt>5yy%|QZ@Pz}*@-a8Say(D$?jQ@_ovS}WWj=W2 zlk<~d1OhyBd2|uu_QHV!gge&S-BKHEj4+0&$A;YE`#&sQt;!IV3-8=LAs^SftTSXk zi|bwcnUZ$qU_*(d)pG)oTqo^hj-g&q#+$$~A(o}*4&g`Z8Lt~9bj^@d6kn_F4I4dXJ#(cHuFan`7MAdBjV*IM&M!63%=`xxW76 z>6cop^|HjZ_Lb_PiHBWa2iT>2rnC#}B~yQk?7*(HNcuW0L%sfgrSLtQ86t0zu9Bjt z@7j;OmNtu4C1-glw1sn9<$mlOO2e(aNG(_e;90XqGjTDe%W#Q zrDP1~c}b;TR=G1AENl!G)rhAof{Uwb{7lRAnT?z^jr6gFoWjPYhQj*#ns5%in8e@J zYs^`+sj4ogrh4O+hA?d?ys2rHlL$BSMmXWdoQ*PP6+G_~Zpbkzwub8(wuWbj@SGLm zD}6bA=3|gy5P?Aij!XocJ%DWZ#^xilEQ7foMBqq6fX5HWbA(O;G$P|W`%K${BabiI zC=Ty!;5`ls5)SWoU>}5X_5LT`=fL|N;Aj7G8t~vfj*N_E^&SWBBV-umpZOp0-a&h& zx(`%-OPac0&yc=dAD=fjUnt(+==tR@9Pfcb4&&u4SNV6;eGJ~)ctWG~)SNVzhusAJ zi+qJ-X+8#i%zez!G#}GUZ(s0{m;+vJ?{Tn}W5{NhbI`T+-1exzv%GwQc#i{qVkvub zwX63ydT#drUR#9lf*oKNqy&3O`gX$doo5hd7-W~opZ77%_wvmOcdWR;4!Dm2?e@MQ z=40=q`+mNUp}9tS544$9Z}_lMjCaQRIUjECaj=$=Hep?B%Pv{ZJGM#u;M+u!I?Y?G z_CvVMzg=chS+m6>eQ|#|nv_7_@dP5{ z$YFeRJ@;O;f8q$x9LVv~r5S?| z=gNNmuN24eT{lX)waMi@eu^(!mHLxPoR03A=gD;2=S#m^`7H&K?ofXBCnc@R+wCIb z+@228rQ~x^K?+9tZ__#FuU+MbPF)?>zaYhc4|3f~4*D$NNwh>@r3XI91@ct+wRFwl zPC4*FE>FopAJQ|`LpsPO_#juMZKhKWe2~jh?F#xVIj8-=2f0!u2Yrw; zjC*NFlorJke2{Baa?l4kbGTCue2_yw0DX{KA8^_Me2@bl^nqRz;2bVztK6@ z_rL;Yzk+tHw=1?I%Yz^Cc}gC7A)lw}FNp{TdGJHNO36bn($(7wLuD{xThW~+Lx;|G4omn(VbMY>+{ z;D>yRl80X4r?*SwAN-K-Q1Z|V+*>^I4}Qq^D0%2bx?b|&hkVvTi68VrUT^2fKlmYE zs^p;;>3Ye7AM(vg9(sXak4O2z5BYW_552(8OCJ1??^g2Ai+p>@gCFvNe2E|QqW)y5 zenPK*;D>ykl80X4?qoF`mUdPj|8N`h)g^>xkF&fYar%UVuhJJW?Ds%os6IUeRct2eTElFQU>9zbYit z>n(Jq%lh0L*SiQ^C?SXW1XuYD50*$BnCA&Da?)-oSYa5uig_O6AnBrco~SR^MVVW! zi}E}VmsuQ^k~n8}ykgi`6X6#{PS7!21111=fgNBMWDxcebmv>jE{rF+*WV!e^$^_= z7uM1IOhi4N#^WJ&9L5gwJhfW9jK#mS3*$x)h-HvZc8So&M|E=ZBe3=1PtKI}SZCvV zXX&Dr(OCu*&2|Yyo@S{Jy}?98^xl(K>yKND%&yo6@C1L{!|~&aYATs z%jta7C}YG0DyP=0HQnbfk^14clt?;jvA_NUa;T@S@{!wAJsr6H2jeFDCqA>eBeeg3 z9bgxf2=+3>^Ld{rmf@vE<*#ggCi|8zL}~Ebebg)TA54!ShFrnK{RKVGbk)tJ?8|3Q zgJQ2uisqYpULF}S+pe&WbJowjH`n7Br)$#b7=gnZ!0r5X$^zQkkLWy+{$teP&34kM zU#-fA{tf+Ew12xu_A}9bPu(Bt<2;PJ>>0U;D$)uHxQ8wsW5=!!tWK9m+WWWOby7e4 z(xsBFTI;WWgB;pX_jzveuc>yU`nR?rzQ#vf9(J<->1%w%*WvYniQ-{n(2drwzm@)1MNa@Cy2N7 zh%?uAlIXrltbx<3rsH)wbl2vxuaeH=MmMjJIKX$~ITT@NCrH^@wi~5TCTUsXVhI%bkaeaN)S$`uV_j8=R z{&uHJZm;@#j*6FD(SO(aJ3l?K9{Dl40p#m1*I)O3p8NGo`bn3VR{9>zDv1O9Xl@Vj z3F^;>_pS2k=5H&poC-NmZE$;vMm=>}8U=7smIY$JRVsr;zFsIREM-K(YDP_L!A zXy4UPt*Eb(ruy7jZKGu<{@v;?--mTzumDEkJKsCtSvKCc{ks`$##deW9l~Oa)J8#G z^;gd0aKlODYVXv2I4IZ!c7R=QUjTc_yj?;4O7Lkq3f*ZxC5R9+9dv(enpa;9Nyar9 z*G58o#J3C2J{?(hfgNBMDu8gXm!u+O7k1=_iaU+APlgQRq`gMuMeeKnbQ2jCa&9AP z_x?$ z84p2-HRJ52{8*llA?KcN88;CA`|7gUUTu`oRyDtZ`Ihpn>biq@WwoBzqkOE-wkR59 z{Y<8uPtK!+hthdk+7&~7sA_nHGIo;&9GmMex#6o*m}$Ft*gp^LFt6Sp9AC6bP# z@GwWgF0cdaQgx}c3+#26v)O0zY!^OOsd}snq#56)AZ!14J$|6kunX(}yYyZr?E-rZ zw0!INvD<}hqdVDa^LyZKR}P)~@YAph>;Su>~h5r?#C>r(^kykJmaqH5utGi8 z?M7rT-3QQNMEKbG^1V;UbH4A@UEg6pH&1z*)R1i7yi&W9kK`$j9OgU!LfsSJIHizv zd}ZXvV)B366MyA>lpOAa_y4u;k@uH8gTRef|Eu_a%_T*88Lp~-`>E^Sy<~6Mx?Hh8 zR@tMU&;Q-6=PbM;W2Z>xz^1i(FZr%f@Q2)sMf~r_K2q@R=O66+QuC@#)^*KonR~Zo z{<$;1JohQm@zha2Xw5&qWq!=$wn6A{|e?a(idNzpl@H z#+Y?sh;)RIzmJ~ptRJ%ce!`r*vVKV|5C83J^L0G+y{t_$sIw@V_2Tegpb9>| z8)?CPAMOKNn`FO>`$Ig}isut?KZxgT?HRd-#?QD996R>fOt<^M-Ug{3exORyRUenW zU7y=I#!ryLb-K0MMLzQVVyOe`?l+YoK!EGKqCm zk9fXbg>2s;74zA1Xr*V4hd#Gpukn+--{1*?53upNWiY`o*adcgT{>!{U0^SvPS{1R z>q_-(7w>gmJqxf)ymemPF3n^YKl6L>?ZWQ>9$9vQ9blKzT4@*9%d*S#eHPwq7fIXO z%R?4};|zB3h<9x-50hOUc4&!D#J3A~q(_!rUPucs(w1amm-ec8$8eNE&weDHZtlbl7o!Nr3>nFl~<)7^rnQIkqb;I!^+V zKAIj~%_NP^yJ~OL+9-;z`(AdDn$!Xm@g}a>JIzBG1G~TuunW?Jy+B)j#H9O+tLad_ z72|a_BVES0^-K0KH#V#tVa!N>SR7s&6A!mmhmM?nOsvbP@%HOf)I@SV))kV&xh@w! z-*R0p{ll{^r|!RSKZgAeaG!?fpK)J?^*Fr0W;Y+t&)!FEW-j$-W5*gJZc#PBzAl#+ zk=Hf&r8^|u{t4;Z^|_s+{X-7zzk8>Pyna7s9Lo2^cwNr_dt!{&ld7L_l=ldI&jWUV zU8E3U;_&Vtk2s85{jCpfmga%;J8mnl$q>5Q(~{ zR6W-D_4~0lUs`o-hn_}zfgNC%-d)lzu$RmUk0-6~nbJAY-uGj=T|mdXANv#yHPpV@ z!Y+QEyX8E_w~KW@CZEGS^!O&50_*}iz%DIUO1r>bQa`sB`}3qsA4%=Sx*t1I+6(Le zyJY>BvlFGBYeNb^FZwL zxP=|UnMOR_FHj5}-p@&LzY6%tGF+tnz*=?L%`vhWjtvkD<(1C&T-v*!KhXVcFVqk{8oN9``dVNCCg+ zk(qgan%jG+?KjBl8vK?|NjmEq=_7qFAMGDM4;2UO0z1GiNDuasG_6~P zKE5AuhC#G?U+GrD{C^`!SkVzCUe#`mJ< zarX1}Yi0dz`9fm#+%B8SIopNbOGWzckTQm^>of85QM6|D>J=B1@vEtu>S~+9%}xGt zk*a)gGKp$ge3jl;;`%gI3wI-d6L0}eJ=aN`fS)eAYS9HHi&imA;q4p4n>U9y>m2dv zROJ_`RD&yP#G8rnQ*)24RXDBHqE$0UMuST<~CLN zvZl(~&6PEEwc+HE`aFFXm+R9Hw8A+$1QiFIfD3TS{+z@K_-U$ioEn?L4dFVSDGsgS z<@@71@Gt&H)+habAyY3b z(ZC6~0H>1YPoSg2L%8El$10;s^y!zy&zrx(oaq zLPTig^!(4k6a3Y{nxSI z`d^8M<$Ir&{S)?O*G0=#m2GOMu5aQGi*KDVbLQDPLjts0KD%y`>E_)c{VL^`-y!K1 z<@Y`#X+4=#_g_c)Z;K#0lkOLp&%9R}SK~CR) z9ej{$QF72{$;mUM2R_JkC^_hZ9NlS%%Rc152e}?42Yrw;hdbrK2f3`9B`(khx%Gjr z48|Mjfe&(}N)GxgIcX=zfe&)cN)GxUN3*)3`auqSkZV_R&yVl80WD-%B3+ zkk7hJwO^$N<<{#v(g#1}OO-tIqTF8c;D>y(l80X8TW>c=AN-JSSMtz{biL%k5BY8- z5535Lw}<_}5Bb3D5ybl80W@KQDRkL%vnXLof2} zB@ceccPV-3Mg7au`W56K{E+We^3V(XyyU?T`D`_QfL_?$OCJ1?$2bIfQU97f><@m( zqkTg!+HaPNd>b)G$2)Y+7m)V5Wc{I2;ea3d(QMV9pk9EFeV*rko~{a$XpqbMb6=!J ziuUKO%9Vcjd9A9y-0e))uGfCfc8gF(A&2?oE;soP!T#LhqRs#uA^UT~4zLSs2YU(n z;3q^Hz|6H>X1PXu(1;_T#~Qv&;2IzkVCwr@GsY2c<#;GpW7HwV7xUv zp~YR2Lp>hmcC$vB98RYlk%yn)_7b9OpuK&c&ZBiIPWIgHdF|}1w~YeOUtpcE^+DN= z(XXK2(fe^+7oZdCD@+fgK7`i^<;axmVSx8fa?1FN^UXuQqW1VoyRX-~pfBNG69A{rA zd_zsZFHjYppQ~Yqbwb3;(CEMGI^mnNPRLmIiCMp3Ha%%ta;BPd!3MR z^0Q6|T!2&eJrXD2=Z({my-vtD`B^6fF2JexUWpU%>jNj>>wH#y6gc~q@2_=2w|3`p znTyWD0~g?wb-%<3`1OU;k-AREI8|$fa~rmze*!MRDenP^6Y$ei>FZyOewXd^`s7!> zzt#yECqL_izy&zrx(odJ!0CuxCuE%btP=tk-~?QNA87bieK@k$2^l9iv^TeVCbT=; zuMDmex~~&5PHhAz?jLbKS^gc_KjA)8pHIX5oIXGH9$hSWfAL*pr|0NAEv+JRh0FI) z+P|&zE5Gz>l5TlK`mnK=&-v#0D9GWyrTgnH^7{UquYbNo>Q&F7dL^R5FH;q50@INT zNw$mbCzbDdKUqP0vhdNjv*UHMt!_h7YO(fZNlYuGKX@N@fgNC%s)warU@w_7dXFh2 z?;k;%S4$f20gj=FGt~eD@BQI^l4*Oq)Dis`_me!OWq;r7tc)9tiEaa$sF*xqyYO)o z-FtF9)?J$MBw6bS+@Dj~0e0#AhO`UpCCfRw*f3sv24()^7K^sq1@HNJ*#+^?qkP>i zVxI}#mt~8_=tjaWJeM%SWnLgn`~HS}%g0UAzz9QofgNBM^n++OGPhIcx$GPETRA7% zm?-FbDR2)R+#Yr*T<%efXfI6L<5e^~-7fTg<{smU^m~me7n~skpZk11*e>qvg*&$+ zaDPs9J%U|OUf2utK=pBb@v=)r<{XE0b$XzbE9+6&PjP!`q5c^3vy?%uS#JAVo^#p1P!jB&)zT^Ga{W&js>B_xz)AI5+jGMNA(<%J% zsQe#pC@Q$`Ym-HJmW}(v!Z#-d3+{ht(O!;!Z`-=asUPsei;$fHM&nw7#?DePK_`$7DW&GvOPjTIVwmmsNPicS7;I-%Ezg0b@ zpyoHnxa3i$!tJvyjn=2sxc)f`CbCb*Jns8*>SYfW>icu@_|Dxy7QQ=Ie}r=W`Jk?e z{0t)yxQWh=F5GbX{W(+kF6M?Vc^?Sh^*+%5 zcQLu76I_aWq<$9@c7R<_G}uefH^C0-xrCcC)pH8pEM7`=XuYaOmvRGhaiwwNx$Q>^ zc#vZ~m#{u?S=v%MT$H&4aXsdHd9KI0V@>ujowmmfgmZ2$*_4rN)$V>p=Z*rXOd_mj zsIwiid?xYO!@~T zA^5FNN;-S5vu=5nfb$)pdIdT3CGPU?IQ#fi-Z77SnRM}7pYmP%c>m9iFkX}C&>fx~ z!3~+Db*_O!!!ED`?1CJ^UXs3@u$;UPapE0w<5WT0pB=eRG2mGd%w6E!f5cmQ_)PZk zchWFW?p=Dcc*p#HdMf39C!;HcdOU?};x>12zotc}U6mfjK(@Cz0myL21{ z@LOD<$7=LA5ledJuNlsI*$MufH(8}I4zwelxhw}cgd{=--d<-*50cVPL>>~1LmLse zp5Xd|cwBdI?|^5V@r*Xsn845ezo=4TEou1hcQf49lFGZ}bp(F+kvkIrL+B z-*b@?ZJEXFkc&^##7`_2u1+i3T5uIpF2CmL#=UYe|V~ zO)TyH=HmJkp$Z5)z%H;W>?P9Wz2rlq_gi`3wIxYo&4S}XxVT!3;tXpT9`SS!;n?F} ztXUMM-)Izi=+o2-(rXS@zS)^cvj%!=bJKG8!(bQK0d_&oU@t+x{-kUlo#RWUJ~zDN z)!vVnJn-^4#nW&7Q8D=A`Dib*U2t~U^NXJ4eK%uHIv?@0T5+u3%PzVWowl?Lj5D@N zJCz&#;LDV)L~4|JtUqocPFAr;8^Z*$tT)r9|Ahkw7M?*dbLp5sktfgrn)x12BqJ(~ zLGQzkfcr<4@Xk8kQU5E!z}2SfO?5rL(dBwf@nx<PL*OTrFN&PZBz}>RI{&nO^Gw zmA>-ZUzBvW@&mtg&zF51C$r_Y^FwTgxg7^780o)F=bXQ0l^;5Fb&vxei%9c?sKO4g3rq-m3Hso6TKkD~ zBF=dIjS_Vp;`dP_YN;33YyBP7S}i`RN1V8=1x08;TPFv#PG(PPvZ}{AgS?O9(5Pi} zmH|a`dkImF(BAs{9aZ!f=sz${LcgN-zvu_`{)|Bzr>?C-3HzZ#Y}Oe#k_F zkHnlqza}EJSo1)MYt^E&{q zs))bPeLuTjN-z3t5zvTN(eT7PknI~5G!OKu@kRz8VDa|nXUclaHspG&JE?`Ak(4em ztyFVpfI7+lAjzMY{UCC|>C9O^IXE9x)$CDd!7L(F4F_FMYSr+G|C+v{%{Dv8A? z&bSX}=MnERkNK*Rp7{ehq+BBZUiDXA|Bk$8;$a8a1sK3ylD58Guw_f@-rU@yLx%C$ zy+$OH{JtHxeRhfT6Oz;4|2d@J%P#XXovG@yzmyI=H@BDa)9HReUC)0`Nn*SgFLg1y zGCJhSve_2u+)I&H_}tvVLJqxi_ipjLFU#|}U5}g8VAvo6g9r>FFo?h)0)q$)A~1-+ zAOeF33?eXyz#syH2n-@Hh`=BMg9v;y5a2n>!TG|EhOGxnIf%d@0)q$)A~1-+AOeF3 z3?eXyz#syH2n-@Hh`=BMg9r>FFo-~ZAmDF4v5lYiwK?~vDEWEIHsZqj8F*gW%3)9?CkGrWW6DuTZiAF-lOgPqs#jiP;T?_ zTs7qI{BG&5T;%mV;DcW-k*d`D8#cXer#(~-b`$uoa~sL>`x?r3eP82GwEsIFeLFi| zLcb;=wOH?KB&JnU@&S^t3+w>9bo`&R3+yGc6r??^f4|Sl9?_vo_cLwZx8rl_{ffI4 zBld*?-Q@oMg?QfG`MyS*u_J>ID@Cs}w#)z0aWgTvy{{p)@bm7{wI%p;clT=&hrHiP zzg*!0-zz_QdZa#mG0Hq|xk(%C%eROL&3rl)6waT=y@ zLY%rhxW4%boPY~(f-LX@4S!{2ZMbIL^2#Oz`1DhiFAF#As1L5IZU_fgg=;s58+@kE zIL&!qw!6nPS@fCqV8&@B1)v}NJDt1LyVcwa*#&)`b2|KTc>)#f%{rZG&UEq48U!M@KW!3fi)NHhguUKfjF(j@}JjVE9Ost`_ z3^gXJxWu&5z9YX^I4Ivm^&tsDJ3;z-JMl`?>JMrv8=ETX>cb6{)S-B>$AqUUzr1c| zIM`GdTvoY@+Q{ZaE-^8Ac!2touTW@FOiXM5>M!am>MzF4sMk`GzZvogF`fc#?v?bt z6tIVmF?1ZQIJG z)+yUh8RZ9c@I4`=lE&)XZ@vs^ml%%arx$_M?d_0=-apUcK+a> zcX$5jymf{DnDJC+`N#eonjUBiaUSHs()9hGB)=K*qlr^OtmjtxX2{f6F3#UDO@1@v zSM<%0X``zOmOn1P8M1=D8Ipf$LBa1jT^2i+we zrhhYp>jt!yU-`;>oWoD!#$$7)8MIOM(@24zZ-!tV=s8lMC1F<@J!hT|>o-GqKSjeB z*xwAnetp=V5Bv4OK-k9*H2ktvYpXYh>r&dX&#iuRy`}EY|0?~!+tSbbyY#D+9~dR~ zQ$~K^r@CJs(tn#2a{hW%exP6X`MMOOK=45>`=HD(^jUI~#3&7N;DcPbl7l|T>HGD8 z4{|L^4*D!Pd4}}B2e}R<2Yry!_v-^6Q5}#^@IkIr z$w43F@C9ecfe&)cN)GxUS1)F>t^EkW2f2172Yrw;3}-&U2f1z~2YryM&veRx4|3px zKG5dyYH`ZtKj;PS-5&UXAM&M2 z9(v1_-Mr+%5BX*#54~9`T`zg?L%vlyR{ zKQH{j4|!Y{p%?Y9*#m#@Lmv5qUZn3P-$u;1{$hQxmTKrAQ-sL z)AI=id~2SDzmJqjv%NHD%e%%VymPEmzm^N3#dWAN}`qTCd z_xTalYjc?e}ju1_Qys41{(2_EBep#(xFdfa62Bx{h-({_lmSvjVlsp*i)$vb3ML> zlyE)Poz!CAFECGE*o*cr-cJX$mto`&BVVVJ%yVSHVuOx{zIWO@ zW97ajQp?b!luaSKuua_TBG+w)k19bgxv3VTWV3Thw16}r*fF8F%S z?SXy9i55JLI^0jKX8qTYsGD7MO*(BQJ21}J zE+N7Z*QXy-wutQ0(HQE8b||CVnKr@@^s8fB+ejnE7Z`6~T?FG0j59DVgLx@^eu*$SXZ(H}a?x*VMS#LfPbHFPrJ(gc;vF@i5*BYzqg9w3L zU?QMZ5%-_ZSovc5pZl2ZqT?5IaR2x(Rq1&xm>tF&-I6rkaBURwKKFC< z4G{SqU>N& zZG{gnyBw*{iNOxA3jl+?3}f`uhVdzCA8nm#GOA440E5A7y2%XqV4k}Zuea*!)qbzJmSSX$q4GJ?eiq> zr~N=ZF(PHX{zV<8di-I#KEe*L3)&m(Me7@6kAq}~>&U;Z`26iDwmj6aDVVV+6(LeyC5g9m!uP$ zCpn*RLQA93)39V@kZbCBu2pae)_TmY{J_5a@M?6KPl`h!4%`!E+NV)u1_De zd6Ja^zeuRR$6;mEvveJ2jdS)>I*HVXvf{E$;o7j#RJk>5R94p}W8Os43FJ7(52eRT zx?A&;NuOmn4>;U(1hQm$zhu-xK6qX8g#*hL(zDt5?BBV2g7A+`4;t%7 z^|zJWa`w>->!f0rJY@g+D9?xV?O@|~HP+2U^C4@2(52~%q`#hat`SrmtY@e(%lHEM z{GHZ3x>^S47b2REEOEEGUeu`zi9X(#MDsM#MT8e19(poCION^SS8U{EPnPu%zLj5= zl?Ug|dRIm29Ab>7yrf0vbHu%|WE9*vP21~p#M$8AAOeF3eAEy)h3=(~{-_mtu)Ko^ zXb8|4t^kL14FyvqKSNy6B|Vfz0BYSbdhLBUy@I}-`HSe-f#2um_s(@)xJDN(TXaFm zqE!`33YRZ3R!P0~e>sk{hkUfoa|Q<`A1#9qmUa*UI|AuOI^VfOU0QlZ^gM-=kdkel zqVA`rN*^lu-je(5Ef0L1W=0|fxOdb0aq#Q@=m#Um+HxI@etp=V$Ge4tAy9PF88SW| z7r5Pg>ps;U>wO&>V(=UWfA5*Dd-=Z{wX|T%mMwh!3ej8!`JuusTOMG#kk(}jX&f49^$u3A!LQU1?Tl}Cy^Z^|~pyxF~U&iFQ~ z`7`iw7;yhzW1|u1T{oO*$b%p9n16#_=0#hHP;CfgmOJFZ4|${uy)2(W2m3<)Z7cnD zQjB@Hy^5z}qHMSACrZEdWM?~OoA6wReE)#7(j4>twE-&{dsX5Pa=&OfnVOpgxnx92Tqtu$C+JZA=H=S7(1^IFLi zIu3kq7xzU4d_L~cPl|JyE(N%_vt7daIY@MJ+;6g8#(_)nOvj@OIqa9Co~L7Jh}#d( z-J`xfPUp-Q*dW^noeGzALj3y2>qPM!r^6K%dLE;5PKOUT>m2=6tS{{yDV8#kg1=?X z*~`Z}>gdh-W8CW)()wulR=u~k0ejimE?E=++&ahzv271}WPi)`1^t>=eF>c8tS?<% z&i*Pk4STL+I$U3%=TOy`(%b*vV10=~4?F9AltEl?xxN6mMCwZw@#FgUT{`D>9{7v1 ze+iu8tS{!~&1`zwaB zj-ms)H`BTG)RLvD;~LqIa=zLq81o2UqjQ$c*5(sx!dsHh6zQwbH>swuR2=e+d?Me_ ziSjg5Z>>rt;}tG*+DIcAf9Y}>Lz6)Q7pxKYZKseD#yjw5d7tQ|bLsN)sb*|yTDpC! z7fYYvs1toM4l)cPFo?iM0)dvsx5a%;Yq9hXX`$(wm#MCpJa2*-6}RhCynGzJ>X&Q9 z-6!d5r%o-+2x{!sIHbSkAGHLG-meah|8z_~iZqWyxGtkUe4Wni*V*XxUR~dDy$4np z2Y`mZbotJ@%fmI(H&<6~ZK&KneN$yEZIeHvzShU(-<}WX&B>WDBWHVM^Y+I2oYYf* z)wPVnLoNWj}#oL>wWhFgV*~$ z4fPRV!1W&WLBHNFE2MjQs`piA%K4Qu2ov}E>I7?9VcCwPUOus@iI)z?S@G8RShgFR z5^>7$U4^{<$M1t!JduLt>9Sl@M0Ug%ERyjdem;WMP?e*{Tts@bw+Pxj&yV5YHEb(C ze5U6Kv=MTT3l^$8AjKoX=lT<&;sQsv`Dv>li~+k?U#?9%*EiqJoKrvtuX7fZs`@A8 zKkEOeOS*62!gdksRSGxf{Irh0VXR$j7&pqOf^y+787Z+`*t8Fr> zYsF&>dUQfGUj}t|?#3O}HBG5#)in;%g9r>FaHJs6zUDt8-TI$(D-0t@7fQT;dJh%I zjZZJ#EK~Um&{)!^Hz7Yfg_59*(#LV`@ z^ORn)D~ifCHB{F(H5!dgzCS`Lm8!3gd!=w>hBJ2j&MrSU%!kzq)5P{YvGIawK>U5| zvwI5oShy=+jYp9!`*=!(MG#~8XuAl}X%4rC+0SWTWJ(v3@ZG{<^9H?6eNu;?Fh9J= zA^b?ek0Wzp^6wV*gTO;Ed`?`T)1S}viVt$su4Hc&3h;if(y?##@)3SkRy+qw_i6Mz z{egv&R?K84c|XW~E@e8C6&9T1J z2faopmLnSHs6TFeAAA_&BC$ENY4d%{21+7|J0;5Lwktaz_0`qelkASA23%pUS9*~y z(#cZk!tTgVS>2{>;ilrcT7GyTY}GX6D^dU7TDnLF=|T_kv#2)tw4jUq8dZPAeLK;p z&(lBmd@%(Ru$_qQdE>&}7`C%`9UX9<4fL+cH@7h>b*^qSO?N)Zr zx+A__?D1@uEOk9%yR;AuJtwO6vW>Gi037N&a0ITnz5;Jq->nSW>iaA!H1V@uWj8Mg z)MxPN_1R1ANC^k-z!|tB|FDOJJJ%}1u;HEyUO#?So@_7W%GYH%U)=xO<2hx$|A!vk zE~#E82SWeP?G@$amruF;=x6EF;q3b#aKy@8O;vR%EWC87@vI{eMQ}dYKKvdG_)b^( z1An8uTb{9<_8yy2U0dB`gd3y}j`%*O!H&~m98hlHfPM}52xj_o$06CPA&o!Obq)IM zz8wef#l@k4mcnTEU@B!_KLsGpYjl1LA*Vu6YUtAo*{s*zZAv%Af z-hYkG->COlF|Pw0;M4p~;-Evw=_fRQBj-Szf&+=d`YrOrxDLemn-PUKg&sF2cBX&n zQhr^+!`bhp?JP0j5qqpWXCAxLX^yjp+0XSj=+SvBK4*ED&zl$8r0>P&74DSwPRE}- z<-e2c5h8o!x$D%^jZdRJ6IUkhNC1a3_N~Ek>hm|ypSsVu*^ZE#Mq9jF^kEERT=~c< zlFvoM@9!){`)SoLqn}1PUi0lMiq=+d4%g9SdpMl%MG{J-pHM%Idgc`U;Hc7TUJk^| zLtupS{ZQsToc(m*TsdCPQaLwwl79qmX)L|&nH@?&}IA$|2* z&Ui}u>3@I!wdc&udv z=P2-u^!5F7IL||eK4FF?%e?Gbrv=Zn z>s($a`uOFQDZIeQ`Yz;2HV?;p8sV^P3|qsu3v(Dddz@G^SK%^N{_DJuiSNsA>#>Fa zVLXfWBw41OK@{oakG3ZfJ#SO#!{-Rz_bQz<@Di&`a}4cN&ujYDx<2z|8pTFPpalHW zDC}rD$l2xDRU>^~qw70AGT%J~^4g^I4Op*d$F14Q z4lZ?yvu(G7bDb?m=)A)I!I`&; zLwzK*%30;*0NS4?WGs?VvYG4Uj-_RLVi~)x59&NNU4bhF!|uF~FPA$=2fLv7=Rb)? z;L-cUH6a@8al(3egHt=d)ZiiD5j|v5hHdVbIdWjhmRPsW%%&n zTQV~ck!-tQc z<0z9bq5O?Bk2~%-bL6N|2a-+xsH2YFGG)@#19N82GtW8a9COBu8Rp3+pKP9b>Z#`Z z`3uYi^B0?Lx&Fag~zeS zj@dnH)-1CqRBRS344G%0b(T5l#GrZ7#1qYl6DOLdopzde?z!ih^XAPHX-}R!S%giW zKHZ!)ZJNj@=k=6e&WP!h;7ODR zvH{zI%gwepdE!at#H@+t)TvX=a~I^Bd2<(-vu5R*R0dHOIKL+n79&TEE?j6%qC8EW7!+k(Kz0e`7nutd zEHKB9&oW0JJC5ssc|6t25l4+Mj~R6g*AGuyoO#BX2Tq@sZBCvvS){YNtjxTqyxd%~ zW{p`?RAlDm<(V9|j*jvRE-=ehtuklMoGI{OT;|W8Z!TWE*eon8G}-=R$Bh?hXPWp1>O)LB%{qR1y(yqApV)N2VFEv+Cc}1O|e5|GX zT)cX*5 zdCejLpLgu=4>&!C3g5#DiUoPyz zb%XQCVcc#xPYcLSv#GvtJ>|N<_N8_bwFA}9EsQU>F~*bayRov;+`MU%xg{JnFS_U= zQO2{*Jk6XtYbxdQG*REVoLoPqO*@tRh31--7n(WKXUMu+Tx_07^_a`g^@Q_s+_>XJ z`ctM(rus29iUGwPU>w&|c~=vzTz^=Gk41|XnHP|)Ic)aqT8HjmFb-aIaAEcKD&DPO0Wr<`)K$?cKr zJh!C^!nvxd%DkBD&Fy{0^s`KE3ydY_tGc?%+`4tExnaWwbLGmFCgWdHQX{MvAMeuQj(fZZ&J_K4#X`)R_A!@U0%z1O?nRDmNH7_NZ^Ov1xu3CMe zSx`_QY_(`niCIWC;{JQgv7^lKt^rLxVLn`d5JUSa0V$rI^wn_W$P$hviFMO&OSDM)?v6qCNK zBkC^IJ8A>t4^Usfo9hwRan1+h)ZE-`UU}7(=2cf+B@V80bLP%5&(6y=XB6g|v*zUr z-c3~QVzN13hZv*vW-|&J*p1)8zE0OgfRSO(%*r$#szO@c-F+ z(-_N+?9T5>nuRmAM}jTG(qKmJagQu2C3Ul^*le=Z-6U(@x2z_MERv6J&3u(_tGDD* zB&&*5#o9M6ZKw?!7BGO(1`IEs+z@OF9vF7R;Mg9+zzF_i82+FShGD>fA;TZ8fB$nL z?!E72R&^#z$<{P)qUzmnado)%go21je_O-un zH26O6_!jTd`;mvc#LEW`?5FQ`Sz9#Du3UdVy?kpqy>j((dg;=o^enPiWvQQ5E?!KR zq0REzn)ScrglH&vpn8fY6<0sL!?-?&{5r+68rK?&d*Gj)jIF4P-hp;!>8IV_-vO?8 z-umLohnLf9AAOi!z51cGQ*G?RYnQKFNmoDoFzsKzo-VJfSYF9E{g>>BGD5OLV^{t1 zHt&BEUQnGhHupf6-$Q;0Ur7did)MLYtz{{Bn6|69h}de;i&>v^?HeJtKzqwSY? z|1vxxzWf&a_T0`FjK_P7p?+_`F?bE?^G)>Fv&K&v3ulol5wEC^kwY04__bgC)m>fs zPhmYUb!xya{(nl&&?RozB7vS6HE$?`^oDMn@qnYS0T^Mzg`2FAfhreaIi*TlUM1TGL zDl`y1RrW_8eU#q1bt}D2AFG`&eNT1x4)1@-Xe568;DZm0_mA_8_)K-baA6344($Ds zQQ}wegvPdT>$B+Z7hn3ebniO+p*kR!O%H1<-Mn)xy?Os?dga3_R;NGw?jM@2d+)vX z((Bak8g={d>Q$2usK`yCq}>Q}W<<3T!4bCPer_#Ncq_cILo&7IGszxxMs()~Yr=9yofG>%X?olw}~ zmb;ZOGV@3CXHI{q@j@SNyEe|%1xTVJ%zPpTVZ zw?+GY#GLO(FMRuj&tH7$rO&_pofkg`2mRq+i)lQ``RlC z{&I-_O>C<27t8t z?kwhLCyM$1MGDe;zZMFN*VvoS{KZ?gH#gjV>?N}k74oaxPd@%Qy?Nt?jr|iRkEb6K zzjga2n08-!?D(HP=y2p>)lkaqXp-Sj@sNOte%nLCvA@ZqEM*wJI@{(bw?&v@TQ=>2`j z#Z#w_rJsEI2p#cJx@SK)=Opj@U98VuT_&B|L`+j-?7v9Slb{ziHHo4=yk-7=f8yO;4XXk^b=0Pt#lIzrA~e zEsv$2e)b7;zme|Qw_yZ{JBjdGr}L{s-Wix6>=={);Qi z>A5%GV9xj!c<@rX_TEbR8oK5j@eeLvPFKP1ub&0;oqHRca4CIn?E|p+o9SC`aQ{7U zH5g9MpL_ExIR7HgyqCWD)|=_;#MjX8?_ar`o_p)<^tIRDOxISydmmh(p7+uBSE%!$ z^ap3=)BDu(Dp>RgvUq;}RC*WQy8h8M<~&Ezlc!Iix9_CaZ``!`=!p}=Z{1FBesn86 ze(ZR9^4N*=7W(rx|Al#uA3vJjfVXeoxs{$gbuvA2?5OGd+mw0g)M!?+*OPc%c5`$6MUH|M4g3QR*vxtW@5C$7*2WWq5Fyz6(BW z)T-$USaG8GyOp$7uNrn7O~z@3In%q$-zMB2O_sS|<$o<*CcHdePOIFnRo*rIwL*UB z`D(S2jtNgzCTW#tE6h2iUnk2e=_`9)O;4OYnSS=ePtzN>uET$?GN(9}eg?nYfp+`g zzZ1ugz<-b6pUwY`+;q)P6>JB`&fB!+ox#YmZ^#0w4=^^NHn07s&A3ugpM-CqX zN9{!p+({pO`oQ{e&w;%rQyzWx8T@fBeV6u$UnVPKFy@=sXe#M@7uQnNUp9z(?cMa^ zd&E~K>AAO=cf9*fx~jPn80{_QgKxd_E_2JZbamw-Hl=s4ZM~DOF~@jsWfl6qP1-r0 zU8W4;(DTiA&hf4l<7dex;jV+os?%pq+qk*@(N*KedFUd3ya66OO8=c=oJyYExb=~> z;~4T%{CMN`ZR5wI@Sphc_N_a{kH?WQ;>Ua37e5|7df52!?)^K)j|bs#$+xSbGxNj~ z^CzL}1M7!_@SEh}Lue>|JOn?^pFUyr6F(jlf5DHEZ;}g#;AP3jJ9qAxd_0DXIC_x# z)JO91IJ|%42>gd^zmI%8cH(%tAAWojT=Q5pZ~ zTBA>2d36sqozv;3Km1{O9sK<&@=tV)@^9Z>>@V=&r;NLM+~1F0ICk_9$NDv4`nh@*FsbJ%+J({~q%2{>Sv=;q)N#?%tid>8J3k`ryF+-O%ZF`pIXH(svju zb>zADVF1?C*r*}Hmub6fLmE3x#^*A;I7X&dx!-_aC(Fbqj8Dd@_;<|Qam1L^_*E|D`WaFwZ#3IK2r! zN=BVL$^4G~e{laH@|O1>Je;1w&U6nNi60O0zLUt`d-w0Al8=&Sl8^UP{zup81M(v$ z#81*wM|t;A;y2;-o0Na-_z7g*aj?a$^vB-~ROAc`#UcOHrjisaX+v~5NO)HGw zOP4OgZ)@n6v+3LKRMHPFUBVu+mY#j%EaMyf^1=J?;A;9NbHcZg5oSZ;zHBz)C)t%Q zzJJm9`3-nj{Cx5K55VnjG0!B9y!ha~56ph{COT{lUcE$_yI+Ya`Klv1Shy08D_c8tSfcpmy>~lIkyl-;;0OM40UUa-K+yTw^ zf>rJ^E(jKe~R?`0+UU^*-(Rh;b)=)VLJBQ-6yeH7zCI|waq-MnRb;)M7EU2zv)xJut21DCu${~C0;n|^rZ z8sqeMdYZVN|4{Px#If`g@>%?L{l-<~=`oXsx8T*A$Zw4W@u$X$`1K@X=NLS8{RVOI z8)HlTdhOcv^wy0#*f7teCytyj8^Sy2ln<|bn7)S&dF=6VqfGD-{CVZlhuAh`-wpWhI=B~kc=FiE^wUp1vwH5?1AiSokv{qae2AQn`ZvnI zgW^Br`Xg}EBl<#m;_#t;CO3pTX7S(Q8T=>ve`l$k_PU+4d;WadUTmkG_EOsI^wQ4x zZo1eejkxU5=lQ>QzMU>EVXG&9r?-Typp89ak^G&sw-n;%DYHu%x=-Fk%3mVC=JIXc zv7qvny7ms?it9JTfBTFMkKo5!(BUAs_7rpwuDE&Qw#jwrSMlRbWS-=cLIuO(k3=cRAOkJ1yj;Dvjdf53nH(Gxds-M|+7zVXi+Z@gym=?XTmQ}F)T zADm?@+@PPXqOVV5t9TvT=||~h>{F-aPp9**oxxspExmgEN{Sr;UOJ5||Ip?$!m?+u z(aX*%Jn=d>TJrQVa~;X|AHY{97;p3BI|m-QdhIGavBop=@ZX#1)eo^*7!$``P>Opll_t!*7?bT;~4=W|uz;roW8*{E+*y6}|rY8F=*r zvpI_&&v0M-c!hEQs_-AUhK zlJla2_)&BaKi+$Amv$dEy&!%0kZ~)16kWuRnwOnG|L!9$eJQ)Q@R<7L=B=B|hb|-E zjw6fakpVZ-Yseny&mW+lZ+vt!z4qaCo&&f{*b_*aT!3_*s9)_MPlhpYC&hPkhhf z-`V)A?myo>?RT_z)Z+)k^_jyS|LLLWe2;6-Gy6Q>>VeJW|H*&%|7G7u;=6Ny<^R-f z^(S4N{JJ7De+U1Af6wfH#fB(LG5%L6th&Ya$Ts$i{`Zsr!TIfJ`am?=%=4n_X7W8L zkKQFatoZHkDKhi-?a}*H?33yd?>%js^q$zBjmD3>XU&6F8Tr%u6pwXOn*SAT z*fA}^CpXI5|LfH}Ri*f!?6$I57v-MrMn7x2PX(h~`fs=?+Hdz?l$+cAp0fO>qk#BB zd$VJI$zj;}^~#^JuEKx+OD~J7j7MkFl<(yY@=c{hK8*S#^5J8bfntGAdEKnue#+OB zk3S^^#2?R5M(i&wvWXAlnw@_+Hp;@Un;doC`MP~;*z6*aiuFQhE>kjNQ?cko3P7G=TS*ZJtH2~e}(lIl1->2ozIRE)g3Vza9$oO-%0-KD-`PL@0m)T}0ApTJQ#QxetSiCg*r+kt# zk>0Noj`^Gqe>vHGn!R{{!)JcY_Xq!1WKf=G{_gaC;n}ixpMJH`NEW~NK`5|$tjlcK zGjYQRx5C_9eiz&Er#(dL|EBS__7GhOnLKyIG}HMU>v-Ds>>*MmX5SstVqHQ-XZ&8a zlYZ-aCf3F4`d4oc)-276_4PUz`!c6_q-}XEDNs_Nq`>1SU?~6PuXFpaMc`M+spEjb(Vvdoxf|k*ek$^$Nv|mxWYT5 zKA!z9OT@5VW>JPJC67Bf^d3+DJOAv`pT6*4{NwNG`VFqXaeQ;ObbtOA{kPax#cx_|#)|7a=LTwdV}>wmTruNsb2t{>$*-KXg18aiTw$|L#7$ zyVI{FU+|PzE9Y0J@@D?5{$~S!Y$u*sUzuszmw0eJg<{G-pL_CE`(hu@hBvw&TU=gC z3X~KmDexo;7&;1gFxSrUi6`Mf@&vsdb8me0Gs5lOmhs@P|40Ar_ly67EZh_xjQV&Z zJeXrb$y5EUzs};p|24h*r{Acgf1>NKn*Pb3pD6L5(=O6)RyReOdaj5EBi$Z{2mjeW z8iYQ1<>iO}c=C8W81P?)2fq>U;A8BB!h@4xf_?D$yxLm}ZOK0P>`CX35)Vc`C|+m7 zF}|Lcwv&GA@xAI1|Nm7yqiH>T^7=*^#`?$W)|kA^T~eT=z*m(5UxIxwhnZW(gSo6L z_Rr&OgXG^6?SoMtZ-fW)(uy)vsd;=B56;>Le{!nCgVS`3`loo!b3{BC>Gn80xM}-f zz<(JYd@>muDaRi@+b-iDzcpn2#6d2OXOh z=UVH-F^~GH$Uj$J-cI_J_QBavQpQUPloa^tQeX-Xt|P-=1|IyE^HLv+2mg5Gxb9_t z(SPu1@L<%(8{xrU$=($8(E97FeQtKMMTu^Tsn*0wJ8|i+mn&momh#f7i($$+xub9Gck9$+$ zYkH5xgFO3}zMmxOFv-di0mHG9c(FU;QBY%U*;<*P*UI*p8{XPev-eDQE|(7FxLxN83Z=BpCszzSv;8g4yw$k zht^+b@!+g|@TYHunz`1&XZ|a&{Fv-rw$YW>dEm-;#as&jNq^+BTj?T^L)TA;o_9 z#W*jeq~CO(PS3ZB_Y~IOMrnSh{4FU^QlO;3<0+uk+$-C9{@^bGG{c|a!5H}m1mgdg z7Oz{|PZFQn(jqqTuM~gC4&*$-t@Zj%<^9TPm&L3QSr^JIff`OggU{4TJeYUwtX_)oJV(TXk#0|o z2Lt}g@Zcu_4+fl=zu7~(Pahaozr^p=9Srf`OggFkMTc+k5}zq2?n z#`7Ez4@SB@H69H3FT;cXe!znPC+2VV(C*Vmt82~S)=^+y(3bGvp9lUZ@t}A?f5q!; zIL2c>#r^+w(yz1+TE~<>B?U?floWsh+m8qH<7Ser+6T>d(ESICo%MJuD4ZDaVARLk zg$Gv`N<5hNO0K`79?$i^=ZbhR((S47V8DMF9{f)N9t=1!ubYR!gYAVy{0Eb7&EDE< zd`tU_e-ij(JMql=iWmE#+)uKeK6y%MAIxb{hDr*Q6euZ>B>8zW8*C?e;(0S}!~5AZ z{H1)sc*}S&#}>u+Yz_}beY_DK%uAF0)ZhB+?0%Bj^9K*MOFZbbi}WjEkr>W%L_8Sj z_BcGa>GKBz{>$*-p9DM@aAN*u5A8mEtU6knP2Ey_OL*{B;E$g-9!$dc`}yuKF7iVR zZ**0EOs8)r{k{tJ!5^Ql=Ms2J>|SOrDNs`2t3?5QU3h!XoB3CwLJI4}k-l0dj{jp? zyl(BhnQ43&?SoMtZ-fVPJs{nqzxCHyJgD;ri|5V!#!`s~opzCa(|SCosppD#Fw*UD zcyQC_4+i{~;lckp;K6_s^SXHmJlI}M7H5;U65kRYJRA69JMql=$`|{fv=6SQPo7fR z2Xk7Kp^^e61xgA$jeT(Q-!IPS{H59lqdwjU4`wym00;WLD=*LD!CCv@pLa?;I8DbQ z7K!0JN5q4XZjZx*o3;-I{FmXu|32WsfD`jKdk8!@>5SWh&f4sqO~>@y&kL=Bp^ow0<^JMGmGW9rprpW8fdXH`da*B5iI`t19*p{U zyYS#odL$*-p9MS^aAN*u5A8mEe9~BGerfwj{vz0drbVX zdy921t`|pryb&I>R$IMPzW&xbVdDDj}vF4Aun3r3oHu80RC-5!SrH@#jQ z@Lz@p|F?h#15V8A=AqrEPqusY#cv*~F7(>1wJ(ATx3s_br-468JQ(?)c%2Q$_G}GwI%t0LWV5<7`XX>}Yv&LCQQ(j5 z#51#PobH3te{em0@|4m(nA4&Rl@ur`P*UK_un+1?>+rWlJm~o1i+-;z>f`OggU^mj zJQzE68iy2dVV)!6!AQ5K#)AR>Wq9!a33xEz#Qe=35+0m%2IIZM>dNfBO~!vEw<|yK z3GsQd82F>agW?DM6|b}57?1fB_y5~TzpsLQ@R_&%?f>+*E?WnbKP3f93X~Lh0tL3; zK3I^s(hD1&NBzeu$AixBs{Uo{FOK?nBRrVfETbM;fBjkO#eXp=@nFtax&DrNJlFr8 zE8@XOx2MK~0sm!qFnQx|iPxS9I5DrAhrol~X7#Dgqu$bfk{6eqKYreL=1L%h^L&xd zW1lHQ3}0b<9u58(d0O%Q7YoOC#OvegQM~W(|9R6d*{3=s$kU#z}mcBVW81?Z+crdS%aEt!dUuW^) z?0%9zS}XCO(=O6aG@SjP=ZJVP((Q40aMSxq0{+YJ;I9Wf7;s|#W)Fb}d)1}p*ADjk zOJ5KZZV3TWDv~SI}ahm=m9$ZhKJf*~gIW5XiNr93AB?TfL6z1FLPriST$Ab|= zZS-WG_AlkZE#g7jLn4eZg%yeKdD4I34t>8k>f`OggNyH#crfqUSsWPSd5(w&Bi)`F z4+i{~;lbYucrf6^{LLN$5B6L7T-|d!W^ZjazNPiz9|!)}PCQuf#RzSPboa4Yo;UOO zt}XH4<7rdgDJf7=;HyZ1FJrwp(^^}_g9Uq2v2Qkq2ctgT2oL6^x!!cUic<6VtbK5H zz4*lsN<27C$08Pq;XFsggOP5J!-Jb%FAn%G!-LNTJQ#3d{$>w>2Pd`huv#C_-r00~ zOL%ZK@W*!I!Sywdbay^3@!)z2#gq~cMoN^|k^&_KN(zVqU&49R`Qq%CiU*@U-Yz`& z%;gdf=3}UcLyF-%N5q4XZcmK|1OChK;Ld;t15V7}?4jMK&ooz`VskO2Y-xY-!N4Ee zi3hWpR@T^Q+Lw4RBh0!$i3it_q)aF&P*UJ4O@S%<;4`zNc+z_Dm-)RqojDWEosrFO zQ|rZ1A8&*QeXpQe>voiluCw;RS^vR5yHeu8oL`DKq!`X~L_8Sj_BcGaY5&21|1v!I z-GB!JPR!rzA@Jbhq+9!fu7g&_miz~Q<3s0nzrOMae`s>fa zgFn7n;z6ffq@VSb`m69i&k^xpq}x;D!GQlF9*l2#Cg8*vk5};EN_#Z^((vG)2mUDW z;QFyOJ>DX}#GZi{KcreQOCsXL} zy9v`jbHa{jl&l z#?4=wg^tc2ZTFh<zDS769`la8Gbk=pA8^>Qgw(tM^)g+ngHCM;U++f&TPUafbaW$E1wTDbP z<~mh=SCh5mVzSz8_xPz2Q)o@0xk10(8#jl^!mvLXB+J!~{_jl2YlCJo!p~LLR;Rj< z^s3$Fxfh;)I~i4%n~lU?(qUKBxIeCT6rc_(?FMgb*FxqO-cBZ?q+Rd#D%==U8#`6S z{-8M=x0~D`bGuRN^y^EiZl`Hw+Ix09x05$1ZBQLAp7ZG3pgL^!)XZvqsoBuoWaZq> zx06NvsFJ$Y7puL6W}`B0cblUzeWJvM z=K8h7DrIf2Hiq?nqvt;3`O|4#<0zk7H#S`87=l#mYQoxmpZFBs+$b@BVBhS z!)B*C<^jFG*=cr@2?SlXe)N9Qn}*q&hSuHH2J{;?TPjr#jmE=syC8&x+ZUVOa{7h0 z&9#R8u1Z(ty6CA_EU2sD^CtKE6iU;)_u&uggi+Gd?NQ>tb2NmujhdZ~+Eh;n)swkN zuhFm6CauH*YLo@6sCvIU5IZDYd+A8^8a10sNvmINSv8alOQysI*ZvsvG zbdClyPtP^_Eh;~%_LJ6X#Rh_S=G$*4Hf*R*r#j4Q1gq17kf;tr#cCE4yW*umd$~VO z8sk+uax{X)hYX>?Vl}CE+5_5V*JiJg(5O+;AC4FMl@X0>CJnw}5Xhl+R#roUD{Jsd zyG4n1Sxes7U!mrzf;FK6Ps902i%+!L<7C9hZ_?4DdXxTa4e7$((679=)fzR)Loy?= zS!s8v*jl}la4bf5(t-8b&6P@XjrPzAV|`1mw0n)_YNESIr@971&sBTvZZcP|))(QL zd;}&+hsHy)FtXv+(K!Z~2P>lvM3VTb6ca{$c&KUVR^Mbis4g_EW8l;p?@m^S%|WuJ zpYe*QIbIPhb<0LFuNqjsT#Qf$iB7NaXgnDpiToW%hK5&j&?H39LUaAD*{`))QLBIg zjphJ0RLGeOF;*Q7V6M@CK_tE#@!n-!P&5CBG=9%1(P}QC6nb$o+FXZ!-@Q^+3!UaF_0pw z4JV^ThQ`3F=TW3<2LWb$Ons3Z{nkihNqnj6kZv1R8Q$HBk;huE2Rq5YYv~tN zvnNq9Fw!I|i|zVir9T-XsuMI*QcIQ+#B&7+D-tq@C2V!!Fb8fL#mMY=Ii!diF+;Q49xJ|B9X50wR?&|B46?g7ve#9+HQl4!n4KVE)NT^AoXXK) z#Olg$MVi=~V>Zb$-Ev7~#dRiKt8W8oqlBe)Zz*0w5^8y2QE7;sQ1-&Gx{NSWVyE4* zGDUmEQ3qBf#%sq~Gg_=R`YXD15!q%hAwW`3X_DNQjX^@MA@q$?!nLwEK@Evz^X}e( z%miMT&X|)#K)lz$1;|5G!MW$(=3mmUS!CDS#uiqjv9O7-UVn^KKo!)GJtGLF@q&7; zq7^jSO}w>$6v&^7JsTqS{lYXteJnAoW}YxQeW zQAa{6@HjXY1FS)gEKlkVP1p)=(o7aH=-xATQ9h zJlF3r9?(3aDmPr8+DKS1p3@K5jnQGxb{8rK6Mj0?`lMGKN=p;#*T=xjkp*23k+@I= zHc6*ds@?tsB-k5COgMp;dzFG zM~Ox+wd$g1K?{rgE~*aAhTY{2-%5ak#u5TwiU7z*fmN)YO43w>tHlx370Vj~Ym(lU zbTJG0Fkt3Ttso5PbPozsW}&q_crmFq(4du2!&n|X1PWugnLL$Bv>HG%?E_TmVztvp zLl2lW^(sy3UZ)V7MJ=rvi7c|%AGR+tAM&AM(rg4ppsyY)rV=$`)R^o9ZNfP3*a%Zz z$%WoX!=*azRx|?JjTme9!V_rmO6YIpLT0pkAbBcKNEI6jPsg-TsIUeqVV(k>Ghqsi zM{rEQNL{a;>ruDKb?RT{;>W+IDRz%pq+F z>6998t9-GvDcSHyOv|&!lu&pC%u+9v`eckY0fVh|>Bk{pnT`^5Ll4n?4k6W%A(38j z&0&&w;&MTl6 zh9AESKYnY5U-Yw}pIQPC8S2ME3kr!$3_M7u2cVI0z90;P+@}=~$!;bWh3R4NhSRb$ z0r%I}lI4CUS+MCFZS6HXOiwin$ikI&7E}504q@GKK{sB7H&qh?aolV01pOXE=-R5F zmgaNJVfDK+SzzRh?4=%39*yftexnf8-QpOv2d5G&N3T8V7YZ=7VeO)a$9;Rqd)q{c zL|~n9m1o+iZ(RuzDul0El;WS5d=IX5M0p&Bm_-edukH} z8V zyqk)R!7SMZgymNzk7YM`cYj49VwXL~u*q^NZ29KgO4S;+T|%^k98F#%twqzOt7~>M zX{<57p)->aoaJ~?B1EwuO%%l7Bf=AM453gvq>#-7AW2X(1~G}C=9Euz*#bsMrAV^@ zn`~+mWnR=6{a$CyX)ivqIzUYe4~D!_;&7Q)hHe~4n^sUQ0D7MYdrH02=V_Z6qpvMs z)}ZIrI8E#N`y z$uR|C64I~PiEO@=%r((B9-p%uA_SJh{+MEul{VCnk_{7k1%pmCo1`90mYaeys(Te; zCo4_UZi_pT#hpoON7CYV7X}=j6nr{pZI0jOjZ;71#m4fJK-t6E+^pRu?hGgHawej#28k_VY{)KfZ}?| zO0tN>X;_0&n95wPGpYtMrYPM><)K=0nRz%p!tJ4l(2o6{qkcVaMjm6TvHV7S?&U$i zz7DD%bpcj&rptkC1>Tv-C6o=(jra%-86S7(XJ=@?>?nZ-7KFWelZ0P0SDOCzA%lTJ z#1?njpc*aedr6MXR-m4%dcLVCt6gW&duUL3COv(B(F4`3;Fj{wr8eDgV z>kip5+^XT}Ssd=!>5xVBl!2r>=y%q*Fr&0syG~1B_50u%NHCzET@oWZ7n&ZvSpsSQe;i(y?D5a}~wa-orK2l#o@C ztJM*b2*e@vj8R~Q#iWkCNHQN|extn{E(kp|7K+DEhjoPV%ysD&GpJ!8Vl0U))LWxU z8fk<@O-A=gZ$(z^Wu{xqwU}rFq+R5nL&TnA}8_BGzM`6POh7+tC$+L5cjDGjo-%aKa4ZyubRRtbl{kDD- z1sIA{JcL9&64Vh)pHxb?Acr-LgmV}gOedQwo#hT~S!n7Cx9H*mOd%~3ST`z%QI%3H z?Cp-03AK+_)iLJ?;?235VQjUr%ZS1O4n+GEIdN-bt zR`-e>_4dp)yL;Te8mn@3&LEh1JV$Gbl_)J zEgI-52NW=obD7qu)GwH8S$#scqWu_xT35*L$f!#mGwyO_S|K7ZiPi;UY72+-jGB zeOU;-kxf~XO%#|Z$W7jR5aC+ptI}y>lfb^n*6!K(XI$z1>eo4AW`sAx(fOM4)OBEz z@!|>R;<*vMLkY6#i@q`Jwl$kiC4;eD$sv1{NjNiHEuc_=0dR0O&sJ$pO0p1Hp1RI*t z9YIi0<3g~qybxn`n?|{`2MS^mOF{%YWF8r^+$9*w%1FFclxFhPsv$!{5a3J^6&X>` ziajxB##S=R=IUbxmhN|g4Fa?$dx7=x3SC)2;`QsAKo~A$(YvyO?Ucn3<_;`-F7#N{ z8+$aDbavNgJ@v)@AX-#g{c0Cc1V2gK)i?*=^@T#ha8{jyu~_*{abmJs1Xz*P3vG@Yy0EM#VKR7~sew6RCapo_(3RfQ!ofGei*@hHG5f^^V>1?BBATOdP= zdr5jI>gt%k5_Ne-By@45y+aL%8mdw?>03;x#gsxLE7h4+S7ajMm741+pc$x2ukVnu zhwoQ4075t9Q753ZT)2s zW)tsW-DfG`Mg!4fHwf4b(+}1c14f1S3Tl#dNena^_!CB&t}RyjJtX@f(@Q!Y^&FnS zJi;uW{$Ot8VIhj7X(&hu9yGn~i4G)0bXMykPkEK(pM#7L_B9A>tHiz-UqP&68i+D1 zjw5&>kWkv$2nzz!;IgJQvrs1sX(cx>p#p((4BP3BEP-MCwnrW8VrDI=x6S%%@`Jgo z&Avoz^~rRi=u4s)9N8?)gb`s3r!&c4LG9XH-!4q=JyBqDVt!1_;|Z_Wgb{?qWS?38 zO467ljpc-?32cI8L~_N-lo{bgGfDs`%-KMbU~5XhwkU$ZWON~36HI|M+T8Dl>kdVB z>SvdJq-^l7k<-*1^C!7EX}~eHv6>!9wM6;PbIy9YAKw z!YLc(0w#KfO&g21khAk0fYtAHfh0f&vAU+ElA5~q>GEp5(>$#u9Ta;dK=t!1^~;C} zP?tgrLE0R+Kq2W1xlhGC&n6u$~ z#_VD~`ppQ>18^K4F@)ti*Vt=PR3qA=``bPI>h$`(2(n`$FAikme%Iuhk(=Ja)u-J9 zRCo}(se!yf9j8S`9QEq7p+8j=SZrABT>ckR@&;?ASUAo!h_CB*`aZ3sxG?V^#SK<6 z5I}nQ@iCnWrV;B^b33AP*f+IQ4l`jAZa3s1B~M5rVHDu>oSCj{N@mU=h6`@H!SBOtQ4+APE%B3-t3UKbee_P(tKPx-f)Pb)jA>_(Vyn z(^ag~DugSq+@B@kJfSyU3b^%2P8X&W1l}939jG8iMn-9|14M1KtIo*7B{%U5 z015577K0`27y4D4(d=~!dR7LEA{tqCW#HIVFwIdxeA_&1u3PrT*5u;FHCuXPh2P7h z-z9ddIsY`xznF&cN;i@?ndY?KU=w?zgBBk~*d2gpUN}^R?{Vzm z$3~$73{{w9RI5AQtFnwC8>obUnRC@B4**7&uq?V&=Fr{*OssK^y-MVOe>;7o1~>|% zNu6a4Ei-uO?cM;_L!lpPA9>b%DuB1qSi$mDR|Bzw%H(Q6n~KB;Zwp>dXlC7>Yjqj; zOa!Y)cC9y7s*PnKyGGw6j-jP6(OzAKO9sh;<{2QbU`C9ejC$YR&%JqDrO-fBg_K}x z6gfgT)N83K8Db#*syRxxs>A(qakRUvw2T&MxQrm$S5O~}&S0){x`l{HNAOhe1844_ z1H4UL&PN?sOa#8k#Sp$R)5>(lsnn2Dti90h2RW|(J1t;=yNaPRre#Cm4{jX%)Z~mg z)X#!`aN&p^HUwmoXEY&=rPexqbDE2q$B+ViwY$F>-i!Z@y`W#0z(X&bh5|tX?dyS1 z!2oRyFzTXlxqxJn8d4TbPY9B(m<7R^R%bZNu0ikPu*ISb+~$U8I*c&3dVX01=hyIp z0udu9Y!54d9C7W6m6LeF1(l}@+3h0td!{Ua48N%D)qe0ftKv|K-J#kyU|j8+&lj<_ z9-?ffgVjDmx!|{z#Z3qsLQv8`6R)uBpU3NT4)Y8tRT2eq6a^)i#~VpF;}v2u8%$*s zEZ33~Ik~5cxvK=D2GIq^8HVXRAymZN{{e+GX+Q?hN0r$+juA*FTb)lvnEaV9b_V<9 zAdRN#3>Ze3*Xy;AQm=VJt6sOU$n_u-YyduU+at}j{Zjt>P%JDguSEWDtn6MJH%BL% z!+DeU+zR7-<&e}xr-|{dc$7{3}saLAiThQaw?Zatwt7_2bW;B zj1{mnv^J0Ui>({?nlrFJ$$X|i%pZVJW{M!?%uFT}m^Igi9+OGCRws=%T*8~IHWr-+ z3TlqVsId6%_SoNTv20T9vAmKoZ~h>5C<+E5HJWT^X(Lr)kux!vwQ!GBaG4Zg8CA}? z#zFydEntzgAvHwHGPATt6=t>>!|ovI*}9We3c;t8S&Rgx;+8MI))u~eEc6ZG+VC4d zgkiL(X!J=Jnp*G3+KB-hzG2A$#x%#nJTB|jMVmk=gh{C*e+GxV~X@OR&y=urs{^C{?waQIt)n0X>vo=`t*`Wa&+=he0Ub}08 zklY|7nHX)yPejbf*kR}_oEw_*fK*LGm@NnNTZrI~3jz!groni*pC9b>{0exN3tTq) z`ECr=IN#L~tBpCxud-O2tm!8dri}wl>@5=vPA2^--34FS&|2Eq8BZZ?!_XCXdR}FkM6B;V zw8DiIRnY>$8Pmd6c~2FmTWE^4EQN7`abIiho&yOZLEsUo-8?3xrk2=q68#pC<9hHz ziZ?KWw(DWjCNhOtxBW5z%z_bO6LICaZ@<74xwRnU3tKgrYu5_lQS*Yl>Xw5wh?uZ; z9t*;z@hxqeVq#4*TEWdOiwWhx%K7b(U`5e+c}Dyo`zx`LwC|<-o|w=~RvRR(D+q0_ zE;T7r6f8x#l8cov4kTEDuPm?L1t`Li0%GfGJ*hx&9?;4fo@p@;iU6yF5|JwAf5l=~ zFsHcan8>^($E^GY{`>-mwvk8u7Uw$Zh@nig*@7e7EZL@E@uF;61_ZQcG!mtPb%#lv z(^)D?wx$=QSKA$LfenFT0%d!F z5^|cqNbs@SOXF;a)7=oCyJ|JElDa0yK+D1YKHK!^o&pGtV4nntyXm*N+O|En%Oe)? zGmG+k8^4Y43{Pm(VY`I{?$UJ7-S8Ssns|NvAj1{uAO#>1Z(oSDF*h6mP0$-%E0Vx}rWt0it6`j_xqqS|$43E*hON^;S zdp015(Vdwbs|8}v7*<>3JS0r`A~rMYGON{y2(e{+UIR}C1pK1COQKzxv5MV(*?U70 zG?`l|L|`;(p^8j;%!uUZ#NLuHc<>$99XAA3S-}qpW`-OhDn#=v5`3*Jjv~e2BfA-< zN+u9uP6%U()p~tmO`l0OcQC}TZ!X1>;~YL6HQfs~W$vsEbwap8rX5xmQS@34v_9}& zg=MmLnqA%Q#itRPCJEWK4N)n?Kv=vBpJGFxqu5_I@)H8ut2mSe(&)|R=8Z;;zPG+ntpW5h(9xxk@@DyS{oVjWUIzg_3p;W}DE=M+_-CuHK&A*Pm= zW^bT?aR|?D&>p-jH4|(1L*9_&r1Zy4vW49UE!Y$P(jUO*YGfcgf zq}>R#4*w!^s$kYyUz8S|j)w6G*q$w2&Kv9=4mYwkPFFZf)@o-ggQ=_p5--!rj2A5R zl&6_HZ;lXiud`$=e!G;n5ZS7DL9z|d%#Ysm%wq%0?GPl{LM>#@d$BVeXjIUf*GHn&q zuVn9q3CP=**&Gv$aVs%R;$0^3Z%Gw*>{Z|MdY&Cw(B(SUpd zE%xYCn>psUdx6o7>Vj(k5r^T27-!UqAX$i&1rEJIVMlv+&SrqW_F#6cU!zT;xp~31 z?+XA#)m(ToU*z{rz+ph}1ObX4VT336T?#|F^NMCi)3Myo1&xSTX3VKreoxPVt$_>m zJ}^d;-%wP)7K#p!XK^(PzdmJEPzDbz4Z0(*QrO=$XNlT2?h8{`u5B4Wq#iFqd^{ZF z=jtY$xsiOeqYE9@863Q4T7!weysxM$JD&85Z+m;y^ewTAef%}?oKsy{SFm5TLvqL( zWCBTc2E1t5(Lu5ef)(L1laW4g>gb{Pu8x;uX{?X68@fr&aDZ@kB)TF%PYVTyB+wRS zV^-dPgg)7`;bWZZpkA+ce?>dv$+_0n>1%K`Bi))6!m6P?rXgf7+QyR3gpn(+Mjlq9 zK;~c!sx4sr2!mEZ=5HY*?mJAl=mak(NGZ167{o-GYK@C(WJ%3_Mnh}jhg-B*?mPro{O5W z+igQhG=lSxav>t+Bwr~ZDu}OHDg4Ia2fPYA9j3psmTHdd20>!5kEWJ+yl{R}K=#=^ zH;u=Au9R!mR|oOnH7t9s1;Ey0t+GKZ{Cy-75wVhpy0m-7u0-w1ATV@bm&&A#aAA;e z+=8x_Ljk#Qqc<1W>DTV9>Sry%@6{rHWr>D$8@zt($Rq_p6^X9&Yl4vjtW9N>cgp*? z&5ED>>X;rPCSaIP_$$O_#_M27%`#}9nMm|gh&wwXGjRvhkI_|AXXA}I+}E^IfQPJf z*pv>@uX;x?nMFDLa~%rFm=jXiS(f0+F20h=wA|ih{)EEF3zftsXoR*_(iav1hkFD* zq&&ubp&xlSVGv+Nm^?$Vl`Z3A7t<~!`4yY7IE)>aB@9L_%J*0l#etaJ>IfE}=LLT- zV_L6H9ey)-vr|)abItZippDn~lrg_CEEvc&@k_WxGtb66`4anjxF=U>2%zml>^kEv zb%HHt0&0RA*jGlJlO zg@u^a9~?&oQJpgbW6|9hoTNV~Sr@nuc^h~k#{4WmZCP}&9?Fn4$oyv4=wKQt>BTBE zyVaMZ>j^rn$pXl$?3Nk*j5<30PusD?UQFrf>0stF`{JT($KLfKs@{Rh;8!Z6r#rIY z8%E^-GyoNcy zm{=(!Y9z)v1F4wR#!P*^!hWKL7-mJzLZpH=3}m6>q}0q@z_A9LGh@PnPz_P6jj*;2 z65o-|1P!aBO7NVa-vSrWpWvk!_vx-M$E3@S6SrDc8UyyUimlzrC3KY=OQ7G}z&$)I zz!XZh9+GO4FtxuEbpu~Ws^fw=_ElUvU6FT@z|_&} zD>oeC_(EZ*W50$57b9UTkvVG)=wsF=6Gt_Kbg)K;!G2Kn-EPYv$>p2e_hNY`m zO*Z)k7{IB#Q>`(tVPIevD26?wt3b>x%7x*Dc_NC@b9>ae)EOtv);-3~>ku#=wD2k? z@`xcVLdU2wp2>o~H7aNoL08*2l?6Z%W+rCv*%1>O@w%yNyk|V(XDM)a2O>v2qf^X$ zoet{}2P%2Fpu)D5V{froEX7mc=ltD7rtjJroN`MKrFlH&!9xvR)m^couI5GN$sRTy zWk%D`i7(1w2T&Fh>=7j-E6|y-X0~{b*i_n*P4IaJ%If=VH*v(Q3v#!&EJ7PGVCRY= zpH#L)rHAlp?ij(cbU(o&kBa`DSCtquf3kbpYHtA_f}ylwe*x>+$Yb)3uH=soI4m-M zv8I<=iq#G(XR%7NTVsh#v{5!YbOcvC@ZMD1#k$~(hLn$U#RAM*)jk@Pu@(atW55+X zw~U1r+tv%#bDRpR*|>To!~?Sxq7{EY;LY{8vMYu&xy?mmJhFi96}a2Sf--q1e`kz` zcNU`Iog$~%J;Aih;wCOX|VQ(c}rME#r^kI2fM<%GXjcQa9AcbWgP0I%D+6R(BWE145h zttwET(~j&p#JiQ5rrvy397NTwu?E|)S(_&~Ft85l2 z5Eih3eSn-6C^SX8lR3VbJ3@g{>C*`dgQ>L4F~?ghc&KOdWNTtf*1;x~iO`fXS!_AR z;0E(9DBPnDW^yYfdqN0V38olTpij|RR%=@MA*y*s;VyouE^N&T9|$Q?8O`%C_oFmv6Z=BP_flK3OTehkb6r)k_(PF-wSxl<#YuE2eL_wIjUNBZUlzY5WIpOtC{; zl`E#$Lhy6~8y5;0Y+=2a5M~pFEKqt{LfG^%h~SFr4RI)A*JoHg9CN7+B`phNIsP|E z;6c+P9+c%RWH2&&s+}<6L9^3&&<3Rk4HF0!)A_i(nQo!6374Yqa3Yk5~ zcKR!ZvEM|RCQLG&7lct5W4U~vN+>YPOuE)5R5R_s3wwYoyNuKlILyaFN89TyMIi|q zzpt3aVjg2|U5E+n7oySZ7lo|h|C;uZ8KEp{7BQ9UYL4X#PD>@ai1|Ph1jJ{MPIApwMd9oCdH|C36sT>Ly@7d}_%ovt3!UTi`iO@-|C1iof5^UqY zp0m_UO69TX47fJ+LR&0Lh)-wIovcX9roo@3G@7-EQNwOoEPLM9xFpf=NYHumda9V{ zqe`iwfGmSGD=Wt0n~>9vF2eR~KVJ}# zAVhUpE#nZU1V2~YoW_!E38zu9&mb9VLJe=X5}dQ`E3~ZYSn9X8@M#(R8-@ zq>alHSk~+cGAh$1#+rEv%EVypk#9!WUA0o}EUgPhrx3%p!9C3O--fVGt<#FDeIr5` zOgG1ga*{mW7;PmWYk>g%8JO~)+xoZp=Bh4VqLQ?y3>fpql~Nu5#95fX%S)s zzenuQGKlAEYyFyRw@?u8wFK~FmEamq`gS8S=55=tV!OF2VgPKu3mlJ+B|;~{3c%Te zHcdrZ>Fn#^!au+(frULfD74n1tWXBI8@&l^C_Ab(D_$Yav!N}8#ITJ~_H(&cvfdnn zD^;o#3=y_?%t(qm*wqqRYrYRVUSKb7;%MWXYXsG?~j9mekoZ0*uM z^4VnT(Eb9DM4!!w?pi*m)oZbl3mvoUxrn5vF%9XX7+~jGHS_B!x>dww4hXCD{^%?P zMOkP-GRWF2iD{ZOI7P{_*uz_pJxNGC_dsF7!-Cnl7m>(jrZmtqX$QfgHC0YG!uL=k z*gI|}4GSmUCz*vLm}oGdV+fQ4SZ)tFYJf?dQdkM#Ya(JRiGS)~J?e?>eHVFLX%ci^ z)ncj{j%?IwV|g$*MK`@Ho{s_36M3_3;%$qx0#z1}?}IPfLOyqHV1bW@;c`eH@i7hw zJ{d#hLZ~EN8BB1;Voa*wN^D*uA&Wb@_zWh?qtTg+RiPLwil(>Pt(@G=b0Pa0cTXhcM1L31wu<4ehLXXwn}SoU;hanX6ig$DB;x zU|QyP4N;CUSSy`Fjzr{r-d??uRgc7$^jObhwjz#XAxZ}4D&7WOPjlKWSozIN1+LJ` zefr_OZ0SLlSQypB$&NB0nhPn$l|szRj%Q3)YC6={8{`Ak>lnhSohRs|GNKq}KpdPXZL)>M~P7|xxAIno^&K^A=o zO1z;fTY8*-i|N)Z;U8&1dM$@SS{w*SLBYZeon}F2YAcWj*)nMh zsTwQTBkkCP76fj0bYfE%ZD0Tcn=r%3leLU|ZU@V*I)f%m-YpowTCLC0LYITL^=SzX znPp3me%R?@r!d$?3KM>e9$hm8HD(#bUM&7L#$fA;C5(NkCPuxo(QN^QAa8wbK4Pho z(?GSRr+^(a>*uo00fty!HH;zzqoJwKq_90+ew5ttJueIws!9pEbXoWYNO{>>?$r&u zYGV(o!7N=SE*;z?0PRm`sQaNN+YiYdWnO`F%}RC|m2A3^X+B1)J!b>QqMu zj)s7;>8#r`0{1z z7^6FB?J-}%)^0oVy|I^3m^4m>y@$2q{XOW;WL_?WtB1&Lp*4jpY9Y{;5=kUc{^D`0u%p=c4NQpni$sy!Nl!sKJz7X?Yc10KlK>u`& zN6~K6jO#J?4&~@$pI(A@>@*|UAQCbSoK>|YSSQ|A)G&emrB1dihZ>RWf-G6=2U%z;RG3=SJ^sPb89bM@^G-Q+{0;lAT~%vUG|RyrbdDse0g^pt(T80SJI@geO^iEGZ!V*{Kg$ z!AyQ~2Peq6=X|EC@@Qq*C$>OVTXI$H@noRYtPu0VycAg?%QvWl83e;Z?wg}A{ubsD zoRvvsvM_xq0Bu`d?T1;Bd4wO2+H&02QehUQw27-x=#xiyJ#IRU_{kn#VZK}0V>$uE zk%$)BeB`hg5$)Mh^}q#01d`Z~!?Q04p75h#Q5)K4Vg%3`N*3_%O|dq~+z23rRRQN* zoB;4`(KiOUa!z`3z8?-%*L#@=*)d~Q2V)#OA()owe@m9MaH<^jIOp5dyBwLa!uVn= zm=iG55`RMoKmq*PwM@wj4=*i=8fpXaP9o;L!f+91$54DYtDh*?PwuFayG#M8SqPF< zM=Lu34<7Z1Z~uA`1ouEbmek3nHFPhF$kha|pJ>W}u)@roND#apErEI9MhW(vq*1Q{ zYk_!nnG1u&<1UV1(I;5g;=q|1jDcP_HDgUf1L<3gVkYIZ8ev|csr+PH8)R~f;1LTW zzZ9l4T*Tth7@}nRMe*36?1s>;F?kw@V0i?YM*LF7srpN&PCyk=0(y&dKf> zD{a+Ra4z~qi?n>kfM332fN??vS->{JjhYL>(?B@}h*b!2gij^e6MT?rv{}GGcRi#u zg-5pQgtKWRxX}+NTQHIjT9d~fgw=EeA$?*_j_3iqnsTv_sV&Wy^CS+_^UR1N-S7)m zP{nHcn96t&!S9C~Nor`rt;rkdyb!VyDzPX&DCK2Vc;0VOf(NVyA-fcn2VFe#rZBr! z$n==rZbq6shxY&Gu~1*V((;BHGuKGkOO~yw14bQ?n!vY2Uj_)pG@jGxvvW>rV-}t@ zcd${oGG7322|3%fg2|{k@lC)mX@M=Y-aQ+Q%w+c>HyNuVMZ|F)_FWL5_g0JPne9nx zFCin$$FRLb*9P(2=H#wk2-~+(>?^{~L{e|&>Iy3WDUB_Hq!0eSdZ9jy+O8K8pb>sp zK0m}nZ!u`#hhcG;`jUZXuIADys}U?_n}uC)K@mrz`0zW_*`f>o(?OD)mBVGdqyKuvDtFyid5T ztC0|h#X~kZkt?w9fjJ;)Pby|I$;@4tl~}ZPk1&|s15MTxbbh@0(uOi!5cY`EF(ITg zz|j(jb$N&gu=&H}IAMke?z^Y8cEIsTX)0{O6f*{GF#dxWwh-ma2*PGgfnwyE$!2Sn zQp{^ZGf`wp;0HizJRYBZ=4HWS&*Y52;ufcrsX@2_^y_x#k{g5tALn4#{HRM%zCMi7jCe98dFbaDdG94I3;9pUi+#b*+uHh z4;{b=vm@Z=%^Q{`^)JHvHXxIWJZU09aZN)P0bwN#*qH6X~Si3Yy! z6MhE6W&PN$i;C}RiZRY{#CSdDpQs-Lg{27CPo+-?0%e&dc>a)2Ol~a&LHboGP7ZcO z7_73!0tJH|UD;&JQp0JtEtUjg(zAvGWg1pCBf9)7vagwkHAePK`B6uU6N*udwGe{j z4n_)Qg&Na=Bo3j;^V1Igo#QL_wum`Pjs zhWv~g{7m@qsU@S|14wTVxQWKP(U-Mcd%Aau79W|=+8jnkK3Ov04|8P1)gAU|KwXHI zxf=usmEBVbysM$W34$i@6$645dCSnm9j>cg~517)l z<9K~v1DgYUYeS7)=8Nt=LovaK>FYa0gCR4lr1^FTdI$5nwnW$-f>C>cLxauwf&oWi z*K<1hM=-=aPMmIns!VqgE!wHzG6KXJ7K`F3Q%Vun#JJ%WQ^lN5!to^IU3}0BC}diL z6RGw2c^E<}w%WnA%sE4x3lH{@-|p&;WOZknj zT2JI-Ty!emCP#YOJ~BwFvyqaT&tjlIuoruzZCS97;HoGIRGsl>UxzTwY!*DKmB>aU zfesWwlImm_sR=u+SOFxQs?PE)B*t`0+%yA57R6<8(Uo;9v%YKPsqe2C0!!QO$Yq(5Qx^`H(mK{>cslLO*~ zWW*pwv=qXbH?ISDD^x7pooK%-J#XZ-&v;k}B(A9pMS!Yf1PyMQjt9d@BqlfAW}lg> z5kVqHv^B(Nv}T*vD@(R;LR?`hCgopoGHY}=f-tYM>z59qX3#wv#Txc6v3xo-(^BnuqcMb77q7-mT`RxqCzM? zJ*dSJc2Q~1psc&JRn|s}cv$Ddg~tjB;b~H2coK&%px+E~+ky(EvRDk|`L!(&))!(` z>j?#FE4)boUxii(betddBvnvhhf>x3?JXKMG+8)o7P4@ykSFBl0P~&p)wr-H%+}Wm z`@^JysAUz9VKxUD02o|Z#N|-DWuLf@ksw8}<8rnxKC_-Ri-y~D0Hmi`BC~Bq%ZwYC zg7PrS9#*hy>{<&9rFun_Xxqrx|7Klojs-B8Z-jSFu`bNS1k5aFoUlf2Ied7l9)1#$ zHhN2$;e4nN7(qr^RH~hHY&#n`(@JM~ML&KxL#EVl(30hlAxg9Iu<{YkMha6Eb`u*l z?Iq$89aAG&DP|8&ygFW;FA2p1bo{h5G^jgopb>O}kM;^ zITu^g^3p_+HPafL=hb(L5bZW1IWQpx!=Y8kKJgFu$Bx9w4o_5~)h^x%8K=^wa+~_d z0HDSAFs7Yw?OX!CyURV9sFQ=CfH8(XlM&o-Ru1WUoeYI|nm|KlBNCC%Q#V=hl`1jl z0a6@G4|G-tsM8_8c2U~Wun3^3qTt7}DRY}k@ZuE~dziuKz7S}f=VCL{fqY(3(L;+T zs2PK9G70$ZMJ_6HML#Y3rX@ye-=)m}!MW9TC)t3w$sw zo+4hUVX}Y=f*p%@6~cBlfRQFvu{Pn(kBfat!;R&3aE9qOh;Hl& zzGvoY8%^ECMea$A5Jdu3*NT}v19;RetSI3PmI>aXrlh{$ z2x2O8Q*sEK3ChL=x9p%@fOt4ilC>IR-aNr%V7zUL!Mu|5N2D>#pH94F?pI(k6d%$Y z>ytifhdf3&$*~>}pf)~(EF)RfIiEG!5m~75WTrd5sS0*(w-69oV??W^ zDi-bw7l1vsaO+p4pd)CyvTDJW1iP<*$R^T<;8eObAJwhr=w&;TyvELBdx;(l!_rK> zUMmmw_*}iXA&>dElwA@&vT`k?LW(g~rj>!=4AKFR4DwHVC@Fr=1A)Xnk0Mmqqa|*` zr;{1AAw(l7%#=N#7ZC@sFYuvhzc^=Gm_-KN*;!0-+3q)({p%bUvM40yc#JRzBAZ8r zYsjy@kZ3R}hcNiW`bg;r$M~T%QwToDumu>8n(ZAaVm_Ie?DbySXGa;T{~1t#KmX7I z$K5~$LnPQGR5=e@GSfglY~t;yQHow2h+u0v4jvE;Vnw%8+sAnHrB?=rE(7e7nouGl z%$_8%iGc~8`<6IDUL07GtiAfK4~w^|y>Drso3oDeNR}+uVDDkOVNqJa=NU{EBVj9i zRMW%2UW@p^u?oQgh<~{xYBub?URquVizngRoFQiK$9IH99MsT+;}Nv1PS9>xKxb0e z-9lZ%>*A*`joxSeQ?R8 zFd|G6+E%3*HTuF)NU+WC(@A#dhWY{>W$Q)tWDl@2*|V&p`TYoE?0=z)rFzjDFpUC! z--8(3O)*0e9Ml$&1Dv?)ngTX<3%+@sh#$;G?`BmKRXm}ipX8K+G_<)#MINPbMKgTz z4{dD66Gveeqtqje6inIJCvm_DAB|E8_U#~5$-m)g7W5d@SP9Ill?~-u?(1kq9Tn@$ zZ6p6=bGYB!VNmb3nn?4#b!wcinfTN>oNs6}3Sj^Z-+Zusj3kRO`@pD-Py-zpswtB! z5SobDM?(c2TuYn?ksfy#1 zC_V#n`23iNBTji(>WpSu z*-fhi#t1+Fv<42wUW(4p7{LZ+`PHB@S(&9UqGaP`6GI2P<2dQFF2AOph^hve#b@r& zv2z%0#UyHzA2y(V@sQ3Qpclc%7N-(gb7+Z2S#oNsSMb2R_l;mCf1Dj zu$tbF-%(hbcG=CbD_Vec|4!#s^XcSF%(?!+TtE?+?Yfo@nM3KwBf~SiaINBA(*~)0 z698BiHur=uA8`tW2nKB8h&-f&>0Nft=vXeFD~Dv6&C#}gBSdUf!paqMpsg`^Ljuhq z!zU&9+*#G^$;m(_B)6(*#mR8&9@$MXv5Vxc0Y^HA2WJ8{D(0xe`LF1^Zo?u({iux9A4RdU_O-J-AK` zK+pJ5mm$@(kT0y!WWJ5cMZa&_b4n&gKm!r#z@BzkIqFxjHWo zbEut+W37CiwQSMG#GaN9T`)O4<@QV5H!sR0Dfxi+351nL4MA%KBZrA2LnXe*=H+e_ zwi@Y~LL(H-J&J~Gk3-O@Q<3cG@<>S54Rj1HT#m8;{FACE!xj zI$DMA;Iw9PKt<>+05ok+^EXimd!yapuvudeMJoCznKp>Aj3v>M6@hKYu%=sQEJLl@ z(*{q@ZMTIc3QRPe1{8xpgwHG{yfPJI;*s4!)LNLemysX)tD(-T!6k)nY+BrqPjHpx zwxTL3yQi`&vQc47u`xNja<(?nnIqv-!)c6SGvax~n8^V^M9?c*T4hxsUVRs>r@?FT z>b%Vjb>U<$B)Q8iW!STu}OHW_dM;z2t+#{`PIOZkRMNtS_s7tRc1;rxLNfVm$^ zz^Th9eZ(@>dGRpH!@iGcW6msETCEXv^eWZI%+=!38vb}(nJi)Pv_2EMeB&dc>U z!_SQX9u>FQZlS`HvhVrJSme^AEEpbTfCiaFB<(7~5V0G0Eg0r(tqGVh*Z{(jh|%y9 zzM__o>Nq3wfgi1$rj}wPDjx^Ev7~s{MtOJ(4GQ0VGhiM?2Y@wrg-cv$zm}}p%-PUy zg#`0m^@LEKXYuKgn+#^QYtR8$04ia(hDjG21g@&;CP}mh!$PvTsn%L%;|t3MZlhY! z)YbAK0KjfjjOZ%fcqVIIIJiDC;_cJsj~+dzj_~2C;3CgSSTtM>_%J9$g@(F zHg)GY#w|{lIZJ@i6~O>u%4Zbyu+g8BVr};*Ibx&!82AG91ud7xAeg` za0s6~5-(UjhA>APxCh{Nn5`^eAl9h{y1A!26jz#5Q*2u*Usw7|@K^Gec(hY7l zz&;hz7!BYWR(>!iD8LLD>c;?^2LXSqgXiY`usVj~tR>ihXV&pCG+@q7Q`XHR#>d9K9JDEKCjCr$a@o|%LB z`3p0xU{OXVsds#sHPE4O)+DoYQ(fgikV%T%2r)av@`|n7w=t2EOGRebF|OpQ1?%TY zq_XI_FRM1aeNx1}tnTTH>MBP*`D(dAkL3Bpp@B{<3>DjfF@Ek=I zjGCrH3lGxHscTqmCeCz`(q*~Bt!%T3nmsNSsIqCMWiskXcgcCKY#s6gy|U!u5`#&c zlkYmw`gtn76^Lv7>!uv^PUk~6S)H5RIT)Hy7P) zlMnjkOlJ#N8^|Pzx+Od4vIU?;vqSGJ#EhO>y z;>M@kjb=K^Gd<>m7E%+g*37ZOa?zj4TFyOzmhX6qYcQTmTXsfVQprV#yxgXoJ(%}) ziZoa~82DxdI4+o#UEr>f!e(n77-t}SQFSw62c&RmVKBUfX#Oi`Gj zNgg^U2;pXCOe9`cHW4>6HgT}1zlbZeUsN|-bqZ@KqmVoVA`_nL$ML@`!f6Uf|V<7A}ya|1N{&Wo7=-@$qO2iSK(O?xgbAROV^|C ziHw{uWvIKS?cBZ~k$9-RmK}2E`)J)&nSCy%O6E4Gq*%@#<;Pagb7bf-qzz^6$7rF~ zmrg(JoV4YQm_|P@TifP~R(`mP$$(t(cW(&ra*-=#(}%-F@tTuAH`0#E+{$##Tu;oL zM2cJHCS29jPb>|c?ucy8%9Bg-nXMGF`(t~$Q!P}P&j`#!Agn9**~~JrP|Ms8;9-9` z5~J6VF-f|r@NEYP#pI||1V@IRlNqAvNVR*$dpRLAUX0{!TN6hl+OAZz zn-yv!W%(iR=P>A+1A3V>>Ykrjf%JvkN|yk%*Tz$%O|@<_(QU>YT)vH`KIyYV#znbo zT0~u#5ruZf@Oz=7xMp3%T2BA0C-2PS680H+d1&CX%sgBO^nZlh);$|6!EstfBK9gcWLVn!*Ei0`2uDcSB0 z49e{6EQ~HHfNqT0T&EPsJ?-EU=Biox3558NMmmRcP0@a`S8)YBX&_-4yvAyVa zMor0{$X7%r!I|>zV3M4&Dr44*k8jxSPm-#UDL?BwYNVFyjr(vsOthMfOfeJOOp+%_ zR7r_C+1f=Sty(2do{`D6aQdV~?$7Cb3z-8*rSlRqePY;0P7Jlv9wS)Gh*x~0KayXn z=b>^`u01DO#!-gMwEE~Dybnh#m0SxeaF``?1)bhZHjDHxUZl!av+9$=wuJes!_DL- zPqKXFohW@0KjW@MCy_au>dtjyl|COKMDdz>k6&tzun z-d|;AanztBlZ+&TciB{?{O#Sxh@?wprpSJ2W{wuj-^@NTamq|)4yZCidO2Zq#C{_B zH)N-}_WPP&pUg~=Pi);LqB7Gb7g1!(vT{t=um=;vY}vfkF$t?o ztV4`LcDR9)q6ebCdNrpaG%f%WER!WHa~n?OfSRSPbj8mYGP5BiL$>{%#OsZm_`>lIw_`;IZl2@ zwV0N~JX^+#V!DZv{9-!UvU_>CPKc)s_;q!+ztFZQ$AaQIl)=QXjuemlxbLH^c||4CTeG5(Y0x7PFVcB%_!{Uk3PM8eN>9(Yj4oKfidVBF?SWYtmFo0$s$#Uhm0Cr$S++4={y zizg{WU%|n(Ze5PO6wbhmnwyezQpNm|)=33)J}wtk5*zmPAydbic3aGLmRvew*Ct#4 zYT5rVQm)N(=Y+GE-DG~|n@+Nrp4&2uX{P8KEaN6!Q8S#y+4?GlT;VTfk5XWeyFx0m z<<14eU2)s;Y9(h5#Wk6H78KLb-TdV`O6!|K?aSreVm3@y)+beWdqtb8Ymhl^<`o@K z`^_4>m}y8Jtr|DNbUj7AD{7E5eDaLpQ^Q$Q)F@Hzhlfpi$!mwjYqIoW#X@Adz!Xt_ zE4X->Wek@#i`kW0pX{0H(#L7CAuBX6YX^t1IVdD-S{TIF^zYopvOz9m<=saYds zzLzUAnLguYhx0Z!Q-3#-#i_4K;gI{v^u{Mpu!^EWy<$)hatt z24$u!5{@%BM3$`=q?l%pU>(60xo(BVY9Dulr?37!K|Q&wJy{7j!yfb=Z0ohm!U6xhsRJdfZH@?@@Om+&KAv-PJ2Li8=eG; zg>aZf4a|r$D{Pj?n+4jn@wkYTW+dIW-_2{YjddxIix?+9LVTa zs&td1%+1eT>lv(>;JHJj+g)ml+A~*2>Ss8PrWUH+GaN}D#}InR%Ov+WEuLUW?Cv+ zm_&_Lp0?m<7=;us>(|kak<^E9(K~UQK2EPkjF7E&lctYz#lHG?h;(I^Ckl;HY8~AU zO<(k~#x4qT>>qkm)1-)JQfeR+eC zbg&%9Op4VAu5EM}$t87W@h>4r`!o5dZFMoNMmeI^lM0clFMTLkGUe+Px0aa-EP6@o zLKxFKUh!ddurN|OiL(saTTt;q*>OV^eWSan*{XbUAsQK&7lanKuf|NYn9GM z?YU9P^$jYCJPvA{4WG_Mu;G&v`L5U4a2iUnQN3vFiW}(nNQ!BtO{Z}6tfZKBBFo0H z)C__ie#wd<+%_*;Mw#)JQJn=Bay_2AqRfz$EH*?V+*eSEoQ)o~2soS0)(7v3Il}a* zv~D?tr`F}M59KOoT)BBX5$LL2_pX{r2tTBn7xpP6&#k$JWQTX)>@- z?c`IThD-(uRSdG@

+>tU|qF5Ozm_Po+h%jdcYrm0M_>V?JLhtS62$mD`QcgO&cc5rvki4f+@^y<1T|dX^Cr za(Ell4N~Ryl3!M4{Fy+TFVxN8PRr%G+1!M?)Mhs2XZGldy4PLUrB*XpE)Abq)SAhX zqB;aTLC3PFW{8cz%QRDHxOoL;z$uJ4y{$Ylbx9iCMM78E*e&X_enhmm?VgPa?ntnO@zy7~hJzb^OO>vOFrI-I>_*k#{xO^1Mt>?}}cg z%bT&X!E>2@A6A(%x)df;d)zBE(TPow&?KXn$BR{2;*8R=!hL!@-a4Zw-GE-Ih}}!{ zwW~yV#KdgZixoDX^=ww;$qY{UQ&}Xjb1G_W%PjV^RmS|V*CCk!gjI?9@rNnHCl=FX zXwT-tO4uuz@f51`-qKaHOwzU8q_OOj4cAio=6?OBx>B9nMwRLuBWWYECMM}xCHn@v z8>HpT%a}!nMHu=VLNY}tITvB5OLKq^>O8y!{v8d#8Y=Gm^vQ|5t35S*LS(j7-18!{3BVpNgRowdYXhWuQ$Uw?5q;M! z3p5>3(>4mvOW4>kuXD-nv8=)vr1jRU$P+n>bk$m+^T5?{_ILDn;Od2)JA<*SueX_; zqnNOsY;j~~rRi;<@Q#3M8rG0VgcYu-UIj}Oo!zz~CE;2rvi;I6B;98?ZXv!I(kYRy zSxP{5-a`Dy34@=J>IWgTRBsGw8FON)eJ}kjn6pyut3UcOr-a;Rnq<^Sh#5nPY%vu~ zO4i@37fj+bCTyO{9){doE0~m?nXIFt-B1J4<+o0Cp|N>SC-3TqxD2ArTn$Xzg}Par zg-5CsWJ6Oq7IjwfqD+}S*-W*r@?V!NN;U5M?Il94e=nnwes1udF0VJ@t8tK0HP)w{_V0Fas_U z-QrZY?4f%1fE<>#%%CeydoXtE4`b3tb{RP>hwT+uE)nmI%UcL9k-pyLd3Hz&-}H@sJ2Hg&X8CsRhwVk&1Bu$Z375Us`Lp`M&FGhp${Xv=18F}qjN z)BV_$JTC0uihB}ng~hxk*+uS^7BeamEynobo;hoYV)i8mIa`$@c{dwmD@Gy-Z)}D0EYl5s^+rx@?h}b%L&~z58COQ$($$x_i~HiReOKtw|7+h+*cnrd~DXtRk z<>r@%cDWsQRv0b~R*$kw9aC7Sms#N&4qt4VZZsU3%WP$jn><}6iFAx3*t4W={|~$Q ztd)mPG(G#(t!42f(YVRlRuj2mMBSFEd|A*%?6F^db$f}-sN|j;)mWCObi7x$n=>w- z14n7}|HG18HW?$I;<=aJukK$eFC37~Vqxn4@R7B`C^^;oU%A&b)WbaEbM?@gG9PiC z>?#cG^7@g)<(qN(R_qz*vs;k_jXo0d`NK@r8-+1t@0|$a}f1d zHP7no%~IQ~m8!KT%I=5X<<)l2dbQFkreoCw)ekokI^l8~Zb^iRkNowj(yB3jmew)E z0pTCBqR>ZfRl}X6pfi7C`0GV3>G7(3bxYm%Z+tFcH6~WX!OB->3E?#P)EM;^l@>J?n_Ga?)LmJ+PU$W7mWa-T z=Owjigtf#PtJaef<-OH#TaAAu__xw?)-Iv)TlQ1sJ+09@S??Tw>kyKJoJF3p8_^(TthZ&c^3a~2m@weAveh1oECTcSBgj*&u@ zfp{2k3AwyP4dQQ>&ZRB*m4>Q3<(RM5pqfVv`cY4oks8U@D8gt=4C<&fX+r2!v%RQh zs(ysqT9;owWl{%MS^8fTK91#|sLE>@X(#{ssml5v>Br9!lxG^b*jNq2*Vfc%Nxjr% z_dm%qCk|ez)#6ua{z}U0;8P6$q9RH})QKQ}(3?lvC1q+P+s+!cJvKz(p0zeAuZ9)v$RD_Nqe-^lRekT3kt7 zYe8+?*MYjo>*33Fh?TKh9~vNw#K(r1H-g3>IU(_DLMRfF0*jEE5>hi_-5gpJvELGT zD`*XEARgL=^Tey#A#V>Ipd;aRBDN;(L261V)dl+!b|NG}h?K5ipWCj-sZFrd(*& zY7C6k@vcocJ~a-;!vvU!*(8`uiHTVr0CsV6o1#1X^KjwG=;Yb;7)j zS`?%fNzc0+R>1AB67yAX2dsuQ=&dEpJ7FEH*WouLKN@1%kbG{WHc3+jL@YGNZoI)?xJqrO>FL=cHRs35yt(n5g(*ZZUX6@HzPg(55hz6 zFgyZVFnbiX>TrT;8*S(@(*8JlPhkEetVX^ao+8Yr;TiOv#m;l^JiMS<(wiyuBD@4I z!%pJ#3N7SS;{6(}BpElmU^nc6y_C>CTF!p#z77ZAARK}>;7vFTNAUkGI10z$ZQQ;C z$KhRg58j6pn4N@E@Bw@XAAz*VkKq&e6i&lu@Hu<|U&2>#2EK-~@C|$m-@*6r1N;a- z!8!OD&ciS8EBpq(!yj+~{)E5aZ@38mz`x|5w6*_0Sw3ZfZMD_)w`jaQ=qF>hi|#>~ z1zR?9r6Q;tk>GSn<>B5K?QIZ1F_hbzAT8`t>bYPqcZv>As)Gur__g1 zs7qTNDS6X>mBCF}D2Kk(oATJL02M6>hrSs7%8+0MR2A%1g=(m;f$C5LYNB^7)PmYj z$7-kQTAfrq#zU!x*Wq7%>@@(XpA8WkL1SowSyLUBPc=i{oV2#UkCw<=!D@0sa&aH| z(HeCd2vLVRh1)shjs14e9y&lr=medi3nYS+LlR;Lk|70BAq~=@D|CYl$b|01tp{X5 zPv`~NkORFz(&6TLAME#qe$b!z4S<2z83cnt(z}XONWWUxZ}`*@><@($TK6z3Q4P1G zzm~F<{A;grEoqk>)d=!&q}4@@B5y`R0i#DO=^2CDv2YZBWgIKso@7==pNsi;m_Qyk zB+Z4MNNamKG_aUHB#CShQSr;7vFTN8l|u z3di7Wcn6NdyQJ|w;`ToB6L1nv!3Xdmd;}j8hfm;BI89tXgU`|b0=`7=D>#GvYd8zv zz_;jq2j7#XeE0!=grCqm2S3Ak_yxPa!f)_9`~er>PxuS|hKukIVg8HwA1IqX*Y+x# ziIWG`VCF>}jeiknN;yWN_JPbFqR@-RjUNIK1F;Z9-;87JRGi&T?*Wv=O+1u>(wLWl zve+#L zVtsgxG&VqN2#ugIG=Zkj%uZ9y?VxI5cVn*a&K)vHrOcTtsFrpnGjf?FWirR;u3F*7 z%!irZB5y;OW{n{00{U3g?Vvq$fR4}!Izw5^yC5doJ($Z#STg?#swBb>L9#9VTDnS+ zJR`(Z{7(ZJ(?htGeoV%C>C4jbrz>HH{22wK3CFA(Y&8b`vA7#&_ta~y@u&w87fHLBr}o0Hc!XBH*Md|Pbs6I%E#XIc7mD$Q(>CU+Zt-RE%{qCFHKq`k7p2m0cJB{7Jko0 zJqOZ|OP?_p{Ttv$^xQPwgnS<6H^Y1#7sfK;zW{j(ZWdzy7FYy}VF@gSTj4fX2Fr0P z^O_Zix5G*(iyy1(KI#tqSxwzs18d<#?%|?jrB*hI{a*H{sojcpq-=hmEkw z?#oQMXx>O2bMv8}+HCh%57-0LgZ4o6kUdB}Y!6nC*hAQ98mb<(hpDahaJ9|ORgc*t z)Z_L@^#uMsX^&Fd?a}Hfcp9F8XW=>G(~5LFkN5)YfEVEK#MfXK?AG}|M(rUkQ7WMJ;?F+p@5fB)$?KTQczXcxAo2DQ{vpiYfH&bV z`ckKkX#2U;GuK?Hx6nI^c|5Bx*;74+-#tjD2ld;yeFx%Mxk(*7j=guCFprWCUc&a! z#!e!hf)7{;ir??y<|QXgQ;!E~zu!my1o<4vyk)QBPtmxCST)Li!$}?HVC{dQ-x5|o z?T?IUC0JETTis`0*{_54INB)Vjy)dHt3I$N;8v**`SX!IQJd|vCu#AdJsBHb^)cao zLi#^NJZbvi%8-ses_bpEm$l|1}H>rZ9hVk#j{#m)8VOFLhE zWlvFOFq8Trbwlb%h`jyU9z$yms3V-g!v943J45H?dF1iT0C@f7x@$B{8$r-*6T#!a(ZjKXyR~(rgK@m%s>iD$JU4~iL}ItA6W@4N>9I~2K2HMsYY8eE z{J0N5jP{4|89#y$2eL;|!gI6ZA8Q{S4!c^oE9IF_R3y$mRa)C!;P~%TWl)#JuGHvq zh~=RIRD=+I%J^J~@G29(1kXYzEw`vDo<*vvXR)e=*){l4f?b1v4&zFBDtY8p)wLgt z@z@VBgNt#}Sku!?U9028UKakfy#Mn-Dt^CJdjtj`-EbtO3Y4+R*X45&Dw9 zQtpjCw>kOYQ%$tFF>C5sM!(~hp_rNRa13=L!Es-LosKeBO;3VqR>VIEzd3%ifR-R* zN-M`fg`yDF9vs$Hk)~GbkT9xhzs;-_pRX5yZKql_HBlhsD zWAAvq<8HX>=^3tiK{n(-Z|LJ0qWWULAN0q~02t`mpayyFa?)hn4ffovhIsBl->Zgd z`}b0l+%&OwhF(bT+^~lxVcW8UWA>DCJsTO>T)U<`MmS}11UDmbI|?_W5vAW5Uz&6r`$KIDLRhqwPAl6On1Tvv1{bk4cRZ1Jpids z(w?N8XW&i-tv z^C)b^P6YPH5a(^kL+sSW>2R;q?kGA=Q>3Mf6@meA)AK*pHp)y@LH$;WgyDU^ndf|N8Mv z*pCGK+za~%XaE0n$C?)N13J#kl|0Wn{oQlwkmq^z27bsG7-GlL)D_md*gp(Mh*LcE zMDkYZONbp!Gp?}?7BlpZA|7Fv)96dRU_OPPZ$pTkPt%XFPR76Ekb)bx|7_}cIXuR^ zi~aX7e}{NB1@ZfR{63-mH|25?JEu^8;MwW)@yu;de+1I+eN0|_g8Wm&(}0Bk}nOnqqd2 zzT;;dZ^j&UcV&)Y>Pzvqbl$NeZRZH9=91c8g8Bu2eudxQclZM?;P0RC7yOO-Ww;3c zz%KOuB|cIQ2CCgf!b?!|@LT4_(nh6j$$s&_*bjL2(5LKG|KY~0pZ2m-?yeD7zc7c9 zwVZ4Mh+7NM1`o(Qor6pj0g+JF_9~y3b1#SnKLj8KV!c&W(Ce-@Wc?uXmOU!YyN`OZ z51;nY=a_wcDUSly*K*EQf&ircgxCRRHwKga*h^3)(I1FTJbuf3qm(y+vj{idudC9; zPuAvTuvZq!L3!d>0edxZUlFkqRE7i{FIg)dP*uDKR8{XmRn04BM~Bok-ZxZr@0+TI zH>hgDwNMLcUhl>y)J558`dK}vbMPnu|CKey#ZoFkhOXvMA;W;jMxO4LNjO% zEkMTUmWVOfZH1q$Nr&Wn8^pHI4%$Np=m?#lGwJFAiP%qq5F|qiq~cc^q(fKe1{shE z-Ju6$K~Lxf+4z?Oy`c|&_Jw}P=aTdNkq^MmKo~?G42B^v6o#QU9DA=($8wSHCoe`2 z{z&g(H41m5LH5zdU^W)}<6t~YfQjBC?AN}fCV9K6$=J(-eEiBIpLW`hsO!B))fDgD zYAQ_g`qgxpf!_r%6Zf-VHq7xJQ**smE*WQuH81ot+-o=*-6@k^c%Mj-$le_ zv3IjtLR#c3RmyBB{@e;}X?wRJE`#N;0&d6sN>~MVz-m|nYvE2<2kT)2+y!^TJ#a7F z2lvB9*aVy50eBD|f`{P|*aDBjR^`jivspV0bGWA_=5J}RDEdKNp+k>}5Q*K*Rl7JF;8J!!u$ zU~dP!2rt3QuoGSZX}{u+)SXv}M_XLV`QB^f>n_+0d+>L!_oUiK82i1a@K^Sy4y!7- zm3@QPNy7m+h(Cwm4R{j{qjv<}f}?N@-iCMJIJ^t*!TWFmPQoep06v6|;A8j%zdnW2 z$UlQj?^~SanRtKh{Xl);{ZM^LJVV6$E7EWVJ71$di}($E3*W)_@B{n^KfyWp8T;q4 z`wQZ)sDFdsQU5`BD+%KQ;-8rP1%H$Fi>UvB9Mb(ScK-tv!M<$-eKUB#3lR_rK8S+o zh>w&XdjW`vSgT?qWKRE{3ZjmK5>S%PJU-%Moxi0b9wChntJ3I|0Xbinc2O3;%0YST zS3s-?m5^6POn@rLt3oxn26xq=2Gj&u7ha243$xl#2kJ)jRrTPy2-fAO8$iPd87tVM zMXxb5L9Z$9njtoa7RXzIlzl7It)UI^Zi`+k^xC0r4;`Q*bb`*%1@lD2q=--0Z*|8D z_l(AzeS|Pih7?GJG)RZ8aDcWiX8>{*&<%A4WI}i70a?(KJm>{7-ex1_KyT;+eW4$A z`ojPi2!miS41u9A42DB4jDV5283m(Z42(r@9E^tvFcG~;Fd6b7AHC~g3QUD*Fdb$< z0p>Gd7R-h@Fc%~rZ@~OUo$s<2@1EJnoJ98GWp7^g#y@4Q^C`9bQ{A>(Qx9*_-o9lezxbBt9H zpED=&syk4xhBdGj?u2!)9yY*Ta5vlo_Y#-;;C|#AVH2cqk}dwo+*bV93=hDA@DMx< zkB|pj5FZ8E8`+Au4IYEX;fV;j_3|bCpjSPK-Rq??;ve5ffMr}&?Asn z(x;`XXCu0*=ddgJ_B`SXumfI%mtZR8@N&c%wKL*tWMAXzYsW3?1I%BABj|qMX+>U1 zxzSJ3K6b%wsL#o~=p2qfje0BM zTXi(zJIe8_I)+&d!kWu?*OIX;lYU6*%iFk@@_7gIG^< zzmpMPs8hsU*7c@OqmM=XA$$ZM!zWJumBHUn;WT^(pTifJeF#w$-GH@Y|&i-5>Tc4Q$6qQM`@oiM~0h=m};VXp*~gm@?grJ)RF zWuYAM@=yVJMW__1RAu~0K(7jvCHSi7SA%OXs}41wCR~fXTG*)#b)YWP!`^jJ9~z); z2#t_8Mr;C2anlU3IkbS5&W}^a7zoYm zAJrhl!SF5ha7g4iH5C6$KQH5t>F0-G?)LS=k>^73KA*EM^hV-#6pV&3Fc!UWkU)Pj zp7_qU&NDANPfE}0{`G0*0Wvp@$Hs)nU+8;(Wqtmeni$zhO^OVt$>dKS?xe5EN4!4r zciQYPY6^Zz+@>N^L*~46ht;tGhr4SV*Wduc+83XgK$mTd4cvl7yBjjyiWFD zFOcWPzZ=lM5pKf%Ji;%)?ak1Z@aN6>>m z?DgD%zj8J&=b)>RufbgUuC>VTM7|DjJ>mw$yWno*_aNR&zTOA-!$#PI-e!0J9)ySB z;mCj0Ba#1+-=>ak!QP|jZ-s5}7(9;N6YwPR?eG*l4bMa>D~p>?&yvRH$e+^Qztr>S zzW_VnMe_J1n2+0+VJEx-uVVHZ`n!=3+x{7v)^ z!x4B3j>0i`8{UEA@GiWE-S=^G0#3py_#iSteTeuGd<>t!r*IlRgU{g$_!7Q?Gw?P3 zoP}@TTlfyW@8Jjd5q^Sm@H3o;U*K2xjr{)|{(uYcCvN|O`IP(L#P1^f6Zwz&mwf*( z(z4{I?S zuK_1??i^9t-zO>#y%N5lD(U-F#rrrT!Cq-717)Ece#zKg9&*smJ<+;P06YU1--O??3?jvH{?A+{`iXG-o+iTxO> z8F6>dprze3N8N(3mM7M#hgnO^T0v`Q18t!lw1*DR5jy$0tIobytBWsa zCHms5B+?M_m9Ub1C9M?9Qy~osXq)MXU7;Jih5s3pQzmqWb%fgkF$?Nr){{8(f^6*O zAohkn$ooP+=nn&Y@zy|JDXSy5_PA+6T7zm3^=!QKEe}`+o+5gAR2+X^~ zI^EwUsFA)>Y7}`rn!Fo>pIxv!7JH_Q>ASHz9wxvRX9hZS%;tb|n{X}AM%HLQWPa3@T} z%{tP)9ya*OI%Qefio9w*m!o}Ntqhd9i+C4sd$R0R?Ub?ZCfs}AUbqkL2Z`H8*aVyL zL*};yj4%%nuLt2FUs?4q`Sggdf>q*w`W;kTd=;%n@nfs6lC=&0B<+tOJ`PXd$CJLw zta`4N28mySwVm>M3j4C&dz$cNe0c_OqOS_0?bY0hT?tRdEAd18s%m+-Ey~P}I?LIC zubLHoMfYMisGcK?=XH43Smmy0PwKkZb=$Vd%NGcD2fXOS^(Dl0#N%beoe%g=6jLvgZ=P29Dsvx2;RWIH{mcGAd+9N}hdrOWb4%1q9Zr9bSXKKIop?G3CibQ|LyUO4}_Z;1RWID@}( z{_!<_N_x&BeuLh(@Ev>)6Unz9d=0H@E(_1?hia)G$(Ntt9PZ^T{b$7UxcvowMgKSW z9sWT70{jVo!QaH;B5nE~_!sm4fXShv!6`e6Js|KRAHdy%h$zOts797wk7WVniwdYH zhz36dqRhN32K%uPjB1SCE7jXZRviACc*=S@ph`qFvDnEbCz?=aWsGZTmBhag^*0{B zN<}r}7VVY%a_c6oKT5v0Fl|rP2W5z_>=U`;k>vT8lzG`G@jp?O!{73RQ31-bCap-E zDuL`TUt~|Ka+HjP&99OM3D<Z|E*q}|rT{5p{HxrWTyCGYE_Zb0}A$(KFMpJaV85qC09e5vbYTjJH0G`A(qN;Se> zV`u_Rp;=TrOTLs6b#rJzTrJjUEs?i^*3bsp!X1=PJHl%p)!vHdmNY9w?Pn=&n0LUR zj?f7@W2X!D6CnvgkPIo13TcoIT_MD+bU*RxMz|S}3EiOwWMSSDdOsd6rp#qR+-_%iuLhzw2seXa2>BD@#yc%X4Ml$#>fw;U4fq7Y&yDI}jewCb z3P!^i7z^WIJWPOzFbO6@9^}LIFa@R(w`ozGtm*hagSZqB?o5zFd5X}t*~&hy}Am=6nJA>0CsU@$qdHqFk*|U~U^T3P zwQwh_1NlC91Kb67!#!{>+z0o=M%Vc1Uw1b;VF0; zo`GlKId~pkfF1B6yaX@9PIv`gh1Xyg?1nwC7xuw^cpVPFK{y0&z?*Owj=)=R6pq2$ z@D3b@ci}yFA5OqYI0YZThwu@644=TKa2h^?&*2OB625{n@HL!;Z{S<_4!(yU;79lg z&cV-c9)5ve;Wzjl{(uYcC;SC}!$tT9{)PX5O%=stK-u5{FGN5j_#g_R!4Cn5fmjGa z9F%~P5D%rGG?am|P!7sN1*iy>pfV&t6{rf;;2Nk7HJ~P33$>s&)PcHC53Ymy&;S}j zBWMgwpeZzqPSS0$IdZ9Y_tGAuKMV1tNqOKDMfV?FBD+{Eq7$u_&sfC zKo|srVF(O`Vb~pxU%4;>M#3l<4P!7H3*%rs>IpCr`6QSOd5{m+Lsj~-DfqXEadIm5 zror^+pqc>%FcW6MY?uRcv3mn{ZiJg)9^4G`VF4_JTcT5~MTm=G2`q(M;Wk(X%V7m! z-wrF0uYx;ZHLQWPa3`#T^{@f%BHX*-9=I3o!|na#=SIvn!De^>9)ySBVay(ZE!cY$ z^;X!1`Y}Ya_rV+Iw9pgzc!G!tbXcM3Z_3@mbtI2hU^v0_;HkBKBT_mtiNo z0 z-_1HAllgci=9!pxw@yU&U~Wv`MmVS71Jd>(d;}lEC%F9-%snjT$jCo~&oTQVI@9`+ z_e5{}m&R1pvfK8OMdGumI$@-vAE_ya1&-=FyueKPKX z5C87RU?eoec~_QCK4Yx2dR!&18QP+ zExg2vC>H3Eh=cjgycYh{hC2R%R$c5=^AEKuc?Vhb2>Uw1tnZiaT!&k&fZY|`1ylp_ zpaO9>d)ej;PQLB4nXfj)uSQ`%xqpjXzQ1gO*pzrTgXYkJc(sI9=(mP8{$W;Iznl}B zz2&`&NW0=O6<~;~@Vi`T@>`(HjCoVHoy@L#}_c9)CulHxfp{ zXc&Xpb>!z*#Bu&H)B`y`k-6_!T@S`%X98w&R^Y+jME^K#XA=68{o|Qlj3+(gbver! zsf>YAUU|3)QI7fkn%4FH3Dm*y)^GL@YYOhB`X}Ots5_}?{z*mTlO21M1HBeAWBe6+ z)k#+eHQnDq&42=!3A13fKOZw$Rp(>3aF1XP`O%gyD5F5Z)Depy>jryQu)aJOG>CCgW)GYD%2VM+PA`OF;;+UY(10{jtu zvp0J$`E#Ex|CyAHYgf+kWc|t7fV6D%&!YZ{n{>5_ILV%Fh_6@0{$}Fx0LXsNgV=ot z9`?^64ATe5I4pO49zlPLf3A+J)IFmwH`Teni~FrknnLPE{55X2q4yZHq0PwNTLNFh zx^ZtvzGTv$Nj{YH%)?)CBjwC|!7pFSidyWrX)u1IVCQkaoHnp_Ax=+{cKIf_jAsFU zB&hA^Jq1tu7qZq}NDeFvm)SE;9G^ve4xR_eCpot)Mc&F+xi9$5dm3`S_6hZ22X;c7 zTFc8Gk`Hp$`67BI-poS?|7F+-ufVJDnt!n_yIuYz#8dW=luBoel{4#j!Vp*;V&@iX zH-5Q$ZF`VQoFtxmA%PglIkJh{QsTDI+K0Zpg0i1*UiaUs%R}y1%h_B*z8;QK2h;)V z7(d;%Wa54h{X_5u$QurCA|3|mOOL=?{$;w~I*R-lybbTbad;QrgZKT*8E;JbPY?$w z4~geV%uIhR{r58K6#hyahue;X7jnjv36U#xJ(Y7uDHl^u#otxoI7%EOKjnVqY5e~Tb4j@a z+6X>J?+eQPOaC2=yC!W?r%XRon0KbGNSR2wR+Co}miad1EBrVE>BL#=m85sDBoDqO@1&nPi<@uYTlkK=_};&ke%_6PmpFLo3ndP+Cn0YraBqV2{OG@v zHe%Y#PuMvJKjX)F_yzm-``76<^egH54fRvF`5jDoN&8r@+rQLfY0qvre_;25e*<+> z>grv(Ee{~Qrap1rhyQ>1rB2_i+n{_yDsz?+Ixp^_q)orE#CI?GQ@oAJ8Sme?m%1w7 zLtOOVr`wg>Yms>TLmDLCrGNStd;b9!l$8}Q_U(Xt&0ZK6Pk4S0Q2v0-S4>@=f++J3w>`vD7iDY?(O29B zfq*#+j0tQcpEeTiM#2@p11dHk`<;6JhzqkG36hre_!$@2WL4&id{%wfm-)&jt0t|w zgpMC~{76eYl!DT@k-2Ue|h?Sr+BtR9AHx#6uS0ye{)@JtA z-Lq2mK?6Z`4OAyCH3APk7h9cYHW%xjt>wt#qENRhhN5_v0V4Q=qVEwqF7AbZ9g z5IaIA=!~5%kO)Z-3Or=h(XSaiQpjr!8-VA^GfVA75==TD-3!aUb1HGXS^o4%V9|n-G z0|N(1Cu`6^jv7pSBwo^I4I%!rpDy1555?{<;xQb(To{47kuWMC_uDz64m?cyME?=` z6cM>+K%E|ge`Ar4gYn2GX#cr$hjE!&W0$cHWD>_?=;}+`%-45kWzr;bx)63d%8~yz@>}$+&rvu~+2GHywA&5SMHJ64VOB+X-(aNV{Eycn9WY zY>@W6oxV%lQ_s*}4QoK^%3Ad9gmthUHUyrczY)9Ksf4@1^h*-=r|FlCnUvjKI{as@ zp!e(*^yCE(Nt^V4@{))6BYwW%#ErW*gfDMINxZ(}oaSEQXvRhEy=%KW9J?lMe^Gw2 zhLrid86(B5%u&SO7sGLoasGbo{-t7iGSBSndD%&?`&|xqMhVw^XR$LJH%ad%@?tY_ zd;p5)nfUVx^LR;9g6f7n8EYQI-b3&(JOW$bQP>LG;4!BRq%Sn-d{xggCGRD?RQomR zWMO_w-|)Cj$1cVfH~%=R#-AtA-wsdV@6+%MJPXgk^Y8-ffEVEcXqhG+yE+^ip_TK-4oqhiYJMz+sn;tX%+(ZqLdLZ-KkbZ?l#%VD# z-#0F1QoozH$oGu{Y`K{&>wnG&oV?phUhJbRCUAdgf8ZebD&{6%IrpQ?i>k%0?gj=7wgwIlp|(tiNE4S5NsEU>eu?V9+qUxfJ~-494zG~emk#9iv? z8~F1k9EKwx--^lE-6720BF;zQ7;V3{_b~Gp*>861w&{D`#_xCFIJ^t*!TWH8*JvsL zyA{Och;~*3bDTQS)RHyoznF)3u_uC;d;Y_3 z9nw-OmgCiT-sOA!ukinj{{u%)*0gTDlG_)Y2hon|^D2>XLu-t2 z%|9mH%=uzI(d$9ELofYi)fjoT$h6UFF{f!y=B=)kh#TmCuVKTpI_U_h&oDD@jLBPL zHSo74T&vUZIcA?(wPHTAYC|2Ui&;ImF6Il$!<=c?N8JD#LZg^3wSQtJ{@j{Nteg>U;}&ZGU^oU?e>a2PO)H<{iBXs zD*mTIIxMCi>5AA5GH{m(-D7^DZu4#%@+{~Hy)e&)9Ow;wV$P9o?%O-^x)l4y&^P8h z^+MYFFU%P^)8bEm*hn8d0DmM;2jX7duN;Ip7^I(*@){EJEB*x3Q0nQhnBSPw(f_g+ zBkOF*H~B_f{2GH=zEvHL+gyv3f>`6u6|OT9Wp8b=|@dnKdEmlC{s z#SB4>AwFYa9E5lUOX|&d>;>>|0%8JwRDr7gKQZGx4SSQ&pA31B57)>1rPD6o3l{Kt zmei$5w5iGdi^!AIl$em38uJfz_M%miab_BBro#*MV2KO(H2r`3^R_03xC z3#(<%J;aM%rc9#=)AUvIvA00m^*d$(EiRX zurel=k$_z@%63&ukg&OvfIJn^^2FIv-^FY-$lQAkqLlyIm=ffTyT?Tv#OzMY*2R>> z57wdhEpG~Jh>6F4zB8f^-w;zu$8$rByf()DZsK%zOc~PU)@9Ro-4j!mbg+-Z+Dqo9 z@;%qR*u4+#hmE+|1e@Uj)DOZ#F`cNrrtj~9_%Pu=LSMZF9>u?{*x3e;!Q=2mOatmT z@n;Nr67_a?3Z8~%;8~EqL`HbCm&3Z1y7^p8edc-QEz0K!;|1*PKztGLC3qS6PQ+Ib zUqyV4aCRZ?hCQ$s_F=Xk=!cZtmp0=SZJ7K!fVq6fR)h2$q%E$9{8mZ%ABt(I#ZtV^ z#+M=7jbq+|UAapi;v0lEdaNsFzlpm|F|E~MI1=-#dMl=bIvOM2i?vh7V#?cZ6UIBZ zJ5GCQPM`QL@*em&#)-#!sNW}UC*UM3#OxG$AHatoclISrxwroj>W{ILik(joKZVoy z{~3G^U%;2x`3la!*C2U#7JJ{ox9}Z$@=d_^$bWzzQU3(z;Ac1wzre5XTTBH)sz7zE zKs_>XDZ{rH?taVfxc>t}sv`BPn!13SKS{GOuV~AD#9x^I9aG7cccEq6H)|W(6aDx_ z%>IFYA)P!o`>>UDooy5~nzE{7|A!eL&+G5}EkqkUu@x4dN^FVDs*&ng5#jZ1vZ~kDA!2>DXaT$k-=#Puzp1|R{dKvk#)*Fbfs0X5-TsD(e$CTio4>~GZP^}rS3xm+E)4*u4SmG5MY zy|%<(<_@yvs)rkSFY`J?*}JKa*Z}_;f~@Bnp>7OKK=!elA~u8Ou#hu=7KkmO6|{yn zAm>DKel!-^qHYK7cjN7mcYu!2iMV%$E|3UG5Q1b#!CbxpOGTar>ChDl&%Vt0RyXuA zAQQSn56B|!axOL(dLr+IU)hj@ShQV-< zw}5l;dj!b45hD>tp+6eNz*rau<3ZjIo`ARozua%zC!(H&o5>(|8uL)+!}Tx)rouFs z4l|$tX2L9(4Rc^F+yFPiO)w9?Zie}>ozwzYh~6!*C|16QmA46kYH@5=wInt{ErnZS zWsgYSE;yoYBY&2`^4QJvmYZqKo9REPN3qx1x6_uo1>A4f>)I=0>)NYggX#`g9lJ`c ziM?B`g*)+cU2HvjJ)-Q_-pUvzXBYAo#8BG72I6uT@sl&GyAh?%N;%zw{9d>Z?k5hi zr@0Yv6KrN;^#J07@DMy4d!7AAto!XZ_upf$u^+|VR@fF>-+nAs-eqcFKTcRrKvQcq zZM&f@FEz>c>QAD#9i-prk6Oz2Db(_&;nRrEz_aiiJP$9x4v_EMUqpNfUWT7hyWhd@ zMEwf93a`N~*bRGNFYF_3($4oI%0ATVhzCf^K{y0&z?*Owj=)=RRJYePe7DxnK87D} z!#g1FiON~capdp9d)iOd&$v0E!;$k?&YMu5ifyF(S9hI3FG~L|{gUK;WBR|w^lgpl z+Zxf=n{SpYkoOhPeG}V^FoWt_!uk%r2Q%K6w0?+f zPMn85_QS{|UesE8on!-5aoyEIYAqhSI4Wfj(0e&hjQI;diUlrwj1 zg2>~7t?UxP)^^EY8#_MO)-HuvX($uqE;#%q@!~Esb!4C9H9q_9Iezmh}1l!p)gB`h1-x0lz z=&PzQ0{b@xYk#liA!hv?u_3ubCmwVq*3Ovau&7{ z@dEYT>@9WCbAo1s+ZsKg!vnyak(WhtN+# zX5L$9gBxQfnLK0MA|Kj8d*~2M!CoyD7bW{qsmwD>SdY^TgC`^W2+PX+>U$s zw!3pMU5DL8>v0c)Jsxwe(-k+eU&Na?RFM7H zj=Yd7tL-%0rIWv1@w=nWD>uEFdLGm*9KY_&DZ1ldcl?ucgA8uE$ljd%-bJRJfjxO| zqNBta8nTAU#P3A(ee~P;m~|(N9zmI%af=SKp1~~gNM7U3!p{TjX$DoVU{AY(ex0`` zdO?*Plzqc2JBM=b4YipD%2*&}+6VtG-AgRKhsZkaZye>a&~h-<&r;=?h(OW_DJ$&6!Ot9#z}*W zZ)5Ry9QiOl*oS;|`@_EY-50<6;~(%d9$%Cuge<0%wEvcU^U8_d5E~D zf1OU8^R2eR);g=GYs+&FpX-&3SQKPaV4)<`RcFn9l`S z-`s#G=g1PyjUer42ji5iV{bw|4{nC}umBdqEwBg{!xC6Z9BvKXLOounZVL`!z8g@> zf?d^eSi+oVMR2Hnd$1Dk2vt%m5m&(-xLXZtU@hDU>tH=>AdYt--VOJF%wbxPfA^w) zAKVWcVH0MX;V@(B1E?QF{t(ET?_t!Bz!s2k|55U9D{Mpk7Z|a53W^D zk&dT>X0HAWX3xTNm_3j90^$zD7vUv%8Fs=e@M>@o-;7Jz*# zM!pC3g1lKT?Rp>b1MHpeM|@r6*lor*eGvH}-Uf3o#`Hhuqhs_Q?Q+7B@BH2g4yUdv z?r0X?@jOm^-VH`uh3}5bz9VG;o8dkDG{09OcSCcT`^g^m2>X5d%M9_?t8Z3e3ElT_yF?{;UoAsIMV(k*g<^?r}6hQ!u}k-z-&3MfLHX6w7*3EtKewb zj_9#=M?KCOLpuqmud#a;WKH`G`rpELsK194^nO77Bm4yC;Ac2bn6fVZ1^KV=8~m=r zlXw#*D3Ja~`qV!#zYw-3`yAXu!Tw+P^Edhz;S6d?^FN6HqRuCs{}G2w<}f^PudFym zy*TzAA*s0!84{}8vU@#C;(B6Ujan|!$jv+8l9?HX~D*yor;`X)K) zGj!o8g?eyZTs~!*kG*{C z@s=oh?mdqXue-}$h19(Uq%)rJvmxQhURxvVg?M#7R*knC$BnU@pkEl533gM`IWjoT zZiaqy?6!cGag*)JzU%E)aZ~K3yc*AaQo@wCF{jd+yQoP`{w;-kPlYr{hpx~KG9VMW zLl4M;p3n=jAqV$z=kNkC?~R{*pl{rBl-9GVU!3%BLDio)4FLCCe_-76{8E@}F8yCR zzfWM|JP1FF{ziuM&4bY!0z+X~Tst)!a`A5j+)O@AGEAk9-1gjOPXU2vto@!M>~$r(!-W zZkinzTR`0^AQuWKKQn)sjz2T7R}eRYHJjL(Vb6?{SN>;WZzlHSRE6;uJM#95%y|m< z1psF3n9sso%9`(Gs4sKk3hcS~a|7{^)4}GPd)$cs=6t}o9qsiqznA(V>q>5@#&uQm zbUYc8;|lB0eDZ4nEW}LO)wA@qx5OPItbke+7f_2ale%>q^+)n(3F@UFc`R#iS=Zi5 zJmg)++Ypz*a##Vk!%9fuSD~s10-0)UoE`F^+Tnl%?I#>@I;4Ziu?ty#Z zKDZw?!Y0@Z55R-)5IhWzz!rFv_-~DyO&-oB4`(}hXzJEB;_(>By}`#x`xEdaY=;Ee zS_ONK{Z!ms%6Beq=i*k@5qvw3oBHYutL&h92D`G3c@|OL1bvP$pNAJHqaAVbD-Ac` z_J(k{vJUv0eG{qs&3*C<4ma4p@f#&C#@$4161nVY8}pEwN54~4kGTVWzf4#mb+cn% z+%lJdSK{VhX5Z+G{RPY|i~D8Fiu$>bw2B?M>rm8R`Q->#-;JLerue;xx_&kDqW&)~ z5@(afSL2pAdal2mCB!YgEFEsTUyZw!_9tPnU!(Kkwy;{p$q>I}VbZ|dhCGpVWhbq_ zJghHzGUwZ^%WQ>{Hs)B4eff@A%w(@Cg6$Iat8b+;$b+V!(SJ6 z{}y^j;h5H+V>bx*hnM%UAFwy`Hg?~^uC)2%i0^{L?>%@QPQXbxh5iS$i4Wl;_!vHc zPvJCXpTXzY`vSG>SDW8sk~YM // For exception class +#include // For string +#include // For invocation to atoi. + +using namespace std; + +/** + * Signals a problem with the execution of a socket call. + */ +class SocketException : public exception { +public: + /** + * Construct a SocketException with a explanatory message. + * @param message explanatory message + * @param incSysMsg true if system message (from strerror(errno)) + * should be postfixed to the user provided message + */ + SocketException(const string &message, bool inclSysMsg = false) throw(); + + /** + * Provided just to guarantee that no exceptions are thrown. + */ + ~SocketException() throw(); + + /** + * Get the exception message + * @return exception message + */ + const char *what() const throw(); + +private: + string userMessage; // Exception message +}; + +/** + * Base class representing basic communication endpoint + */ +class Socket { +public: + /** + * Close and deallocate this socket + */ + ~Socket(); + + /** + * Get the local address + * @return local address of socket + * @exception SocketException thrown if fetch fails + */ + string getLocalAddress() throw(SocketException); + + /** + * Get the local port + * @return local port of socket + * @exception SocketException thrown if fetch fails + */ + unsigned short getLocalPort() throw(SocketException); + + /** + * Set the local port to the specified port and the local address + * to any interface + * @param localPort local port + * @exception SocketException thrown if setting local port fails + */ + void setLocalPort(unsigned short localPort) throw(SocketException); + + /** + * Set the local port to the specified port and the local address + * to the specified address. If you omit the port, a random port + * will be selected. + * @param localAddress local address + * @param localPort local port + * @exception SocketException thrown if setting local port or address fails + */ + void setLocalAddressAndPort(const string &localAddress, + unsigned short localPort = 0) throw(SocketException); + + /** + * If WinSock, unload the WinSock DLLs; otherwise do nothing. We ignore + * this in our sample client code but include it in the library for + * completeness. If you are running on Windows and you are concerned + * about DLL resource consumption, call this after you are done with all + * Socket instances. If you execute this on Windows while some instance of + * Socket exists, you are toast. For portability of client code, this is + * an empty function on non-Windows platforms so you can always include it. + * @param buffer buffer to receive the data + * @param bufferLen maximum number of bytes to read into buffer + * @return number of bytes read, 0 for EOF, and -1 for error + * @exception SocketException thrown WinSock clean up fails + */ + static void cleanUp() throw(SocketException); + + /** + * Resolve the specified service for the specified protocol to the + * corresponding port number in host byte order + * @param service service to resolve (e.g., "http") + * @param protocol protocol of service to resolve. Default is "tcp". + */ + static unsigned short resolveService(const string &service, + const string &protocol = "tcp"); + +private: + // Prevent the user from trying to use value semantics on this object + Socket(const Socket &sock); + void operator=(const Socket &sock); + +protected: + int sockDesc; // Socket descriptor + Socket(int type, int protocol) throw(SocketException); + Socket(int sockDesc); +}; + +/** + * Socket which is able to connect, send, and receive + */ +class CommunicatingSocket : public Socket { +public: + /** + * Establish a socket connection with the given foreign + * address and port + * @param foreignAddress foreign address (IP address or name) + * @param foreignPort foreign port + * @exception SocketException thrown if unable to establish connection + */ + void connect(const string &foreignAddress, unsigned short foreignPort) + throw(SocketException); + + /** + * Write the given buffer to this socket. Call connect() before + * calling send() + * @param buffer buffer to be written + * @param bufferLen number of bytes from buffer to be written + * @exception SocketException thrown if unable to send data + */ + void send(const void *buffer, int bufferLen) throw(SocketException); + + /** + * Read into the given buffer up to bufferLen bytes data from this + * socket. Call connect() before calling recv() + * @param buffer buffer to receive the data + * @param bufferLen maximum number of bytes to read into buffer + * @return number of bytes read, 0 for EOF, and -1 for error + * @exception SocketException thrown if unable to receive data + */ + int recv(void *buffer, int bufferLen) throw(SocketException); + + /** + * Get the foreign address. Call connect() before calling recv() + * @return foreign address + * @exception SocketException thrown if unable to fetch foreign address + */ + string getForeignAddress() throw(SocketException); + + /** + * Get the foreign port. Call connect() before calling recv() + * @return foreign port + * @exception SocketException thrown if unable to fetch foreign port + */ + unsigned short getForeignPort() throw(SocketException); + +protected: + CommunicatingSocket(int type, int protocol) throw(SocketException); + CommunicatingSocket(int newConnSD); +}; + +/** + * TCP socket for communication with other TCP sockets + */ +class TCPSocket : public CommunicatingSocket { +public: + /** + * Construct a TCP socket with no connection + * @exception SocketException thrown if unable to create TCP socket + */ + TCPSocket() throw(SocketException); + + /** + * Construct a TCP socket with a connection to the given foreign address + * and port + * @param foreignAddress foreign address (IP address or name) + * @param foreignPort foreign port + * @exception SocketException thrown if unable to create TCP socket + */ + TCPSocket(const string &foreignAddress, unsigned short foreignPort) + throw(SocketException); + +private: + // Access for TCPServerSocket::accept() connection creation + friend class TCPServerSocket; + TCPSocket(int newConnSD); +}; + +/** + * TCP socket class for servers + */ +class TCPServerSocket : public Socket { +public: + /** + * Construct a TCP socket for use with a server, accepting connections + * on the specified port on any interface + * @param localPort local port of server socket, a value of zero will + * give a system-assigned unused port + * @param queueLen maximum queue length for outstanding + * connection requests (default 5) + * @exception SocketException thrown if unable to create TCP server socket + */ + TCPServerSocket(unsigned short localPort, int queueLen = 5) + throw(SocketException); + + /** + * Construct a TCP socket for use with a server, accepting connections + * on the specified port on the interface specified by the given address + * @param localAddress local interface (address) of server socket + * @param localPort local port of server socket + * @param queueLen maximum queue length for outstanding + * connection requests (default 5) + * @exception SocketException thrown if unable to create TCP server socket + */ + TCPServerSocket(const string &localAddress, unsigned short localPort, + int queueLen = 5) throw(SocketException); + + /** + * Blocks until a new connection is established on this socket or error + * @return new connection socket + * @exception SocketException thrown if attempt to accept a new connection fails + */ + TCPSocket *accept() throw(SocketException); + +private: + void setListen(int queueLen) throw(SocketException); +}; + +/** + * UDP socket class + */ +class UDPSocket : public CommunicatingSocket { +public: + /** + * Construct a UDP socket + * @exception SocketException thrown if unable to create UDP socket + */ + UDPSocket() throw(SocketException); + + /** + * Construct a UDP socket with the given local port + * @param localPort local port + * @exception SocketException thrown if unable to create UDP socket + */ + UDPSocket(unsigned short localPort) throw(SocketException); + + /** + * Construct a UDP socket with the given local port and address + * @param localAddress local address + * @param localPort local port + * @exception SocketException thrown if unable to create UDP socket + */ + UDPSocket(const string &localAddress, unsigned short localPort) + throw(SocketException); + + /** + * Unset foreign address and port + * @return true if disassociation is successful + * @exception SocketException thrown if unable to disconnect UDP socket + */ + void disconnect() throw(SocketException); + + /** + * Send the given buffer as a UDP datagram to the + * specified address/port + * @param buffer buffer to be written + * @param bufferLen number of bytes to write + * @param foreignAddress address (IP address or name) to send to + * @param foreignPort port number to send to + * @return true if send is successful + * @exception SocketException thrown if unable to send datagram + */ + void sendTo(const void *buffer, int bufferLen, const string &foreignAddress, + unsigned short foreignPort) throw(SocketException); + + /** + * Read read up to bufferLen bytes data from this socket. The given buffer + * is where the data will be placed + * @param buffer buffer to receive data + * @param bufferLen maximum number of bytes to receive + * @param sourceAddress address of datagram source + * @param sourcePort port of data source + * @return number of bytes received and -1 for error + * @exception SocketException thrown if unable to receive datagram + */ + int recvFrom(void *buffer, int bufferLen, string &sourceAddress, + unsigned short &sourcePort) throw(SocketException); + + /** + * Set the multicast TTL + * @param multicastTTL multicast TTL + * @exception SocketException thrown if unable to set TTL + */ + void setMulticastTTL(unsigned char multicastTTL) throw(SocketException); + + /** + * Join the specified multicast group + * @param multicastGroup multicast group address to join + * @exception SocketException thrown if unable to join group + */ + void joinGroup(const string &multicastGroup) throw(SocketException); + + /** + * Leave the specified multicast group + * @param multicastGroup multicast group address to leave + * @exception SocketException thrown if unable to leave group + */ + void leaveGroup(const string &multicastGroup) throw(SocketException); + +private: + void setBroadcast(); +}; + +#endif diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/config.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/config.h new file mode 100644 index 0000000..4fd19be --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/config.h @@ -0,0 +1,34 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2017 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#define FRAME_HEIGHT 720 +#define FRAME_WIDTH 1280 +#define FRAME_INTERVAL (1000/30) +#define PACK_SIZE 4096 //udp pack size; note that OSX limits < 8100 bytes +#define ENCODE_QUALITY 80 +#define SERVER_ADDRESS "127.0.0.1" // Server IP adress +#define SERVER_PORT "10000" // Server Port +#define MAX_FRAME_ID 30000 // max number of recorded frames, 16.6min max at 30 FPS (max frame ID sort of hardcoded in image naming too, see below) diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/msdirent.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/msdirent.h new file mode 100644 index 0000000..445d040 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/msdirent.h @@ -0,0 +1,372 @@ +/***************************************************************************** + * dirent.h - dirent API for Microsoft Visual Studio + * + * Copyright (C) 2006 Toni Ronkko + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * ``Software''), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Mar 15, 2011, Toni Ronkko + * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0. + * + * Aug 11, 2010, Toni Ronkko + * Added d_type and d_namlen fields to dirent structure. The former is + * especially useful for determining whether directory entry represents a + * file or a directory. For more information, see + * http://www.delorie.com/gnu/docs/glibc/libc_270.html + * + * Aug 11, 2010, Toni Ronkko + * Improved conformance to the standards. For example, errno is now set + * properly on failure and assert() is never used. Thanks to Peter Brockam + * for suggestions. + * + * Aug 11, 2010, Toni Ronkko + * Fixed a bug in rewinddir(): when using relative directory names, change + * of working directory no longer causes rewinddir() to fail. + * + * Dec 15, 2009, John Cunningham + * Added rewinddir member function + * + * Jan 18, 2008, Toni Ronkko + * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string + * between multi-byte and unicode representations. This makes the + * code simpler and also allows the code to be compiled under MingW. Thanks + * to Azriel Fasten for the suggestion. + * + * Mar 4, 2007, Toni Ronkko + * Bug fix: due to the strncpy_s() function this file only compiled in + * Visual Studio 2005. Using the new string functions only when the + * compiler version allows. + * + * Nov 2, 2006, Toni Ronkko + * Major update: removed support for Watcom C, MS-DOS and Turbo C to + * simplify the file, updated the code to compile cleanly on Visual + * Studio 2005 with both unicode and multi-byte character strings, + * removed rewinddir() as it had a bug. + * + * Aug 20, 2006, Toni Ronkko + * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified + * comments by removing SGML tags. + * + * May 14 2002, Toni Ronkko + * Embedded the function definitions directly to the header so that no + * source modules need to be included in the Visual Studio project. Removed + * all the dependencies to other projects so that this very header can be + * used independently. + * + * May 28 1998, Toni Ronkko + * First version. + *****************************************************************************/ +#ifndef DIRENT_H +#define DIRENT_H + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat() */ +#if defined(_MSC_VER) && !defined(S_IREAD) +# define S_IFMT _S_IFMT /* file type mask */ +# define S_IFDIR _S_IFDIR /* directory */ +# define S_IFCHR _S_IFCHR /* character device */ +# define S_IFFIFO _S_IFFIFO /* pipe */ +# define S_IFREG _S_IFREG /* regular file */ +# define S_IREAD _S_IREAD /* read permission */ +# define S_IWRITE _S_IWRITE /* write permission */ +# define S_IEXEC _S_IEXEC /* execute permission */ +#endif +#define S_IFBLK 0 /* block device */ +#define S_IFLNK 0 /* link */ +#define S_IFSOCK 0 /* socket */ + +#if defined(_MSC_VER) +# define S_IRUSR S_IREAD /* read, user */ +# define S_IWUSR S_IWRITE /* write, user */ +# define S_IXUSR 0 /* execute, user */ +# define S_IRGRP 0 /* read, group */ +# define S_IWGRP 0 /* write, group */ +# define S_IXGRP 0 /* execute, group */ +# define S_IROTH 0 /* read, others */ +# define S_IWOTH 0 /* write, others */ +# define S_IXOTH 0 /* execute, others */ +#endif + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO) +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct dirent +{ + char d_name[MAX_PATH + 1]; /* File name */ + size_t d_namlen; /* Length of name without \0 */ + int d_type; /* File type */ +} dirent; + + +typedef struct DIR +{ + dirent curentry; /* Current directory entry */ + WIN32_FIND_DATAA find_data; /* Private file data */ + int cached; /* True if data is valid */ + HANDLE search_handle; /* Win32 search handle */ + char patt[MAX_PATH + 3]; /* Initial directory name */ +} DIR; + + +/* Forward declarations */ +static DIR *opendir(const char *dirname); +static struct dirent *readdir(DIR *dirp); +static int closedir(DIR *dirp); +static void rewinddir(DIR* dirp); + + +/* Use the new safe string functions introduced in Visual Studio 2005 */ +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE) +#else +# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size)) +#endif + +/* Set errno variable */ +#if defined(_MSC_VER) +#define DIRENT_SET_ERRNO(x) _set_errno (x) +#else +#define DIRENT_SET_ERRNO(x) (errno = (x)) +#endif + + +/***************************************************************************** + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static DIR *opendir(const char *dirname) +{ + DIR *dirp; + + /* ensure that the resulting search pattern will be a valid file name */ + if (dirname == NULL) { + DIRENT_SET_ERRNO (ENOENT); + return NULL; + } + if (strlen (dirname) + 3 >= MAX_PATH) { + DIRENT_SET_ERRNO (ENAMETOOLONG); + return NULL; + } + + /* construct new DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (dirp != NULL) { + int error; + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly when the current working + * directory is changed between opendir() and rewinddir(). + */ + if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) { + char *p; + + /* append the search pattern "\\*\0" to the directory name */ + p = strchr (dirp->patt, '\0'); + if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') { + *p++ = '\\'; + } + *p++ = '*'; + *p = '\0'; + + /* open directory stream and retrieve the first entry */ + dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data); + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + /* a directory entry is now waiting in memory */ + dirp->cached = 1; + error = 0; + } else { + /* search pattern is not a directory name? */ + DIRENT_SET_ERRNO (ENOENT); + error = 1; + } + } else { + /* buffer too small */ + DIRENT_SET_ERRNO (ENOMEM); + error = 1; + } + + if (error) { + free (dirp); + dirp = NULL; + } + } + + return dirp; +} + + +/***************************************************************************** + * Read a directory entry, and return a pointer to a dirent structure + * containing the name of the entry in d_name field. Individual directory + * entries returned by this very function include regular files, + * sub-directories, pseudo-directories "." and "..", but also volume labels, + * hidden files and system files may be returned. + */ +static struct dirent *readdir(DIR *dirp) +{ + DWORD attr; + if (dirp == NULL) { + /* directory stream did not open */ + DIRENT_SET_ERRNO (EBADF); + return NULL; + } + + /* get next directory entry */ + if (dirp->cached != 0) { + /* a valid directory entry already in memory */ + dirp->cached = 0; + } else { + /* get the next directory entry from stream */ + if (dirp->search_handle == INVALID_HANDLE_VALUE) { + return NULL; + } + if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) { + /* the very last entry has been processed or an error occured */ + FindClose (dirp->search_handle); + dirp->search_handle = INVALID_HANDLE_VALUE; + return NULL; + } + } + + /* copy as a multibyte character string */ + DIRENT_STRNCPY ( dirp->curentry.d_name, + dirp->find_data.cFileName, + sizeof(dirp->curentry.d_name) ); + dirp->curentry.d_name[MAX_PATH] = '\0'; + + /* compute the length of name */ + dirp->curentry.d_namlen = strlen (dirp->curentry.d_name); + + /* determine file type */ + attr = dirp->find_data.dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + dirp->curentry.d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + dirp->curentry.d_type = DT_DIR; + } else { + dirp->curentry.d_type = DT_REG; + } + return &dirp->curentry; +} + + +/***************************************************************************** + * Close directory stream opened by opendir() function. Close of the + * directory stream invalidates the DIR structure as well as any previously + * read directory entry. + */ +static int closedir(DIR *dirp) +{ + if (dirp == NULL) { + /* invalid directory stream */ + DIRENT_SET_ERRNO (EBADF); + return -1; + } + + /* release search handle */ + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->search_handle); + dirp->search_handle = INVALID_HANDLE_VALUE; + } + + /* release directory structure */ + free (dirp); + return 0; +} + + +/***************************************************************************** + * Resets the position of the directory stream to which dirp refers to the + * beginning of the directory. It also causes the directory stream to refer + * to the current state of the corresponding directory, as a call to opendir() + * would have done. If dirp does not refer to a directory stream, the effect + * is undefined. + */ +static void rewinddir(DIR* dirp) +{ + if (dirp != NULL) { + /* release search handle */ + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->search_handle); + } + + /* open new search handle and retrieve the first entry */ + dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data); + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + /* a directory entry is now waiting in memory */ + dirp->cached = 1; + } else { + /* failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + } + } +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/recorder.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/recorder.h new file mode 100644 index 0000000..3ba1aff --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/recorder.h @@ -0,0 +1,85 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2017 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef RECORDER_H +#define RECORDER_H + +#include +#include +#include "config.h" + +#include +#include +#include +#include +#include // file input/output functions +#include // time stamp +#include // time stamp + +class Recorder +{ +public: + // methods + Recorder(); + void initialize(); + void record(libfreenect2::Frame* frame, const std::string& frame_type); + + void stream(libfreenect2::Frame* frame); + + void saveTimeStamp(); + void registTimeStamp(); + +private: + /////// RECORD VIDEO, NOT READY YET (RECORD IMAGE FOR NOW) /////// + // cv::VideoWriter out_capture; + ///////////////////////////////////////////////////////////////// + + cv::Mat cvMat_frame; + + // SAVE IMAGE + //cv::vector img_comp_param; //vector that stores the compression parameters of the image + std::vector img_comp_param; //vector that stores the compression parameters of the image + int frameID; + // int maxFrameID; // 16.6min max at 30 FPS (max frame ID sort of hardcoded in image naming too, see below) + + // static int timeStamps [MAX_FRAME_ID]; + std::vector timeStamps; + + int t_start; + int t_now; + + std::ostringstream oss_recordPath; + std::string recordPath; + // ----------------- + + // Timer + timeb tb; + int nSpan; + int getMilliSpan(int nTimeStart); + int getMilliCount(); +}; + +#endif diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/streamer.h b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/streamer.h new file mode 100644 index 0000000..ca6815b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/include/streamer.h @@ -0,0 +1,57 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2017 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#ifndef STREAMER_H +#define STREAMER_H + +#include + +#include "PracticalSocket.h" +#include +#include "config.h" + +class Streamer +{ +public: + // methods + void initialize(); + void stream(libfreenect2::Frame* frame); + +private: + // frame related parameters + int jpegqual; // Compression Parameter + vector compression_params; + vector encoded; + int total_pack; + int ibuf[1]; + + // udp related parameters + string servAddress; // Server IP adress + unsigned short servPort; // Server port + UDPSocket sock; +}; + +#endif diff --git a/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/recorder.cpp b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/recorder.cpp new file mode 100644 index 0000000..89afc39 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libfreenect2/tools/streamer_recorder/recorder.cpp @@ -0,0 +1,190 @@ +/* + * This file is part of the OpenKinect Project. http://www.openkinect.org + * + * Copyright (c) 2017 individual OpenKinect contributors. See the CONTRIB file + * for details. + * + * This code is licensed to you under the terms of the Apache License, version + * 2.0, or, at your option, the terms of the GNU General Public License, + * version 2.0. See the APACHE20 and GPL2 files for the text of the licenses, + * or the following URLs: + * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * If you redistribute this file in source form, modified or unmodified, you + * may: + * 1) Leave this header intact and distribute it under the same terms, + * accompanying it with the APACHE20 and GPL20 files, or + * 2) Delete the Apache 2.0 clause and accompany it with the GPL2 file, or + * 3) Delete the GPL v2 clause and accompany it with the APACHE20 file + * In all cases you must keep the copyright notice intact and include a copy + * of the CONTRIB file. + * + * Binary distributions must follow the binary distribution requirements of + * either License. + */ + +#include "recorder.h" +#include +#include + +Recorder::Recorder() : timeStamps(MAX_FRAME_ID) +{ +} + +// get initial time in ms +int Recorder::getMilliCount() +{ + ftime(&tb); + int nCount = tb.millitm + (tb.time & 0xfffff) * 1000; + return nCount; +} + +// get time diff from nTimeStart to now +int Recorder::getMilliSpan(int nTimeStart) +{ + nSpan = Recorder::getMilliCount() - nTimeStart; + if(nSpan < 0) + nSpan += 0x100000 * 1000; + return nSpan; +} + +// get time diff from nTimeStart to now +void Recorder::registTimeStamp() +{ + // record time stamp for FPS syncing + timeStamps[frameID] = Recorder::getMilliSpan(t_start); + // printf("Elapsed time = %u ms \n", timeStamps[frameID]); + + frameID++; +} + +void Recorder::initialize() +{ + std::cout << "Initialize Recorder." << std::endl; + + /////// RECORD VIDEO, NOT READY YET (RECORD IMAGE FOR NOW) /////// + + // // out_capture.open("TestVideo.avi", CV_FOURCC('M','J','P','G'), 30, cv::Size(depth->height, depth->width)); // JPEG + // out_capture.open("TestVideo.avi", CV_FOURCC('P','I','M','1'), 30, cv::Size(depth->height, depth->width),1); // MPEG, last argument defines image color yes o (channel 3 or 1) + // // out_capture.open("TestVideo.avi", CV_FOURCC('D','I','V','X'), 30, cv::Size(depth->height, depth->width)); + + // if( !out_capture.isOpened() ) + // { + // std::cout << "AVI file can not open." << std::endl; + // return 1; + // } + + ///////////////////////////////////////////////////////////////// + + // record image: define compression parameters and frame counter + img_comp_param.push_back(CV_IMWRITE_JPEG_QUALITY); //specify the compression technique + img_comp_param.push_back(100); //specify the compression quality + frameID = 0; + + // record timeStamp + t_start = getMilliCount(); +} + +void Recorder::record(libfreenect2::Frame* frame, const std::string& frame_type) +{ + if(frame_type == "depth") + { + // std::cout << "Run Recorder." << std::endl; + cvMat_frame = cv::Mat(frame->height, frame->width, CV_32FC1, frame->data) / 10; + // TODO: handle relative path + check Windows / UNIX compat. + oss_recordPath << "../recordings/depth/" << std::setw( 5 ) << std::setfill( '0' ) << frameID << ".depth"; + } + else if (frame_type == "registered" || frame_type == "rgb") + { + cvMat_frame = cv::Mat(frame->height, frame->width, CV_8UC4, frame->data); + // TODO: handle relative path + check Windows / UNIX compat. + oss_recordPath << "../recordings/regist/" << std::setw( 5 ) << std::setfill( '0' ) << frameID << ".jpg"; + // std::cout << frame->height << ":" << frame->width << ":" << frame->bytes_per_pixel << std::endl; + } + + recordPath = oss_recordPath.str(); + + // SAVE IMAGE + cv::imwrite(recordPath, cvMat_frame, img_comp_param); //write the image to file + // std::cout << recordPath << std::endl; + + // show image + // cv::namedWindow( "recorded frame", CV_WINDOW_AUTOSIZE); + // cv::imshow("recorded frame", cvMat_frame); + // cv::waitKey(0); + + // reset ostr + oss_recordPath.str(""); + oss_recordPath.clear(); + + // feedback on current recording state + if(frameID % 100 == 0) + std::cout << "-> " << frameID << "/" << MAX_FRAME_ID << " recorded frames/maxFrameID (" << frame_type << ")" << std::endl; + + /////// RECORD VIDEO, NOT READY YET (RECORD IMAGE FOR NOW) /////// + + // cv::Mat frame_depth = cv::Mat(depth->height, depth->width, CV_32FC1, depth->data) / 4500.0f; + // cv::convertScaleAbs(frame_depth, frame_depth); + + // DISPLAY INFOS + // std::cout << "kinect (h,w): " << depth->height << "," << depth->width << std::endl; + + // cv::Size s = frame_depth.size(); + // double rows = s.height; + // double cols = s.width; + // std::cout << "cvMat (h,w): " << rows << "," << cols << std::endl; + + // RECORD VIDEO + // std::cout << "11111" << std::endl; + // std::cout << "Img channels: " << frame_depth.channels() << std::endl; + // std::cout << "Img depth: " << frame_depth.depth() << std::endl; + // std::cout << "Img type: " << frame_depth.type() << std::endl; + + // frame_depth.convertTo(frame_depth, CV_8UC1); // IPL_DEPTH_8U + // cv::cvtColor(frame_depth, frame_depth, CV_GRAY2BGR); // convert image to RGB + + // CONVERT form CV_32FC1 to CV_8UC1 + // double minVal, maxVal; + // minMaxLoc(frame_depth, &minVal, &maxVal); //find minimum and maximum intensities + // cv::Mat draw; + // frame_depth.convertTo(frame_depth, CV_8UC1, 255.0/(maxVal - minVal), -minVal * 255.0/(maxVal - minVal)); + + // out_capture.open("TestVideo.avi", CV_FOURCC('P','I','M','1'), 30, dest_rgb.size()); + // cv::Mat imgY = cv::Mat(dest_rgb.size(), CV_32FC1); + // cv::cvtColor(frame_depth, frame_depth, CV_GRAY2BGR); // convert image to RGB + // std::cout << "111111" << std::endl; + // if( !frame_depth.empty() && frame_depth.data) + // { + // std::cout << "Img channels: " << frame_depth.channels() << std::endl; + // std::cout << "Img depth: " << frame_depth.depth() << std::endl; + // std::cout << "Img type: " << frame_depth.type() << std::endl; + + // out_capture.write(frame_depth); + // // out_capture << frame_depth; // same same + // std::cout << "22222" << std::endl; + // } + + ///////////////////////////////////////////////////////////////// +} + +// save timeStamp file for FPS syncing +void Recorder::saveTimeStamp() +{ + // TODO: handle relative path + check Windows / UNIX compat. + std::ofstream fout("../recordings/timeStamp.txt"); + if(fout.is_open()) + { + std::cout << "recording lasted " << ((timeStamps[frameID-1]-timeStamps[0])/1000.0) << " sec(s), writing timeStamp data..." << std::endl; + fout << "# Elapsed time in ms # \n"; + for(int i = 0; i + +void Streamer::initialize() +{ + std::cout << "Initialize Streamer." << std::endl; + + jpegqual = ENCODE_QUALITY; // Compression Parameter + + servAddress = SERVER_ADDRESS; + servPort = Socket::resolveService(SERVER_PORT, "udp"); // Server port + + compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); + compression_params.push_back(jpegqual); +} + +void Streamer::stream(libfreenect2::Frame* frame) +{ + try + { + // int total_pack = 1 + (encoded.size() - 1) / PACK_SIZE; + cv::Mat frame_depth = cv::Mat(frame->height, frame->width, CV_32FC1, frame->data) / 10; + cv::imencode(".jpg", frame_depth, encoded, compression_params); + + // resize image + // resize(frame, encoded, Size(FRAME_WIDTH, FRAME_HEIGHT), 0, 0, INTER_LINEAR); + + // show encoded frame + // cv::namedWindow( "streamed frame", CV_WINDOW_AUTOSIZE); + // cv::imshow("streamed frame", encoded); + // cv::waitKey(0); + + total_pack = 1 + (encoded.size() - 1) / PACK_SIZE; + + // send pre-info + ibuf[0] = total_pack; + sock.sendTo(ibuf, sizeof(int), servAddress, servPort); + + // send image data packet + for(int i = 0; i < total_pack; i++) + sock.sendTo( & encoded[i * PACK_SIZE], PACK_SIZE, servAddress, servPort); + } + catch (SocketException & e) + { + std::cerr << e.what() << std::endl; + // exit(1); + } +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/.gitattributes b/Code/RK3588/PIBot_ROS/third_party/libuvc/.gitattributes new file mode 100644 index 0000000..f49e821 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/.gitattributes @@ -0,0 +1,4 @@ +# make sure that .gitignore, .travis.yml,... are not part of a +# source-package generated via 'git archive' +.git* export-ignore +/.* export-ignore diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/.gitignore b/Code/RK3588/PIBot_ROS/third_party/libuvc/.gitignore new file mode 100644 index 0000000..5f97a27 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/.gitignore @@ -0,0 +1,2 @@ +# Build directory (recommended location) +build/ diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/.travis.yml b/Code/RK3588/PIBot_ROS/third_party/libuvc/.travis.yml new file mode 100644 index 0000000..fe27da4 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/.travis.yml @@ -0,0 +1,16 @@ +sudo: false +language: cpp +compiler: + - gcc + - clang +addons: + apt: + packages: + - libusb-1.0-0-dev + - libjpeg-dev +before_script: + - mkdir build + - cd build + - cmake .. +script: + - make diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/CMakeLists.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/CMakeLists.txt new file mode 100644 index 0000000..f3c8116 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/CMakeLists.txt @@ -0,0 +1,214 @@ +cmake_minimum_required(VERSION 3.1) +project(libuvc + VERSION 0.0.6 + LANGUAGES C +) + +# Additional search scripts path for libusb-1.0, libjpeg, OpenCV +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) + +# Xcode and Visual Studio do not using CMAKE_BUILD_TYPE cache variable +# so we use Release build type only with single configuration generators. +if (NOT CMAKE_CONFIGURATION_TYPES) + if(NOT CMAKE_BUILD_TYPE) + message(STATUS "No build type selected, default to Release") + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) + endif() +endif() + +if(NOT CMAKE_BUILD_TARGET) + message(STATUS "No target type selected, default to both shared and static library") + set(CMAKE_BUILD_TARGET "Both" CACHE STRING "" FORCE) +endif() + +option(BUILD_EXAMPLE "Build example program" ON) +option(BUILD_TEST "Build test program" OFF) +option(ENABLE_UVC_DEBUGGING "Enable UVC debugging" OFF) + +set(libuvc_DESCRIPTION "A cross-platform library for USB video devices") +set(libuvc_URL "https://github.com/libuvc/libuvc") + +set(SOURCES + src/ctrl.c + src/ctrl-gen.c + src/device.c + src/diag.c + src/frame.c + src/init.c + src/stream.c + src/misc.c +) + +find_package(LibUSB) + +# JpegPkg name to differ from shipped with CMake +find_package(JpegPkg QUIET) +if(JPEG_FOUND) + message(STATUS "Building libuvc with JPEG support.") + set(LIBUVC_HAS_JPEG TRUE) + list(APPEND SOURCES src/frame-mjpeg.c) +else() + message(WARNING "JPEG not found. libuvc will not support JPEG decoding.") +endif() + +if(${CMAKE_BUILD_TARGET} MATCHES "Shared") + set(BUILD_UVC_SHARED TRUE) +elseif(${CMAKE_BUILD_TARGET} MATCHES "Static") + set(BUILD_UVC_STATIC TRUE) +elseif(${CMAKE_BUILD_TARGET} MATCHES "Both") + set(BUILD_UVC_SHARED TRUE) + set(BUILD_UVC_STATIC TRUE) +else() + message(FATAL_ERROR "Invalid build type ${CMAKE_BUILD_TARGET}" ) +endif() + +if(BUILD_UVC_SHARED) + add_library(uvc SHARED ${SOURCES}) + set_target_properties(uvc PROPERTIES + VERSION ${libuvc_VERSION} + SOVERSION ${libuvc_VERSION_MAJOR} + # Exported name of target within namespace LibUVC + EXPORT_NAME UVCShared + ) + list(APPEND UVC_TARGETS uvc) + if(NOT LibUVC_STATIC) + add_library(LibUVC::UVC ALIAS uvc) + endif() + # Aliases defined here available only if project included + # via addsubdirectory + add_library(LibUVC::UVCShared ALIAS uvc) +endif() + +if(BUILD_UVC_STATIC) + add_library(uvc_static STATIC ${SOURCES}) + set_target_properties(uvc_static PROPERTIES + OUTPUT_NAME uvc + # Exported name of target within namespace LibUVC + EXPORT_NAME UVCStatic + ) + list(APPEND UVC_TARGETS uvc_static) + add_library(LibUVC::UVCStatic ALIAS uvc_static) + if(LibUVC_STATIC) + add_library(LibUVC::UVC ALIAS uvc_static) + endif() +endif() + +configure_file(include/libuvc/libuvc_config.h.in + include/libuvc/libuvc_config.h + @ONLY +) + +foreach(target_name IN LISTS UVC_TARGETS) + target_include_directories(${target_name} + PUBLIC + # Different paths for includes for build and install phase supported + # via INSTALL_INTERFACE and BUILD_INTERFACE generator expressions. + $ + $ + $ + ) + target_link_libraries(${target_name} + # libusb-1.0 used internally so we link to it privately. + PRIVATE LibUSB::LibUSB + ) + if(JPEG_FOUND) + target_link_libraries(${target_name} + PRIVATE JPEG::JPEG + ) + endif() + set_target_properties(${target_name} PROPERTIES + PUBLIC_HEADER "include/libuvc/libuvc.h;${CMAKE_CURRENT_BINARY_DIR}/include/libuvc/libuvc_config.h" + ) + if(ENABLE_UVC_DEBUGGING) + target_compile_definitions(${target_name} + PRIVATE + UVC_DEBUGGING + ) + endif() +endforeach() + +if(BUILD_EXAMPLE) + add_executable(example src/example.c) + find_package(Threads) + target_link_libraries(example + PRIVATE + LibUVC::UVC + Threads::Threads + ) +endif() + +if(BUILD_TEST) + # OpenCV defines targets with transitive dependencies not with namespaces but using opencv_ prefix. + # This targets provide necessary include directories and linked flags. + find_package(OpenCVPkg REQUIRED + COMPONENTS + opencv_core + opencv_highgui + ) + + add_executable(uvc_test src/test.c) + target_link_libraries(uvc_test + PRIVATE + LibUVC::UVC + opencv_core + opencv_highgui + ) +endif() + + +include(GNUInstallDirs) +set(CMAKE_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/libuvc) + +install( + TARGETS ${UVC_TARGETS} + EXPORT libuvcTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libuvc +) + +install(EXPORT libuvcTargets + FILE libuvcTargets.cmake + NAMESPACE LibUVC:: + DESTINATION ${CMAKE_INSTALL_CMAKEDIR} +) + +install(FILES + cmake/FindLibUSB.cmake + cmake/FindJpegPkg.cmake + DESTINATION ${CMAKE_INSTALL_CMAKEDIR} +) + +include(CMakePackageConfigHelpers) +write_basic_package_version_file(libuvcConfigVersion.cmake + COMPATIBILITY AnyNewerVersion +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/libuvcConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_CMAKEDIR} +) + +if(JPEG_FOUND) + # If we have used JPEG library we need to + # add linker flag for it in config file for pkgconfig + set(PKGCONFIG_JPEG_LDFLAG "-ljpeg") +endif() + +configure_file(libuvc.pc.in + ${PROJECT_BINARY_DIR}/libuvc.pc + @ONLY +) + +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/libuvc.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) + +install(FILES libuvcConfig.cmake + DESTINATION ${CMAKE_INSTALL_CMAKEDIR} +) + + diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/LICENSE.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/LICENSE.txt new file mode 100644 index 0000000..4acc5dd --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/LICENSE.txt @@ -0,0 +1,31 @@ +Software License Agreement (BSD License) + +Copyright (C) 2010-2015 Ken Tossell +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the author nor other contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/README.md b/Code/RK3588/PIBot_ROS/third_party/libuvc/README.md new file mode 100644 index 0000000..c6a6e38 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/README.md @@ -0,0 +1,29 @@ +`libuvc` is a cross-platform library for USB video devices, built atop `libusb`. +It enables fine-grained control over USB video devices exporting the standard USB Video Class +(UVC) interface, enabling developers to write drivers for previously unsupported devices, +or just access UVC devices in a generic fashion. + +## Getting and Building libuvc + +Prerequisites: You will need `libusb` and [CMake](http://www.cmake.org/) installed. + +To build, you can just run these shell commands: + + git clone https://github.com/libuvc/libuvc + cd libuvc + mkdir build + cd build + cmake .. + make && sudo make install + +and you're set! If you want to change the build configuration, you can edit `CMakeCache.txt` +in the build directory, or use a CMake GUI to make the desired changes. + +There is also `BUILD_EXAMPLE` and `BUILD_TEST` options to enable the compilation of `example` and `uvc_test` programs. To use them, replace the `cmake ..` command above with `cmake .. -DBUILD_TEST=ON -DBUILD_EXAMPLE=ON`. +Then you can start them with `./example` and `./uvc_test` respectively. Note that you need OpenCV to build the later (for displaying image). + +## Developing with libuvc + +The documentation for `libuvc` can currently be found at https://int80k.com/libuvc/doc/. + +Happy hacking! diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_imac.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_imac.txt new file mode 100644 index 0000000..e367025 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_imac.txt @@ -0,0 +1,228 @@ + +Bus 001 Device 007: ID 05ac:8501 Apple, Inc. Built-in iSight [Micron] +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x05ac Apple, Inc. + idProduct 0x8501 Built-in iSight [Micron] + bcdDevice 1.89 + iManufacturer 1 Micron + iProduct 2 Built-in iSight + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 267 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 0 + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 49 + dwClockFrequency 13.500000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 16 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 1 + bmControls 0x00000000 + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 2 + bSourceID 1 + wMaxMultiplier 0 + bControlSize 2 + bmControls 0x00000039 + Brightness + Saturation + Sharpness + Gamma + iProcessing 0 + bmVideoStandards 0x 9 + None + SECAM - 625/50 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 3 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 2 + iTerminal 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0008 1x 8 bytes + bInterval 10 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 14 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 1 + wTotalLength 155 + bEndPointAddress 130 + bmInfo 0 + bTerminalLink 3 + bStillCaptureMethod 0 + bTriggerSupport 0 + bTriggerUsage 0 + bControlSize 1 + bmaControls( 0) 27 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 3 + guidFormat {55595659-0000-1000-8000-00aa00389b71} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 383976960 + dwMaxBitRate 383976960 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 0 + dwMinFrameInterval 333333 + dwMaxFrameInterval 333333 + dwFrameIntervalStep 0 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 383976960 + dwMaxBitRate 383976960 + dwMaxVideoFrameBufferSize 202752 + dwDefaultFrameInterval 333333 + bFrameIntervalType 0 + dwMinFrameInterval 333333 + dwMaxFrameInterval 333333 + dwFrameIntervalStep 0 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 383976960 + dwMaxBitRate 383976960 + dwMaxVideoFrameBufferSize 153600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 0 + dwMinFrameInterval 333333 + dwMaxFrameInterval 333333 + dwFrameIntervalStep 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x1400 3x 1024 bytes + bInterval 1 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 14 Video + bDeviceSubClass 2 Video Streaming + bDeviceProtocol 0 + bMaxPacketSize0 8 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_macbook.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_macbook.txt new file mode 100644 index 0000000..62d0337 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/isight_macbook.txt @@ -0,0 +1,228 @@ + +Bus 001 Device 010: ID 05ac:8501 Apple, Inc. Built-in iSight [Micron] +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x05ac Apple, Inc. + idProduct 0x8501 Built-in iSight [Micron] + bcdDevice 1.89 + iManufacturer 1 Micron + iProduct 2 Built-in iSight + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 267 + bNumInterfaces 2 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 100mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 0 + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 49 + dwClockFrequency 13.500000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 16 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 1 + bmControls 0x00000000 + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 2 + bSourceID 1 + wMaxMultiplier 0 + bControlSize 2 + bmControls 0x00000039 + Brightness + Saturation + Sharpness + Gamma + iProcessing 0 + bmVideoStandards 0x 9 + None + SECAM - 625/50 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 3 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 2 + iTerminal 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0008 1x 8 bytes + bInterval 10 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 14 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 1 + wTotalLength 155 + bEndPointAddress 130 + bmInfo 0 + bTerminalLink 3 + bStillCaptureMethod 0 + bTriggerSupport 0 + bTriggerUsage 0 + bControlSize 1 + bmaControls( 0) 27 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 3 + guidFormat {55595659-0000-1000-8000-00aa00389b71} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 383976960 + dwMaxBitRate 383976960 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 0 + dwMinFrameInterval 333333 + dwMaxFrameInterval 333333 + dwFrameIntervalStep 0 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 383976960 + dwMaxBitRate 383976960 + dwMaxVideoFrameBufferSize 202752 + dwDefaultFrameInterval 333333 + bFrameIntervalType 0 + dwMinFrameInterval 333333 + dwMaxFrameInterval 333333 + dwFrameIntervalStep 0 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 383976960 + dwMaxBitRate 383976960 + dwMaxVideoFrameBufferSize 153600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 0 + dwMinFrameInterval 333333 + dwMaxFrameInterval 333333 + dwFrameIntervalStep 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x1400 3x 1024 bytes + bInterval 1 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 14 Video + bDeviceSubClass 2 Video Streaming + bDeviceProtocol 0 + bMaxPacketSize0 8 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/logitech_hd_pro_920.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/logitech_hd_pro_920.txt new file mode 100644 index 0000000..2fbe69c --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/logitech_hd_pro_920.txt @@ -0,0 +1,1817 @@ + +Bus 001 Device 018: ID 046d:082d Logitech, Inc. HD Pro Webcam C920 +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x046d Logitech, Inc. + idProduct 0x082d HD Pro Webcam C920 + bcdDevice 0.11 + iManufacturer 0 + iProduct 2 HD Pro Webcam C920 + iSerial 1 E1CA2A7F + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 3452 + bNumInterfaces 4 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 0 + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 214 + dwClockFrequency 300.000000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 18 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 3 + bmControls 0x00020a2e + Auto-Exposure Mode + Auto-Exposure Priority + Exposure Time (Absolute) + Focus (Absolute) + Zoom (Absolute) + PanTilt (Absolute) + Focus, Auto + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 3 + bSourceID 1 + wMaxMultiplier 16384 + bControlSize 2 + bmControls 0x0000175b + Brightness + Contrast + Saturation + Sharpness + White Balance Temperature + Backlight Compensation + Gain + Power Line Frequency + White Balance Temperature, Auto + iProcessing 0 + bmVideoStandards 0x1b + None + NTSC - 525/60 + SECAM - 625/50 + NTSC - 625/50 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 6 + guidExtensionCode {d09ee423-7811-314f-ae52-d2fb8a8d3b48} + bNumControl 10 + bNrPins 1 + baSourceID( 0) 3 + bControlSize 2 + bmControls( 0) 0xff + bmControls( 1) 0x03 + iExtension 0 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 8 + guidExtensionCode {e48e6769-0f41-db40-a850-7420d7d8240e} + bNumControl 7 + bNrPins 1 + baSourceID( 0) 1 + bControlSize 2 + bmControls( 0) 0x3b + bmControls( 1) 0x03 + iExtension 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 9 + guidExtensionCode {a94c5d1f-11de-8744-840d-50933c8ec8d1} + bNumControl 17 + bNrPins 1 + baSourceID( 0) 1 + bControlSize 3 + bmControls( 0) 0xf3 + bmControls( 1) 0xff + bmControls( 2) 0x23 + iExtension 0 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 10 + guidExtensionCode {1502e449-34f4-fe47-b158-0e885023e51b} + bNumControl 7 + bNrPins 1 + baSourceID( 0) 1 + bControlSize 2 + bmControls( 0) 0xaa + bmControls( 1) 0x07 + iExtension 0 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 11 + guidExtensionCode {212de5ff-3080-2c4e-82d9-f587d00540bd} + bNumControl 2 + bNrPins 1 + baSourceID( 0) 1 + bControlSize 2 + bmControls( 0) 0x00 + bmControls( 1) 0x41 + iExtension 0 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 12 + guidExtensionCode {41769ea2-04de-e347-8b2b-f4341aff003b} + bNumControl 11 + bNrPins 1 + baSourceID( 0) 3 + bControlSize 2 + bmControls( 0) 0x07 + bmControls( 1) 0x7f + iExtension 0 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 4 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 3 + iTerminal 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0040 1x 64 bytes + bInterval 8 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 16 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 3 + wTotalLength 2822 + bEndPointAddress 129 + bmInfo 0 + bTerminalLink 4 + bStillCaptureMethod 0 + bTriggerSupport 0 + bTriggerUsage 0 + bControlSize 1 + bmaControls( 0) 27 + bmaControls( 1) 27 + bmaControls( 2) 27 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 19 + guidFormat {59555932-0000-1000-8000-00aa00389b71} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 2 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 24576000 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 90 + dwMinBitRate 1152000 + dwMaxBitRate 6912000 + dwMaxVideoFrameBufferSize 28800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 1536000 + dwMaxBitRate 9216000 + dwMaxVideoFrameBufferSize 38400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 2027520 + dwMaxBitRate 12165120 + dwMaxVideoFrameBufferSize 50688 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 180 + dwMinBitRate 4608000 + dwMaxBitRate 27648000 + dwMaxVideoFrameBufferSize 115200 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 6144000 + dwMaxBitRate 36864000 + dwMaxVideoFrameBufferSize 153600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 7 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 8110080 + dwMaxBitRate 48660480 + dwMaxVideoFrameBufferSize 202752 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 8 + bmCapabilities 0x00 + Still image unsupported + wWidth 432 + wHeight 240 + dwMinBitRate 8294400 + dwMaxBitRate 49766400 + dwMaxVideoFrameBufferSize 207360 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 9 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 360 + dwMinBitRate 18432000 + dwMaxBitRate 110592000 + dwMaxVideoFrameBufferSize 460800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 10 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 448 + dwMinBitRate 28672000 + dwMaxBitRate 172032000 + dwMaxVideoFrameBufferSize 716800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 11 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 38400000 + dwMaxBitRate 184320000 + dwMaxVideoFrameBufferSize 960000 + dwDefaultFrameInterval 416666 + bFrameIntervalType 6 + dwFrameInterval( 0) 416666 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 1333333 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 12 + bmCapabilities 0x00 + Still image unsupported + wWidth 864 + wHeight 480 + dwMinBitRate 33177600 + dwMaxBitRate 159252480 + dwMaxVideoFrameBufferSize 829440 + dwDefaultFrameInterval 416666 + bFrameIntervalType 6 + dwFrameInterval( 0) 416666 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 1333333 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 42 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 13 + bmCapabilities 0x00 + Still image unsupported + wWidth 960 + wHeight 720 + dwMinBitRate 55296000 + dwMaxBitRate 165888000 + dwMaxVideoFrameBufferSize 1382400 + dwDefaultFrameInterval 666666 + bFrameIntervalType 4 + dwFrameInterval( 0) 666666 + dwFrameInterval( 1) 1000000 + dwFrameInterval( 2) 1333333 + dwFrameInterval( 3) 2000000 + VideoStreaming Interface Descriptor: + bLength 42 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 14 + bmCapabilities 0x00 + Still image unsupported + wWidth 1024 + wHeight 576 + dwMinBitRate 47185920 + dwMaxBitRate 141557760 + dwMaxVideoFrameBufferSize 1179648 + dwDefaultFrameInterval 666666 + bFrameIntervalType 4 + dwFrameInterval( 0) 666666 + dwFrameInterval( 1) 1000000 + dwFrameInterval( 2) 1333333 + dwFrameInterval( 3) 2000000 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 15 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 720 + dwMinBitRate 73728000 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 1843200 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 3 + dwFrameInterval( 0) 1000000 + dwFrameInterval( 1) 1333333 + dwFrameInterval( 2) 2000000 + VideoStreaming Interface Descriptor: + bLength 34 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 16 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 896 + dwMinBitRate 114688000 + dwMaxBitRate 172032000 + dwMaxVideoFrameBufferSize 2867200 + dwDefaultFrameInterval 1333333 + bFrameIntervalType 2 + dwFrameInterval( 0) 1333333 + dwFrameInterval( 1) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 17 + bmCapabilities 0x00 + Still image unsupported + wWidth 1920 + wHeight 1080 + dwMinBitRate 165888000 + dwMaxBitRate 165888000 + dwMaxVideoFrameBufferSize 4147200 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 1 + dwFrameInterval( 0) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 18 + bmCapabilities 0x00 + Still image unsupported + wWidth 2304 + wHeight 1296 + dwMinBitRate 238878720 + dwMaxBitRate 238878720 + dwMaxVideoFrameBufferSize 5971968 + dwDefaultFrameInterval 4999998 + bFrameIntervalType 1 + dwFrameInterval( 0) 4999998 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 19 + bmCapabilities 0x00 + Still image unsupported + wWidth 2304 + wHeight 1536 + dwMinBitRate 283115520 + dwMaxBitRate 283115520 + dwMaxVideoFrameBufferSize 7077888 + dwDefaultFrameInterval 4999998 + bFrameIntervalType 1 + dwFrameInterval( 0) 4999998 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + VideoStreaming Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 16 (FORMAT_FRAME_BASED) + bFormatIndex 2 + bNumFrameDescriptors 17 + guidFormat {48323634-0000-1000-8000-00aa00389b71} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 2 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + bVariableSize 1 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 24576000 + dwMaxBitRate 147456000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 90 + dwMinBitRate 1152000 + dwMaxBitRate 6912000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 1536000 + dwMaxBitRate 9216000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 2027520 + dwMaxBitRate 12165120 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 180 + dwMinBitRate 4608000 + dwMaxBitRate 27648000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 6144000 + dwMaxBitRate 36864000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 7 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 8110080 + dwMaxBitRate 48660480 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 8 + bmCapabilities 0x00 + Still image unsupported + wWidth 432 + wHeight 240 + dwMinBitRate 8294400 + dwMaxBitRate 49766400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 9 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 360 + dwMinBitRate 18432000 + dwMaxBitRate 110592000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 10 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 448 + dwMinBitRate 28672000 + dwMaxBitRate 172032000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 11 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 38400000 + dwMaxBitRate 230400000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 12 + bmCapabilities 0x00 + Still image unsupported + wWidth 864 + wHeight 480 + dwMinBitRate 33177600 + dwMaxBitRate 199065600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 13 + bmCapabilities 0x00 + Still image unsupported + wWidth 960 + wHeight 720 + dwMinBitRate 55296000 + dwMaxBitRate 331776000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 14 + bmCapabilities 0x00 + Still image unsupported + wWidth 1024 + wHeight 576 + dwMinBitRate 47185920 + dwMaxBitRate 283115520 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 15 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 720 + dwMinBitRate 73728000 + dwMaxBitRate 442368000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 16 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 896 + dwMinBitRate 114688000 + dwMaxBitRate 688128000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 17 (FRAME_FRAME_BASED) + bFrameIndex 17 + bmCapabilities 0x00 + Still image unsupported + wWidth 1920 + wHeight 1080 + dwMinBitRate 165888000 + dwMaxBitRate 995328000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwBytesPerLine 0 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + VideoStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 6 (FORMAT_MJPEG) + bFormatIndex 3 + bNumFrameDescriptors 17 + bFlags 1 + Fixed-size samples: Yes + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 24576000 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 90 + dwMinBitRate 1152000 + dwMaxBitRate 6912000 + dwMaxVideoFrameBufferSize 28800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 1536000 + dwMaxBitRate 9216000 + dwMaxVideoFrameBufferSize 38400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 2027520 + dwMaxBitRate 12165120 + dwMaxVideoFrameBufferSize 50688 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 180 + dwMinBitRate 4608000 + dwMaxBitRate 27648000 + dwMaxVideoFrameBufferSize 115200 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 6144000 + dwMaxBitRate 36864000 + dwMaxVideoFrameBufferSize 153600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 7 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 8110080 + dwMaxBitRate 48660480 + dwMaxVideoFrameBufferSize 202752 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 8 + bmCapabilities 0x00 + Still image unsupported + wWidth 432 + wHeight 240 + dwMinBitRate 8294400 + dwMaxBitRate 49766400 + dwMaxVideoFrameBufferSize 207360 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 9 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 360 + dwMinBitRate 18432000 + dwMaxBitRate 110592000 + dwMaxVideoFrameBufferSize 460800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 10 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 448 + dwMinBitRate 28672000 + dwMaxBitRate 172032000 + dwMaxVideoFrameBufferSize 716800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 11 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 38400000 + dwMaxBitRate 230400000 + dwMaxVideoFrameBufferSize 960000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 12 + bmCapabilities 0x00 + Still image unsupported + wWidth 864 + wHeight 480 + dwMinBitRate 33177600 + dwMaxBitRate 199065600 + dwMaxVideoFrameBufferSize 829440 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 13 + bmCapabilities 0x00 + Still image unsupported + wWidth 960 + wHeight 720 + dwMinBitRate 55296000 + dwMaxBitRate 331776000 + dwMaxVideoFrameBufferSize 1382400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 14 + bmCapabilities 0x00 + Still image unsupported + wWidth 1024 + wHeight 576 + dwMinBitRate 47185920 + dwMaxBitRate 283115520 + dwMaxVideoFrameBufferSize 1179648 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 15 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 720 + dwMinBitRate 73728000 + dwMaxBitRate 442368000 + dwMaxVideoFrameBufferSize 1843200 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 16 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 896 + dwMinBitRate 114688000 + dwMaxBitRate 688128000 + dwMaxVideoFrameBufferSize 2867200 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 54 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 17 + bmCapabilities 0x00 + Still image unsupported + wWidth 1920 + wHeight 1080 + dwMinBitRate 165888000 + dwMaxBitRate 995328000 + dwMaxVideoFrameBufferSize 4147200 + dwDefaultFrameInterval 333333 + bFrameIntervalType 7 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 416666 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 1333333 + dwFrameInterval( 6) 2000000 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x00c0 1x 192 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0180 1x 384 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0280 1x 640 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0320 1x 800 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 6 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x03b0 1x 944 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 7 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0a80 2x 640 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 8 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0b20 2x 800 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 9 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0be0 2x 992 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 10 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x1380 3x 896 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 11 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x13fc 3x 1020 bytes + bInterval 1 + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 2 + bInterfaceCount 2 + bFunctionClass 1 Audio + bFunctionSubClass 2 Streaming + bFunctionProtocol 0 + iFunction 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 1 Audio + bInterfaceSubClass 1 Control Device + bInterfaceProtocol 0 + iInterface 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdADC 1.00 + wTotalLength 38 + bInCollection 1 + baInterfaceNr( 0) 3 + AudioControl Interface Descriptor: + bLength 12 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Microphone + bAssocTerminal 0 + bNrChannels 1 + wChannelConfig 0x0003 + Left Front (L) + Right Front (R) + iChannelNames 0 + iTerminal 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 3 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 5 + iTerminal 0 + AudioControl Interface Descriptor: + bLength 8 + bDescriptorType 36 + bDescriptorSubtype 6 (FEATURE_UNIT) + bUnitID 5 + bSourceID 1 + bControlSize 1 + bmaControls( 0) 0x03 + Mute Control + Volume Control + iFeature 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 255 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 2 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 16000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0044 1x 68 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 2 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 255 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 2 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 24000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0064 1x 100 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 3 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 255 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 2 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 32000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0084 1x 132 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/ms_lifecam_show.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/ms_lifecam_show.txt new file mode 100644 index 0000000..d8f9650 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/ms_lifecam_show.txt @@ -0,0 +1,767 @@ + +Bus 001 Device 010: ID 045e:0729 Microsoft Corp. +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x045e Microsoft Corp. + idProduct 0x0729 + bcdDevice 1.00 + iManufacturer 1 Microsoft + iProduct 2 Microsoft LifeCam Show(TM) + iSerial 0 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 961 + bNumInterfaces 5 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 320mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 2 Microsoft LifeCam Show(TM) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 2 Microsoft LifeCam Show(TM) + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 79 + dwClockFrequency 24.000000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 18 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 3 + bmControls 0x00000a0a + Auto-Exposure Mode + Exposure Time (Absolute) + Zoom (Absolute) + PanTilt (Absolute) + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 2 + bSourceID 1 + wMaxMultiplier 0 + bControlSize 2 + bmControls 0x0000073b + Brightness + Contrast + Saturation + Sharpness + Gamma + Backlight Compensation + Gain + Power Line Frequency + iProcessing 0 + bmVideoStandards 0x 9 + None + SECAM - 625/50 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 3 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 2 + iTerminal 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 4 + guidExtensionCode {5dc717a9-1941-da11-ae0e-000d56ac7b4c} + bNumControl 8 + bNrPins 1 + baSourceID( 0) 1 + bControlSize 3 + bmControls( 0) 0xf9 + bmControls( 1) 0x01 + bmControls( 2) 0xc0 + iExtension 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x000a 1x 10 bytes + bInterval 5 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 15 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 2 + wTotalLength 587 + bEndPointAddress 130 + bmInfo 0 + bTerminalLink 3 + bStillCaptureMethod 2 + bTriggerSupport 1 + bTriggerUsage 1 + bControlSize 1 + bmaControls( 0) 27 + bmaControls( 1) 27 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 6 + guidFormat {59555932-0000-1000-8000-00aa00389b71} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 3 (STILL_IMAGE_FRAME) + bEndpointAddress 0 + bNumImageSizePatterns 6 + wWidth( 0) 352 + wHeight( 0) 288 + wWidth( 1) 640 + wHeight( 1) 480 + wWidth( 2) 320 + wHeight( 2) 240 + wWidth( 3) 176 + wHeight( 3) 144 + wWidth( 4) 160 + wHeight( 4) 120 + wWidth( 5) 800 + wHeight( 5) 600 + bNumCompressionPatterns 6 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 0 (Unspecified) + bTransferCharacteristics 0 (Unspecified) + bMatrixCoefficients 0 (Unspecified) + VideoStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 6 (FORMAT_MJPEG) + bFormatIndex 2 + bNumFrameDescriptors 9 + bFlags 1 + Fixed-size samples: Yes + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 666667 + bFrameIntervalType 1 + dwFrameInterval( 0) 666667 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 7 + bmCapabilities 0x00 + Still image unsupported + wWidth 1024 + wHeight 768 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 1333333 + bFrameIntervalType 1 + dwFrameInterval( 0) 1333333 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 8 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 960 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 1333333 + bFrameIntervalType 1 + dwFrameInterval( 0) 1333333 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 9 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 1200 + dwMinBitRate 196608000 + dwMaxBitRate 196608000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 1333333 + bFrameIntervalType 1 + dwFrameInterval( 0) 1333333 + VideoStreaming Interface Descriptor: + bLength 42 + bDescriptorType 36 + bDescriptorSubtype 3 (STILL_IMAGE_FRAME) + bEndpointAddress 0 + bNumImageSizePatterns 9 + wWidth( 0) 352 + wHeight( 0) 288 + wWidth( 1) 640 + wHeight( 1) 480 + wWidth( 2) 320 + wHeight( 2) 240 + wWidth( 3) 176 + wHeight( 3) 144 + wWidth( 4) 160 + wHeight( 4) 120 + wWidth( 5) 800 + wHeight( 5) 600 + wWidth( 6) 1024 + wHeight( 6) 768 + wWidth( 7) 1280 + wHeight( 7) 960 + wWidth( 8) 1600 + wHeight( 8) 1200 + bNumCompressionPatterns 9 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 0 (Unspecified) + bTransferCharacteristics 0 (Unspecified) + bMatrixCoefficients 0 (Unspecified) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0080 1x 128 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0400 1x 1024 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0b00 2x 768 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0c00 2x 1024 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 6 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x1380 3x 896 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 7 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x82 EP 2 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x1400 3x 1024 bytes + bInterval 1 + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 2 + bInterfaceCount 2 + bFunctionClass 1 Audio + bFunctionSubClass 2 Streaming + bFunctionProtocol 0 + iFunction 2 Microsoft LifeCam Show(TM) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 1 Audio + bInterfaceSubClass 1 Control Device + bInterfaceProtocol 0 + iInterface 2 Microsoft LifeCam Show(TM) + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdADC 1.00 + wTotalLength 39 + bInCollection 1 + baInterfaceNr( 0) 3 + AudioControl Interface Descriptor: + bLength 12 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Microphone + bAssocTerminal 0 + bNrChannels 1 + wChannelConfig 0x0000 + iChannelNames 0 + iTerminal 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 6 (FEATURE_UNIT) + bUnitID 2 + bSourceID 1 + bControlSize 1 + bmaControls( 0) 0x00 + bmaControls( 1) 0x03 + Mute + Volume + iFeature 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 3 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 1 + bSourceID 2 + iTerminal 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 1 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 14 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 1 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 2 Discrete + tSamFreq[ 0] 44100 + tSamFreq[ 1] 48000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x83 EP 3 IN + bmAttributes 1 + Transfer Type Isochronous + Synch Type None + Usage Type Data + wMaxPacketSize 0x0062 1x 98 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 4 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 3 Human Interface Device + bInterfaceSubClass 1 Boot Interface Subclass + bInterfaceProtocol 1 Keyboard + iInterface 0 + HID Device Descriptor: + bLength 9 + bDescriptorType 33 + bcdHID 1.10 + bCountryCode 0 Not supported + bNumDescriptors 1 + bDescriptorType 34 Report + wDescriptorLength 24 + Report Descriptors: + ** UNAVAILABLE ** + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x85 EP 5 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0001 1x 1 bytes + bInterval 10 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000.txt new file mode 100644 index 0000000..5b859b3 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000.txt @@ -0,0 +1,1543 @@ + +Bus 001 Device 009: ID 046d:0809 Logitech, Inc. Webcam Pro 9000 +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + idVendor 0x046d Logitech, Inc. + idProduct 0x0809 Webcam Pro 9000 + bcdDevice 0.10 + iManufacturer 0 + iProduct 0 + iSerial 2 XXXXXXXX + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 2589 + bNumInterfaces 4 + bConfigurationValue 1 + iConfiguration 0 + bmAttributes 0x80 + (Bus Powered) + MaxPower 500mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 0 + bInterfaceCount 2 + bFunctionClass 14 Video + bFunctionSubClass 3 Video Interface Collection + bFunctionProtocol 0 + iFunction 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 1 Video Control + bInterfaceProtocol 0 + iInterface 0 + VideoControl Interface Descriptor: + bLength 13 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdUVC 1.00 + wTotalLength 245 + dwClockFrequency 48.000000MHz + bInCollection 1 + baInterfaceNr( 0) 1 + VideoControl Interface Descriptor: + bLength 18 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Camera Sensor + bAssocTerminal 0 + iTerminal 0 + wObjectiveFocalLengthMin 0 + wObjectiveFocalLengthMax 0 + wOcularFocalLength 0 + bControlSize 3 + bmControls 0x0000080e + Auto-Exposure Mode + Auto-Exposure Priority + Exposure Time (Absolute) + PanTilt (Absolute) + VideoControl Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 5 (PROCESSING_UNIT) + Warning: Descriptor too short + bUnitID 2 + bSourceID 1 + wMaxMultiplier 16384 + bControlSize 2 + bmControls 0x0000175b + Brightness + Contrast + Saturation + Sharpness + White Balance Temperature + Backlight Compensation + Gain + Power Line Frequency + White Balance Temperature, Auto + iProcessing 0 + bmVideoStandards 0x1b + None + NTSC - 525/60 + SECAM - 625/50 + NTSC - 625/50 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 4 + guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d221e} + bNumControl 10 + bNrPins 1 + baSourceID( 0) 2 + bControlSize 2 + bmControls( 0) 0xff + bmControls( 1) 0x03 + iExtension 0 + VideoControl Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 13 + guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d221f} + bNumControl 7 + bNrPins 1 + baSourceID( 0) 2 + bControlSize 2 + bmControls( 0) 0x6f + bmControls( 1) 0x01 + iExtension 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 8 + guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d2251} + bNumControl 3 + bNrPins 1 + baSourceID( 0) 4 + bControlSize 3 + bmControls( 0) 0x19 + bmControls( 1) 0x00 + bmControls( 2) 0x00 + iExtension 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 10 + guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d2252} + bNumControl 24 + bNrPins 1 + baSourceID( 0) 4 + bControlSize 3 + bmControls( 0) 0xff + bmControls( 1) 0xff + bmControls( 2) 0xff + iExtension 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 14 + guidExtensionCode {b7935ba4-15c7-0245-90f4-532a3b311365} + bNumControl 4 + bNrPins 1 + baSourceID( 0) 1 + bControlSize 3 + bmControls( 0) 0x0f + bmControls( 1) 0x00 + bmControls( 2) 0x00 + iExtension 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 9 + guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d2256} + bNumControl 5 + bNrPins 1 + baSourceID( 0) 4 + bControlSize 3 + bmControls( 0) 0x0c + bmControls( 1) 0x00 + bmControls( 2) 0x00 + iExtension 0 + VideoControl Interface Descriptor: + bLength 28 + bDescriptorType 36 + bDescriptorSubtype 6 (EXTENSION_UNIT) + bUnitID 12 + guidExtensionCode {82066163-7050-ab49-b8cc-b3855e8d2250} + bNumControl 17 + bNrPins 1 + baSourceID( 0) 4 + bControlSize 3 + bmControls( 0) 0xfe + bmControls( 1) 0x7f + bmControls( 2) 0x70 + iExtension 0 + VideoControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 5 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 0 + bSourceID 4 + iTerminal 0 + ** UNRECOGNIZED: 20 41 01 0b 82 06 61 63 70 50 ab 49 b8 cc b3 85 5e 8d 22 55 01 01 04 03 01 00 00 00 00 00 00 00 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x87 EP 7 IN + bmAttributes 3 + Transfer Type Interrupt + Synch Type None + Usage Type Data + wMaxPacketSize 0x0010 1x 16 bytes + bInterval 8 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + VideoStreaming Interface Descriptor: + bLength 16 + bDescriptorType 36 + bDescriptorSubtype 1 (INPUT_HEADER) + bNumFormats 3 + wTotalLength 1852 + bEndPointAddress 129 + bmInfo 0 + bTerminalLink 5 + bStillCaptureMethod 2 + bTriggerSupport 1 + bTriggerUsage 0 + bControlSize 1 + bmaControls( 0) 27 + bmaControls( 1) 27 + bmaControls( 2) 27 + VideoStreaming Interface Descriptor: + bLength 27 + bDescriptorType 36 + bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) + bFormatIndex 1 + bNumFrameDescriptors 18 + guidFormat {59555932-0000-1000-8000-00aa00389b71} + bBitsPerPixel 16 + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 24576000 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 1536000 + dwMaxBitRate 9216000 + dwMaxVideoFrameBufferSize 38400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 2027520 + dwMaxBitRate 12165120 + dwMaxVideoFrameBufferSize 50688 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 6144000 + dwMaxBitRate 36864000 + dwMaxVideoFrameBufferSize 153600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 8110080 + dwMaxBitRate 48660480 + dwMaxVideoFrameBufferSize 202752 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 360 + dwMinBitRate 18432000 + dwMaxBitRate 110592000 + dwMaxVideoFrameBufferSize 460800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 7 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 400 + dwMinBitRate 20480000 + dwMaxBitRate 122880000 + dwMaxVideoFrameBufferSize 512000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 46 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 8 + bmCapabilities 0x00 + Still image unsupported + wWidth 768 + wHeight 480 + dwMinBitRate 29491200 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 737280 + dwDefaultFrameInterval 400000 + bFrameIntervalType 5 + dwFrameInterval( 0) 400000 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 2000000 + VideoStreaming Interface Descriptor: + bLength 46 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 9 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 456 + dwMinBitRate 29184000 + dwMaxBitRate 145920000 + dwMaxVideoFrameBufferSize 729600 + dwDefaultFrameInterval 400000 + bFrameIntervalType 5 + dwFrameInterval( 0) 400000 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 2000000 + VideoStreaming Interface Descriptor: + bLength 46 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 10 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 504 + dwMinBitRate 32256000 + dwMaxBitRate 161280000 + dwMaxVideoFrameBufferSize 806400 + dwDefaultFrameInterval 400000 + bFrameIntervalType 5 + dwFrameInterval( 0) 400000 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 2000000 + VideoStreaming Interface Descriptor: + bLength 46 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 11 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 38400000 + dwMaxBitRate 192000000 + dwMaxVideoFrameBufferSize 960000 + dwDefaultFrameInterval 400000 + bFrameIntervalType 5 + dwFrameInterval( 0) 400000 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 2000000 + VideoStreaming Interface Descriptor: + bLength 46 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 12 + bmCapabilities 0x00 + Still image unsupported + wWidth 864 + wHeight 480 + dwMinBitRate 33177600 + dwMaxBitRate 165888000 + dwMaxVideoFrameBufferSize 829440 + dwDefaultFrameInterval 400000 + bFrameIntervalType 5 + dwFrameInterval( 0) 400000 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 2000000 + VideoStreaming Interface Descriptor: + bLength 38 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 13 + bmCapabilities 0x00 + Still image unsupported + wWidth 960 + wHeight 720 + dwMinBitRate 55296000 + dwMaxBitRate 165888000 + dwMaxVideoFrameBufferSize 1382400 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 3 + dwFrameInterval( 0) 666666 + dwFrameInterval( 1) 1000000 + dwFrameInterval( 2) 2000000 + VideoStreaming Interface Descriptor: + bLength 34 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 14 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 720 + dwMinBitRate 73728000 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 1843200 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 2 + dwFrameInterval( 0) 1333333 + dwFrameInterval( 1) 2000000 + VideoStreaming Interface Descriptor: + bLength 34 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 15 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 800 + dwMinBitRate 81920000 + dwMaxBitRate 163840000 + dwMaxVideoFrameBufferSize 2048000 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 2 + dwFrameInterval( 0) 1333333 + dwFrameInterval( 1) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 16 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 904 + dwMinBitRate 115712000 + dwMaxBitRate 115712000 + dwMaxVideoFrameBufferSize 2892800 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 1 + dwFrameInterval( 0) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 17 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 1000 + dwMinBitRate 128000000 + dwMaxBitRate 128000000 + dwMaxVideoFrameBufferSize 3200000 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 1 + dwFrameInterval( 0) 2000000 + VideoStreaming Interface Descriptor: + bLength 30 + bDescriptorType 36 + bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) + bFrameIndex 18 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 1200 + dwMinBitRate 153600000 + dwMaxBitRate 153600000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 1 + dwFrameInterval( 0) 2000000 + VideoStreaming Interface Descriptor: + bLength 79 + bDescriptorType 36 + bDescriptorSubtype 3 (STILL_IMAGE_FRAME) + bEndpointAddress 0 + bNumImageSizePatterns 18 + wWidth( 0) 640 + wHeight( 0) 480 + wWidth( 1) 160 + wHeight( 1) 120 + wWidth( 2) 176 + wHeight( 2) 144 + wWidth( 3) 320 + wHeight( 3) 240 + wWidth( 4) 352 + wHeight( 4) 288 + wWidth( 5) 640 + wHeight( 5) 360 + wWidth( 6) 640 + wHeight( 6) 400 + wWidth( 7) 768 + wHeight( 7) 480 + wWidth( 8) 800 + wHeight( 8) 456 + wWidth( 9) 800 + wHeight( 9) 504 + wWidth(10) 800 + wHeight(10) 600 + wWidth(11) 864 + wHeight(11) 480 + wWidth(12) 960 + wHeight(12) 720 + wWidth(13) 1280 + wHeight(13) 720 + wWidth(14) 1280 + wHeight(14) 800 + wWidth(15) 1600 + wHeight(15) 904 + wWidth(16) 1600 + wHeight(16) 1000 + wWidth(17) 1600 + wHeight(17) 1200 + bNumCompressionPatterns 18 + bCompression( 0) 5 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + VideoStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 6 (FORMAT_MJPEG) + bFormatIndex 2 + bNumFrameDescriptors 18 + bFlags 1 + Fixed-size samples: Yes + bDefaultFrameIndex 1 + bAspectRatioX 0 + bAspectRatioY 0 + bmInterlaceFlags 0x00 + Interlaced stream or variable: No + Fields per frame: 1 fields + Field 1 first: No + Field pattern: Field 1 only + bCopyProtect 0 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 1 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 480 + dwMinBitRate 24576000 + dwMaxBitRate 147456000 + dwMaxVideoFrameBufferSize 614400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 2 + bmCapabilities 0x00 + Still image unsupported + wWidth 160 + wHeight 120 + dwMinBitRate 1536000 + dwMaxBitRate 9216000 + dwMaxVideoFrameBufferSize 38400 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 3 + bmCapabilities 0x00 + Still image unsupported + wWidth 176 + wHeight 144 + dwMinBitRate 2027520 + dwMaxBitRate 12165120 + dwMaxVideoFrameBufferSize 50688 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 4 + bmCapabilities 0x00 + Still image unsupported + wWidth 320 + wHeight 240 + dwMinBitRate 6144000 + dwMaxBitRate 36864000 + dwMaxVideoFrameBufferSize 153600 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 5 + bmCapabilities 0x00 + Still image unsupported + wWidth 352 + wHeight 288 + dwMinBitRate 8110080 + dwMaxBitRate 48660480 + dwMaxVideoFrameBufferSize 202752 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 6 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 360 + dwMinBitRate 18432000 + dwMaxBitRate 110592000 + dwMaxVideoFrameBufferSize 460800 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 7 + bmCapabilities 0x00 + Still image unsupported + wWidth 640 + wHeight 400 + dwMinBitRate 20480000 + dwMaxBitRate 122880000 + dwMaxVideoFrameBufferSize 512000 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 8 + bmCapabilities 0x00 + Still image unsupported + wWidth 768 + wHeight 480 + dwMinBitRate 29491200 + dwMaxBitRate 176947200 + dwMaxVideoFrameBufferSize 737280 + dwDefaultFrameInterval 333333 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 9 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 456 + dwMinBitRate 29184000 + dwMaxBitRate 175104000 + dwMaxVideoFrameBufferSize 729600 + dwDefaultFrameInterval 666666 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 10 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 504 + dwMinBitRate 32256000 + dwMaxBitRate 193536000 + dwMaxVideoFrameBufferSize 806400 + dwDefaultFrameInterval 666666 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 11 + bmCapabilities 0x00 + Still image unsupported + wWidth 800 + wHeight 600 + dwMinBitRate 38400000 + dwMaxBitRate 230400000 + dwMaxVideoFrameBufferSize 960000 + dwDefaultFrameInterval 666666 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 12 + bmCapabilities 0x00 + Still image unsupported + wWidth 864 + wHeight 480 + dwMinBitRate 33177600 + dwMaxBitRate 199065600 + dwMaxVideoFrameBufferSize 829440 + dwDefaultFrameInterval 666666 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 13 + bmCapabilities 0x00 + Still image unsupported + wWidth 960 + wHeight 720 + dwMinBitRate 55296000 + dwMaxBitRate 331776000 + dwMaxVideoFrameBufferSize 1382400 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 50 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 14 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 720 + dwMinBitRate 73728000 + dwMaxBitRate 442368000 + dwMaxVideoFrameBufferSize 1843200 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 6 + dwFrameInterval( 0) 333333 + dwFrameInterval( 1) 400000 + dwFrameInterval( 2) 500000 + dwFrameInterval( 3) 666666 + dwFrameInterval( 4) 1000000 + dwFrameInterval( 5) 2000000 + VideoStreaming Interface Descriptor: + bLength 46 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 15 + bmCapabilities 0x00 + Still image unsupported + wWidth 1280 + wHeight 800 + dwMinBitRate 81920000 + dwMaxBitRate 409600000 + dwMaxVideoFrameBufferSize 2048000 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 5 + dwFrameInterval( 0) 400000 + dwFrameInterval( 1) 500000 + dwFrameInterval( 2) 666666 + dwFrameInterval( 3) 1000000 + dwFrameInterval( 4) 2000000 + VideoStreaming Interface Descriptor: + bLength 34 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 16 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 904 + dwMinBitRate 115712000 + dwMaxBitRate 231424000 + dwMaxVideoFrameBufferSize 2892800 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 2 + dwFrameInterval( 0) 1000000 + dwFrameInterval( 1) 2000000 + VideoStreaming Interface Descriptor: + bLength 34 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 17 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 1000 + dwMinBitRate 128000000 + dwMaxBitRate 256000000 + dwMaxVideoFrameBufferSize 3200000 + dwDefaultFrameInterval 1000000 + bFrameIntervalType 2 + dwFrameInterval( 0) 1000000 + dwFrameInterval( 1) 2000000 + VideoStreaming Interface Descriptor: + bLength 34 + bDescriptorType 36 + bDescriptorSubtype 7 (FRAME_MJPEG) + bFrameIndex 18 + bmCapabilities 0x00 + Still image unsupported + wWidth 1600 + wHeight 1200 + dwMinBitRate 153600000 + dwMaxBitRate 307200000 + dwMaxVideoFrameBufferSize 3840000 + dwDefaultFrameInterval 2000000 + bFrameIntervalType 2 + dwFrameInterval( 0) 1000000 + dwFrameInterval( 1) 2000000 + VideoStreaming Interface Descriptor: + bLength 83 + bDescriptorType 36 + bDescriptorSubtype 3 (STILL_IMAGE_FRAME) + bEndpointAddress 0 + bNumImageSizePatterns 18 + wWidth( 0) 640 + wHeight( 0) 480 + wWidth( 1) 160 + wHeight( 1) 120 + wWidth( 2) 176 + wHeight( 2) 144 + wWidth( 3) 320 + wHeight( 3) 240 + wWidth( 4) 352 + wHeight( 4) 288 + wWidth( 5) 640 + wHeight( 5) 360 + wWidth( 6) 640 + wHeight( 6) 400 + wWidth( 7) 768 + wHeight( 7) 480 + wWidth( 8) 800 + wHeight( 8) 456 + wWidth( 9) 800 + wHeight( 9) 504 + wWidth(10) 800 + wHeight(10) 600 + wWidth(11) 864 + wHeight(11) 480 + wWidth(12) 960 + wHeight(12) 720 + wWidth(13) 1280 + wHeight(13) 720 + wWidth(14) 1280 + wHeight(14) 800 + wWidth(15) 1600 + wHeight(15) 904 + wWidth(16) 1600 + wHeight(16) 1000 + wWidth(17) 1600 + wHeight(17) 1200 + bNumCompressionPatterns 18 + bCompression( 0) 5 + bCompression( 1) 10 + bCompression( 2) 15 + bCompression( 3) 20 + bCompression( 4) 25 + VideoStreaming Interface Descriptor: + bLength 6 + bDescriptorType 36 + bDescriptorSubtype 13 (COLORFORMAT) + bColorPrimaries 1 (BT.709,sRGB) + bTransferCharacteristics 1 (BT.709) + bMatrixCoefficients 4 (SMPTE 170M (BT.601)) + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x00c0 1x 192 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 2 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0180 1x 384 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 3 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 4 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0280 1x 640 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 5 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0320 1x 800 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 6 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x03b0 1x 944 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 7 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0a80 2x 640 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 8 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0b20 2x 800 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 9 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0be0 2x 992 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 10 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x1380 3x 896 bytes + bInterval 1 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 11 + bNumEndpoints 1 + bInterfaceClass 14 Video + bInterfaceSubClass 2 Video Streaming + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x13fc 3x 1020 bytes + bInterval 1 + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 2 + bInterfaceCount 2 + bFunctionClass 1 Audio + bFunctionSubClass 2 Streaming + bFunctionProtocol 0 + iFunction 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 2 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 1 Audio + bInterfaceSubClass 1 Control Device + bInterfaceProtocol 0 + iInterface 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 1 (HEADER) + bcdADC 1.00 + wTotalLength 38 + bInCollection 1 + baInterfaceNr( 0) 3 + AudioControl Interface Descriptor: + bLength 12 + bDescriptorType 36 + bDescriptorSubtype 2 (INPUT_TERMINAL) + bTerminalID 1 + wTerminalType 0x0201 Microphone + bAssocTerminal 0 + bNrChannels 1 + wChannelConfig 0x0000 + iChannelNames 0 + iTerminal 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 3 (OUTPUT_TERMINAL) + bTerminalID 3 + wTerminalType 0x0101 USB Streaming + bAssocTerminal 1 + bSourceID 5 + iTerminal 0 + AudioControl Interface Descriptor: + bLength 9 + bDescriptorType 36 + bDescriptorSubtype 6 (FEATURE_UNIT) + bUnitID 5 + bSourceID 1 + bControlSize 1 + bmaControls( 0) 0x03 + Mute + Volume + bmaControls( 1) 0x00 + iFeature 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 0 + bNumEndpoints 0 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 1 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 1 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 1 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 16000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x86 EP 6 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0044 1x 68 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 2 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 1 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 1 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 24000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x86 EP 6 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0064 1x 100 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 3 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 1 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 1 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 32000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x86 EP 6 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x0084 1x 132 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 3 + bAlternateSetting 4 + bNumEndpoints 1 + bInterfaceClass 1 Audio + bInterfaceSubClass 2 Streaming + bInterfaceProtocol 0 + iInterface 0 + AudioStreaming Interface Descriptor: + bLength 7 + bDescriptorType 36 + bDescriptorSubtype 1 (AS_GENERAL) + bTerminalLink 3 + bDelay 1 frames + wFormatTag 1 PCM + AudioStreaming Interface Descriptor: + bLength 11 + bDescriptorType 36 + bDescriptorSubtype 2 (FORMAT_TYPE) + bFormatType 1 (FORMAT_TYPE_I) + bNrChannels 1 + bSubframeSize 2 + bBitResolution 16 + bSamFreqType 1 Discrete + tSamFreq[ 0] 48000 + Endpoint Descriptor: + bLength 9 + bDescriptorType 5 + bEndpointAddress 0x86 EP 6 IN + bmAttributes 5 + Transfer Type Isochronous + Synch Type Asynchronous + Usage Type Data + wMaxPacketSize 0x00c4 1x 196 bytes + bInterval 4 + bRefresh 0 + bSynchAddress 0 + AudioControl Endpoint Descriptor: + bLength 7 + bDescriptorType 37 + bDescriptorSubtype 1 (EP_GENERAL) + bmAttributes 0x01 + Sampling Frequency + bLockDelayUnits 0 Undefined + wLockDelay 0 Undefined +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 ? + bDeviceProtocol 1 Interface Association + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0000 + (Bus Powered) diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_builtin_ctrls.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_builtin_ctrls.txt new file mode 100644 index 0000000..2b2969e --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_builtin_ctrls.txt @@ -0,0 +1,13 @@ +Listing available controls for device video0: + Exposure, Auto Priority + Exposure (Absolute) + Exposure, Auto + Backlight Compensation + Sharpness + White Balance Temperature + Power Line Frequency + Gain + White Balance Temperature, Auto + Saturation + Contrast + Brightness diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_extra_ctrls.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_extra_ctrls.txt new file mode 100644 index 0000000..205aaf6 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cameras/quickcampro9000_extra_ctrls.txt @@ -0,0 +1,18 @@ +Listing available controls for device video0: + Raw bits per pixel + Disable video processing + LED1 Frequency + LED1 Mode + Focus + Exposure, Auto Priority + Exposure (Absolute) + Exposure, Auto + Backlight Compensation + Sharpness + White Balance Temperature + Power Line Frequency + Gain + White Balance Temperature, Auto + Saturation + Contrast + Brightness diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/changelog.txt b/Code/RK3588/PIBot_ROS/third_party/libuvc/changelog.txt new file mode 100644 index 0000000..50b2bd8 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/changelog.txt @@ -0,0 +1,114 @@ +Changes in 0.0.6 (2017-09-21) +---------------- + +New features: + - Added support for pkg-config. + - Silence pkg-config when searching for libjpeg + - Resolve pkg-config conflict, update CONF_LIBRARY #11 + - Actually use pkg-config to find libjpeg, and set cflags and ldflags for it. #78 + - Add a pkg-config file to allow build systems to identify the flags needed for compiling and linking against this library #77 + - Add support for 16-bit greyscale image format (Y16) #77 + - Add support for 8-bit raw colour formats, specifically: BA81, GRBG, GBRG, RGGB and BGGR #77 + - Improve detection of The Imaging Source Cameras that implement the UVC protocols but don't announce themselves as UVC cameras (and ignore similar cameras that appear to be UVC but are not). #77 + - add routine for listing frame configs #76 + - New Travis configuration + - Add uvc_find_devices function to support libuvc_ros index selection #36 + - VideoStreaming status processing #30 + - Add conversion from YUYV to Y (GRAY8) and UV (GRAY8) #27 + - Add LICENSE.txt. + - Add Dw_clock_frequency field and populate acording to UVC1.0 or 1.1 spec. #19 + - Changes to enable compilation with Windows MSVC #13 + - Modify ABS_FMT macro to function correctly with MSVC. + - Implement gettimeofday for MSVC. + - Use portable memset instead of bzero for MSVC compatibility. + - Annotate libusb callback methods with LIBUSB_CALL for MSVC. + + - Merge of bulk mode transfer support from Tridge, Mauricio and James (#8) + - Support for BY8 frames + - (Very basic) support for UVC1.1 camera data structures + - Support for frame-based video streams + - Support for TIS astro CCD cameras + - Squashed a few possible bugs + - Added section descriptions and control getter/setter documentation + +Bug fixes: + - update CMakeLists.txt + - Add missing include (for ${CMAKE_INSTALL_LIBDIR}), fix static-/shared-only build #15 + - Allow both static and dynamic versions of library to be built to work more neatly when building into runtime and development packages #77 + + - Update device.c, reduce salience of the alert which end user perceives as more important than it actually is. #79 + - Clean up transfer buffers when an error occurs #77 + - Fixed the issue that camera control functions can not work well with some cameras #41 + UVC specification says that low byte of wIndex (for camera control) is interface number for camera control interface but current implementation of libuvc expects it is always zero and sometimes cause trouble. + Fixed camera control issue when using uvc_get_ctrl_len/uvc_get_ctrl/uvc_set_ctrl with camera that interface number of camera control interface is not zero. + - In some (as yet unidentified) circumstances it is possible for an interface to be claimed more than once. This can cause an error. #77 + - A race allows queued transfers to arrive and be viable for resubmission even when a stream is no longer running. #77 + - Querying stream controls before claiming the interface can fail, so claim the interface first, then do the query. #77 + - Show error code in error message to help debugging #77 + - Add specific error messages for unsupported frame formats to make failures clearer #77 + - Clean up compiler warnings #77 + - Remove libusb.h from the public header #62 + - Fix the first captured image being dropped #51 + The first frame generated by any camera was always lost in the libuvc layer, and not passed on to the listening application. + The start value of seq (thus hold_seq) could be arbitrary, but it must be non-zero. Both the callback listener and the polling function's last_seq / last_polled_seq start initialised to zero, which causes any image with hold_seq zero to be ignored. + - Build fix for Chromium #48, #58 + Some platforms use different version of libusb. For instance, Chromium compiles libusb by itself. So hard coding of libuse version (i.e. ) causes compile failure. + Remove libusb.h from the public header, This should fix the include path problems seen when including libuvc.h into other programs + - pthread_cond_timedwait nanoseconds shouldn't be greater than 1 billion #47 + While using the library and testing the timed poll with 500000 us wait time, I noticed that it often happened that the timedwait returned EINVAL. +According to http://stackoverflow.com/questions/11319063/pthread-cond-timedwait-root-causes-of-einval +this might happen for several reasons, and one of them is when the number of nanoseconds in the timespec is greater than 1 billion (1 billion = 1 second). + Thus, I added a check that correctly updates the seconds and nanoseconds, bringing the nanosecond values in the range 0-999999999. + In Issue #16 it is mentioned that code sometimes crashes on uvc_stream_get_frame with some specific timeout values, this might have been the cause. + Fix for wrong setting of pthread_cond_timedwait nanoseconds + - Fix control functions for processors and other devices #32 + When using a control function that is pertinent to a particular device (such as a processing device), the id of that device needs to be passed to the camera, or the call will fail + - Added docs for some more controls and switched to yaml doc file + - Updated documentation index + - Enable uvc_mjpeg2rgb function, if JPEG is supported + +Changes in 0.0.5 (2014-07-19) +---------------- + +New features: + - Added support for all of the camera terminal and processing unit controls, including the controls + that appeared in UVC 1.1 and 1.5. + - Added LIBUVC_VERSION_GTE(major, minor, patch) macro. + +Bug fixes: + - Switching to explicit kernel driver detachment since auto_detach isn't available in libusb < 1.0.16. + - The cmake module now looks for libuvc.dylib instead of libuvc.so on OS X. + + +Changes in 0.0.4 (2014-06-26) +---------------- + +New features: + - Support devices with multiple streaming interfaces and multiple concurrent streams. + A new uvc_stream* API is added, along with a uvc_stream_handle type to encapsulate the + state of a single UVC stream. Multiple streams can run alongside each other, provided + your USB connection has enough bandwidth. Streams can be individually stopped and + resumed; the old uvc_start/stop_streaming API is still provided as a convenient way + to interact with the usual one-stream devices. + - Added support for MJPEG streams. + - Added functions for checking/setting autofocus mode. + - Added an interface to set/get arbitrary controls on units and terminals. + - Made the input, output, processing and extension units public. + - Implemented uvc_get_device and uvc_get_libusb_handle. + - Add a library-owned flag to uvc_frame_t so that users may allocate their own frame buffers. + +Bug fixes: + - Send frames as soon as they're received, not when the following frame arrives + - Fixed call to NULL when no status callback is provided. + - Fixed crash that occurred during shutdown if the USB device was disconnected during streaming. + +Miscellaneous improvements: + - Hid the transfer method (isochronous vs bulk) from the user. This was never really + selectable; the camera's streaming interface supports either bulk or isochronous + transfers, so now libuvc will figure out which one is appropriate. The `isochronous` + parameter has been converted to a `flags` parameter, which is currently unused but + could be used to convey up to 7 bits of stream mode information in the future. + - Improved the method for claiming the camera's interfaces. + - Renamed UVC_COLOR_FORMAT_* to UVC_FRAME_FORMAT_*. The old #defines are still available. + - Simplified format definition and lookup. + - Improved transfer status (error) handling. diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindJpegPkg.cmake b/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindJpegPkg.cmake new file mode 100644 index 0000000..b533d9c --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindJpegPkg.cmake @@ -0,0 +1,82 @@ +#[==============================================[ +FindJpegPkg +----------- + +Searching jpeg library library and creating imported +target JPEG::JPEG (this is different from shipped one with CMake) + +#]==============================================] + +# TODO Append parts for Version compasion and REQUIRED support +if (MSVC OR MINGW) + return() +endif() + +# Try to find JPEG using a module or pkg-config. If that doesn't work, search for the header. +if (NOT TARGET JPEG::JPEG) + find_package(JPEG) + if (JPEG_FOUND) + message(STATUS "Found JPEG library using standard module") + set(IMPORTED_JPEG_INCLUDE_DIRS ${JPEG_INCLUDE_DIR}) + set(IMPORTED_JPEG_LIBRARIES ${JPEG_LIBRARIES}) + else() + find_package(PkgConfig) + pkg_check_modules(JPEG libjpeg) + if(JPEG_FOUND) + message(STATUS "JPEG found by pkgconfig") + + if (DEFINED JPEG_INCLUDE_DIRS) + set(IMPORTED_JPEG_INCLUDE_DIRS ${JPEG_INCLUDE_DIRS}) + endif() + + if(JPEG_LIBRARIES) + find_library(JPEG_LIBRARY + NAMES ${JPEG_LIBRARIES} + PATHS ${JPEG_LIBDIR} ${JPEG_LIBRARY_DIRS} + ) + if(JPEG_LIBRARY) + set(IMPORTED_JPEG_LIBRARIES ${JPEG_LIBRARY}) + else() + message(WARNING "Could not found libjpeg library file") + endif() + endif() + else() + message(STATUS "Searching library manually") + find_path(IMPORTED_JPEG_INCLUDE_DIRS + NAMES jpeglib.h + ) + + if (NOT IMPORTED_JPEG_LIBRARIES) + find_library(IMPORTED_JPEG_LIBRARIES + NAMES jpeg + ) + endif() + endif() + endif() + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(JPEG + REQUIRED_VARS IMPORTED_JPEG_LIBRARIES IMPORTED_JPEG_INCLUDE_DIRS + ) + + if(JPEG_FOUND) + set(JpegPkg_FOUND TRUE) + if (NOT TARGET JPEG::JPEG) + add_library(JPEG::JPEG + UNKNOWN IMPORTED + ) + if(IMPORTED_JPEG_INCLUDE_DIRS) + set_target_properties(JPEG::JPEG PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${IMPORTED_JPEG_INCLUDE_DIRS} + ) + endif() + if(IMPORTED_JPEG_LIBRARIES) + set_target_properties(JPEG::JPEG PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION ${IMPORTED_JPEG_LIBRARIES} + ) + endif() + endif() + endif() + +endif() diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindLibUSB.cmake b/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindLibUSB.cmake new file mode 100644 index 0000000..43f3201 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindLibUSB.cmake @@ -0,0 +1,51 @@ +#[==============================================[ +FindLibUSB +----------- + +Searching libusb-1.0 library and creating imported +target LibUSB::LibUSB + +#]==============================================] + +# TODO Append parts for Version compasion and REQUIRED support + +if (MSVC OR MINGW) + return() +endif() + +if (NOT TARGET LibUSB::LibUSB) + find_package(PkgConfig) + pkg_check_modules(LibUSB REQUIRED + libusb-1.0 + ) + + if(LibUSB_FOUND) + message(STATUS "libusb-1.0 found using pkgconfig") + + add_library(LibUSB::LibUSB + UNKNOWN IMPORTED + ) + if (DEFINED LibUSB_INCLUDE_DIRS AND NOT LibUSB_INCLUDE_DIRS STREQUAL "") + set_target_properties(LibUSB::LibUSB PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${LibUSB_INCLUDE_DIRS} + ) + endif() + + if(LibUSB_LIBRARIES) + find_library(LibUSB_LIBRARY + NAMES ${LibUSB_LIBRARIES} + PATHS ${LibUSB_LIBDIR} ${LibUSB_LIBRARY_DIRS} + ) + if(LibUSB_LIBRARY) + set_target_properties(LibUSB::LibUSB PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION ${LibUSB_LIBRARY} + ) + else() + message(WARNING "Could not found libusb-1.0 library file") + endif() + endif() + endif() +else() + message(WARNING "libusb-1.0 could not be found using pkgconfig") +endif() diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindOpenCVPkg.cmake b/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindOpenCVPkg.cmake new file mode 100644 index 0000000..9d12f8b --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/cmake/FindOpenCVPkg.cmake @@ -0,0 +1,86 @@ +#[==============================================[ +FindOpenCVPkg +----------- + +Searching OpenCV components on systems which does not have fully installed OpenCV. +Such systems does not include OpenCVConfig.cmake and OpenCVConfigVersion.cmake files. +Example of such system is Ubuntu 18.04. +This package try to use OpenCV config file first if it exists. + +#]==============================================] + +if (${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS) + set(comps ${${CMAKE_FIND_PACKAGE_NAME}_FIND_COMPONENTS}) +else() + set(comps) +endif() + +list(LENGTH comps comps_count) +message(STATUS "Components requested: ${comps}") + +# Try to find components using standard OpenCV config package +if(comps_count GREATER 0) + find_package(OpenCV QUIET + COMPONENTS ${comps} + ) + if(OpenCV_FOUND) + set(OpenCVPkg_FOUND TRUE) + return() + endif() +else() + find_package(OpenCV QUIET) + if(OpenCV_FOUND) + set(OpenCVPkg_FOUND TRUE) + return() + endif() +endif() + +if(comps_count EQUAL 0) + set(err_level) + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED) + set(err_level FATAL_ERROR) + endif() + if (${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY) + set(err_level STATUS) + endif() + message(${err_level} "Without standart OpenCV config file you must list components you want") + return() +endif() + +unset(required_comps_not_found) +foreach(comp IN LISTS comps) + string(REPLACE "opencv_" "" comp_name ${comp}) + set(include_rel_path "opencv2/${comp_name}.hpp" "opencv2/${comp_name}/${comp_name}.hpp") + find_path(OpenCV_${comp}_INCLUDE_DIR + NAMES ${include_rel_path} + ) + find_library(OpenCV_${comp}_LIBRARY + NAMES ${comp} + ) + if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED_${comp} AND + (NOT OpenCV_${comp}_INCLUDE_DIR OR NOT OpenCV_${comp}_LIBRARY)) + list(APPEND required_comps_not_found ${comp}) + else() + message(STATUS "Found component ${comp}: ${OpenCV_${comp}_LIBRARY}") + endif() +endforeach() + +if(required_comps_not_found) + message(FATAL_ERROR "Following required components not found: ${required_comps_not_found}") + return() +endif() + +foreach(comp IN LISTS comps) + if(NOT TARGET ${comp}) + message(STATUS "No target ${comp} yet. Creating it") + add_library(${comp} + UNKNOWN IMPORTED + ) + set_target_properties(${comp} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${OpenCV_${comp}_INCLUDE_DIR} + IMPORTED_LOCATION ${OpenCV_${comp}_LIBRARY} + ) + endif() +endforeach() + +set(OpenCVPkg_FOUND TRUE) diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/doxygen.conf b/Code/RK3588/PIBot_ROS/third_party/libuvc/doxygen.conf new file mode 100644 index 0000000..226134a --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/doxygen.conf @@ -0,0 +1,2284 @@ +# Doxyfile 1.8.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = libuvc + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- +# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, +# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = YES + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = src \ + include/libuvc + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = include/libuvc/libuvc_internal.h \ + include/utlist.h + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = src + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = doc + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /libusb 1.0+ and run: + +\code +$ git clone https://github.com/ktossell/libuvc.git +$ cd libuvc +$ mkdir build +$ cd build +$ cmake -DCMAKE_BUILD_TYPE=Release .. +$ make && make install +\endcode + +\section Example +In this example, libuvc is used to acquire images in a 30 fps, 640x480 +YUV stream from a UVC device such as a standard webcam. + +\include example.c + +*/ + +/** + * @defgroup init Library initialization/deinitialization + * @brief Setup routines used to construct UVC access contexts + */ +#include "libuvc/libuvc.h" +#include "libuvc/libuvc_internal.h" + +/** @internal + * @brief Event handler thread + * There's one of these per UVC context. + * @todo We shouldn't run this if we don't own the USB context + */ +void *_uvc_handle_events(void *arg) { + uvc_context_t *ctx = (uvc_context_t *) arg; + + while (!ctx->kill_handler_thread) + libusb_handle_events_completed(ctx->usb_ctx, &ctx->kill_handler_thread); + return NULL; +} + +/** @brief Initializes the UVC context + * @ingroup init + * + * @note If you provide your own USB context, you must handle + * libusb event processing using a function such as libusb_handle_events. + * + * @param[out] pctx The location where the context reference should be stored. + * @param[in] usb_ctx Optional USB context to use + * @return Error opening context or UVC_SUCCESS + */ +uvc_error_t uvc_init(uvc_context_t **pctx, struct libusb_context *usb_ctx) { + uvc_error_t ret = UVC_SUCCESS; + uvc_context_t *ctx = calloc(1, sizeof(*ctx)); + + if (usb_ctx == NULL) { + ret = libusb_init(&ctx->usb_ctx); + ctx->own_usb_ctx = 1; + if (ret != UVC_SUCCESS) { + free(ctx); + ctx = NULL; + } + } else { + ctx->own_usb_ctx = 0; + ctx->usb_ctx = usb_ctx; + } + + if (ctx != NULL) + *pctx = ctx; + + return ret; +} + +/** + * @brief Closes the UVC context, shutting down any active cameras. + * @ingroup init + * + * @note This function invalides any existing references to the context's + * cameras. + * + * If no USB context was provided to #uvc_init, the UVC-specific USB + * context will be destroyed. + * + * @param ctx UVC context to shut down + */ +void uvc_exit(uvc_context_t *ctx) { + uvc_device_handle_t *devh; + + DL_FOREACH(ctx->open_devices, devh) { + uvc_close(devh); + } + + if (ctx->own_usb_ctx) + libusb_exit(ctx->usb_ctx); + + free(ctx); +} + +/** + * @internal + * @brief Spawns a handler thread for the context + * @ingroup init + * + * This should be called at the end of a successful uvc_open if no devices + * are already open (and being handled). + */ +void uvc_start_handler_thread(uvc_context_t *ctx) { + if (ctx->own_usb_ctx) + pthread_create(&ctx->handler_thread, NULL, _uvc_handle_events, (void*) ctx); +} + diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/src/misc.c b/Code/RK3588/PIBot_ROS/third_party/libuvc/src/misc.c new file mode 100644 index 0000000..8ce850f --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/src/misc.c @@ -0,0 +1,58 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (C) 2010-2012 Ken Tossell +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the author nor other contributors may be +* used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ +#include +#include + +#if __APPLE__ +char *strndup(const char *s, size_t n) { + size_t src_n = 0; + const char *sp = s; + char *d; + + while (*sp++) + src_n++; + + if (src_n < n) + n = src_n; + + d = malloc(n + 1); + + memcpy(d, s, n); + + d[n] = '\0'; + + return d; +} +#endif + diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/src/stream.c b/Code/RK3588/PIBot_ROS/third_party/libuvc/src/stream.c new file mode 100644 index 0000000..5013087 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/src/stream.c @@ -0,0 +1,1546 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (C) 2010-2012 Ken Tossell +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the author nor other contributors may be +* used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ +/** + * @defgroup streaming Streaming control functions + * @brief Tools for creating, managing and consuming video streams + */ + +#include "libuvc/libuvc.h" +#include "libuvc/libuvc_internal.h" +#include "errno.h" + +#ifdef _MSC_VER + +#define DELTA_EPOCH_IN_MICROSECS 116444736000000000Ui64 + +// gettimeofday - get time of day for Windows; +// A gettimeofday implementation for Microsoft Windows; +// Public domain code, author "ponnada"; +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + FILETIME ft; + unsigned __int64 tmpres = 0; + static int tzflag = 0; + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + tmpres /= 10; + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + return 0; +} +#endif // _MSC_VER +uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh, + uint16_t format_id, uint16_t frame_id); +uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh, + uint16_t format_id, uint16_t frame_id); +void *_uvc_user_caller(void *arg); +void _uvc_populate_frame(uvc_stream_handle_t *strmh); + +static uvc_streaming_interface_t *_uvc_get_stream_if(uvc_device_handle_t *devh, int interface_idx); +static uvc_stream_handle_t *_uvc_get_stream_by_interface(uvc_device_handle_t *devh, int interface_idx); + +struct format_table_entry { + enum uvc_frame_format format; + uint8_t abstract_fmt; + uint8_t guid[16]; + int children_count; + enum uvc_frame_format *children; +}; + +struct format_table_entry *_get_format_entry(enum uvc_frame_format format) { + #define ABS_FMT(_fmt, _num, ...) \ + case _fmt: { \ + static enum uvc_frame_format _fmt##_children[] = __VA_ARGS__; \ + static struct format_table_entry _fmt##_entry = { \ + _fmt, 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, _num, _fmt##_children }; \ + return &_fmt##_entry; } + + #define FMT(_fmt, ...) \ + case _fmt: { \ + static struct format_table_entry _fmt##_entry = { \ + _fmt, 0, __VA_ARGS__, 0, NULL }; \ + return &_fmt##_entry; } + + switch(format) { + /* Define new formats here */ + ABS_FMT(UVC_FRAME_FORMAT_ANY, 2, + {UVC_FRAME_FORMAT_UNCOMPRESSED, UVC_FRAME_FORMAT_COMPRESSED}) + + ABS_FMT(UVC_FRAME_FORMAT_UNCOMPRESSED, 6, + {UVC_FRAME_FORMAT_YUYV, UVC_FRAME_FORMAT_UYVY, UVC_FRAME_FORMAT_GRAY8, + UVC_FRAME_FORMAT_GRAY16, UVC_FRAME_FORMAT_NV12, UVC_FRAME_FORMAT_BGR}) + FMT(UVC_FRAME_FORMAT_YUYV, + {'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_UYVY, + {'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_GRAY8, + {'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_GRAY16, + {'Y', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_NV12, + {'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_BGR, + {0x7d, 0xeb, 0x36, 0xe4, 0x4f, 0x52, 0xce, 0x11, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}) + FMT(UVC_FRAME_FORMAT_BY8, + {'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_BA81, + {'B', 'A', '8', '1', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_SGRBG8, + {'G', 'R', 'B', 'G', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_SGBRG8, + {'G', 'B', 'R', 'G', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_SRGGB8, + {'R', 'G', 'G', 'B', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + FMT(UVC_FRAME_FORMAT_SBGGR8, + {'B', 'G', 'G', 'R', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + ABS_FMT(UVC_FRAME_FORMAT_COMPRESSED, 2, + {UVC_FRAME_FORMAT_MJPEG, UVC_FRAME_FORMAT_H264}) + FMT(UVC_FRAME_FORMAT_MJPEG, + {'M', 'J', 'P', 'G'}) + FMT(UVC_FRAME_FORMAT_H264, + {'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}) + + default: + return NULL; + } + + #undef ABS_FMT + #undef FMT +} + +static uint8_t _uvc_frame_format_matches_guid(enum uvc_frame_format fmt, uint8_t guid[16]) { + struct format_table_entry *format; + int child_idx; + + format = _get_format_entry(fmt); + if (!format) + return 0; + + if (!format->abstract_fmt && !memcmp(guid, format->guid, 16)) + return 1; + + for (child_idx = 0; child_idx < format->children_count; child_idx++) { + if (_uvc_frame_format_matches_guid(format->children[child_idx], guid)) + return 1; + } + + return 0; +} + +static enum uvc_frame_format uvc_frame_format_for_guid(uint8_t guid[16]) { + struct format_table_entry *format; + enum uvc_frame_format fmt; + + for (fmt = 0; fmt < UVC_FRAME_FORMAT_COUNT; ++fmt) { + format = _get_format_entry(fmt); + if (!format || format->abstract_fmt) + continue; + if (!memcmp(format->guid, guid, 16)) + return format->format; + } + + return UVC_FRAME_FORMAT_UNKNOWN; +} + +/** @internal + * Run a streaming control query + * @param[in] devh UVC device + * @param[in,out] ctrl Control block + * @param[in] probe Whether this is a probe query or a commit query + * @param[in] req Query type + */ +uvc_error_t uvc_query_stream_ctrl( + uvc_device_handle_t *devh, + uvc_stream_ctrl_t *ctrl, + uint8_t probe, + enum uvc_req_code req) { + uint8_t buf[34]; + size_t len; + uvc_error_t err; + + memset(buf, 0, sizeof(buf)); + + if (devh->info->ctrl_if.bcdUVC >= 0x0110) + len = 34; + else + len = 26; + + /* prepare for a SET transfer */ + if (req == UVC_SET_CUR) { + SHORT_TO_SW(ctrl->bmHint, buf); + buf[2] = ctrl->bFormatIndex; + buf[3] = ctrl->bFrameIndex; + INT_TO_DW(ctrl->dwFrameInterval, buf + 4); + SHORT_TO_SW(ctrl->wKeyFrameRate, buf + 8); + SHORT_TO_SW(ctrl->wPFrameRate, buf + 10); + SHORT_TO_SW(ctrl->wCompQuality, buf + 12); + SHORT_TO_SW(ctrl->wCompWindowSize, buf + 14); + SHORT_TO_SW(ctrl->wDelay, buf + 16); + INT_TO_DW(ctrl->dwMaxVideoFrameSize, buf + 18); + INT_TO_DW(ctrl->dwMaxPayloadTransferSize, buf + 22); + + if (len == 34) { + INT_TO_DW ( ctrl->dwClockFrequency, buf + 26 ); + buf[30] = ctrl->bmFramingInfo; + buf[31] = ctrl->bPreferredVersion; + buf[32] = ctrl->bMinVersion; + buf[33] = ctrl->bMaxVersion; + /** @todo support UVC 1.1 */ + } + } + + /* do the transfer */ + err = libusb_control_transfer( + devh->usb_devh, + req == UVC_SET_CUR ? 0x21 : 0xA1, + req, + probe ? (UVC_VS_PROBE_CONTROL << 8) : (UVC_VS_COMMIT_CONTROL << 8), + ctrl->bInterfaceNumber, + buf, len, 0 + ); + + if (err <= 0) { + return err; + } + + /* now decode following a GET transfer */ + if (req != UVC_SET_CUR) { + ctrl->bmHint = SW_TO_SHORT(buf); + ctrl->bFormatIndex = buf[2]; + ctrl->bFrameIndex = buf[3]; + ctrl->dwFrameInterval = DW_TO_INT(buf + 4); + ctrl->wKeyFrameRate = SW_TO_SHORT(buf + 8); + ctrl->wPFrameRate = SW_TO_SHORT(buf + 10); + ctrl->wCompQuality = SW_TO_SHORT(buf + 12); + ctrl->wCompWindowSize = SW_TO_SHORT(buf + 14); + ctrl->wDelay = SW_TO_SHORT(buf + 16); + ctrl->dwMaxVideoFrameSize = DW_TO_INT(buf + 18); + ctrl->dwMaxPayloadTransferSize = DW_TO_INT(buf + 22); + + if (len == 34) { + ctrl->dwClockFrequency = DW_TO_INT ( buf + 26 ); + ctrl->bmFramingInfo = buf[30]; + ctrl->bPreferredVersion = buf[31]; + ctrl->bMinVersion = buf[32]; + ctrl->bMaxVersion = buf[33]; + /** @todo support UVC 1.1 */ + } + else + ctrl->dwClockFrequency = devh->info->ctrl_if.dwClockFrequency; + + /* fix up block for cameras that fail to set dwMax* */ + if (ctrl->dwMaxVideoFrameSize == 0) { + uvc_frame_desc_t *frame = uvc_find_frame_desc(devh, ctrl->bFormatIndex, ctrl->bFrameIndex); + + if (frame) { + ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; + } + } + } + + return UVC_SUCCESS; +} + +/** @internal + * Run a streaming control query + * @param[in] devh UVC device + * @param[in,out] ctrl Control block + * @param[in] probe Whether this is a probe query or a commit query + * @param[in] req Query type + */ +uvc_error_t uvc_query_still_ctrl( + uvc_device_handle_t *devh, + uvc_still_ctrl_t *still_ctrl, + uint8_t probe, + enum uvc_req_code req) { + + uint8_t buf[11]; + const size_t len = 11; + uvc_error_t err; + + memset(buf, 0, sizeof(buf)); + + if (req == UVC_SET_CUR) { + /* prepare for a SET transfer */ + buf[0] = still_ctrl->bFormatIndex; + buf[1] = still_ctrl->bFrameIndex; + buf[2] = still_ctrl->bCompressionIndex; + INT_TO_DW(still_ctrl->dwMaxVideoFrameSize, buf + 3); + INT_TO_DW(still_ctrl->dwMaxPayloadTransferSize, buf + 7); + } + + /* do the transfer */ + err = libusb_control_transfer( + devh->usb_devh, + req == UVC_SET_CUR ? 0x21 : 0xA1, + req, + probe ? (UVC_VS_STILL_PROBE_CONTROL << 8) : (UVC_VS_STILL_COMMIT_CONTROL << 8), + still_ctrl->bInterfaceNumber, + buf, len, 0 + ); + + if (err <= 0) { + return err; + } + + /* now decode following a GET transfer */ + if (req != UVC_SET_CUR) { + still_ctrl->bFormatIndex = buf[0]; + still_ctrl->bFrameIndex = buf[1]; + still_ctrl->bCompressionIndex = buf[2]; + still_ctrl->dwMaxVideoFrameSize = DW_TO_INT(buf + 3); + still_ctrl->dwMaxPayloadTransferSize = DW_TO_INT(buf + 7); + } + + return UVC_SUCCESS; +} + +/** Initiate a method 2 (in stream) still capture + * @ingroup streaming + * + * @param[in] devh Device handle + * @param[in] still_ctrl Still capture control block + */ +uvc_error_t uvc_trigger_still( + uvc_device_handle_t *devh, + uvc_still_ctrl_t *still_ctrl) { + uvc_stream_handle_t* stream; + uvc_streaming_interface_t* stream_if; + uint8_t buf; + uvc_error_t err; + + /* Stream must be running for method 2 to work */ + stream = _uvc_get_stream_by_interface(devh, still_ctrl->bInterfaceNumber); + if (!stream || !stream->running) + return UVC_ERROR_NOT_SUPPORTED; + + /* Only method 2 is supported */ + stream_if = _uvc_get_stream_if(devh, still_ctrl->bInterfaceNumber); + if(!stream_if || stream_if->bStillCaptureMethod != 2) + return UVC_ERROR_NOT_SUPPORTED; + + /* prepare for a SET transfer */ + buf = 1; + + /* do the transfer */ + err = libusb_control_transfer( + devh->usb_devh, + 0x21, //type set + UVC_SET_CUR, + (UVC_VS_STILL_IMAGE_TRIGGER_CONTROL << 8), + still_ctrl->bInterfaceNumber, + &buf, 1, 0); + + if (err <= 0) { + return err; + } + + return UVC_SUCCESS; +} + +/** @brief Reconfigure stream with a new stream format. + * @ingroup streaming + * + * This may be executed whether or not the stream is running. + * + * @param[in] strmh Stream handle + * @param[in] ctrl Control block, processed using {uvc_probe_stream_ctrl} or + * {uvc_get_stream_ctrl_format_size} + */ +uvc_error_t uvc_stream_ctrl(uvc_stream_handle_t *strmh, uvc_stream_ctrl_t *ctrl) { + uvc_error_t ret; + + if (strmh->stream_if->bInterfaceNumber != ctrl->bInterfaceNumber) + return UVC_ERROR_INVALID_PARAM; + + /* @todo Allow the stream to be modified without restarting the stream */ + if (strmh->running) + return UVC_ERROR_BUSY; + + ret = uvc_query_stream_ctrl(strmh->devh, ctrl, 0, UVC_SET_CUR); + if (ret != UVC_SUCCESS) + return ret; + + strmh->cur_ctrl = *ctrl; + return UVC_SUCCESS; +} + +/** @internal + * @brief Find the descriptor for a specific frame configuration + * @param stream_if Stream interface + * @param format_id Index of format class descriptor + * @param frame_id Index of frame descriptor + */ +static uvc_frame_desc_t *_uvc_find_frame_desc_stream_if(uvc_streaming_interface_t *stream_if, + uint16_t format_id, uint16_t frame_id) { + + uvc_format_desc_t *format = NULL; + uvc_frame_desc_t *frame = NULL; + + DL_FOREACH(stream_if->format_descs, format) { + if (format->bFormatIndex == format_id) { + DL_FOREACH(format->frame_descs, frame) { + if (frame->bFrameIndex == frame_id) + return frame; + } + } + } + + return NULL; +} + +uvc_frame_desc_t *uvc_find_frame_desc_stream(uvc_stream_handle_t *strmh, + uint16_t format_id, uint16_t frame_id) { + return _uvc_find_frame_desc_stream_if(strmh->stream_if, format_id, frame_id); +} + +/** @internal + * @brief Find the descriptor for a specific frame configuration + * @param devh UVC device + * @param format_id Index of format class descriptor + * @param frame_id Index of frame descriptor + */ +uvc_frame_desc_t *uvc_find_frame_desc(uvc_device_handle_t *devh, + uint16_t format_id, uint16_t frame_id) { + + uvc_streaming_interface_t *stream_if; + uvc_frame_desc_t *frame; + + DL_FOREACH(devh->info->stream_ifs, stream_if) { + frame = _uvc_find_frame_desc_stream_if(stream_if, format_id, frame_id); + if (frame) + return frame; + } + + return NULL; +} + +/** Get a negotiated streaming control block for some common parameters. + * @ingroup streaming + * + * @param[in] devh Device handle + * @param[in,out] ctrl Control block + * @param[in] format_class Type of streaming format + * @param[in] width Desired frame width + * @param[in] height Desired frame height + * @param[in] fps Frame rate, frames per second + */ +uvc_error_t uvc_get_stream_ctrl_format_size( + uvc_device_handle_t *devh, + uvc_stream_ctrl_t *ctrl, + enum uvc_frame_format cf, + int width, int height, + int fps) { + uvc_streaming_interface_t *stream_if; + + /* find a matching frame descriptor and interval */ + DL_FOREACH(devh->info->stream_ifs, stream_if) { + uvc_format_desc_t *format; + + DL_FOREACH(stream_if->format_descs, format) { + uvc_frame_desc_t *frame; + + if (!_uvc_frame_format_matches_guid(cf, format->guidFormat)) + continue; + + DL_FOREACH(format->frame_descs, frame) { + if (frame->wWidth != width || frame->wHeight != height) + continue; + + uint32_t *interval; + + ctrl->bInterfaceNumber = stream_if->bInterfaceNumber; + UVC_DEBUG("claiming streaming interface %d", stream_if->bInterfaceNumber ); + uvc_claim_if(devh, ctrl->bInterfaceNumber); + /* get the max values */ + uvc_query_stream_ctrl( devh, ctrl, 1, UVC_GET_MAX); + + if (frame->intervals) { + for (interval = frame->intervals; *interval; ++interval) { + // allow a fps rate of zero to mean "accept first rate available" + if (10000000 / *interval == (unsigned int) fps || fps == 0) { + + ctrl->bmHint = (1 << 0); /* don't negotiate interval */ + ctrl->bFormatIndex = format->bFormatIndex; + ctrl->bFrameIndex = frame->bFrameIndex; + ctrl->dwFrameInterval = *interval; + + goto found; + } + } + } else { + uint32_t interval_100ns = 10000000 / fps; + uint32_t interval_offset = interval_100ns - frame->dwMinFrameInterval; + + if (interval_100ns >= frame->dwMinFrameInterval + && interval_100ns <= frame->dwMaxFrameInterval + && !(interval_offset + && (interval_offset % frame->dwFrameIntervalStep))) { + + ctrl->bmHint = (1 << 0); + ctrl->bFormatIndex = format->bFormatIndex; + ctrl->bFrameIndex = frame->bFrameIndex; + ctrl->dwFrameInterval = interval_100ns; + + goto found; + } + } + } + } + } + + return UVC_ERROR_INVALID_MODE; + +found: + return uvc_probe_stream_ctrl(devh, ctrl); +} + +/** Get a negotiated still control block for some common parameters. + * @ingroup streaming + * + * @param[in] devh Device handle + * @param[in] ctrl Control block + * @param[in, out] still_ctrl Still capture control block + * @param[in] width Desired frame width + * @param[in] height Desired frame height + */ +uvc_error_t uvc_get_still_ctrl_format_size( + uvc_device_handle_t *devh, + uvc_stream_ctrl_t *ctrl, + uvc_still_ctrl_t *still_ctrl, + int width, int height) { + uvc_streaming_interface_t *stream_if; + uvc_still_frame_desc_t *still; + uvc_format_desc_t *format; + uvc_still_frame_res_t *sizePattern; + + stream_if = _uvc_get_stream_if(devh, ctrl->bInterfaceNumber); + + /* Only method 2 is supported */ + if(!stream_if || stream_if->bStillCaptureMethod != 2) + return UVC_ERROR_NOT_SUPPORTED; + + DL_FOREACH(stream_if->format_descs, format) { + + if (ctrl->bFormatIndex != format->bFormatIndex) + continue; + + /* get the max values */ + uvc_query_still_ctrl(devh, still_ctrl, 1, UVC_GET_MAX); + + //look for still format + DL_FOREACH(format->still_frame_desc, still) { + DL_FOREACH(still->imageSizePatterns, sizePattern) { + + if (sizePattern->wWidth != width || sizePattern->wHeight != height) + continue; + + still_ctrl->bInterfaceNumber = ctrl->bInterfaceNumber; + still_ctrl->bFormatIndex = format->bFormatIndex; + still_ctrl->bFrameIndex = sizePattern->bResolutionIndex; + still_ctrl->bCompressionIndex = 0; //TODO support compression index + goto found; + } + } + } + + return UVC_ERROR_INVALID_MODE; + + found: + return uvc_probe_still_ctrl(devh, still_ctrl); +} + +/** @internal + * Negotiate streaming parameters with the device + * + * @param[in] devh UVC device + * @param[in,out] ctrl Control block + */ +uvc_error_t uvc_probe_stream_ctrl( + uvc_device_handle_t *devh, + uvc_stream_ctrl_t *ctrl) { + + uvc_query_stream_ctrl( + devh, ctrl, 1, UVC_SET_CUR + ); + + uvc_query_stream_ctrl( + devh, ctrl, 1, UVC_GET_CUR + ); + + /** @todo make sure that worked */ + return UVC_SUCCESS; +} + +/** @internal + * Negotiate still parameters with the device + * + * @param[in] devh UVC device + * @param[in,out] still_ctrl Still capture control block + */ +uvc_error_t uvc_probe_still_ctrl( + uvc_device_handle_t *devh, + uvc_still_ctrl_t *still_ctrl) { + + int res = uvc_query_still_ctrl( + devh, still_ctrl, 1, UVC_SET_CUR + ); + + if(res == UVC_SUCCESS) { + res = uvc_query_still_ctrl( + devh, still_ctrl, 1, UVC_GET_CUR + ); + + if(res == UVC_SUCCESS) { + res = uvc_query_still_ctrl( + devh, still_ctrl, 0, UVC_SET_CUR + ); + } + } + + return res; +} + +/** @internal + * @brief Swap the working buffer with the presented buffer and notify consumers + */ +void _uvc_swap_buffers(uvc_stream_handle_t *strmh) { + uint8_t *tmp_buf; + + pthread_mutex_lock(&strmh->cb_mutex); + + (void)clock_gettime(CLOCK_MONOTONIC, &strmh->capture_time_finished); + + /* swap the buffers */ + tmp_buf = strmh->holdbuf; + strmh->hold_bytes = strmh->got_bytes; + strmh->holdbuf = strmh->outbuf; + strmh->outbuf = tmp_buf; + strmh->hold_last_scr = strmh->last_scr; + strmh->hold_pts = strmh->pts; + strmh->hold_seq = strmh->seq; + + /* swap metadata buffer */ + tmp_buf = strmh->meta_holdbuf; + strmh->meta_holdbuf = strmh->meta_outbuf; + strmh->meta_outbuf = tmp_buf; + strmh->meta_hold_bytes = strmh->meta_got_bytes; + + pthread_cond_broadcast(&strmh->cb_cond); + pthread_mutex_unlock(&strmh->cb_mutex); + + strmh->seq++; + strmh->got_bytes = 0; + strmh->meta_got_bytes = 0; + strmh->last_scr = 0; + strmh->pts = 0; +} + +/** @internal + * @brief Process a payload transfer + * + * Processes stream, places frames into buffer, signals listeners + * (such as user callback thread and any polling thread) on new frame + * + * @param payload Contents of the payload transfer, either a packet (isochronous) or a full + * transfer (bulk mode) + * @param payload_len Length of the payload transfer + */ +void _uvc_process_payload(uvc_stream_handle_t *strmh, uint8_t *payload, size_t payload_len) { + size_t header_len; + uint8_t header_info; + size_t data_len; + + /* magic numbers for identifying header packets from some iSight cameras */ + static uint8_t isight_tag[] = { + 0x11, 0x22, 0x33, 0x44, + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xfa, 0xce + }; + + /* ignore empty payload transfers */ + if (payload_len == 0) + return; + + /* Certain iSight cameras have strange behavior: They send header + * information in a packet with no image data, and then the following + * packets have only image data, with no more headers until the next frame. + * + * The iSight header: len(1), flags(1 or 2), 0x11223344(4), + * 0xdeadbeefdeadface(8), ??(16) + */ + + if (strmh->devh->is_isight && + (payload_len < 14 || memcmp(isight_tag, payload + 2, sizeof(isight_tag))) && + (payload_len < 15 || memcmp(isight_tag, payload + 3, sizeof(isight_tag)))) { + /* The payload transfer doesn't have any iSight magic, so it's all image data */ + header_len = 0; + data_len = payload_len; + } else { + header_len = payload[0]; + + if (header_len > payload_len) { + UVC_DEBUG("bogus packet: actual_len=%zd, header_len=%zd\n", payload_len, header_len); + return; + } + + if (strmh->devh->is_isight) + data_len = 0; + else + data_len = payload_len - header_len; + } + + if (header_len < 2) { + header_info = 0; + } else { + /** @todo we should be checking the end-of-header bit */ + size_t variable_offset = 2; + + header_info = payload[1]; + + if (header_info & 0x40) { + UVC_DEBUG("bad packet: error bit set"); + return; + } + + if (strmh->fid != (header_info & 1) && strmh->got_bytes != 0) { + /* The frame ID bit was flipped, but we have image data sitting + around from prior transfers. This means the camera didn't send + an EOF for the last transfer of the previous frame. */ + _uvc_swap_buffers(strmh); + } + + strmh->fid = header_info & 1; + + if (header_info & (1 << 2)) { + strmh->pts = DW_TO_INT(payload + variable_offset); + variable_offset += 4; + } + + if (header_info & (1 << 3)) { + /** @todo read the SOF token counter */ + strmh->last_scr = DW_TO_INT(payload + variable_offset); + variable_offset += 6; + } + + if (header_len > variable_offset) + { + // Metadata is attached to header + memcpy(strmh->meta_outbuf + strmh->meta_got_bytes, payload + variable_offset, header_len - variable_offset); + strmh->meta_got_bytes += header_len - variable_offset; + } + } + + if (data_len > 0) { + memcpy(strmh->outbuf + strmh->got_bytes, payload + header_len, data_len); + strmh->got_bytes += data_len; + + if (header_info & (1 << 1)) { + /* The EOF bit is set, so publish the complete frame */ + _uvc_swap_buffers(strmh); + } + } +} + +/** @internal + * @brief Stream transfer callback + * + * Processes stream, places frames into buffer, signals listeners + * (such as user callback thread and any polling thread) on new frame + * + * @param transfer Active transfer + */ +void LIBUSB_CALL _uvc_stream_callback(struct libusb_transfer *transfer) { + uvc_stream_handle_t *strmh = transfer->user_data; + + int resubmit = 1; + + switch (transfer->status) { + case LIBUSB_TRANSFER_COMPLETED: + if (transfer->num_iso_packets == 0) { + /* This is a bulk mode transfer, so it just has one payload transfer */ + _uvc_process_payload(strmh, transfer->buffer, transfer->actual_length); + } else { + /* This is an isochronous mode transfer, so each packet has a payload transfer */ + int packet_id; + + for (packet_id = 0; packet_id < transfer->num_iso_packets; ++packet_id) { + uint8_t *pktbuf; + struct libusb_iso_packet_descriptor *pkt; + + pkt = transfer->iso_packet_desc + packet_id; + + if (pkt->status != 0) { + UVC_DEBUG("bad packet (isochronous transfer); status: %d", pkt->status); + continue; + } + + pktbuf = libusb_get_iso_packet_buffer_simple(transfer, packet_id); + + _uvc_process_payload(strmh, pktbuf, pkt->actual_length); + + } + } + break; + case LIBUSB_TRANSFER_CANCELLED: + case LIBUSB_TRANSFER_ERROR: + case LIBUSB_TRANSFER_NO_DEVICE: { + int i; + UVC_DEBUG("not retrying transfer, status = %d", transfer->status); + pthread_mutex_lock(&strmh->cb_mutex); + + /* Mark transfer as deleted. */ + for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) { + if(strmh->transfers[i] == transfer) { + UVC_DEBUG("Freeing transfer %d (%p)", i, transfer); + free(transfer->buffer); + libusb_free_transfer(transfer); + strmh->transfers[i] = NULL; + break; + } + } + if(i == LIBUVC_NUM_TRANSFER_BUFS ) { + UVC_DEBUG("transfer %p not found; not freeing!", transfer); + } + + resubmit = 0; + + pthread_cond_broadcast(&strmh->cb_cond); + pthread_mutex_unlock(&strmh->cb_mutex); + + break; + } + case LIBUSB_TRANSFER_TIMED_OUT: + case LIBUSB_TRANSFER_STALL: + case LIBUSB_TRANSFER_OVERFLOW: + UVC_DEBUG("retrying transfer, status = %d", transfer->status); + break; + } + + if ( resubmit ) { + if ( strmh->running ) { + int libusbRet = libusb_submit_transfer(transfer); + if (libusbRet < 0) + { + int i; + pthread_mutex_lock(&strmh->cb_mutex); + + /* Mark transfer as deleted. */ + for (i = 0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) { + if (strmh->transfers[i] == transfer) { + UVC_DEBUG("Freeing failed transfer %d (%p)", i, transfer); + free(transfer->buffer); + libusb_free_transfer(transfer); + strmh->transfers[i] = NULL; + break; + } + } + if (i == LIBUVC_NUM_TRANSFER_BUFS) { + UVC_DEBUG("failed transfer %p not found; not freeing!", transfer); + } + + pthread_cond_broadcast(&strmh->cb_cond); + pthread_mutex_unlock(&strmh->cb_mutex); + } + } else { + int i; + pthread_mutex_lock(&strmh->cb_mutex); + + /* Mark transfer as deleted. */ + for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) { + if(strmh->transfers[i] == transfer) { + UVC_DEBUG("Freeing orphan transfer %d (%p)", i, transfer); + free(transfer->buffer); + libusb_free_transfer(transfer); + strmh->transfers[i] = NULL; + break; + } + } + if(i == LIBUVC_NUM_TRANSFER_BUFS ) { + UVC_DEBUG("orphan transfer %p not found; not freeing!", transfer); + } + + pthread_cond_broadcast(&strmh->cb_cond); + pthread_mutex_unlock(&strmh->cb_mutex); + } + } +} + +/** Begin streaming video from the camera into the callback function. + * @ingroup streaming + * + * @param devh UVC device + * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or + * {uvc_get_stream_ctrl_format_size} + * @param cb User callback function. See {uvc_frame_callback_t} for restrictions. + * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit + * is reserved for backward compatibility. + */ +uvc_error_t uvc_start_streaming( + uvc_device_handle_t *devh, + uvc_stream_ctrl_t *ctrl, + uvc_frame_callback_t *cb, + void *user_ptr, + uint8_t flags +) { + uvc_error_t ret; + uvc_stream_handle_t *strmh; + + ret = uvc_stream_open_ctrl(devh, &strmh, ctrl); + if (ret != UVC_SUCCESS) + return ret; + + ret = uvc_stream_start(strmh, cb, user_ptr, flags); + if (ret != UVC_SUCCESS) { + uvc_stream_close(strmh); + return ret; + } + + return UVC_SUCCESS; +} + +/** Begin streaming video from the camera into the callback function. + * @ingroup streaming + * + * @deprecated The stream type (bulk vs. isochronous) will be determined by the + * type of interface associated with the uvc_stream_ctrl_t parameter, regardless + * of whether the caller requests isochronous streaming. Please switch to + * uvc_start_streaming(). + * + * @param devh UVC device + * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or + * {uvc_get_stream_ctrl_format_size} + * @param cb User callback function. See {uvc_frame_callback_t} for restrictions. + */ +uvc_error_t uvc_start_iso_streaming( + uvc_device_handle_t *devh, + uvc_stream_ctrl_t *ctrl, + uvc_frame_callback_t *cb, + void *user_ptr +) { + return uvc_start_streaming(devh, ctrl, cb, user_ptr, 0); +} + +static uvc_stream_handle_t *_uvc_get_stream_by_interface(uvc_device_handle_t *devh, int interface_idx) { + uvc_stream_handle_t *strmh; + + DL_FOREACH(devh->streams, strmh) { + if (strmh->stream_if->bInterfaceNumber == interface_idx) + return strmh; + } + + return NULL; +} + +static uvc_streaming_interface_t *_uvc_get_stream_if(uvc_device_handle_t *devh, int interface_idx) { + uvc_streaming_interface_t *stream_if; + + DL_FOREACH(devh->info->stream_ifs, stream_if) { + if (stream_if->bInterfaceNumber == interface_idx) + return stream_if; + } + + return NULL; +} + +/** Open a new video stream. + * @ingroup streaming + * + * @param devh UVC device + * @param ctrl Control block, processed using {uvc_probe_stream_ctrl} or + * {uvc_get_stream_ctrl_format_size} + */ +uvc_error_t uvc_stream_open_ctrl(uvc_device_handle_t *devh, uvc_stream_handle_t **strmhp, uvc_stream_ctrl_t *ctrl) { + /* Chosen frame and format descriptors */ + uvc_stream_handle_t *strmh = NULL; + uvc_streaming_interface_t *stream_if; + uvc_error_t ret; + + UVC_ENTER(); + + if (_uvc_get_stream_by_interface(devh, ctrl->bInterfaceNumber) != NULL) { + ret = UVC_ERROR_BUSY; /* Stream is already opened */ + goto fail; + } + + stream_if = _uvc_get_stream_if(devh, ctrl->bInterfaceNumber); + if (!stream_if) { + ret = UVC_ERROR_INVALID_PARAM; + goto fail; + } + + strmh = calloc(1, sizeof(*strmh)); + if (!strmh) { + ret = UVC_ERROR_NO_MEM; + goto fail; + } + strmh->devh = devh; + strmh->stream_if = stream_if; + strmh->frame.library_owns_data = 1; + + ret = uvc_claim_if(strmh->devh, strmh->stream_if->bInterfaceNumber); + if (ret != UVC_SUCCESS) + goto fail; + + ret = uvc_stream_ctrl(strmh, ctrl); + if (ret != UVC_SUCCESS) + goto fail; + + // Set up the streaming status and data space + strmh->running = 0; + /** @todo take only what we need */ + strmh->outbuf = malloc( LIBUVC_XFER_BUF_SIZE ); + strmh->holdbuf = malloc( LIBUVC_XFER_BUF_SIZE ); + + strmh->meta_outbuf = malloc( LIBUVC_XFER_META_BUF_SIZE ); + strmh->meta_holdbuf = malloc( LIBUVC_XFER_META_BUF_SIZE ); + + pthread_mutex_init(&strmh->cb_mutex, NULL); + pthread_cond_init(&strmh->cb_cond, NULL); + + DL_APPEND(devh->streams, strmh); + + *strmhp = strmh; + + UVC_EXIT(0); + return UVC_SUCCESS; + +fail: + if(strmh) + free(strmh); + UVC_EXIT(ret); + return ret; +} + +/** Begin streaming video from the stream into the callback function. + * @ingroup streaming + * + * @param strmh UVC stream + * @param cb User callback function. See {uvc_frame_callback_t} for restrictions. + * @param flags Stream setup flags, currently undefined. Set this to zero. The lower bit + * is reserved for backward compatibility. + */ +uvc_error_t uvc_stream_start( + uvc_stream_handle_t *strmh, + uvc_frame_callback_t *cb, + void *user_ptr, + uint8_t flags +) { + /* USB interface we'll be using */ + const struct libusb_interface *interface; + int interface_id; + char isochronous; + uvc_frame_desc_t *frame_desc; + uvc_format_desc_t *format_desc; + uvc_stream_ctrl_t *ctrl; + uvc_error_t ret; + /* Total amount of data per transfer */ + size_t total_transfer_size = 0; + struct libusb_transfer *transfer; + int transfer_id; + + ctrl = &strmh->cur_ctrl; + + UVC_ENTER(); + + if (strmh->running) { + UVC_EXIT(UVC_ERROR_BUSY); + return UVC_ERROR_BUSY; + } + + strmh->running = 1; + strmh->seq = 1; + strmh->fid = 0; + strmh->pts = 0; + strmh->last_scr = 0; + + frame_desc = uvc_find_frame_desc_stream(strmh, ctrl->bFormatIndex, ctrl->bFrameIndex); + if (!frame_desc) { + ret = UVC_ERROR_INVALID_PARAM; + goto fail; + } + format_desc = frame_desc->parent; + + strmh->frame_format = uvc_frame_format_for_guid(format_desc->guidFormat); + if (strmh->frame_format == UVC_FRAME_FORMAT_UNKNOWN) { + ret = UVC_ERROR_NOT_SUPPORTED; + goto fail; + } + + // Get the interface that provides the chosen format and frame configuration + interface_id = strmh->stream_if->bInterfaceNumber; + interface = &strmh->devh->info->config->interface[interface_id]; + + /* A VS interface uses isochronous transfers iff it has multiple altsettings. + * (UVC 1.5: 2.4.3. VideoStreaming Interface) */ + isochronous = interface->num_altsetting > 1; + + if (isochronous) { + /* For isochronous streaming, we choose an appropriate altsetting for the endpoint + * and set up several transfers */ + const struct libusb_interface_descriptor *altsetting = 0; + const struct libusb_endpoint_descriptor *endpoint = 0; + /* The greatest number of bytes that the device might provide, per packet, in this + * configuration */ + size_t config_bytes_per_packet; + /* Number of packets per transfer */ + size_t packets_per_transfer = 0; + /* Size of packet transferable from the chosen endpoint */ + size_t endpoint_bytes_per_packet = 0; + /* Index of the altsetting */ + int alt_idx, ep_idx; + + config_bytes_per_packet = strmh->cur_ctrl.dwMaxPayloadTransferSize; + + /* Go through the altsettings and find one whose packets are at least + * as big as our format's maximum per-packet usage. Assume that the + * packet sizes are increasing. */ + for (alt_idx = 0; alt_idx < interface->num_altsetting; alt_idx++) { + altsetting = interface->altsetting + alt_idx; + endpoint_bytes_per_packet = 0; + + /* Find the endpoint with the number specified in the VS header */ + for (ep_idx = 0; ep_idx < altsetting->bNumEndpoints; ep_idx++) { + endpoint = altsetting->endpoint + ep_idx; + + struct libusb_ss_endpoint_companion_descriptor *ep_comp = 0; + libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp); + if (ep_comp) + { + endpoint_bytes_per_packet = ep_comp->wBytesPerInterval; + libusb_free_ss_endpoint_companion_descriptor(ep_comp); + break; + } + else + { + if (endpoint->bEndpointAddress == format_desc->parent->bEndpointAddress) { + endpoint_bytes_per_packet = endpoint->wMaxPacketSize; + // wMaxPacketSize: [unused:2 (multiplier-1):3 size:11] + endpoint_bytes_per_packet = (endpoint_bytes_per_packet & 0x07ff) * + (((endpoint_bytes_per_packet >> 11) & 3) + 1); + break; + } + } + } + + if (endpoint_bytes_per_packet >= config_bytes_per_packet) { + /* Transfers will be at most one frame long: Divide the maximum frame size + * by the size of the endpoint and round up */ + packets_per_transfer = (ctrl->dwMaxVideoFrameSize + + endpoint_bytes_per_packet - 1) / endpoint_bytes_per_packet; + + /* But keep a reasonable limit: Otherwise we start dropping data */ + if (packets_per_transfer > 32) + packets_per_transfer = 32; + + total_transfer_size = packets_per_transfer * endpoint_bytes_per_packet; + break; + } + } + + /* If we searched through all the altsettings and found nothing usable */ + if (alt_idx == interface->num_altsetting) { + ret = UVC_ERROR_INVALID_MODE; + goto fail; + } + + /* Select the altsetting */ + ret = libusb_set_interface_alt_setting(strmh->devh->usb_devh, + altsetting->bInterfaceNumber, + altsetting->bAlternateSetting); + if (ret != UVC_SUCCESS) { + UVC_DEBUG("libusb_set_interface_alt_setting failed"); + goto fail; + } + + /* Set up the transfers */ + for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; ++transfer_id) { + transfer = libusb_alloc_transfer(packets_per_transfer); + strmh->transfers[transfer_id] = transfer; + strmh->transfer_bufs[transfer_id] = malloc(total_transfer_size); + + libusb_fill_iso_transfer( + transfer, strmh->devh->usb_devh, format_desc->parent->bEndpointAddress, + strmh->transfer_bufs[transfer_id], + total_transfer_size, packets_per_transfer, _uvc_stream_callback, (void*) strmh, 5000); + + libusb_set_iso_packet_lengths(transfer, endpoint_bytes_per_packet); + } + } else { + for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; + ++transfer_id) { + transfer = libusb_alloc_transfer(0); + strmh->transfers[transfer_id] = transfer; + strmh->transfer_bufs[transfer_id] = malloc ( + strmh->cur_ctrl.dwMaxPayloadTransferSize ); + libusb_fill_bulk_transfer ( transfer, strmh->devh->usb_devh, + format_desc->parent->bEndpointAddress, + strmh->transfer_bufs[transfer_id], + strmh->cur_ctrl.dwMaxPayloadTransferSize, _uvc_stream_callback, + ( void* ) strmh, 5000 ); + } + } + + strmh->user_cb = cb; + strmh->user_ptr = user_ptr; + + /* If the user wants it, set up a thread that calls the user's function + * with the contents of each frame. + */ + if (cb) { + pthread_create(&strmh->cb_thread, NULL, _uvc_user_caller, (void*) strmh); + } + + for (transfer_id = 0; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; + transfer_id++) { + ret = libusb_submit_transfer(strmh->transfers[transfer_id]); + if (ret != UVC_SUCCESS) { + UVC_DEBUG("libusb_submit_transfer failed: %d",ret); + break; + } + } + + if ( ret != UVC_SUCCESS && transfer_id > 0 ) { + for ( ; transfer_id < LIBUVC_NUM_TRANSFER_BUFS; transfer_id++) { + free ( strmh->transfers[transfer_id]->buffer ); + libusb_free_transfer ( strmh->transfers[transfer_id]); + strmh->transfers[transfer_id] = 0; + } + ret = UVC_SUCCESS; + } + + UVC_EXIT(ret); + return ret; +fail: + strmh->running = 0; + UVC_EXIT(ret); + return ret; +} + +/** Begin streaming video from the stream into the callback function. + * @ingroup streaming + * + * @deprecated The stream type (bulk vs. isochronous) will be determined by the + * type of interface associated with the uvc_stream_ctrl_t parameter, regardless + * of whether the caller requests isochronous streaming. Please switch to + * uvc_stream_start(). + * + * @param strmh UVC stream + * @param cb User callback function. See {uvc_frame_callback_t} for restrictions. + */ +uvc_error_t uvc_stream_start_iso( + uvc_stream_handle_t *strmh, + uvc_frame_callback_t *cb, + void *user_ptr +) { + return uvc_stream_start(strmh, cb, user_ptr, 0); +} + +/** @internal + * @brief User callback runner thread + * @note There should be at most one of these per currently streaming device + * @param arg Device handle + */ +void *_uvc_user_caller(void *arg) { + uvc_stream_handle_t *strmh = (uvc_stream_handle_t *) arg; + + uint32_t last_seq = 0; + + do { + pthread_mutex_lock(&strmh->cb_mutex); + + while (strmh->running && last_seq == strmh->hold_seq) { + pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex); + } + + if (!strmh->running) { + pthread_mutex_unlock(&strmh->cb_mutex); + break; + } + + last_seq = strmh->hold_seq; + _uvc_populate_frame(strmh); + + pthread_mutex_unlock(&strmh->cb_mutex); + + strmh->user_cb(&strmh->frame, strmh->user_ptr); + } while(1); + + return NULL; // return value ignored +} + +/** @internal + * @brief Populate the fields of a frame to be handed to user code + * must be called with stream cb lock held! + */ +void _uvc_populate_frame(uvc_stream_handle_t *strmh) { + uvc_frame_t *frame = &strmh->frame; + uvc_frame_desc_t *frame_desc; + + /** @todo this stuff that hits the main config cache should really happen + * in start() so that only one thread hits these data. all of this stuff + * is going to be reopen_on_change anyway + */ + + frame_desc = uvc_find_frame_desc(strmh->devh, strmh->cur_ctrl.bFormatIndex, + strmh->cur_ctrl.bFrameIndex); + + frame->frame_format = strmh->frame_format; + + frame->width = frame_desc->wWidth; + frame->height = frame_desc->wHeight; + + switch (frame->frame_format) { + case UVC_FRAME_FORMAT_BGR: + frame->step = frame->width * 3; + break; + case UVC_FRAME_FORMAT_YUYV: + frame->step = frame->width * 2; + break; + case UVC_FRAME_FORMAT_NV12: + frame->step = frame->width; + break; + case UVC_FRAME_FORMAT_MJPEG: + frame->step = 0; + break; + case UVC_FRAME_FORMAT_H264: + frame->step = 0; + break; + default: + frame->step = 0; + break; + } + + frame->sequence = strmh->hold_seq; + frame->capture_time_finished = strmh->capture_time_finished; + + /* copy the image data from the hold buffer to the frame (unnecessary extra buf?) */ + if (frame->data_bytes < strmh->hold_bytes) { + frame->data = realloc(frame->data, strmh->hold_bytes); + } + frame->data_bytes = strmh->hold_bytes; + memcpy(frame->data, strmh->holdbuf, frame->data_bytes); + + if (strmh->meta_hold_bytes > 0) + { + if (frame->metadata_bytes < strmh->meta_hold_bytes) + { + frame->metadata = realloc(frame->metadata, strmh->meta_hold_bytes); + } + frame->metadata_bytes = strmh->meta_hold_bytes; + memcpy(frame->metadata, strmh->meta_holdbuf, frame->metadata_bytes); + } +} + +/** Poll for a frame + * @ingroup streaming + * + * @param devh UVC device + * @param[out] frame Location to store pointer to captured frame (NULL on error) + * @param timeout_us >0: Wait at most N microseconds; 0: Wait indefinitely; -1: return immediately + */ +uvc_error_t uvc_stream_get_frame(uvc_stream_handle_t *strmh, + uvc_frame_t **frame, + int32_t timeout_us) { + time_t add_secs; + time_t add_nsecs; + struct timespec ts; + struct timeval tv; + + if (!strmh->running) + return UVC_ERROR_INVALID_PARAM; + + if (strmh->user_cb) + return UVC_ERROR_CALLBACK_EXISTS; + + pthread_mutex_lock(&strmh->cb_mutex); + + if (strmh->last_polled_seq < strmh->hold_seq) { + _uvc_populate_frame(strmh); + *frame = &strmh->frame; + strmh->last_polled_seq = strmh->hold_seq; + } else if (timeout_us != -1) { + if (timeout_us == 0) { + pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex); + } else { + add_secs = timeout_us / 1000000; + add_nsecs = (timeout_us % 1000000) * 1000; + ts.tv_sec = 0; + ts.tv_nsec = 0; + +#if _POSIX_TIMERS > 0 + clock_gettime(CLOCK_REALTIME, &ts); +#else + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#endif + + ts.tv_sec += add_secs; + ts.tv_nsec += add_nsecs; + + /* pthread_cond_timedwait FAILS with EINVAL if ts.tv_nsec > 1000000000 (1 billion) + * Since we are just adding values to the timespec, we have to increment the seconds if nanoseconds is greater than 1 billion, + * and then re-adjust the nanoseconds in the correct range. + * */ + ts.tv_sec += ts.tv_nsec / 1000000000; + ts.tv_nsec = ts.tv_nsec % 1000000000; + + int err = pthread_cond_timedwait(&strmh->cb_cond, &strmh->cb_mutex, &ts); + + //TODO: How should we handle EINVAL? + if (err) { + *frame = NULL; + pthread_mutex_unlock(&strmh->cb_mutex); + return err == ETIMEDOUT ? UVC_ERROR_TIMEOUT : UVC_ERROR_OTHER; + } + } + + if (strmh->last_polled_seq < strmh->hold_seq) { + _uvc_populate_frame(strmh); + *frame = &strmh->frame; + strmh->last_polled_seq = strmh->hold_seq; + } else { + *frame = NULL; + } + } else { + *frame = NULL; + } + + pthread_mutex_unlock(&strmh->cb_mutex); + + return UVC_SUCCESS; +} + +/** @brief Stop streaming video + * @ingroup streaming + * + * Closes all streams, ends threads and cancels pollers + * + * @param devh UVC device + */ +void uvc_stop_streaming(uvc_device_handle_t *devh) { + uvc_stream_handle_t *strmh, *strmh_tmp; + + DL_FOREACH_SAFE(devh->streams, strmh, strmh_tmp) { + uvc_stream_close(strmh); + } +} + +/** @brief Stop stream. + * @ingroup streaming + * + * Stops stream, ends threads and cancels pollers + * + * @param devh UVC device + */ +uvc_error_t uvc_stream_stop(uvc_stream_handle_t *strmh) { + int i; + + if (!strmh->running) + return UVC_ERROR_INVALID_PARAM; + + strmh->running = 0; + + pthread_mutex_lock(&strmh->cb_mutex); + + for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) { + if(strmh->transfers[i] != NULL) { + int res = libusb_cancel_transfer(strmh->transfers[i]); + if(res < 0 && res != LIBUSB_ERROR_NOT_FOUND ) { + free(strmh->transfers[i]->buffer); + libusb_free_transfer(strmh->transfers[i]); + strmh->transfers[i] = NULL; + } + } + } + + /* Wait for transfers to complete/cancel */ + do { + for(i=0; i < LIBUVC_NUM_TRANSFER_BUFS; i++) { + if(strmh->transfers[i] != NULL) + break; + } + if(i == LIBUVC_NUM_TRANSFER_BUFS ) + break; + pthread_cond_wait(&strmh->cb_cond, &strmh->cb_mutex); + } while(1); + // Kick the user thread awake + pthread_cond_broadcast(&strmh->cb_cond); + pthread_mutex_unlock(&strmh->cb_mutex); + + /** @todo stop the actual stream, camera side? */ + + if (strmh->user_cb) { + /* wait for the thread to stop (triggered by + * LIBUSB_TRANSFER_CANCELLED transfer) */ + pthread_join(strmh->cb_thread, NULL); + } + + return UVC_SUCCESS; +} + +/** @brief Close stream. + * @ingroup streaming + * + * Closes stream, frees handle and all streaming resources. + * + * @param strmh UVC stream handle + */ +void uvc_stream_close(uvc_stream_handle_t *strmh) { + if (strmh->running) + uvc_stream_stop(strmh); + + uvc_release_if(strmh->devh, strmh->stream_if->bInterfaceNumber); + + if (strmh->frame.data) + free(strmh->frame.data); + + free(strmh->outbuf); + free(strmh->holdbuf); + + free(strmh->meta_outbuf); + free(strmh->meta_holdbuf); + + pthread_cond_destroy(&strmh->cb_cond); + pthread_mutex_destroy(&strmh->cb_mutex); + + DL_DELETE(strmh->devh->streams, strmh); + free(strmh); +} diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/src/test.c b/Code/RK3588/PIBot_ROS/third_party/libuvc/src/test.c new file mode 100644 index 0000000..47fe096 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/src/test.c @@ -0,0 +1,153 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (C) 2010-2012 Ken Tossell +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the author nor other contributors may be +* used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ +#include +#include + +#include "libuvc/libuvc.h" + +void cb(uvc_frame_t *frame, void *ptr) { + uvc_frame_t *bgr; + uvc_error_t ret; + IplImage* cvImg; + + printf("callback! length = %u, ptr = %d\n", frame->data_bytes, (int) ptr); + + bgr = uvc_allocate_frame(frame->width * frame->height * 3); + if (!bgr) { + printf("unable to allocate bgr frame!"); + return; + } + + ret = uvc_any2bgr(frame, bgr); + if (ret) { + uvc_perror(ret, "uvc_any2bgr"); + uvc_free_frame(bgr); + return; + } + + cvImg = cvCreateImageHeader( + cvSize(bgr->width, bgr->height), + IPL_DEPTH_8U, + 3); + + cvSetData(cvImg, bgr->data, bgr->width * 3); + + cvNamedWindow("Test", CV_WINDOW_AUTOSIZE); + cvShowImage("Test", cvImg); + cvWaitKey(10); + + cvReleaseImageHeader(&cvImg); + + uvc_free_frame(bgr); +} + +int main(int argc, char **argv) { + uvc_context_t *ctx; + uvc_error_t res; + uvc_device_t *dev; + uvc_device_handle_t *devh; + uvc_stream_ctrl_t ctrl; + + res = uvc_init(&ctx, NULL); + + if (res < 0) { + uvc_perror(res, "uvc_init"); + return res; + } + + puts("UVC initialized"); + + res = uvc_find_device( + ctx, &dev, + 0, 0, NULL); + + if (res < 0) { + uvc_perror(res, "uvc_find_device"); + } else { + puts("Device found"); + + res = uvc_open(dev, &devh); + + if (res < 0) { + uvc_perror(res, "uvc_open"); + } else { + puts("Device opened"); + + uvc_print_diag(devh, stderr); + + res = uvc_get_stream_ctrl_format_size( + devh, &ctrl, UVC_FRAME_FORMAT_YUYV, 640, 480, 30 + ); + + uvc_print_stream_ctrl(&ctrl, stderr); + + if (res < 0) { + uvc_perror(res, "get_mode"); + } else { + res = uvc_start_streaming(devh, &ctrl, cb, 12345, 0); + + if (res < 0) { + uvc_perror(res, "start_streaming"); + } else { + puts("Streaming for 10 seconds..."); + uvc_error_t resAEMODE = uvc_set_ae_mode(devh, 1); + uvc_perror(resAEMODE, "set_ae_mode"); + int i; + for (i = 1; i <= 10; i++) { + /* uvc_error_t resPT = uvc_set_pantilt_abs(devh, i * 20 * 3600, 0); */ + /* uvc_perror(resPT, "set_pt_abs"); */ + uvc_error_t resEXP = uvc_set_exposure_abs(devh, 20 + i * 5); + uvc_perror(resEXP, "set_exp_abs"); + + sleep(1); + } + sleep(10); + uvc_stop_streaming(devh); + puts("Done streaming."); + } + } + + uvc_close(devh); + puts("Device closed"); + } + + uvc_unref_device(dev); + } + + uvc_exit(ctx); + puts("UVC exited"); + + return 0; +} + diff --git a/Code/RK3588/PIBot_ROS/third_party/libuvc/standard-units.yaml b/Code/RK3588/PIBot_ROS/third_party/libuvc/standard-units.yaml new file mode 100644 index 0000000..198c401 --- /dev/null +++ b/Code/RK3588/PIBot_ROS/third_party/libuvc/standard-units.yaml @@ -0,0 +1,518 @@ +units: + camera_terminal: + type: standard + description: Standard camera input terminal (captures images from sensor) + control_prefix: CT + controls: + scanning_mode: + control: SCANNING_MODE + length: 1 + fields: + mode: + type: int + position: 0 + length: 1 + doc: '0: interlaced, 1: progressive' + ae_mode: + control: AE_MODE + length: 1 + fields: + mode: + type: int + position: 0 + length: 1 + doc: '1: manual mode; 2: auto mode; 4: shutter priority mode; 8: aperture + priority mode' + doc: + get: |- + @brief Reads camera's auto-exposure mode. + + See uvc_set_ae_mode() for a description of the available modes. + set: |- + @brief Sets camera's auto-exposure mode. + + Cameras may support any of the following AE modes: + * UVC_AUTO_EXPOSURE_MODE_MANUAL (1) - manual exposure time, manual iris + * UVC_AUTO_EXPOSURE_MODE_AUTO (2) - auto exposure time, auto iris + * UVC_AUTO_EXPOSURE_MODE_SHUTTER_PRIORITY (4) - manual exposure time, auto iris + * UVC_AUTO_EXPOSURE_MODE_APERTURE_PRIORITY (8) - auto exposure time, manual iris + + Most cameras provide manual mode and aperture priority mode. + ae_priority: + control: AE_PRIORITY + length: 1 + fields: + priority: + type: int + position: 0 + length: 1 + doc: '0: frame rate must remain constant; 1: frame rate may be varied + for AE purposes' + doc: + get: |- + @brief Checks whether the camera may vary the frame rate for exposure control reasons. + See uvc_set_ae_priority() for a description of the `priority` field. + set: |- + @brief Chooses whether the camera may vary the frame rate for exposure control reasons. + A `priority` value of zero means the camera may not vary its frame rate. A value of 1 + means the frame rate is variable. This setting has no effect outside of the `auto` and + `shutter_priority` auto-exposure modes. + exposure_abs: + control: EXPOSURE_TIME_ABSOLUTE + length: 4 + fields: + time: + type: int + position: 0 + length: 4 + doc: '' + doc: + get: |- + @brief Gets the absolute exposure time. + + See uvc_set_exposure_abs() for a description of the `time` field. + set: |- + @brief Sets the absolute exposure time. + + The `time` parameter should be provided in units of 0.0001 seconds (e.g., use the value 100 + for a 10ms exposure period). Auto exposure should be set to `manual` or `shutter_priority` + before attempting to change this setting. + exposure_rel: + control: EXPOSURE_TIME_RELATIVE + length: 1 + fields: + step: + type: int + position: 0 + length: 1 + signed: true + doc: number of steps by which to change the exposure time, or zero to + set the default exposure time + doc: '@brief {gets_sets} the exposure time relative to the current setting.' + focus_abs: + control: FOCUS_ABSOLUTE + length: 2 + fields: + focus: + type: int + position: 0 + length: 2 + doc: focal target distance in millimeters + doc: '@brief {gets_sets} the distance at which an object is optimally focused.' + focus_rel: + control: FOCUS_RELATIVE + length: 2 + fields: + focus_rel: + type: int + position: 0 + length: 1 + signed: true + doc: TODO + speed: + type: int + position: 1 + length: 1 + doc: TODO + focus_simple_range: + control: FOCUS_SIMPLE + length: 1 + fields: + focus: + type: int + position: 0 + length: 1 + doc: TODO + focus_auto: + control: FOCUS_AUTO + length: 1 + fields: + state: + type: int + position: 0 + length: 1 + doc: TODO + iris_abs: + control: IRIS_ABSOLUTE + length: 2 + fields: + iris: + type: int + position: 0 + length: 2 + doc: TODO + iris_rel: + control: IRIS_RELATIVE + length: 1 + fields: + iris_rel: + type: int + position: 0 + length: 1 + doc: TODO + zoom_abs: + control: ZOOM_ABSOLUTE + length: 2 + fields: + focal_length: + type: int + position: 0 + length: 2 + doc: TODO + zoom_rel: + control: ZOOM_RELATIVE + length: 3 + fields: + zoom_rel: + type: int + position: 0 + length: 1 + signed: true + doc: TODO + digital_zoom: + type: int + position: 1 + length: 1 + doc: TODO + speed: + type: int + position: 2 + length: 1 + doc: TODO + pantilt_abs: + control: PANTILT_ABSOLUTE + length: 8 + fields: + pan: + type: int + position: 0 + length: 4 + signed: true + doc: TODO + tilt: + type: int + position: 4 + length: 4 + signed: true + doc: TODO + pantilt_rel: + control: PANTILT_RELATIVE + length: 4 + fields: + pan_rel: + type: int + position: 0 + length: 1 + signed: true + doc: TODO + pan_speed: + type: int + position: 1 + length: 1 + doc: TODO + tilt_rel: + type: int + position: 2 + length: 1 + signed: true + doc: TODO + tilt_speed: + type: int + position: 3 + length: 1 + doc: TODO + roll_abs: + control: ROLL_ABSOLUTE + length: 2 + fields: + roll: + type: int + position: 0 + length: 2 + signed: true + doc: TODO + roll_rel: + control: ROLL_RELATIVE + length: 2 + fields: + roll_rel: + type: int + position: 0 + length: 1 + signed: true + doc: TODO + speed: + type: int + position: 1 + length: 1 + doc: TODO + privacy: + control: PRIVACY + length: 1 + fields: + privacy: + type: int + position: 0 + length: 1 + doc: TODO + digital_window: + control: DIGITAL_WINDOW + length: 12 + fields: + window_top: + type: int + position: 0 + length: 2 + doc: TODO + window_left: + type: int + position: 2 + length: 2 + doc: TODO + window_bottom: + type: int + position: 4 + length: 2 + doc: TODO + window_right: + type: int + position: 6 + length: 2 + doc: TODO + num_steps: + type: int + position: 8 + length: 2 + doc: TODO + num_steps_units: + type: int + position: 10 + length: 2 + doc: TODO + digital_roi: + control: REGION_OF_INTEREST + length: 10 + fields: + roi_top: + type: int + position: 0 + length: 2 + doc: TODO + roi_left: + type: int + position: 2 + length: 2 + doc: TODO + roi_bottom: + type: int + position: 4 + length: 2 + doc: TODO + roi_right: + type: int + position: 6 + length: 2 + doc: TODO + auto_controls: + type: int + position: 8 + length: 2 + doc: TODO + processing_unit: + type: standard + description: Standard processing unit (processes images between other units) + control_prefix: PU + controls: + backlight_compensation: + control: BACKLIGHT_COMPENSATION + length: 2 + fields: + backlight_compensation: + type: int + position: 0 + length: 2 + doc: device-dependent backlight compensation mode; zero means backlight + compensation is disabled + brightness: + control: BRIGHTNESS + length: 2 + fields: + brightness: + type: int + position: 0 + length: 2 + signed: true + doc: TODO + contrast: + control: CONTRAST + length: 2 + fields: + contrast: + type: int + position: 0 + length: 2 + doc: TODO + contrast_auto: + control: CONTRAST_AUTO + length: 1 + fields: + contrast_auto: + type: int + position: 0 + length: 1 + doc: TODO + gain: + control: GAIN + length: 2 + fields: + gain: + type: int + position: 0 + length: 2 + doc: TODO + power_line_frequency: + control: POWER_LINE_FREQUENCY + length: 1 + fields: + power_line_frequency: + type: int + position: 0 + length: 1 + doc: TODO + hue: + control: HUE + length: 2 + fields: + hue: + type: int + position: 0 + length: 2 + signed: true + doc: TODO + hue_auto: + control: HUE_AUTO + length: 1 + fields: + hue_auto: + type: int + position: 0 + length: 1 + doc: TODO + saturation: + control: SATURATION + length: 2 + fields: + saturation: + type: int + position: 0 + length: 2 + doc: TODO + sharpness: + control: SHARPNESS + length: 2 + fields: + sharpness: + type: int + position: 0 + length: 2 + doc: TODO + gamma: + control: GAMMA + length: 2 + fields: + gamma: + type: int + position: 0 + length: 2 + doc: TODO + white_balance_temperature: + control: WHITE_BALANCE_TEMPERATURE + length: 2 + fields: + temperature: + type: int + position: 0 + length: 2 + doc: TODO + white_balance_temperature_auto: + control: WHITE_BALANCE_TEMPERATURE_AUTO + length: 1 + fields: + temperature_auto: + type: int + position: 0 + length: 1 + doc: TODO + white_balance_component: + control: WHITE_BALANCE_COMPONENT + length: 4 + fields: + blue: + type: int + position: 0 + length: 2 + doc: TODO + red: + type: int + position: 2 + length: 2 + doc: TODO + white_balance_component_auto: + control: WHITE_BALANCE_COMPONENT_AUTO + length: 1 + fields: + white_balance_component_auto: + type: int + position: 0 + length: 1 + doc: TODO + digital_multiplier: + control: DIGITAL_MULTIPLIER + length: 2 + fields: + multiplier_step: + type: int + position: 0 + length: 2 + doc: TODO + digital_multiplier_limit: + control: DIGITAL_MULTIPLIER_LIMIT + length: 2 + fields: + multiplier_step: + type: int + position: 0 + length: 2 + doc: TODO + analog_video_standard: + control: ANALOG_VIDEO_STANDARD + length: 1 + fields: + video_standard: + type: int + position: 0 + length: 1 + doc: TODO + analog_video_lock_status: + control: ANALOG_LOCK_STATUS + length: 1 + fields: + status: + type: int + position: 0 + length: 1 + doc: TODO + selector_unit: + type: standard + description: Standard selector unit (controls connectivity between other units) + control_prefix: SU + controls: + input_select: + control: INPUT_SELECT + length: 1 + fields: + selector: + type: int + position: 0 + length: 1 + doc: TODO diff --git a/Code/RK3588/README.md b/Code/RK3588/README.md index 8d793d0..56395e6 100644 --- a/Code/RK3588/README.md +++ b/Code/RK3588/README.md @@ -7,4 +7,6 @@ 其他资料: -PIBot官方资料:https://gitee.com/pibot/pibot_bringup/blob/master/doc/README.md#1-%E8%AF%B4%E6%98%8E \ No newline at end of file +PIBot官方资料:https://gitee.com/pibot/pibot_bringup/blob/master/doc/README.md#1-%E8%AF%B4%E6%98%8E + +> 注意:`build`文件夹是编译生成,不需要纳入git管理 \ No newline at end of file